88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.243 2009/03/27 18:30:21 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.244 2009/04/02 22:39:29 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -4966,6 +4966,7 @@ ExecCleanTargetListLength(List *targetlist)
49664966 * prepared to deal with sets of result tuples. Otherwise, a return
49674967 * of *isDone = ExprMultipleResult signifies a set element, and a return
49684968 * of *isDone = ExprEndResult signifies end of the set of tuple.
4969+ * We assume that *isDone has been initialized to ExprSingleResult by caller.
49694970 */
49704971static bool
49714972ExecTargetList (List * targetlist ,
@@ -4987,9 +4988,6 @@ ExecTargetList(List *targetlist,
49874988/*
49884989 * evaluate all the expressions in the target list
49894990 */
4990- if (isDone )
4991- * isDone = ExprSingleResult ;/* until proven otherwise */
4992-
49934991haveDoneSets = false;/* any exhausted set exprs in tlist? */
49944992
49954993foreach (tl ,targetlist )
@@ -5104,50 +5102,6 @@ ExecTargetList(List *targetlist,
51045102return true;
51055103}
51065104
5107- /*
5108- * ExecVariableList
5109- *Evaluates a simple-Variable-list projection.
5110- *
5111- * Results are stored into the passed values and isnull arrays.
5112- */
5113- static void
5114- ExecVariableList (ProjectionInfo * projInfo ,
5115- Datum * values ,
5116- bool * isnull )
5117- {
5118- ExprContext * econtext = projInfo -> pi_exprContext ;
5119- int * varSlotOffsets = projInfo -> pi_varSlotOffsets ;
5120- int * varNumbers = projInfo -> pi_varNumbers ;
5121- int i ;
5122-
5123- /*
5124- * Force extraction of all input values that we need.
5125- */
5126- if (projInfo -> pi_lastInnerVar > 0 )
5127- slot_getsomeattrs (econtext -> ecxt_innertuple ,
5128- projInfo -> pi_lastInnerVar );
5129- if (projInfo -> pi_lastOuterVar > 0 )
5130- slot_getsomeattrs (econtext -> ecxt_outertuple ,
5131- projInfo -> pi_lastOuterVar );
5132- if (projInfo -> pi_lastScanVar > 0 )
5133- slot_getsomeattrs (econtext -> ecxt_scantuple ,
5134- projInfo -> pi_lastScanVar );
5135-
5136- /*
5137- * Assign to result by direct extraction of fields from source slots ... a
5138- * mite ugly, but fast ...
5139- */
5140- for (i = list_length (projInfo -> pi_targetlist )- 1 ;i >=0 ;i -- )
5141- {
5142- char * slotptr = ((char * )econtext )+ varSlotOffsets [i ];
5143- TupleTableSlot * varSlot = * ((TupleTableSlot * * )slotptr );
5144- int varNumber = varNumbers [i ]- 1 ;
5145-
5146- values [i ]= varSlot -> tts_values [varNumber ];
5147- isnull [i ]= varSlot -> tts_isnull [varNumber ];
5148- }
5149- }
5150-
51515105/*
51525106 * ExecProject
51535107 *
@@ -5165,6 +5119,8 @@ TupleTableSlot *
51655119ExecProject (ProjectionInfo * projInfo ,ExprDoneCond * isDone )
51665120{
51675121TupleTableSlot * slot ;
5122+ ExprContext * econtext ;
5123+ int numSimpleVars ;
51685124
51695125/*
51705126 * sanity checks
@@ -5175,6 +5131,11 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
51755131 * get the projection info we want
51765132 */
51775133slot = projInfo -> pi_slot ;
5134+ econtext = projInfo -> pi_exprContext ;
5135+
5136+ /* Assume single result row until proven otherwise */
5137+ if (isDone )
5138+ * isDone = ExprSingleResult ;
51785139
51795140/*
51805141 * Clear any former contents of the result slot. This makes it safe for
@@ -5184,29 +5145,84 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
51845145ExecClearTuple (slot );
51855146
51865147/*
5187- * form a new result tuple (if possible); if successful, mark the result
5188- * slot as containing a valid virtual tuple
5148+ * Force extraction of all input values that we'll need. The
5149+ * Var-extraction loops below depend on this, and we are also prefetching
5150+ * all attributes that will be referenced in the generic expressions.
5151+ */
5152+ if (projInfo -> pi_lastInnerVar > 0 )
5153+ slot_getsomeattrs (econtext -> ecxt_innertuple ,
5154+ projInfo -> pi_lastInnerVar );
5155+ if (projInfo -> pi_lastOuterVar > 0 )
5156+ slot_getsomeattrs (econtext -> ecxt_outertuple ,
5157+ projInfo -> pi_lastOuterVar );
5158+ if (projInfo -> pi_lastScanVar > 0 )
5159+ slot_getsomeattrs (econtext -> ecxt_scantuple ,
5160+ projInfo -> pi_lastScanVar );
5161+
5162+ /*
5163+ * Assign simple Vars to result by direct extraction of fields from source
5164+ * slots ... a mite ugly, but fast ...
51895165 */
5190- if (projInfo -> pi_isVarList )
5166+ numSimpleVars = projInfo -> pi_numSimpleVars ;
5167+ if (numSimpleVars > 0 )
51915168{
5192- /* simple Var list: this always succeeds with one result row */
5193- if (isDone )
5194- * isDone = ExprSingleResult ;
5195- ExecVariableList (projInfo ,
5196- slot -> tts_values ,
5197- slot -> tts_isnull );
5198- ExecStoreVirtualTuple (slot );
5169+ Datum * values = slot -> tts_values ;
5170+ bool * isnull = slot -> tts_isnull ;
5171+ int * varSlotOffsets = projInfo -> pi_varSlotOffsets ;
5172+ int * varNumbers = projInfo -> pi_varNumbers ;
5173+ int i ;
5174+
5175+ if (projInfo -> pi_directMap )
5176+ {
5177+ /* especially simple case where vars go to output in order */
5178+ for (i = 0 ;i < numSimpleVars ;i ++ )
5179+ {
5180+ char * slotptr = ((char * )econtext )+ varSlotOffsets [i ];
5181+ TupleTableSlot * varSlot = * ((TupleTableSlot * * )slotptr );
5182+ int varNumber = varNumbers [i ]- 1 ;
5183+
5184+ values [i ]= varSlot -> tts_values [varNumber ];
5185+ isnull [i ]= varSlot -> tts_isnull [varNumber ];
5186+ }
5187+ }
5188+ else
5189+ {
5190+ /* we have to pay attention to varOutputCols[] */
5191+ int * varOutputCols = projInfo -> pi_varOutputCols ;
5192+
5193+ for (i = 0 ;i < numSimpleVars ;i ++ )
5194+ {
5195+ char * slotptr = ((char * )econtext )+ varSlotOffsets [i ];
5196+ TupleTableSlot * varSlot = * ((TupleTableSlot * * )slotptr );
5197+ int varNumber = varNumbers [i ]- 1 ;
5198+ int varOutputCol = varOutputCols [i ]- 1 ;
5199+
5200+ values [varOutputCol ]= varSlot -> tts_values [varNumber ];
5201+ isnull [varOutputCol ]= varSlot -> tts_isnull [varNumber ];
5202+ }
5203+ }
51995204}
5200- else
5205+
5206+ /*
5207+ * If there are any generic expressions, evaluate them. It's possible
5208+ * that there are set-returning functions in such expressions; if so
5209+ * and we have reached the end of the set, we return the result slot,
5210+ * which we already marked empty.
5211+ */
5212+ if (projInfo -> pi_targetlist )
52015213{
5202- if (ExecTargetList (projInfo -> pi_targetlist ,
5203- projInfo -> pi_exprContext ,
5204- slot -> tts_values ,
5205- slot -> tts_isnull ,
5206- projInfo -> pi_itemIsDone ,
5207- isDone ))
5208- ExecStoreVirtualTuple ( slot );
5214+ if (! ExecTargetList (projInfo -> pi_targetlist ,
5215+ econtext ,
5216+ slot -> tts_values ,
5217+ slot -> tts_isnull ,
5218+ projInfo -> pi_itemIsDone ,
5219+ isDone ))
5220+ return slot ; /* no more result rows, return empty slot */
52095221}
52105222
5211- return slot ;
5223+ /*
5224+ * Successfully formed a result row. Mark the result slot as containing a
5225+ * valid virtual tuple.
5226+ */
5227+ return ExecStoreVirtualTuple (slot );
52125228}