From 853f07dd33fbe8c243337c663025714022c61e82 Mon Sep 17 00:00:00 2001 From: Marco Slot Date: Fri, 28 Apr 2017 00:55:39 +0200 Subject: [PATCH] Don't change query tree of DDL commands --- .../distributed/executor/multi_utility.c | 22 ++++---- .../regress/expected/multi_prepare_plsql.out | 52 +++++++++++++++++++ src/test/regress/sql/multi_prepare_plsql.sql | 33 ++++++++++++ 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/src/backend/distributed/executor/multi_utility.c b/src/backend/distributed/executor/multi_utility.c index c81d983f5..d322324f8 100644 --- a/src/backend/distributed/executor/multi_utility.c +++ b/src/backend/distributed/executor/multi_utility.c @@ -241,6 +241,9 @@ multi_ProcessUtility(Node *parsetree, if (IsA(parsetree, CopyStmt)) { + /* copy parse tree since we might scribble on it to fix the schema name */ + parsetree = copyObject(parsetree); + parsetree = ProcessCopyStmt((CopyStmt *) parsetree, completionTag, &commandMustRunAsOwner); @@ -272,6 +275,9 @@ multi_ProcessUtility(Node *parsetree, { if (IsA(parsetree, IndexStmt)) { + /* copy parse tree since we might scribble on it to fix the schema name */ + parsetree = copyObject(parsetree); + ddlJobs = PlanIndexStmt((IndexStmt *) parsetree, queryString); } @@ -781,7 +787,13 @@ PlanIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand) isDistributedRelation = IsDistributedTable(relationId); - /* ensure future lookups hit the same relation */ + /* + * Before we do any further processing, fix the schema name to make sure + * that a (distributed) table with the same name does not appear on the + * search path in front of the current schema. We do this even if the + * table is not distributed, since a distributed table may appear on the + * search path by the time postgres starts processing this statement. + */ namespaceName = get_namespace_name(RelationGetNamespace(relation)); createIndexStatement->relation->schemaname = namespaceName; @@ -2569,20 +2581,12 @@ CreateIndexTaskList(Oid relationId, IndexStmt *indexStmt) List *taskList = NIL; List *shardIntervalList = LoadShardIntervalList(relationId); ListCell *shardIntervalCell = NULL; - Oid schemaId = get_rel_namespace(relationId); - char *schemaName = get_namespace_name(schemaId); StringInfoData ddlString; uint64 jobId = INVALID_JOB_ID; int taskId = 1; initStringInfo(&ddlString); - /* set statement's schema name if it is not set already */ - if (indexStmt->relation->schemaname == NULL) - { - indexStmt->relation->schemaname = schemaName; - } - /* lock metadata before getting placement lists */ LockShardListMetadata(shardIntervalList, ShareLock); diff --git a/src/test/regress/expected/multi_prepare_plsql.out b/src/test/regress/expected/multi_prepare_plsql.out index 8727fed5e..9417f742b 100644 --- a/src/test/regress/expected/multi_prepare_plsql.out +++ b/src/test/regress/expected/multi_prepare_plsql.out @@ -1185,6 +1185,58 @@ SELECT key, seq FROM func_parameter_test ORDER BY seq; DROP FUNCTION insert_with_max(text); DROP TABLE func_parameter_test; +-- test prepared DDL, mainly to verify we don't mess up the query tree +SET citus.multi_shard_commit_protocol TO '2pc'; +CREATE TABLE prepare_ddl (x int, y int); +SELECT create_distributed_table('prepare_ddl', 'x'); + create_distributed_table +-------------------------- + +(1 row) + +CREATE OR REPLACE FUNCTION ddl_in_plpgsql() +RETURNS VOID AS +$BODY$ +BEGIN + CREATE INDEX prepared_index ON public.prepare_ddl(x); + DROP INDEX prepared_index; +END; +$BODY$ LANGUAGE plpgsql; +SELECT ddl_in_plpgsql(); + ddl_in_plpgsql +---------------- + +(1 row) + +SELECT ddl_in_plpgsql(); + ddl_in_plpgsql +---------------- + +(1 row) + +-- test prepared COPY +CREATE OR REPLACE FUNCTION copy_in_plpgsql() +RETURNS VOID AS +$BODY$ +BEGIN + COPY prepare_ddl (x) FROM PROGRAM 'echo 1' WITH CSV; +END; +$BODY$ LANGUAGE plpgsql; +SELECT copy_in_plpgsql(); + copy_in_plpgsql +----------------- + +(1 row) + +SELECT copy_in_plpgsql(); + copy_in_plpgsql +----------------- + +(1 row) + +DROP FUNCTION ddl_in_plpgsql(); +DROP FUNCTION copy_in_plpgsql(); +DROP TABLE prepare_ddl; -- clean-up functions DROP FUNCTION plpgsql_test_1(); DROP FUNCTION plpgsql_test_2(); diff --git a/src/test/regress/sql/multi_prepare_plsql.sql b/src/test/regress/sql/multi_prepare_plsql.sql index 0b33aede0..59d278b3d 100644 --- a/src/test/regress/sql/multi_prepare_plsql.sql +++ b/src/test/regress/sql/multi_prepare_plsql.sql @@ -537,6 +537,39 @@ SELECT key, seq FROM func_parameter_test ORDER BY seq; DROP FUNCTION insert_with_max(text); DROP TABLE func_parameter_test; +-- test prepared DDL, mainly to verify we don't mess up the query tree +SET citus.multi_shard_commit_protocol TO '2pc'; +CREATE TABLE prepare_ddl (x int, y int); +SELECT create_distributed_table('prepare_ddl', 'x'); + +CREATE OR REPLACE FUNCTION ddl_in_plpgsql() +RETURNS VOID AS +$BODY$ +BEGIN + CREATE INDEX prepared_index ON public.prepare_ddl(x); + DROP INDEX prepared_index; +END; +$BODY$ LANGUAGE plpgsql; + +SELECT ddl_in_plpgsql(); +SELECT ddl_in_plpgsql(); + +-- test prepared COPY +CREATE OR REPLACE FUNCTION copy_in_plpgsql() +RETURNS VOID AS +$BODY$ +BEGIN + COPY prepare_ddl (x) FROM PROGRAM 'echo 1' WITH CSV; +END; +$BODY$ LANGUAGE plpgsql; + +SELECT copy_in_plpgsql(); +SELECT copy_in_plpgsql(); + +DROP FUNCTION ddl_in_plpgsql(); +DROP FUNCTION copy_in_plpgsql(); +DROP TABLE prepare_ddl; + -- clean-up functions DROP FUNCTION plpgsql_test_1(); DROP FUNCTION plpgsql_test_2();