88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.87 2001/06/19 22:39:11 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.88 2001/09/21 00:11:30 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -54,9 +54,8 @@ static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
5454bool * isNull ,ExprDoneCond * isDone );
5555static Datum ExecEvalFunc (Expr * funcClause ,ExprContext * econtext ,
5656bool * isNull ,ExprDoneCond * isDone );
57- static ExprDoneCond ExecEvalFuncArgs (FunctionCachePtr fcache ,
58- List * argList ,
59- ExprContext * econtext );
57+ static ExprDoneCond ExecEvalFuncArgs (FunctionCallInfo fcinfo ,
58+ List * argList ,ExprContext * econtext );
6059static Datum ExecEvalNot (Expr * notclause ,ExprContext * econtext ,bool * isNull );
6160static Datum ExecEvalAnd (Expr * andExpr ,ExprContext * econtext ,bool * isNull );
6261static Datum ExecEvalOr (Expr * orExpr ,ExprContext * econtext ,bool * isNull );
@@ -600,7 +599,7 @@ GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
600599 * Evaluate arguments for a function.
601600 */
602601static ExprDoneCond
603- ExecEvalFuncArgs (FunctionCachePtr fcache ,
602+ ExecEvalFuncArgs (FunctionCallInfo fcinfo ,
604603List * argList ,
605604ExprContext * econtext )
606605{
@@ -615,14 +614,13 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
615614{
616615ExprDoneCond thisArgIsDone ;
617616
618- fcache -> fcinfo . arg [i ]= ExecEvalExpr ((Node * )lfirst (arg ),
619- econtext ,
620- & fcache -> fcinfo . argnull [i ],
621- & thisArgIsDone );
617+ fcinfo -> arg [i ]= ExecEvalExpr ((Node * )lfirst (arg ),
618+ econtext ,
619+ & fcinfo -> argnull [i ],
620+ & thisArgIsDone );
622621
623622if (thisArgIsDone != ExprSingleResult )
624623{
625-
626624/*
627625 * We allow only one argument to have a set value; we'd need
628626 * much more complexity to keep track of multiple set
@@ -631,12 +629,13 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
631629 */
632630if (argIsDone != ExprSingleResult )
633631elog (ERROR ,"Functions and operators can take only one set argument" );
634- fcache -> hasSetArg = true;
635632argIsDone = thisArgIsDone ;
636633}
637634i ++ ;
638635}
639636
637+ fcinfo -> nargs = i ;
638+
640639return argIsDone ;
641640}
642641
@@ -656,19 +655,25 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
656655ExprDoneCond * isDone )
657656{
658657Datum result ;
658+ FunctionCallInfoData fcinfo ;
659+ ReturnSetInfo rsinfo ;/* for functions returning sets */
659660ExprDoneCond argDone ;
661+ bool hasSetArg ;
660662int i ;
661663
662664/*
663665 * arguments is a list of expressions to evaluate before passing to
664666 * the function manager. We skip the evaluation if it was already
665667 * done in the previous call (ie, we are continuing the evaluation of
666668 * a set-valued function).Otherwise, collect the current argument
667- * values intofcache-> fcinfo.
669+ * values into fcinfo.
668670 */
669- if (fcache -> fcinfo . nargs > 0 && !fcache -> argsValid )
671+ if (!fcache -> setArgsValid )
670672{
671- argDone = ExecEvalFuncArgs (fcache ,arguments ,econtext );
673+ /* Need to prep callinfo structure */
674+ MemSet (& fcinfo ,0 ,sizeof (fcinfo ));
675+ fcinfo .flinfo = & (fcache -> func );
676+ argDone = ExecEvalFuncArgs (& fcinfo ,arguments ,econtext );
672677if (argDone == ExprEndResult )
673678{
674679/* input is an empty set, so return an empty set. */
@@ -679,15 +684,33 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
679684elog (ERROR ,"Set-valued function called in context that cannot accept a set" );
680685return (Datum )0 ;
681686}
687+ hasSetArg = (argDone != ExprSingleResult );
688+ }
689+ else
690+ {
691+ /* Copy callinfo from previous evaluation */
692+ memcpy (& fcinfo ,& fcache -> setArgs ,sizeof (fcinfo ));
693+ hasSetArg = fcache -> setHasSetArg ;
694+ /* Reset flag (we may set it again below) */
695+ fcache -> setArgsValid = false;
696+ }
697+
698+ /*
699+ * If function returns set, prepare a resultinfo node for
700+ * communication
701+ */
702+ if (fcache -> func .fn_retset )
703+ {
704+ fcinfo .resultinfo = (Node * )& rsinfo ;
705+ rsinfo .type = T_ReturnSetInfo ;
682706}
683707
684708/*
685709 * now return the value gotten by calling the function manager,
686710 * passing the function the evaluated parameter values.
687711 */
688- if (fcache -> func .fn_retset || fcache -> hasSetArg )
712+ if (fcache -> func .fn_retset || hasSetArg )
689713{
690-
691714/*
692715 * We need to return a set result.Complain if caller not ready
693716 * to accept one.
@@ -705,7 +728,6 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
705728 */
706729for (;;)
707730{
708-
709731/*
710732 * If function is strict, and there are any NULL arguments,
711733 * skip calling the function (at least for this set of args).
@@ -714,9 +736,9 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
714736
715737if (fcache -> func .fn_strict )
716738{
717- for (i = 0 ;i < fcache -> fcinfo .nargs ;i ++ )
739+ for (i = 0 ;i < fcinfo .nargs ;i ++ )
718740{
719- if (fcache -> fcinfo .argnull [i ])
741+ if (fcinfo .argnull [i ])
720742{
721743callit = false;
722744break ;
@@ -726,11 +748,11 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
726748
727749if (callit )
728750{
729- fcache -> fcinfo .isnull = false;
730- fcache -> rsinfo .isDone = ExprSingleResult ;
731- result = FunctionCallInvoke (& fcache -> fcinfo );
732- * isNull = fcache -> fcinfo .isnull ;
733- * isDone = fcache -> rsinfo .isDone ;
751+ fcinfo .isnull = false;
752+ rsinfo .isDone = ExprSingleResult ;
753+ result = FunctionCallInvoke (& fcinfo );
754+ * isNull = fcinfo .isnull ;
755+ * isDone = rsinfo .isDone ;
734756}
735757else
736758{
@@ -741,14 +763,17 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
741763
742764if (* isDone != ExprEndResult )
743765{
744-
745766/*
746767 * Got a result from current argument.If function itself
747- * returns set,flag that we want toreuse current
748- *argument values on next call.
768+ * returns set,save the current argument values tore-use
769+ *on the next call.
749770 */
750771if (fcache -> func .fn_retset )
751- fcache -> argsValid = true;
772+ {
773+ memcpy (& fcache -> setArgs ,& fcinfo ,sizeof (fcinfo ));
774+ fcache -> setHasSetArg = hasSetArg ;
775+ fcache -> setArgsValid = true;
776+ }
752777
753778/*
754779 * Make sure we say we are returning a set, even if the
@@ -759,22 +784,15 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
759784}
760785
761786/* Else, done with this argument */
762- fcache -> argsValid = false;
763-
764- if (!fcache -> hasSetArg )
787+ if (!hasSetArg )
765788break ;/* input not a set, so done */
766789
767790/* Re-eval args to get the next element of the input set */
768- argDone = ExecEvalFuncArgs (fcache ,arguments ,econtext );
791+ argDone = ExecEvalFuncArgs (& fcinfo ,arguments ,econtext );
769792
770793if (argDone != ExprMultipleResult )
771794{
772-
773- /*
774- * End of arguments, so reset the hasSetArg flag and say
775- * "Done"
776- */
777- fcache -> hasSetArg = false;
795+ /* End of argument set, so we're done. */
778796* isNull = true;
779797* isDone = ExprEndResult ;
780798result = (Datum )0 ;
@@ -789,7 +807,6 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
789807}
790808else
791809{
792-
793810/*
794811 * Non-set case: much easier.
795812 *
@@ -798,18 +815,18 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
798815 */
799816if (fcache -> func .fn_strict )
800817{
801- for (i = 0 ;i < fcache -> fcinfo .nargs ;i ++ )
818+ for (i = 0 ;i < fcinfo .nargs ;i ++ )
802819{
803- if (fcache -> fcinfo .argnull [i ])
820+ if (fcinfo .argnull [i ])
804821{
805822* isNull = true;
806823return (Datum )0 ;
807824}
808825}
809826}
810- fcache -> fcinfo .isnull = false;
811- result = FunctionCallInvoke (& fcache -> fcinfo );
812- * isNull = fcache -> fcinfo .isnull ;
827+ fcinfo .isnull = false;
828+ result = FunctionCallInvoke (& fcinfo );
829+ * isNull = fcinfo .isnull ;
813830}
814831
815832return result ;