From 4a718d293b9172f261d00d9d7dbe2582bed5526f Mon Sep 17 00:00:00 2001 From: Burak Yucesoy Date: Thu, 9 Jun 2016 12:49:54 +0300 Subject: [PATCH] Append shardId before escaping the table name Fixes #550, fixes #545 If table name contains special characters, it needs to be escaped. However in some cases, we escape table name before appending shardId, which causes syntax error in the queries sent to worker nodes. With this change we now append shardId before escaping table names. --- src/backend/distributed/commands/multi_copy.c | 16 ++++-- .../master/master_stage_protocol.c | 6 +-- src/test/regress/input/multi_copy.source | 36 +++++++++++++ src/test/regress/output/multi_copy.source | 50 +++++++++++++++++++ 4 files changed, 100 insertions(+), 8 deletions(-) diff --git a/src/backend/distributed/commands/multi_copy.c b/src/backend/distributed/commands/multi_copy.c index 1dd545c97..3f1c3bcfa 100644 --- a/src/backend/distributed/commands/multi_copy.c +++ b/src/backend/distributed/commands/multi_copy.c @@ -1078,14 +1078,20 @@ static StringInfo ConstructCopyStatement(CopyStmt *copyStatement, int64 shardId) { StringInfo command = makeStringInfo(); - char *qualifiedName = NULL; - qualifiedName = quote_qualified_identifier(copyStatement->relation->schemaname, - copyStatement->relation->relname); + char *schemaName = copyStatement->relation->schemaname; + char *relationName = copyStatement->relation->relname; - appendStringInfo(command, "COPY %s_%ld ", qualifiedName, shardId); + char *shardName = pstrdup(relationName); + char *shardQualifiedName = NULL; - appendStringInfoString(command, "FROM STDIN WITH (FORMAT BINARY)"); + AppendShardIdToName(&shardName, shardId); + + shardQualifiedName = quote_qualified_identifier(schemaName, shardName); + + appendStringInfo(command, + "COPY %s FROM STDIN WITH (FORMAT BINARY)", + shardQualifiedName); return command; } diff --git a/src/backend/distributed/master/master_stage_protocol.c b/src/backend/distributed/master/master_stage_protocol.c index cd930a369..31ce0b17a 100644 --- a/src/backend/distributed/master/master_stage_protocol.c +++ b/src/backend/distributed/master/master_stage_protocol.c @@ -476,14 +476,14 @@ UpdateShardStatistics(int64 shardId) shardQualifiedName = LoadShardAlias(relationId, shardId); if (shardQualifiedName == NULL) { - char *relationName = get_rel_name(relationId); + char *shardName = get_rel_name(relationId); Oid schemaId = get_rel_namespace(relationId); char *schemaName = get_namespace_name(schemaId); - shardQualifiedName = quote_qualified_identifier(schemaName, relationName); + AppendShardIdToName(&shardName, shardId); - AppendShardIdToName(&shardQualifiedName, shardId); + shardQualifiedName = quote_qualified_identifier(schemaName, shardName); } shardPlacementList = FinalizedShardPlacementList(shardId); diff --git a/src/test/regress/input/multi_copy.source b/src/test/regress/input/multi_copy.source index 425f58514..b518d01e2 100644 --- a/src/test/regress/input/multi_copy.source +++ b/src/test/regress/input/multi_copy.source @@ -378,3 +378,39 @@ COPY append.customer_copy FROM '@abs_srcdir@/data/customer.2.data' with (delimit -- Test the content of the table SELECT min(c_custkey), max(c_custkey), avg(c_acctbal), count(*) FROM append.customer_copy; + +-- Test with table name which contains special character +CREATE TABLE "customer_with_special_\\_character"( + c_custkey integer, + c_name varchar(25) not null); + +SELECT master_create_distributed_table('"customer_with_special_\\_character"', 'c_custkey', 'hash'); + +SELECT master_create_worker_shards('"customer_with_special_\\_character"', 4, 1); + +COPY "customer_with_special_\\_character" (c_custkey, c_name) FROM STDIN +WITH (FORMAT 'csv'); +1,customer1 +2,customer2 +\. + +-- Confirm that data was copied +SELECT count(*) FROM "customer_with_special_\\_character"; + +-- Test with table name which starts with number +CREATE TABLE "1_customer"( + c_custkey integer, + c_name varchar(25) not null); + +SELECT master_create_distributed_table('"1_customer"', 'c_custkey', 'hash'); + +SELECT master_create_worker_shards('"1_customer"', 4, 1); + +COPY "1_customer" (c_custkey, c_name) FROM STDIN +WITH (FORMAT 'csv'); +1,customer1 +2,customer2 +\. + +-- Confirm that data was copied +SELECT count(*) FROM "1_customer"; diff --git a/src/test/regress/output/multi_copy.source b/src/test/regress/output/multi_copy.source index 31db8b841..cb16b1498 100644 --- a/src/test/regress/output/multi_copy.source +++ b/src/test/regress/output/multi_copy.source @@ -500,3 +500,53 @@ SELECT min(c_custkey), max(c_custkey), avg(c_acctbal), count(*) FROM append.cust 1 | 7000 | 4443.8028800000000000 | 2000 (1 row) +-- Test with table name which contains special character +CREATE TABLE "customer_with_special_\\_character"( + c_custkey integer, + c_name varchar(25) not null); +SELECT master_create_distributed_table('"customer_with_special_\\_character"', 'c_custkey', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('"customer_with_special_\\_character"', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +COPY "customer_with_special_\\_character" (c_custkey, c_name) FROM STDIN +WITH (FORMAT 'csv'); +-- Confirm that data was copied +SELECT count(*) FROM "customer_with_special_\\_character"; + count +------- + 2 +(1 row) + +-- Test with table name which starts with number +CREATE TABLE "1_customer"( + c_custkey integer, + c_name varchar(25) not null); +SELECT master_create_distributed_table('"1_customer"', 'c_custkey', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('"1_customer"', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +COPY "1_customer" (c_custkey, c_name) FROM STDIN +WITH (FORMAT 'csv'); +-- Confirm that data was copied +SELECT count(*) FROM "1_customer"; + count +------- + 2 +(1 row) +