diff --git a/contrib/shark/expected/test_ddl_and_dml.out b/contrib/shark/expected/test_ddl_and_dml.out index 7080a14698fec4053839008593c5464047980186..8fca83f24332fd1c488f477afb90e84d02bee51b 100644 --- a/contrib/shark/expected/test_ddl_and_dml.out +++ b/contrib/shark/expected/test_ddl_and_dml.out @@ -21,13 +21,13 @@ select * from Products; (2 rows) \d+ Products - Table "test_ddl_and_dml.products" - Column | Type | Modifiers | Storage | Stats target | Description -----------------+----------+-----------------------------------------------------------------------+---------+--------------+------------- - qtyavailable | smallint | | plain | | - unitprice | money | | plain | | - inventoryvalue | money | as ((qtyavailable * unitprice)) persisted | plain | | - retailvalue | money | as (((qtyavailable * unitprice) * (1.5)::double precision)) persisted | plain | | + Table "test_ddl_and_dml.products" + Column | Type | Modifiers | Storage | Stats target | Description +----------------+----------+---------------------------------------------------------------------------------------+---------+--------------+------------- + qtyavailable | smallint | | plain | | + unitprice | money | | plain | | + inventoryvalue | money | collate default as ((qtyavailable * unitprice)) persisted | plain | | + retailvalue | money | collate default as (((qtyavailable * unitprice) * (1.5)::double precision)) persisted | plain | | Has OIDs: no Options: orientation=row, compression=no @@ -48,6 +48,31 @@ ALTER TABLE Products DROP COLUMN UnitPrice; ERROR: cannot drop a column used by a generated column DETAIL: Column "unitprice" is used by generated column "inventoryvalue". DROP TABLE IF EXISTS Products; +-- test for issue #IC13WR +drop table if exists ttb16; +NOTICE: table "ttb16" does not exist, skipping +create table ttb16(str1 varchar(20),str2 varchar(20),str3 as (str1 || str2)); +NOTICE: The virtual computed columns (non-persisted) are currently ignored and behave the same as persisted columns. +insert into ttb16 values('hello ','world'); +insert into ttb16 values('runoob'); +select * from ttb16; + str1 | str2 | str3 +--------+-------+------------- + hello | world | hello world + runoob | | +(2 rows) + +--- expect success +alter table ttb16 add column str4 as (str1 || str2); +NOTICE: The virtual computed columns (non-persisted) are currently ignored and behave the same as persisted columns. +select * from ttb16; + str1 | str2 | str3 | str4 +--------+-------+-------------+------------- + hello | world | hello world | hello world + runoob | | | +(2 rows) + +drop table ttb16; -- case2: top clause DROP TABLE IF EXISTS Products; NOTICE: table "products" does not exist, skipping diff --git a/contrib/shark/sql/test_ddl_and_dml.sql b/contrib/shark/sql/test_ddl_and_dml.sql index 4935303c50311c42bd0285ec17b55b9c06ecfa5e..45a2a82aafcde807130c29995498ab9115d62a0a 100644 --- a/contrib/shark/sql/test_ddl_and_dml.sql +++ b/contrib/shark/sql/test_ddl_and_dml.sql @@ -31,6 +31,17 @@ ALTER TABLE Products DROP COLUMN UnitPrice; DROP TABLE IF EXISTS Products; +-- test for issue #IC13WR +drop table if exists ttb16; +create table ttb16(str1 varchar(20),str2 varchar(20),str3 as (str1 || str2)); +insert into ttb16 values('hello ','world'); +insert into ttb16 values('runoob'); +select * from ttb16; +--- expect success +alter table ttb16 add column str4 as (str1 || str2); +select * from ttb16; +drop table ttb16; + -- case2: top clause DROP TABLE IF EXISTS Products; CREATE TABLE Products(QtyAvailable smallint, UnitPrice money, InventoryValue AS (QtyAvailable * UnitPrice)); @@ -732,4 +743,4 @@ SELECT 1 YES; SELECT 1 ZONE; reset current_schema; -drop schema if exists test_ddl_and_dml cascade; \ No newline at end of file +drop schema if exists test_ddl_and_dml cascade; diff --git a/contrib/shark/src/tablecmds.cpp b/contrib/shark/src/tablecmds.cpp index ba08c7524845699a5c94478a5aaf8aacf7dcdc32..d8b68042c6bb365d7188e4cc382b262d3f9f6935 100644 --- a/contrib/shark/src/tablecmds.cpp +++ b/contrib/shark/src/tablecmds.cpp @@ -257,7 +257,25 @@ static void pltsql_PreAddConstraintsHook(Relation rel, ParseState *pstate, List attTup->atttypid = targettype; attTup->atttypmod = targettypmod; - attTup->attcollation = 0; + /* + * The target column should already be having a collation associated + * with it due to explicit COLLATE clause If suppose collation is not + * valid or there is no explicit COLLATE clause, we try to find column + * collation from finished expession. + */ + if (!OidIsValid(attTup->attcollation)) { + Oid targetcollid; + + /* take care of collations in the finished expression */ + assign_expr_collations(pstate, expr); + targetcollid = exprCollation(expr); + + if (OidIsValid(targetcollid)) { + attTup->attcollation = targetcollid; + } else { + attTup->attcollation = tform->typcollation; + } + } attTup->attndims = tform->typndims; attTup->attlen = tform->typlen; @@ -386,4 +404,4 @@ static bool check_nested_computed_column(Node *node, void *context) } return raw_expression_tree_walker(node, (bool (*)())check_nested_computed_column, (void*)context); -} \ No newline at end of file +} diff --git a/src/gausskernel/optimizer/commands/ddldeparse.cpp b/src/gausskernel/optimizer/commands/ddldeparse.cpp index 394ac063997d309aae7b4196610887579e69a5a9..ea70189752685a8c3f681747c96b7c5f969a4597 100644 --- a/src/gausskernel/optimizer/commands/ddldeparse.cpp +++ b/src/gausskernel/optimizer/commands/ddldeparse.cpp @@ -1718,6 +1718,16 @@ static ObjTree* deparse_ColumnDef(Relation relation, List *dpcontext, bool compo "name", ObjTypeString, coldef->colname, "coltype", ObjTypeObject, new_objtree_for_type(typid, typmod)); + + tmp_obj = new_objtree("COLLATE"); + if (OidIsValid(typcollation)) { + append_object_object(tmp_obj, "%{name}D", + new_objtree_for_qualname_id(CollationRelationId, + typcollation)); + } else { + append_not_present(tmp_obj, "%{name}D"); + } + append_object_object(ret, "%{collation}s", tmp_obj); } else { ObjTree* dummy = new_objtree_VA(NULL, numFour, "schemaname", ObjTypeString, "", @@ -1730,15 +1740,6 @@ static ObjTree* deparse_ColumnDef(Relation relation, List *dpcontext, bool compo "name", ObjTypeString, coldef->colname, "coltype", ObjTypeObject, dummy); } - tmp_obj = new_objtree("COLLATE"); - if (OidIsValid(typcollation)) { - append_object_object(tmp_obj, "%{name}D", - new_objtree_for_qualname_id(CollationRelationId, - typcollation)); - } else { - append_not_present(tmp_obj, "%{name}D"); - } - append_object_object(ret, "%{collation}s", tmp_obj); if (!composite) { /* @@ -1858,6 +1859,19 @@ static ObjTree* deparse_ColumnDef(Relation relation, List *dpcontext, bool compo append_not_present(tmp_obj, "(%{generation_expr}s) STORED"); } append_object_object(ret, "%{generated_column}s", tmp_obj); + + if (coldef->generatedCol == ATTRIBUTE_GENERATED_PERSISTED) { + /* A generated column of the PERSISTED type requires adding COLLATE after the expression. */ + tmp_obj = new_objtree("COLLATE"); + if (OidIsValid(typcollation)) { + append_object_object(tmp_obj, "%{name}D", + new_objtree_for_qualname_id(CollationRelationId, + typcollation)); + } else { + append_not_present(tmp_obj, "%{name}D"); + } + append_object_object(ret, "%{collation}s", tmp_obj); + } } ReleaseSysCache(attrTup); @@ -5943,4 +5957,4 @@ static ObjTree* deparse_CreateTrigStmt(Oid objectId, Node *parsetree) table_close(pg_trigger, AccessShareLock); return ret; -} \ No newline at end of file +}