Skip to content

Commit 5bf12d0

Browse files
committed
Revert fix-rewrite-tlist-v4.patch.
It breaks in_memory regression test: now junk column is always there. Probably this is fine, but I don't understand the internals very well and won't risk here. Moreover, currently we don't need this patch anymore.
1 parent beef2ce commit 5bf12d0

File tree

9 files changed

+144
-227
lines changed

9 files changed

+144
-227
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7022,65 +7022,6 @@ update bar set f2 = f2 + 100 returning *;
70227022
7 | 277
70237023
(6 rows)
70247024

7025-
-- Test that UPDATE/DELETE with inherited target works with row-level triggers
7026-
CREATE TRIGGER trig_row_before
7027-
BEFORE UPDATE OR DELETE ON bar2
7028-
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7029-
CREATE TRIGGER trig_row_after
7030-
AFTER UPDATE OR DELETE ON bar2
7031-
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7032-
explain (verbose, costs off)
7033-
update bar set f2 = f2 + 100;
7034-
QUERY PLAN
7035-
--------------------------------------------------------------------------------------
7036-
Update on public.bar
7037-
Update on public.bar
7038-
Foreign Update on public.bar2
7039-
Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2, f3
7040-
-> Seq Scan on public.bar
7041-
Output: bar.f1, (bar.f2 + 100), bar.ctid
7042-
-> Foreign Scan on public.bar2
7043-
Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, bar2.*
7044-
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
7045-
(9 rows)
7046-
7047-
update bar set f2 = f2 + 100;
7048-
NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
7049-
NOTICE: OLD: (3,333,33),NEW: (3,433,33)
7050-
NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
7051-
NOTICE: OLD: (4,344,44),NEW: (4,444,44)
7052-
NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
7053-
NOTICE: OLD: (7,277,77),NEW: (7,377,77)
7054-
NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
7055-
NOTICE: OLD: (3,333,33),NEW: (3,433,33)
7056-
NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
7057-
NOTICE: OLD: (4,344,44),NEW: (4,444,44)
7058-
NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
7059-
NOTICE: OLD: (7,277,77),NEW: (7,377,77)
7060-
explain (verbose, costs off)
7061-
delete from bar where f2 < 400;
7062-
QUERY PLAN
7063-
---------------------------------------------------------------------------------------------
7064-
Delete on public.bar
7065-
Delete on public.bar
7066-
Foreign Delete on public.bar2
7067-
Remote SQL: DELETE FROM public.loct2 WHERE ctid = $1 RETURNING f1, f2, f3
7068-
-> Seq Scan on public.bar
7069-
Output: bar.ctid
7070-
Filter: (bar.f2 < 400)
7071-
-> Foreign Scan on public.bar2
7072-
Output: bar2.ctid, bar2.*
7073-
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 WHERE ((f2 < 400)) FOR UPDATE
7074-
(10 rows)
7075-
7076-
delete from bar where f2 < 400;
7077-
NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2
7078-
NOTICE: OLD: (7,377,77)
7079-
NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2
7080-
NOTICE: OLD: (7,377,77)
7081-
-- cleanup
7082-
DROP TRIGGER trig_row_before ON bar2;
7083-
DROP TRIGGER trig_row_after ON bar2;
70847025
drop table foo cascade;
70857026
NOTICE: drop cascades to foreign table foo2
70867027
drop table bar cascade;

contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,26 +1656,6 @@ explain (verbose, costs off)
16561656
update bar set f2 = f2 + 100 returning *;
16571657
update bar set f2 = f2 + 100 returning *;
16581658

1659-
-- Test that UPDATE/DELETE with inherited target works with row-level triggers
1660-
CREATE TRIGGER trig_row_before
1661-
BEFORE UPDATE OR DELETE ON bar2
1662-
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
1663-
1664-
CREATE TRIGGER trig_row_after
1665-
AFTER UPDATE OR DELETE ON bar2
1666-
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
1667-
1668-
explain (verbose, costs off)
1669-
update bar set f2 = f2 + 100;
1670-
update bar set f2 = f2 + 100;
1671-
1672-
explain (verbose, costs off)
1673-
delete from bar where f2 < 400;
1674-
delete from bar where f2 < 400;
1675-
1676-
-- cleanup
1677-
DROP TRIGGER trig_row_before ON bar2;
1678-
DROP TRIGGER trig_row_after ON bar2;
16791659
drop table foo cascade;
16801660
drop table bar cascade;
16811661
drop table loct1;

doc/src/sgml/fdwhandler.sgml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,11 @@ AddForeignUpdateTargets (Query *parsetree,
428428
Avoid using names matching <literal>ctid<replaceable>N</></literal>,
429429
<literal>wholerow</literal>, or
430430
<literal>wholerow<replaceable>N</></literal>, as the core system can
431-
generate junk columns of these names. Also, as it assumes that those
432-
expressions have already been simplified enough to execute,
433-
apply <function>eval_const_expressions</> if necessary.
431+
generate junk columns of these names.
434432
</para>
435433

436434
<para>
437-
Although this function is called in the planner, the
435+
This function is called in the rewriter, not the planner, so the
438436
information available is a bit different from that available to the
439437
planning routines.
440438
<literal>parsetree</> is the parse tree for the <command>UPDATE</> or

doc/src/sgml/rules.sgml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,12 @@
167167

168168
<para>
169169
<command>DELETE</command> commands don't need a normal target list
170-
because they don't produce any result. Instead, the planner
170+
because they don't produce any result. Instead, the rule system
171171
adds a special <acronym>CTID</> entry to the empty target list,
172172
to allow the executor to find the row to be deleted.
173173
(<acronym>CTID</> is added when the result relation is an ordinary
174-
table. If it is a view, a whole-row variable is added instead, by
175-
the rule system, as described in <xref linkend="rules-views-update">.)
174+
table. If it is a view, a whole-row variable is added instead,
175+
as described in <xref linkend="rules-views-update">.)
176176
</para>
177177

178178
<para>
@@ -194,7 +194,7 @@
194194
column = expression</literal> part of the command. The planner will
195195
handle missing columns by inserting expressions that copy the values
196196
from the old row into the new one. Just as for <command>DELETE</>,
197-
a <acronym>CTID</> or whole-row variable is added so that
197+
the rule system adds a <acronym>CTID</> or whole-row variable so that
198198
the executor can identify the old row to be updated.
199199
</para>
200200

src/backend/executor/nodeModifyTable.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,6 @@ ExecModifyTable(PlanState *pstate)
16871687
EvalPlanQualSetSlot(&node->mt_epqstate, planSlot);
16881688
slot = planSlot;
16891689

1690-
tupleid = NULL;
16911690
oldtuple = NULL;
16921691
if (junkfilter != NULL)
16931692
{

src/backend/optimizer/plan/planner.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,7 +1486,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
14861486
double tuple_fraction)
14871487
{
14881488
Query *parse = root->parse;
1489-
List *tlist;
1489+
List *tlist = parse->targetList;
14901490
int64 offset_est = 0;
14911491
int64 count_est = 0;
14921492
double limit_tuples = -1.0;
@@ -1616,7 +1616,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
16161616
}
16171617

16181618
/* Preprocess targetlist */
1619-
tlist = preprocess_targetlist(root);
1619+
tlist = preprocess_targetlist(root, tlist);
16201620

16211621
if (parse->onConflict)
16221622
parse->onConflict->onConflictSet =

src/backend/optimizer/prep/preptlist.c

Lines changed: 14 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@
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
@@ -42,9 +41,7 @@
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"
@@ -55,8 +52,6 @@
5552

5653
static 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
*/
6863
List *
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

Comments
 (0)