
/*     
 *      FILE
 *     	rules/linf/rretrieve.l
 *     
 *      DESCRIPTION
 *     	Routines related to processing RETRIEVE queries.
 *     
 */
defvar (,RCS_rretrieve,"$Header: rretrieve.l,v 1.2 89/02/21 01:24:03 hirohama Exp $");

/*     
 *      EXPORTS
 *     	DoRetrieve
 *     	calculateOneField
 *     	runRule
 *     	checkForNeverRules
 */
require ("nodeDefs");

/*    
 *     DoRetrieve
 *    
 */
LispValue
DoRetrieve (theTupletheTuple,theTargetListtheTargetList,relationDescriptorrelationDescriptor,relationIdrelationId,attrDescattrDesc,
bufferPagebufferPage)
LispValue theTuple,theTargetList,relationDescriptor,relationId,attrDesc,bufferPage ;
{
	/* XXX - prog form, maybe incorrect */
	LispValue theTupleLocks = LispNil;
	LispValue res = LispNil;
	LispValue fieldsAlreadyCalculated = LispNil;
	LispValue do_res1 = LispNil;
	LispValue do_res2 = LispNil;
	theTupleLocks = FindTheLocksOfTheTuple (theTuple,bufferPage,relationDescriptor);
	/*    */

	/*    First check for Never retrieve rules */

	/*    */
	;
	do_res1 = foreach (theField, theTargetList) {
		res = checkForNeverRules (/* XXX- QUOTE RETRIEVE,*/,theTuple,theField,theTupleLocks);
		;
		if ( nequal (car (res),/* XXX- QUOTE OK,*/) ) {
			return (res);
		} else {
		};

		;
		;
		if ( not (null (do_res1)) ) {
			return (do_res1);
		} else {
		};

		fieldsAlreadyCalculated = nil;
		;
		do_res2 = foreach (theField, theTargetList) {
			res = calculateOneField (theTuple,theField,theTupleLocks,fieldsAlreadyCalculated,nil,relationDescriptor,
			    relationId,attrDesc,bufferPage);
			;
			if ( nequal (car (res),/* XXX- QUOTE OK,*/) ) {
				return (res);
			} else {
			};

			fieldsAlreadyCalculated = caddr (res);
			;
			theTupleLocks = cadr (res);
			;
			theTuple = cadddr (res);
			;
			bufferPage = caddddr (res);
			;
			;
			;
			if ( not (null (do_res2)) ) {
				return (do_res2);
			} else {
			};

			theTuple = PutBackLocks (theTuple,bufferPage,theTupleLocks);
			;
			bufferPage = ReturnInvalidBuffer ();
			;
			RuleLockIntermediateFree (theTupleLocks);
			return (list (/* XXX- QUOTE OK,*/,theTuple,bufferPage));
			;
		}

		/*    
 *     calculateOneField.
 *    
 *     Calculate the correct value for one given field. It returns a list with
 *     3 (5?) elements:
 *       1) Status (one of OK, LOOP)
 *       2) The new locks for the tuple
 *       3) The fields of the tuple that are calculated so far.
 *       4) The new tuple
 *       5) the buffer page for the new tuple
 *    
 */
		LispValue
		    calculateOneField (theTupletheTuple,theFieldtheField,theTupleLockstheTupleLocks,fieldsAlreadyCalculatedfieldsAlreadyCalculated,
		    fieldsToBeCalculatedfieldsToBeCalculated,relDescrelDesc,relIdrelId,attrDescattrDesc,bufferPagebufferPage)
		    LispValue theTuple,theField,theTupleLocks,fieldsAlreadyCalculated,fieldsToBeCalculated,relDesc,relId,attrDesc,
		    bufferPage ;
		{
			/* XXX - prog form, maybe incorrect */
			LispValue do_res1 = LispNil;
			LispValue result = LispNil;
			LispValue value_tuple = LispNil;
			LispValue value_attrdesc = LispNil;
			LispValue plan_no = LispNil;

			/*    */

			/*    Is this field Already calulated ? */

			/*    */
			if ( member (theField,fieldsAlreadyCalculated) ) {
				return (list (/* XXX- QUOTE OK,*/,theTupleLocks,fieldsAlreadyCalculated,theTuple,bufferPage));
			} else {
			};

			/*    */

			/*    If this field is in the list of fields for which their calculation */

			/*    is pending, then we have entered a loop. */

			/*    */

			if ( member (theField,fieldsToBeCalculated) ) {
				return (list (/* XXX- QUOTE LOOP,*/,theTupleLocks,cons (theField,fieldsAlreadyCalculated),
				    theTuple,bufferPage));
			} else {
			};

			/*    */

			/*    OK, go  on... */

			/*    */

			/*    */

			/*    plan-no is the number of plans we have found so far. */

			/*    */

			plan_no = 1;
			/*    /*!*/ */
			    ;
			do_res1 = lispDo (planString = GetPlanForField (theField,theTupleLocks,plan_no);GetPlanForField (theField,
			    theTupleLocks,plan_no)) { 
				lispDoIf ( eq (0,planString)) {
				}
				result = runRule (planString,theTuple,theField,theTupleLocks,fieldsAlreadyCalculated,fieldsToBeCalculated,
				    relDesc,relId,attrDesc,bufferPage);
				;
				plan_no = 1 + plan_no;
				;
				theTupleLocks = nth (1,result);
				;
				fieldsAlreadyCalculated = nth (2,result);
				;
				theTuple = nth (3,result);
				;
				bufferPage = nth (4,result);
				;
				value_tuple = prestore (nth (5,result));
				;
				value_attrdesc = prestore (nth (6,result));
				;
				switch (nth (0,result)) {

				case: /* XXX- QUOTE OK,*/
					{ 
						if ( DebugLevel >= 1 ) {
							print ("Before Modify-One-Field, old tuple =");
							terpri ();
							debugtup (theTuple,attrDesc);
							terpri ();
							print ("-- value-tuple");
							terpri ();
							;
						} else {
							nil;
						}

						/*   (debugtup value-tuple value-attrdesc) */

						/*                   (setq theValue (amgetattr (cadddddr result)
 *                                             (ReturnInvalidBuffer)
 *                                             1
 *                                             (ExecGetTypeInfo relDesc)
 *                                             0))
 *   		(print "Value - :") (print theValue) (terpri)
 */
						;
						theTuple = modifyOneFieldOfTheTuple (theTuple,bufferPage,relDesc,theField,
						    value_tuple,value_attrdesc);
						/*                   (setq theTuple (modify2OneFieldOfTheTuple        theTuple
 *                                                           bufferPage
 *                                                           relDesc
 *   							theValue))
 */
						;
						bufferPage = ReturnInvalidBuffer ();
						;
						if ( DebugLevel >= 1 ) {
							print ("After Modify-One-Field, new tuple =");
							terpri ();
							debugtup (theTuple,attrDesc);
							terpri ();
							;
						} else {
							nil;
						};

						return (list (/* XXX- QUOTE OK,*/,theTupleLocks,cons (theField,fieldsAlreadyCalculated),
						    theTuple,bufferPage));
					}
					break;

				case: /* XXX- QUOTE LOOP,*/
					{ 
						return (list (/* XXX- QUOTE LOOP,*/,theTupleLocks,cons (theField,fieldsAlreadyCalculated),
						    theTuple,bufferPage));
					}
					break;

				case: /* XXX- QUOTE NOVALUEFOUND,*/
					{ 
						LispNil;
					}
					break;

				default: /* do nothing */
				};

				/*XXX Do List */;
				;
				if ( not (null (do_res1)) ) {
					return (do_res1);
				} else {
					nil;
				};

				/*    */

				/*    Use the value stored in the field. */

				/*    */

				return (list (/* XXX- QUOTE OK,*/,theTupleLocks,cons (theField,fieldsAlreadyCalculated),theTuple,
				    bufferPage));
				;
			}

			/*    
 *     runRule
 *    
 *     It returns a list of:
 *       1) status
 *       2) the tuple locks
 *       3) fieldsAlreadyCalculated
 *       4) the (new) tuple
 *       5) the (new) buffer page
 *       6) the value-tuple
 *       7) the value-tupleDesc
 *    
 */
			LispValue
			    runRule (theCPlanStringtheCPlanString,theTupletheTuple,theFieldtheField,theTupleLockstheTupleLocks,
			    fieldsAlreadyCalculatedfieldsAlreadyCalculated,fieldsToBeCalculatedfieldsToBeCalculated,relDescrelDesc,
			    relIdrelId,attrDescattrDesc,bufferPagebufferPage)
			    LispValue theCPlanString,theTuple,theField,theTupleLocks,fieldsAlreadyCalculated,fieldsToBeCalculated,
			    relDesc,relId,attrDesc,bufferPage ;
			{
				/* XXX - prog form, maybe incorrect */
				LispValue theLispPlanString = LispNil;
				LispValue theOldPlanParseTree = LispNil;
				LispValue theParseTree = LispNil;
				LispValue theOldPlan = LispNil;
				LispValue fieldsNeededInPlan = LispNil;
				LispValue res = LispNil;
				LispValue thePlan = LispNil;
				LispValue result = LispNil;
				LispValue do_res1 = LispNil;
				theLispPlanString = string_c_to_l (theCPlanString);
				;
				c_free (theCPlanString);
				theOldPlanParseTree = string_to_plan (theLispPlanString);
				;
				theOldPlan = cadr (theOldPlanParseTree);
				;
				theParseTree = car (theOldPlanParseTree);
				/*    */

				/*    DEBUG */

				/*    */
				;
				if ( DebugLevel >= 2 ) {
					print (/* XXX- QUOTE */,,,,,,,,,,,,,,,,,,,Plan,,Parse);
					terpri ();
					print (theOldPlanParseTree);
					terpri ();
					print (/* XXX- QUOTE */,,,,,,,,,,,,,,,,,,,ORIGINAL_Plan);
					terpri ()
					    /*    (print theOldPlan) (terpri) */
					;
					print_plan (theOldPlan,0);
					print (/* XXX- QUOTE */,,,,,,,,,,,,,,,,,,,ParseTree);
					terpri ();
					print (theParseTree);
					terpri ();
					;
				} else {
					nil;
				};

				fieldsNeededInPlan = find_parameters (theOldPlan);
				;
				do_res1 = foreach (field_name, fieldsNeededInPlan) {
					field = get_attnum (relId,field_name);
					;
					res = calculateOneField (theTuple,field,theTupleLocks,fieldsAlreadyCalculated,cons
					    (theField,fieldsToBeCalculated),relDesc,relId,attrDesc,bufferPage);
					;
					theTupleLocks = cadr (res);
					;
					fieldsAlreadyCalculated = caddr (res);
					;
					theTuple = cadddr (res);
					;
					bufferPage = caddddr (res);
					;
					if ( nequal (car (res),/* XXX- QUOTE OK,*/) ) {
						return (list (car (res)
						    /*  status */
						,theTupleLocks,fieldsAlreadyCalculated,theTuple,bufferPage,nil,nil));
					} else {
						nil;
					};

					;
					;
					if ( not (null (do_res1)) ) {
						return (do_res1);
					} else {
						nil;
					};

					thePlan = substituteTupleIntoPlan (theOldPlan,theTuple,relDesc,relId,bufferPage);
					;
					if ( DebugLevel >= 2 ) {
						print (/* XXX- QUOTE */,,,,,,,,,,,,,,,,,,Plan_AFTER_SUBST);
						terpri ();
						print_plan (thePlan,0);
						;
					} else {
						nil;
					};

					result = runPlan (thePlan,theParseTree);
					;
					return (list (car (result)
					    /*  status */
					,theTupleLocks,fieldsAlreadyCalculated,theTuple,bufferPage,cadr (result)
					    /*  value-tuple */
					,caddr (result)));
					;
				}

				/*  value-tupleDesc */

				/*    
 *     checkForNeverRules
 *    
 */
				LispValue
				    checkForNeverRules (neverRuleTypeneverRuleType,theTupletheTuple,theFieldtheField,theTupleLockstheTupleLocks)
				    LispValue neverRuleType,theTuple,theField,theTupleLocks ;
				{
					/* XXX- QUOTE OK,*/;
				}

				/*    
 *     runPlan
 *    
 *     returns a list of
 *       1) status
 *       2) value-tuple
 *       3) value tupleDesc
 *    
 */
				LispValue
				    runPlan (thePlanthePlan,theParseTreetheParseTree)
				    LispValue thePlan,theParseTree ;
				{
					/* XXX - prog form, maybe incorrect */
					LispValue queryDesc = LispNil;
					LispValue state = LispNil;
					LispValue res1 = LispNil;
					LispValue res2 = LispNil;
					LispValue res3 = LispNil;
					LispValue command = LispNil;
					if ( DebugLevel >= 1 ) {
						print ("---entering runPlan");
						terpri ();
						;
					} else {
						nil;
					};

					if ( eq (cadar (theParseTree),/* XXX- QUOTE replace,*/) ) {
						if ( DebugLevel >= 1 ) {
							print ("----changing replace to retrieve");
							terpri ();
							;
						} else {
						};

						theParseTree = cons (append (list (caar (theParseTree),/* XXX- QUOTE retrieve,*/),
						    cddar (theParseTree)),cdr (theParseTree));
						;
						if ( DebugLevel >= 2 ) {
							print ("-------------- NEW ParseTree");
							terpri ();
							print (theParseTree);
							terpri ();
							;
						} else {
							nil;
						};

						;
					} else {
						nil;
					};

					state = make_exec_state ();
					;
					if ( DebugLevel >= 1 ) {
						print ("---make-exec-state made...");
						terpri ();
						;
					} else {
						nil;
					};

					command = cadar (theParseTree);
					;
					if ( eq (command,/* XXX- QUOTE retone,*/) ) {
						command = /* XXX- QUOTE retrieve,*/;
						;
					} else {
						nil;
					};

					queryDesc = list (command,theParseTree,thePlan,state,/* XXX- QUOTE start,*/);
					;
					res1 = ExecMain (queryDesc);
					;
					queryDesc = list (command,theParseTree,thePlan,state,/* XXX- QUOTE retone,*/);
					;
					res2 = ExecMain (queryDesc);
					/*    */

					/*    save (tuple schema-info) in LISP memory */

					/*    */
					;
					if ( consp (res2) ) {
						res2 = list (ppreserve (car (res2)),ppreserve (cadr (res2)));
						;
					} else {
						nil;
					};

					/*    */

					queryDesc = list (command,theParseTree,thePlan,state,/* XXX- QUOTE end,*/);
					;
					res3 = ExecMain (queryDesc);
					/*    */

					/*    put (tuple schema-info) to C memory of the current context */

					/*    */

					/*   	(if (dtpr res2) */

					/*   	    (setq res2 (list (ppreserve-to-palloc (car res2)) */

					/*   			     (ppreserve-to-palloc (cadr res2))))) */

					/*    */
					;
					if ( null (res2) ) {
						return (list (/* XXX- QUOTE NOVALUEFOUND,*/,nil,nil));
					} else {
						nil;
					};

					if ( eq (res2,1 /* XXX - true */) ) {
						return (list (/* XXX- QUOTE NOVALUEFOUND,*/,nil,nil));
					} else {
						nil;
					};

					return (list (/* XXX- QUOTE OK,*/,car (res2),cadr (res2)));
					;
				}
