mirror of https://github.com/citusdata/citus.git
Fix use-after-free that may occur for INSERT..SELECT in prepared statements
parent
0d429aff8b
commit
6514d04f01
|
@ -101,6 +101,7 @@ ExecuteSelectIntoRelation(Oid targetRelationId, List *insertTargetList,
|
||||||
int partitionColumnIndex = -1;
|
int partitionColumnIndex = -1;
|
||||||
|
|
||||||
CitusCopyDestReceiver *copyDest = NULL;
|
CitusCopyDestReceiver *copyDest = NULL;
|
||||||
|
Query *queryCopy = NULL;
|
||||||
|
|
||||||
partitionMethod = PartitionMethod(targetRelationId);
|
partitionMethod = PartitionMethod(targetRelationId);
|
||||||
if (partitionMethod == DISTRIBUTE_BY_NONE)
|
if (partitionMethod == DISTRIBUTE_BY_NONE)
|
||||||
|
@ -135,7 +136,14 @@ ExecuteSelectIntoRelation(Oid targetRelationId, List *insertTargetList,
|
||||||
partitionColumnIndex, executorState,
|
partitionColumnIndex, executorState,
|
||||||
stopOnFailure);
|
stopOnFailure);
|
||||||
|
|
||||||
ExecuteQueryIntoDestReceiver(selectQuery, paramListInfo, (DestReceiver *) copyDest);
|
/*
|
||||||
|
* Make a copy of the query, since ExecuteQueryIntoDestReceiver may scribble on it
|
||||||
|
* and we want it to be replanned every time if it is stored in a prepared
|
||||||
|
* statement.
|
||||||
|
*/
|
||||||
|
queryCopy = copyObject(selectQuery);
|
||||||
|
|
||||||
|
ExecuteQueryIntoDestReceiver(queryCopy, paramListInfo, (DestReceiver *) copyDest);
|
||||||
|
|
||||||
executorState->es_processed = copyDest->tuplesSent;
|
executorState->es_processed = copyDest->tuplesSent;
|
||||||
|
|
||||||
|
|
|
@ -2715,6 +2715,19 @@ SELECT * FROM coerce_agg;
|
||||||
2 | {2,2,2}
|
2 | {2,2,2}
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- INSERT..SELECT + prepared statements + recursive planning
|
||||||
|
BEGIN;
|
||||||
|
PREPARE prepared_recursive_insert_select AS
|
||||||
|
INSERT INTO users_table
|
||||||
|
SELECT * FROM users_table
|
||||||
|
WHERE value_1 IN (SELECT value_2 FROM events_table OFFSET 0);
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
ROLLBACK;
|
||||||
-- wrap in a transaction to improve performance
|
-- wrap in a transaction to improve performance
|
||||||
BEGIN;
|
BEGIN;
|
||||||
DROP TABLE coerce_events;
|
DROP TABLE coerce_events;
|
||||||
|
|
|
@ -2082,6 +2082,20 @@ LIMIT 5;
|
||||||
|
|
||||||
SELECT * FROM coerce_agg;
|
SELECT * FROM coerce_agg;
|
||||||
|
|
||||||
|
-- INSERT..SELECT + prepared statements + recursive planning
|
||||||
|
BEGIN;
|
||||||
|
PREPARE prepared_recursive_insert_select AS
|
||||||
|
INSERT INTO users_table
|
||||||
|
SELECT * FROM users_table
|
||||||
|
WHERE value_1 IN (SELECT value_2 FROM events_table OFFSET 0);
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
EXECUTE prepared_recursive_insert_select;
|
||||||
|
ROLLBACK;
|
||||||
|
|
||||||
-- wrap in a transaction to improve performance
|
-- wrap in a transaction to improve performance
|
||||||
BEGIN;
|
BEGIN;
|
||||||
DROP TABLE coerce_events;
|
DROP TABLE coerce_events;
|
||||||
|
|
Loading…
Reference in New Issue