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

Commitdfd26f9

Browse files
committed
Make executor's SELECT INTO code save and restore original tuple receiver.
As previously coded, the QueryDesc's dest pointer was left dangling(pointing at an already-freed receiver object) after ExecutorEnd. It's abit astonishing that it took us this long to notice, and I'm not sure thatthe known problem case with SQL functions is the only one. Fix it bysaving and restoring the original receiver pointer, which seems the mostbulletproof way of ensuring any related bugs are also covered.Per bug #6379 from Paul Ramsey. Back-patch to 8.4 where the currenthandling of SELECT INTO was introduced.
1 parent10ecc0d commitdfd26f9

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

‎src/backend/executor/execMain.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,6 +2445,7 @@ typedef struct
24452445
{
24462446
DestReceiverpub;/* publicly-known function pointers */
24472447
EState*estate;/* EState we are working with */
2448+
DestReceiver*origdest;/* QueryDesc's original receiver */
24482449
Relationrel;/* Relation to write to */
24492450
inthi_options;/* heap_insert performance options */
24502451
BulkInsertStatebistate;/* bulk insert state */
@@ -2651,12 +2652,14 @@ OpenIntoRel(QueryDesc *queryDesc)
26512652
/*
26522653
* Now replace the query's DestReceiver with one for SELECT INTO
26532654
*/
2654-
queryDesc->dest=CreateDestReceiver(DestIntoRel);
2655-
myState= (DR_intorel*)queryDesc->dest;
2655+
myState= (DR_intorel*)CreateDestReceiver(DestIntoRel);
26562656
Assert(myState->pub.mydest==DestIntoRel);
26572657
myState->estate=estate;
2658+
myState->origdest=queryDesc->dest;
26582659
myState->rel=intoRelationDesc;
26592660

2661+
queryDesc->dest= (DestReceiver*)myState;
2662+
26602663
/*
26612664
* We can skip WAL-logging the insertions, unless PITR or streaming
26622665
* replication is in use. We can skip the FSM in any case.
@@ -2677,8 +2680,11 @@ CloseIntoRel(QueryDesc *queryDesc)
26772680
{
26782681
DR_intorel*myState= (DR_intorel*)queryDesc->dest;
26792682

2680-
/* OpenIntoRel might never have gotten called */
2681-
if (myState&&myState->pub.mydest==DestIntoRel&&myState->rel)
2683+
/*
2684+
* OpenIntoRel might never have gotten called, and we also want to guard
2685+
* against double destruction.
2686+
*/
2687+
if (myState&&myState->pub.mydest==DestIntoRel)
26822688
{
26832689
FreeBulkInsertState(myState->bistate);
26842690

@@ -2689,7 +2695,11 @@ CloseIntoRel(QueryDesc *queryDesc)
26892695
/* close rel, but keep lock until commit */
26902696
heap_close(myState->rel,NoLock);
26912697

2692-
myState->rel=NULL;
2698+
/* restore the receiver belonging to executor's caller */
2699+
queryDesc->dest=myState->origdest;
2700+
2701+
/* might as well invoke my destructor */
2702+
intorel_destroy((DestReceiver*)myState);
26932703
}
26942704
}
26952705

‎src/test/regress/expected/select_into.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,28 @@ DETAIL: drop cascades to table selinto_schema.tmp1
5050
drop cascades to table selinto_schema.tmp2
5151
drop cascades to table selinto_schema.tmp3
5252
DROP USER selinto_user;
53+
--
54+
-- CREATE TABLE AS/SELECT INTO as last command in a SQL function
55+
-- have been known to cause problems
56+
--
57+
CREATE FUNCTION make_table() RETURNS VOID
58+
AS $$
59+
CREATE TABLE created_table AS SELECT * FROM int8_tbl;
60+
$$ LANGUAGE SQL;
61+
SELECT make_table();
62+
make_table
63+
------------
64+
65+
(1 row)
66+
67+
SELECT * FROM created_table;
68+
q1 | q2
69+
------------------+-------------------
70+
123 | 456
71+
123 | 4567890123456789
72+
4567890123456789 | 123
73+
4567890123456789 | 4567890123456789
74+
4567890123456789 | -4567890123456789
75+
(5 rows)
76+
77+
DROP TABLE created_table;

‎src/test/regress/sql/select_into.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,18 @@ RESET SESSION AUTHORIZATION;
5252

5353
DROPSCHEMA selinto_schema CASCADE;
5454
DROPUSER selinto_user;
55+
56+
--
57+
-- CREATE TABLE AS/SELECT INTO as last command in a SQL function
58+
-- have been known to cause problems
59+
--
60+
CREATEFUNCTIONmake_table() RETURNS VOID
61+
AS $$
62+
CREATETABLEcreated_tableASSELECT*FROM int8_tbl;
63+
$$ LANGUAGE SQL;
64+
65+
SELECT make_table();
66+
67+
SELECT*FROM created_table;
68+
69+
DROPTABLE created_table;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp