8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -54,9 +54,8 @@ static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
54
54
bool * isNull , ExprDoneCond * isDone );
55
55
static Datum ExecEvalFunc (Expr * funcClause , ExprContext * econtext ,
56
56
bool * 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 );
60
59
static Datum ExecEvalNot (Expr * notclause , ExprContext * econtext , bool * isNull );
61
60
static Datum ExecEvalAnd (Expr * andExpr , ExprContext * econtext , bool * isNull );
62
61
static Datum ExecEvalOr (Expr * orExpr , ExprContext * econtext , bool * isNull );
@@ -600,7 +599,7 @@ GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
600
599
* Evaluate arguments for a function.
601
600
*/
602
601
static ExprDoneCond
603
- ExecEvalFuncArgs (FunctionCachePtr fcache ,
602
+ ExecEvalFuncArgs (FunctionCallInfo fcinfo ,
604
603
List * argList ,
605
604
ExprContext * econtext )
606
605
{
@@ -615,14 +614,13 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
615
614
{
616
615
ExprDoneCond thisArgIsDone ;
617
616
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 );
622
621
623
622
if (thisArgIsDone != ExprSingleResult )
624
623
{
625
-
626
624
/*
627
625
* We allow only one argument to have a set value; we'd need
628
626
* much more complexity to keep track of multiple set
@@ -631,12 +629,13 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
631
629
*/
632
630
if (argIsDone != ExprSingleResult )
633
631
elog (ERROR , "Functions and operators can take only one set argument" );
634
- fcache -> hasSetArg = true;
635
632
argIsDone = thisArgIsDone ;
636
633
}
637
634
i ++ ;
638
635
}
639
636
637
+ fcinfo -> nargs = i ;
638
+
640
639
return argIsDone ;
641
640
}
642
641
@@ -656,19 +655,25 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
656
655
ExprDoneCond * isDone )
657
656
{
658
657
Datum result ;
658
+ FunctionCallInfoData fcinfo ;
659
+ ReturnSetInfo rsinfo ; /* for functions returning sets */
659
660
ExprDoneCond argDone ;
661
+ bool hasSetArg ;
660
662
int i ;
661
663
662
664
/*
663
665
* arguments is a list of expressions to evaluate before passing to
664
666
* the function manager. We skip the evaluation if it was already
665
667
* done in the previous call (ie, we are continuing the evaluation of
666
668
* a set-valued function). Otherwise, collect the current argument
667
- * values into fcache-> fcinfo.
669
+ * values into fcinfo.
668
670
*/
669
- if (fcache -> fcinfo . nargs > 0 && !fcache -> argsValid )
671
+ if (!fcache -> setArgsValid )
670
672
{
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 );
672
677
if (argDone == ExprEndResult )
673
678
{
674
679
/* input is an empty set, so return an empty set. */
@@ -679,15 +684,33 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
679
684
elog (ERROR , "Set-valued function called in context that cannot accept a set" );
680
685
return (Datum ) 0 ;
681
686
}
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 ;
682
706
}
683
707
684
708
/*
685
709
* now return the value gotten by calling the function manager,
686
710
* passing the function the evaluated parameter values.
687
711
*/
688
- if (fcache -> func .fn_retset || fcache -> hasSetArg )
712
+ if (fcache -> func .fn_retset || hasSetArg )
689
713
{
690
-
691
714
/*
692
715
* We need to return a set result. Complain if caller not ready
693
716
* to accept one.
@@ -705,7 +728,6 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
705
728
*/
706
729
for (;;)
707
730
{
708
-
709
731
/*
710
732
* If function is strict, and there are any NULL arguments,
711
733
* skip calling the function (at least for this set of args).
@@ -714,9 +736,9 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
714
736
715
737
if (fcache -> func .fn_strict )
716
738
{
717
- for (i = 0 ; i < fcache -> fcinfo .nargs ; i ++ )
739
+ for (i = 0 ; i < fcinfo .nargs ; i ++ )
718
740
{
719
- if (fcache -> fcinfo .argnull [i ])
741
+ if (fcinfo .argnull [i ])
720
742
{
721
743
callit = false;
722
744
break ;
@@ -726,11 +748,11 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
726
748
727
749
if (callit )
728
750
{
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 ;
734
756
}
735
757
else
736
758
{
@@ -741,14 +763,17 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
741
763
742
764
if (* isDone != ExprEndResult )
743
765
{
744
-
745
766
/*
746
767
* Got a result from current argument. If function itself
747
- * returns set, flag that we want to reuse current
748
- * argument values on next call.
768
+ * returns set, save the current argument values to re-use
769
+ * on the next call.
749
770
*/
750
771
if (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
+ }
752
777
753
778
/*
754
779
* Make sure we say we are returning a set, even if the
@@ -759,22 +784,15 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
759
784
}
760
785
761
786
/* Else, done with this argument */
762
- fcache -> argsValid = false;
763
-
764
- if (!fcache -> hasSetArg )
787
+ if (!hasSetArg )
765
788
break ; /* input not a set, so done */
766
789
767
790
/* Re-eval args to get the next element of the input set */
768
- argDone = ExecEvalFuncArgs (fcache , arguments , econtext );
791
+ argDone = ExecEvalFuncArgs (& fcinfo , arguments , econtext );
769
792
770
793
if (argDone != ExprMultipleResult )
771
794
{
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. */
778
796
* isNull = true;
779
797
* isDone = ExprEndResult ;
780
798
result = (Datum ) 0 ;
@@ -789,7 +807,6 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
789
807
}
790
808
else
791
809
{
792
-
793
810
/*
794
811
* Non-set case: much easier.
795
812
*
@@ -798,18 +815,18 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
798
815
*/
799
816
if (fcache -> func .fn_strict )
800
817
{
801
- for (i = 0 ; i < fcache -> fcinfo .nargs ; i ++ )
818
+ for (i = 0 ; i < fcinfo .nargs ; i ++ )
802
819
{
803
- if (fcache -> fcinfo .argnull [i ])
820
+ if (fcinfo .argnull [i ])
804
821
{
805
822
* isNull = true;
806
823
return (Datum ) 0 ;
807
824
}
808
825
}
809
826
}
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 ;
813
830
}
814
831
815
832
return result ;
0 commit comments