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

Commitc024a3b

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 parent7443ab2 commitc024a3b

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

‎src/backend/executor/execMain.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,6 +2151,7 @@ typedef struct
21512151
{
21522152
DestReceiverpub;/* publicly-known function pointers */
21532153
EState*estate;/* EState we are working with */
2154+
DestReceiver*origdest;/* QueryDesc's original receiver */
21542155
Relationrel;/* Relation to write to */
21552156
inthi_options;/* heap_insert performance options */
21562157
BulkInsertStatebistate;/* bulk insert state */
@@ -2312,12 +2313,14 @@ OpenIntoRel(QueryDesc *queryDesc)
23122313
/*
23132314
* Now replace the query's DestReceiver with one for SELECT INTO
23142315
*/
2315-
queryDesc->dest=CreateDestReceiver(DestIntoRel);
2316-
myState= (DR_intorel*)queryDesc->dest;
2316+
myState= (DR_intorel*)CreateDestReceiver(DestIntoRel);
23172317
Assert(myState->pub.mydest==DestIntoRel);
23182318
myState->estate=estate;
2319+
myState->origdest=queryDesc->dest;
23192320
myState->rel=intoRelationDesc;
23202321

2322+
queryDesc->dest= (DestReceiver*)myState;
2323+
23212324
/*
23222325
* We can skip WAL-logging the insertions, unless PITR or streaming
23232326
* replication is in use. We can skip the FSM in any case.
@@ -2338,8 +2341,11 @@ CloseIntoRel(QueryDesc *queryDesc)
23382341
{
23392342
DR_intorel*myState= (DR_intorel*)queryDesc->dest;
23402343

2341-
/* OpenIntoRel might never have gotten called */
2342-
if (myState&&myState->pub.mydest==DestIntoRel&&myState->rel)
2344+
/*
2345+
* OpenIntoRel might never have gotten called, and we also want to guard
2346+
* against double destruction.
2347+
*/
2348+
if (myState&&myState->pub.mydest==DestIntoRel)
23432349
{
23442350
FreeBulkInsertState(myState->bistate);
23452351

@@ -2350,7 +2356,11 @@ CloseIntoRel(QueryDesc *queryDesc)
23502356
/* close rel, but keep lock until commit */
23512357
heap_close(myState->rel,NoLock);
23522358

2353-
myState->rel=NULL;
2359+
/* restore the receiver belonging to executor's caller */
2360+
queryDesc->dest=myState->origdest;
2361+
2362+
/* might as well invoke my destructor */
2363+
intorel_destroy((DestReceiver*)myState);
23542364
}
23552365
}
23562366

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,28 @@ SELECT *
1111
FROM onek2
1212
WHERE onek2.unique1 < 2;
1313
DROP TABLE tmp1;
14+
--
15+
-- CREATE TABLE AS/SELECT INTO as last command in a SQL function
16+
-- have been known to cause problems
17+
--
18+
CREATE FUNCTION make_table() RETURNS VOID
19+
AS $$
20+
CREATE TABLE created_table AS SELECT * FROM int8_tbl;
21+
$$ LANGUAGE SQL;
22+
SELECT make_table();
23+
make_table
24+
------------
25+
26+
(1 row)
27+
28+
SELECT * FROM created_table;
29+
q1 | q2
30+
------------------+-------------------
31+
123 | 456
32+
123 | 4567890123456789
33+
4567890123456789 | 123
34+
4567890123456789 | 4567890123456789
35+
4567890123456789 | -4567890123456789
36+
(5 rows)
37+
38+
DROP TABLE created_table;

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,17 @@ SELECT *
1616

1717
DROPTABLE tmp1;
1818

19+
--
20+
-- CREATE TABLE AS/SELECT INTO as last command in a SQL function
21+
-- have been known to cause problems
22+
--
23+
CREATEFUNCTIONmake_table() RETURNS VOID
24+
AS $$
25+
CREATETABLEcreated_tableASSELECT*FROM int8_tbl;
26+
$$ LANGUAGE SQL;
27+
28+
SELECT make_table();
29+
30+
SELECT*FROM created_table;
31+
32+
DROPTABLE created_table;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp