From 9e1f19815536beb9dfeb0d7c4b430d54930bf88c Mon Sep 17 00:00:00 2001 From: MoYi Date: Fri, 27 Mar 2020 11:36:13 +0800 Subject: [PATCH] Fix composite create type deparsing to preserve typmod --- src/backend/distributed/commands/type.c | 4 +-- .../distributed/deparser/deparse_type_stmts.c | 8 +++-- .../regress/expected/distributed_types.out | 30 ++++++++++++++----- .../multi_mx_function_table_reference.out | 11 ++++++- src/test/regress/sql/distributed_types.sql | 20 ++++++++----- .../sql/multi_mx_function_table_reference.sql | 5 +++- 6 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/backend/distributed/commands/type.c b/src/backend/distributed/commands/type.c index b974ea2a3..7f848e06f 100644 --- a/src/backend/distributed/commands/type.c +++ b/src/backend/distributed/commands/type.c @@ -712,15 +712,13 @@ RecreateCompositeTypeStmt(Oid typeOid) /* * attributeFormToColumnDef returns a ColumnDef * describing the field and its property * for a pg_attribute entry. - * - * Note: Current implementation is only covering the features supported by composite types */ static ColumnDef * attributeFormToColumnDef(Form_pg_attribute attributeForm) { return makeColumnDef(NameStr(attributeForm->attname), attributeForm->atttypid, - -1, + attributeForm->atttypmod, attributeForm->attcollation); } diff --git a/src/backend/distributed/deparser/deparse_type_stmts.c b/src/backend/distributed/deparser/deparse_type_stmts.c index a3b354e8a..07f84e185 100644 --- a/src/backend/distributed/deparser/deparse_type_stmts.c +++ b/src/backend/distributed/deparser/deparse_type_stmts.c @@ -378,7 +378,11 @@ AppendColumnDefList(StringInfo str, List *columnDefs) static void AppendColumnDef(StringInfo str, ColumnDef *columnDef) { - Oid typeOid = LookupTypeNameOid(NULL, columnDef->typeName, false); + int32 typmod = 0; + Oid typeOid = InvalidOid; + bits16 formatFlags = FORMAT_TYPE_TYPEMOD_GIVEN | FORMAT_TYPE_FORCE_QUALIFY; + + typenameTypeIdAndMod(NULL, columnDef->typeName, &typeOid, &typmod); Oid collationOid = GetColumnDefCollation(NULL, columnDef, typeOid); Assert(!columnDef->is_not_null); /* not null is not supported on composite types */ @@ -388,7 +392,7 @@ AppendColumnDef(StringInfo str, ColumnDef *columnDef) appendStringInfo(str, "%s ", quote_identifier(columnDef->colname)); } - appendStringInfo(str, "%s", format_type_be_qualified(typeOid)); + appendStringInfo(str, "%s", format_type_extended(typeOid, typmod, formatFlags)); if (OidIsValid(collationOid)) { diff --git a/src/test/regress/expected/distributed_types.out b/src/test/regress/expected/distributed_types.out index 33957dfb4..242ebfa34 100644 --- a/src/test/regress/expected/distributed_types.out +++ b/src/test/regress/expected/distributed_types.out @@ -14,7 +14,7 @@ CREATE SCHEMA type_tests2 AUTHORIZATION typeuser; -- to test creation in a speci SET search_path TO type_tests; SET citus.shard_count TO 4; -- single statement transactions with a simple type used in a table -CREATE TYPE tc1 AS (a int, b int); +CREATE TYPE tc1 AS (a int, b varchar(20)); CREATE TABLE t1 (a int PRIMARY KEY, b tc1); SELECT create_distributed_table('t1','a'); create_distributed_table @@ -22,7 +22,7 @@ SELECT create_distributed_table('t1','a'); (1 row) -INSERT INTO t1 VALUES (1, (2,3)::tc1); +INSERT INTO t1 VALUES (1, (2,'3')::tc1); SELECT * FROM t1; a | b --------------------------------------------------------------------- @@ -30,10 +30,18 @@ SELECT * FROM t1; (1 row) ALTER TYPE tc1 RENAME TO tc1_newname; -INSERT INTO t1 VALUES (3, (4,5)::tc1_newname); -- insert with a cast would fail if the rename didn't propagate +INSERT INTO t1 VALUES (3, (4,'5')::tc1_newname); -- insert with a cast would fail if the rename didn't propagate ALTER TYPE tc1_newname SET SCHEMA type_tests2; -INSERT INTO t1 VALUES (6, (7,8)::type_tests2.tc1_newname); -- insert with a cast would fail if the rename didn't propagate --- single statement transactions with a an enum used in a table +INSERT INTO t1 VALUES (6, (7,'8')::type_tests2.tc1_newname); -- insert with a cast would fail if the rename didn't propagate +-- verify typmod was propagated +SELECT run_command_on_workers($$SELECT atttypmod FROM pg_attribute WHERE attnum = 2 AND attrelid = (SELECT typrelid FROM pg_type WHERE typname = 'tc1_newname');$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,24) + (localhost,57638,t,24) +(2 rows) + +-- single statement transactions with an enum used in a table CREATE TYPE te1 AS ENUM ('one', 'two', 'three'); CREATE TABLE t2 (a int PRIMARY KEY, b te1); SELECT create_distributed_table('t2','a'); @@ -65,7 +73,7 @@ ALTER TYPE te1_newname SET SCHEMA type_tests2; INSERT INTO t2 VALUES (3, 'three'::type_tests2.te1_newname); -- transaction block with simple type BEGIN; -CREATE TYPE tc2 AS (a int, b int); +CREATE TYPE tc2 AS (a varchar(10), b int); CREATE TABLE t3 (a int PRIMARY KEY, b tc2); SELECT create_distributed_table('t3','a'); create_distributed_table @@ -73,13 +81,21 @@ SELECT create_distributed_table('t3','a'); (1 row) -INSERT INTO t3 VALUES (4, (5,6)::tc2); +INSERT INTO t3 VALUES (4, ('5',6)::tc2); SELECT * FROM t3; a | b --------------------------------------------------------------------- 4 | (5,6) (1 row) +-- verify typmod was propagated +SELECT run_command_on_workers($$SELECT atttypmod FROM pg_attribute WHERE attnum = 1 AND attrelid = (SELECT typrelid FROM pg_type WHERE typname = 'tc2');$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,14) + (localhost,57638,t,14) +(2 rows) + COMMIT; -- transaction block with simple type BEGIN; diff --git a/src/test/regress/expected/multi_mx_function_table_reference.out b/src/test/regress/expected/multi_mx_function_table_reference.out index 606294670..0abf6ca1a 100644 --- a/src/test/regress/expected/multi_mx_function_table_reference.out +++ b/src/test/regress/expected/multi_mx_function_table_reference.out @@ -33,7 +33,7 @@ SELECT master_remove_node('localhost', :worker_2_port); (1 row) -- reproduction case as described in #3378 -CREATE TABLE zoop_table (x int, y int); +CREATE TABLE zoop_table (x int, y decimal(4, 4)); SELECT create_distributed_table('zoop_table','x'); create_distributed_table --------------------------------------------------------------------- @@ -73,6 +73,15 @@ SELECT public.wait_until_metadata_sync(30000); (1 row) +-- verify typmod of zoop_table.b was propagated +-- see numerictypmodin in postgres for how typmod is derived +SELECT run_command_on_workers($$SELECT atttypmod FROM pg_attribute WHERE attnum = 2 AND attrelid = (SELECT typrelid FROM pg_type WHERE typname = 'zoop_table');$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,262152) + (localhost,57638,t,262152) +(2 rows) + -- clean up after testing DROP SCHEMA function_table_reference CASCADE; NOTICE: drop cascades to 2 other objects diff --git a/src/test/regress/sql/distributed_types.sql b/src/test/regress/sql/distributed_types.sql index df1b7f297..582b35e57 100644 --- a/src/test/regress/sql/distributed_types.sql +++ b/src/test/regress/sql/distributed_types.sql @@ -9,17 +9,20 @@ SET search_path TO type_tests; SET citus.shard_count TO 4; -- single statement transactions with a simple type used in a table -CREATE TYPE tc1 AS (a int, b int); +CREATE TYPE tc1 AS (a int, b varchar(20)); CREATE TABLE t1 (a int PRIMARY KEY, b tc1); SELECT create_distributed_table('t1','a'); -INSERT INTO t1 VALUES (1, (2,3)::tc1); +INSERT INTO t1 VALUES (1, (2,'3')::tc1); SELECT * FROM t1; ALTER TYPE tc1 RENAME TO tc1_newname; -INSERT INTO t1 VALUES (3, (4,5)::tc1_newname); -- insert with a cast would fail if the rename didn't propagate +INSERT INTO t1 VALUES (3, (4,'5')::tc1_newname); -- insert with a cast would fail if the rename didn't propagate ALTER TYPE tc1_newname SET SCHEMA type_tests2; -INSERT INTO t1 VALUES (6, (7,8)::type_tests2.tc1_newname); -- insert with a cast would fail if the rename didn't propagate +INSERT INTO t1 VALUES (6, (7,'8')::type_tests2.tc1_newname); -- insert with a cast would fail if the rename didn't propagate --- single statement transactions with a an enum used in a table +-- verify typmod was propagated +SELECT run_command_on_workers($$SELECT atttypmod FROM pg_attribute WHERE attnum = 2 AND attrelid = (SELECT typrelid FROM pg_type WHERE typname = 'tc1_newname');$$); + +-- single statement transactions with an enum used in a table CREATE TYPE te1 AS ENUM ('one', 'two', 'three'); CREATE TABLE t2 (a int PRIMARY KEY, b te1); SELECT create_distributed_table('t2','a'); @@ -40,11 +43,14 @@ INSERT INTO t2 VALUES (3, 'three'::type_tests2.te1_newname); -- transaction block with simple type BEGIN; -CREATE TYPE tc2 AS (a int, b int); +CREATE TYPE tc2 AS (a varchar(10), b int); CREATE TABLE t3 (a int PRIMARY KEY, b tc2); SELECT create_distributed_table('t3','a'); -INSERT INTO t3 VALUES (4, (5,6)::tc2); +INSERT INTO t3 VALUES (4, ('5',6)::tc2); SELECT * FROM t3; + +-- verify typmod was propagated +SELECT run_command_on_workers($$SELECT atttypmod FROM pg_attribute WHERE attnum = 1 AND attrelid = (SELECT typrelid FROM pg_type WHERE typname = 'tc2');$$); COMMIT; -- transaction block with simple type diff --git a/src/test/regress/sql/multi_mx_function_table_reference.sql b/src/test/regress/sql/multi_mx_function_table_reference.sql index ab6af2a9f..59647e8f5 100644 --- a/src/test/regress/sql/multi_mx_function_table_reference.sql +++ b/src/test/regress/sql/multi_mx_function_table_reference.sql @@ -22,7 +22,7 @@ SELECT start_metadata_sync_to_node('localhost', :worker_2_port); SELECT master_remove_node('localhost', :worker_2_port); -- reproduction case as described in #3378 -CREATE TABLE zoop_table (x int, y int); +CREATE TABLE zoop_table (x int, y decimal(4, 4)); SELECT create_distributed_table('zoop_table','x'); -- Create a function that refers to the distributed table @@ -46,6 +46,9 @@ SELECT create_distributed_function('zoop(int)', '$1'); SELECT 1 FROM master_add_node('localhost', :worker_2_port); SELECT public.wait_until_metadata_sync(30000); +-- verify typmod of zoop_table.b was propagated +-- see numerictypmodin in postgres for how typmod is derived +SELECT run_command_on_workers($$SELECT atttypmod FROM pg_attribute WHERE attnum = 2 AND attrelid = (SELECT typrelid FROM pg_type WHERE typname = 'zoop_table');$$); -- clean up after testing DROP SCHEMA function_table_reference CASCADE;