Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit787db4b

Browse files
committed
Make new GENERATED-expressions code more bulletproof.
In commit8bf6ec3 I assumed that no code path could reachExecGetExtraUpdatedCols without having gone throughExecInitStoredGenerated. That turns out not to be the case inlogical replication: if there's an ON UPDATE trigger on the targettable, trigger.c will call this code before anybody has set up itsgenerated columns. Having seen that, I don't have a lot of faith inthere not being other such paths. ExecGetExtraUpdatedCols can callExecInitStoredGenerated for itself, as long as we are willing toassume that it is only called in CMD_UPDATE operations, which onthe whole seems like a safer leap of faith.Per report from Vitaly Davydov.Discussion:https://postgr.es/m/d259d69652b8c2ff50e14cda3c236c7f@postgrespro.ru
1 parentc159b03 commit787db4b

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

‎src/backend/executor/execUtils.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include"access/transam.h"
5353
#include"executor/executor.h"
5454
#include"executor/execPartition.h"
55+
#include"executor/nodeModifyTable.h"
5556
#include"jit/jit.h"
5657
#include"mb/pg_wchar.h"
5758
#include"miscadmin.h"
@@ -1285,8 +1286,9 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12851286
{
12861287
ListCell*lc;
12871288

1288-
/* Assert that ExecInitStoredGenerated has been called. */
1289-
Assert(relinfo->ri_GeneratedExprs!=NULL);
1289+
/* In some code paths we can reach here before initializing the info */
1290+
if (relinfo->ri_GeneratedExprs==NULL)
1291+
ExecInitStoredGenerated(relinfo,estate,CMD_UPDATE);
12901292
foreach(lc,estate->es_resultrelinfo_extra)
12911293
{
12921294
ResultRelInfoExtra*rextra= (ResultRelInfoExtra*)lfirst(lc);

‎src/backend/executor/nodeModifyTable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ ExecCheckTIDVisible(EState *estate,
257257
* (Currently, ri_extraUpdatedCols is consulted only in UPDATE, but we might
258258
* as well fill it for INSERT too.)
259259
*/
260-
staticvoid
260+
void
261261
ExecInitStoredGenerated(ResultRelInfo*resultRelInfo,
262262
EState*estate,
263263
CmdTypecmdtype)

‎src/include/executor/nodeModifyTable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616
#include"nodes/execnodes.h"
1717

18+
externvoidExecInitStoredGenerated(ResultRelInfo*resultRelInfo,
19+
EState*estate,
20+
CmdTypecmdtype);
21+
1822
externvoidExecComputeStoredGenerated(EState*estate,TupleTableSlot*slot,CmdTypecmdtype);
1923

2024
externModifyTableState*ExecInitModifyTable(ModifyTable*node,EState*estate,inteflags);

‎src/test/subscription/t/011_generated.pl

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use warnings;
44
use PostgresNode;
55
use TestLib;
6-
use Test::Moretests=>2;
6+
use Test::Moretests=>3;
77

88
# setup
99

@@ -22,7 +22,7 @@
2222
);
2323

2424
$node_subscriber->safe_psql('postgres',
25-
"CREATE TABLE tab1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 22) STORED)"
25+
"CREATE TABLE tab1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 22) STORED, c int)"
2626
);
2727

2828
# data for initial sync
@@ -52,9 +52,43 @@
5252

5353
$node_publisher->wait_for_catchup('sub1');
5454

55-
$result =$node_subscriber->safe_psql('postgres',"SELECT a, b FROM tab1");
56-
is($result,qq(1|22
57-
2|44
58-
3|66
59-
4|88
60-
6|132),'generated columns replicated');
55+
$result =$node_subscriber->safe_psql('postgres',"SELECT * FROM tab1");
56+
is($result,qq(1|22|
57+
2|44|
58+
3|66|
59+
4|88|
60+
6|132|),'generated columns replicated');
61+
62+
# try it with a subscriber-side trigger
63+
64+
$node_subscriber->safe_psql(
65+
'postgres',q{
66+
CREATE FUNCTION tab1_trigger_func() RETURNS trigger
67+
LANGUAGE plpgsql AS $$
68+
BEGIN
69+
NEW.c := NEW.a + 10;
70+
RETURN NEW;
71+
END $$;
72+
73+
CREATE TRIGGER test1 BEFORE INSERT OR UPDATE ON tab1
74+
FOR EACH ROW
75+
EXECUTE PROCEDURE tab1_trigger_func();
76+
77+
ALTER TABLE tab1 ENABLE REPLICA TRIGGER test1;
78+
});
79+
80+
$node_publisher->safe_psql('postgres',"INSERT INTO tab1 VALUES (7), (8)");
81+
82+
$node_publisher->safe_psql('postgres',"UPDATE tab1 SET a = 9 WHERE a = 7");
83+
84+
$node_publisher->wait_for_catchup('sub1');
85+
86+
$result =
87+
$node_subscriber->safe_psql('postgres',"SELECT * FROM tab1 ORDER BY 1");
88+
is($result,qq(1|22|
89+
2|44|
90+
3|66|
91+
4|88|
92+
6|132|
93+
8|176|18
94+
9|198|19),'generated columns replicated with trigger');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp