44 * Routines to preprocess the parse tree target list
55 *
66 * For INSERT and UPDATE queries, the targetlist must contain an entry for
7- * each attribute of the target relation in the correct order. For UPDATE and
8- * DELETE queries, it must also contain a junk tlist entry needed to allow the
9- * executor to identify the physical locations of the rows to be updated or
10- * deleted. For all query types, we may need to add junk tlist entries for
11- * Vars used in the RETURNING list and row ID information needed for SELECT
12- * FOR UPDATE locking and/or EvalPlanQual checking.
7+ * each attribute of the target relation in the correct order. For all query
8+ * types, we may need to add junk tlist entries for Vars used in the RETURNING
9+ * list and row ID information needed for SELECT FOR UPDATE locking and/or
10+ * EvalPlanQual checking.
1311 *
14- * The rewriter's rewriteTargetListIU routine also does preprocessing of the
15- * targetlist. The division of labor between here and there is partially
16- * historical, but it's not entirely arbitrary. In particular, consider an
17- * UPDATE across an inheritance tree. What the rewriter does need be done
18- * only once (because it depends only on the properties of the parent
19- * relation). What's done here has to be done over again for each child
20- * relation, because it depends on the column list of the child, which might
21- * have more columns and/or a different column order than the parent.
12+ * The rewriter's rewriteTargetListIU and rewriteTargetListUD routines
13+ * also do preprocessing of the targetlist. The division of labor between
14+ * here and there is partially historical, but it's not entirely arbitrary.
15+ * In particular, consider an UPDATE across an inheritance tree. What the
16+ * rewriter does need be done only once (because it depends only on the
17+ * properties of the parent relation). What's done here has to be done over
18+ * again for each child relation, because it depends on the column list of
19+ * the child, which might have more columns and/or a different column order
20+ * than the parent.
2221 *
2322 * The fact that rewriteTargetListIU sorts non-resjunk tlist entries by column
2423 * position, which expand_targetlist depends on, violates the above comment
4241#include "access/heapam.h"
4342#include "access/sysattr.h"
4443#include "catalog/pg_type.h"
45- #include "foreign/fdwapi.h"
4644#include "nodes/makefuncs.h"
47- #include "optimizer/clauses.h"
4845#include "optimizer/prep.h"
4946#include "optimizer/tlist.h"
5047#include "optimizer/var.h"
5552
5653static List * expand_targetlist (List * tlist , int command_type ,
5754 Index result_relation , List * range_table );
58- static void rewrite_targetlist (Query * parse ,
59- Index result_relation , List * range_table );
6055
6156
6257/*
@@ -66,13 +61,12 @@ static void rewrite_targetlist(Query *parse,
6661 * Returns the new targetlist.
6762 */
6863List *
69- preprocess_targetlist (PlannerInfo * root )
64+ preprocess_targetlist (PlannerInfo * root , List * tlist )
7065{
7166 Query * parse = root -> parse ;
7267 int result_relation = parse -> resultRelation ;
7368 List * range_table = parse -> rtable ;
7469 CmdType command_type = parse -> commandType ;
75- List * tlist ;
7670 ListCell * lc ;
7771
7872 /*
@@ -87,16 +81,6 @@ preprocess_targetlist(PlannerInfo *root)
8781 elog (ERROR , "subquery cannot be result relation" );
8882 }
8983
90- /*
91- * For UPDATE/DELETE, add a necessary junk column needed to allow the
92- * executor to identify the physical locations of the rows to be updated
93- * or deleted.
94- */
95- if (command_type == CMD_UPDATE || command_type == CMD_DELETE )
96- rewrite_targetlist (parse , result_relation , range_table );
97-
98- tlist = parse -> targetList ;
99-
10084 /*
10185 * for heap_form_tuple to work, the targetlist must match the exact order
10286 * of the attributes. We also need to fill in any missing attributes. -ay
@@ -407,96 +391,6 @@ expand_targetlist(List *tlist, int command_type,
407391 return new_tlist ;
408392}
409393
410- /*
411- * rewrite_targetlist - rewrite UPDATE/DELETE targetlist as needed
412- *
413- * This function adds a "junk" TLE that is needed to allow the executor to
414- * find the original row for the update or delete. When the target relation
415- * is a regular table, the junk TLE emits the ctid attribute of the original
416- * row. When the target relation is a foreign table, we let the FDW decide
417- * what to add.
418- */
419- static void
420- rewrite_targetlist (Query * parse , Index result_relation , List * range_table )
421- {
422- Var * var = NULL ;
423- const char * attrname ;
424- TargetEntry * tle ;
425- RangeTblEntry * target_rte ;
426- Relation target_relation ;
427-
428- target_rte = rt_fetch (result_relation , range_table );
429-
430- /*
431- * We assume that the relation was already locked by the rewriter, so
432- * we need no lock here.
433- */
434- target_relation = heap_open (target_rte -> relid , NoLock );
435-
436- if (target_relation -> rd_rel -> relkind == RELKIND_RELATION ||
437- target_relation -> rd_rel -> relkind == RELKIND_MATVIEW ||
438- target_relation -> rd_rel -> relkind == RELKIND_PARTITIONED_TABLE )
439- {
440- /*
441- * Emit CTID so that executor can find the row to update or delete.
442- */
443- var = makeVar (result_relation ,
444- SelfItemPointerAttributeNumber ,
445- TIDOID ,
446- -1 ,
447- InvalidOid ,
448- 0 );
449-
450- attrname = "ctid" ;
451- }
452- else if (target_relation -> rd_rel -> relkind == RELKIND_FOREIGN_TABLE )
453- {
454- /*
455- * Let the foreign table's FDW add whatever junk TLEs it wants.
456- */
457- FdwRoutine * fdwroutine ;
458-
459- fdwroutine = GetFdwRoutineForRelation (target_relation , false);
460-
461- if (fdwroutine -> AddForeignUpdateTargets != NULL )
462- fdwroutine -> AddForeignUpdateTargets (parse , target_rte ,
463- target_relation );
464-
465- /*
466- * If we have a row-level trigger corresponding to the operation, emit
467- * a whole-row Var so that executor will have the "old" row to pass to
468- * the trigger. Alas, this misses system columns.
469- */
470- if (target_relation -> trigdesc &&
471- ((parse -> commandType == CMD_UPDATE &&
472- (target_relation -> trigdesc -> trig_update_after_row ||
473- target_relation -> trigdesc -> trig_update_before_row )) ||
474- (parse -> commandType == CMD_DELETE &&
475- (target_relation -> trigdesc -> trig_delete_after_row ||
476- target_relation -> trigdesc -> trig_delete_before_row ))))
477- {
478- var = makeWholeRowVar (target_rte ,
479- result_relation ,
480- 0 ,
481- false);
482-
483- attrname = "wholerow" ;
484- }
485- }
486-
487- if (var != NULL )
488- {
489- tle = makeTargetEntry ((Expr * ) var ,
490- list_length (parse -> targetList ) + 1 ,
491- pstrdup (attrname ),
492- true);
493-
494- parse -> targetList = lappend (parse -> targetList , tle );
495- }
496-
497- heap_close (target_relation , NoLock );
498- }
499-
500394
501395/*
502396 * Locate PlanRowMark for given RT index, or return NULL if none
0 commit comments