Skip to content

Commit

Permalink
Don't copyObject into the wrong memory context
Browse files Browse the repository at this point in the history
utilityStmt sometimes (such as when it's inside of a plpgsql function)
comes from a cached plan, which is kept in a child of the
CacheMemoryContext. When we naively call copyObject we're copying it into
a statement-local context, which corrupts the cached plan when it's
thrown away.
  • Loading branch information
lithp committed Apr 28, 2018
1 parent ca2818b commit 274a434
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/backend/distributed/executor/multi_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include "foreign/foreign.h"
#include "lib/stringinfo.h"
#include "nodes/bitmapset.h"
#include "nodes/memnodes.h"
#include "nodes/nodes.h"
#include "nodes/params.h"
#include "nodes/parsenodes.h"
Expand Down Expand Up @@ -311,12 +312,17 @@ multi_ProcessUtility(PlannedStmt *pstmt,

if (IsA(parsetree, CopyStmt))
{
/* copy parse tree since we might scribble on it to fix the schema name */
parsetree = copyObject(parsetree);
MemoryContext planContext = GetMemoryChunkContext(parsetree);
MemoryContext previousContext;

parsetree = copyObject(parsetree);
parsetree = ProcessCopyStmt((CopyStmt *) parsetree, completionTag,
&commandMustRunAsOwner);

previousContext = MemoryContextSwitchTo(planContext);
parsetree = copyObject(parsetree);
MemoryContextSwitchTo(previousContext);

if (parsetree == NULL)
{
return;
Expand Down
22 changes: 22 additions & 0 deletions src/test/regress/expected/multi_prepare_plsql.out
Original file line number Diff line number Diff line change
Expand Up @@ -1233,9 +1233,31 @@ SELECT copy_in_plpgsql();

(1 row)

-- test prepared COPY on a non-distributed table
CREATE TABLE local_ddl (x int);
CREATE OR REPLACE FUNCTION local_copy_in_plpgsql()
RETURNS VOID AS
$BODY$
BEGIN
COPY local_ddl (x) FROM PROGRAM 'echo 1' WITH CSV;
END;
$BODY$ LANGUAGE plpgsql;
SELECT local_copy_in_plpgsql();
local_copy_in_plpgsql
-----------------------

(1 row)

SELECT local_copy_in_plpgsql();
local_copy_in_plpgsql
-----------------------

(1 row)

DROP FUNCTION ddl_in_plpgsql();
DROP FUNCTION copy_in_plpgsql();
DROP TABLE prepare_ddl;
DROP TABLE local_ddl;
-- clean-up functions
DROP FUNCTION plpgsql_test_1();
DROP FUNCTION plpgsql_test_2();
Expand Down
15 changes: 15 additions & 0 deletions src/test/regress/sql/multi_prepare_plsql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,24 @@ $BODY$ LANGUAGE plpgsql;
SELECT copy_in_plpgsql();
SELECT copy_in_plpgsql();

-- test prepared COPY on a non-distributed table
CREATE TABLE local_ddl (x int);

CREATE OR REPLACE FUNCTION local_copy_in_plpgsql()
RETURNS VOID AS
$BODY$
BEGIN
COPY local_ddl (x) FROM PROGRAM 'echo 1' WITH CSV;
END;
$BODY$ LANGUAGE plpgsql;

SELECT local_copy_in_plpgsql();
SELECT local_copy_in_plpgsql();

DROP FUNCTION ddl_in_plpgsql();
DROP FUNCTION copy_in_plpgsql();
DROP TABLE prepare_ddl;
DROP TABLE local_ddl;

-- clean-up functions
DROP FUNCTION plpgsql_test_1();
Expand Down

0 comments on commit 274a434

Please sign in to comment.