Fix composite create type deparsing to preserve typmod

pull/3832/head
MoYi 2020-03-27 11:36:13 +08:00 committed by Philip Dubé
parent 249550b815
commit 9e1f198155
6 changed files with 57 additions and 21 deletions

View File

@ -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);
}

View File

@ -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))
{

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;