diff --git a/src/common/backend/parser/parse_coerce.cpp b/src/common/backend/parser/parse_coerce.cpp index 02fb56e2d..ed16ec6c5 100644 --- a/src/common/backend/parser/parse_coerce.cpp +++ b/src/common/backend/parser/parse_coerce.cpp @@ -212,20 +212,23 @@ Node* coerce_to_target_type(ParseState* pstate, Node* expr, Oid exprtype, Oid ta (cformat != COERCE_IMPLICIT_CAST), (result != expr && !IsA(result, Const))); } -#ifdef PGXC - /* Do not need to do that on local Coordinator */ - if (IsConnFromCoord()) -#endif - if (expr != origexpr) { - /* Reinstall top CollateExpr */ - CollateExpr* coll = (CollateExpr*)origexpr; - CollateExpr* newcoll = makeNode(CollateExpr); - newcoll->arg = (Expr*)result; - newcoll->collOid = coll->collOid; - newcoll->location = coll->location; - result = (Node*)newcoll; - } + if (expr != origexpr && ( +#ifdef PGXC + /* Do not need to do that on local Coordinator */ + IsConnFromCoord() || +#endif + type_is_collatable(targettype))) { + + /* Reinstall top CollateExpr */ + CollateExpr* coll = (CollateExpr*)origexpr; + CollateExpr* newcoll = makeNode(CollateExpr); + + newcoll->arg = (Expr*)result; + newcoll->collOid = coll->collOid; + newcoll->location = coll->location; + result = (Node*)newcoll; + } return result; } diff --git a/src/test/regress/expected/charset_utf8mb4_b_db.out b/src/test/regress/expected/charset_utf8mb4_b_db.out index 736fe0c22..5fead0c32 100644 --- a/src/test/regress/expected/charset_utf8mb4_b_db.out +++ b/src/test/regress/expected/charset_utf8mb4_b_db.out @@ -371,6 +371,63 @@ SELECT '高斯' COLLATE "binary"; -- ERROR ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" LINE 1: SELECT '高斯' COLLATE "binary"; ^ +-- test CollateExpr +CREATE TABLE t_collate_expr( + ftext text collate utf8mb4_bin, + fbytea bytea, + fvbit varbit(8), + fint int +); +-- -- test INSERT +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate "binary"); -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: ...SERT INTO t_collate_expr(ftext) VALUES('01100001' collate "b... + ^ +CONTEXT: referenced column: ftext +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate gbk_bin); -- ERROR +ERROR: COLLATION "gbk_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: ...SERT INTO t_collate_expr(ftext) VALUES('01100001' collate gb... + ^ +CONTEXT: referenced column: ftext +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- only reserve top collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate "binary"); -- do not check collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate "binary"); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate "binary"); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate utf8mb4_general_ci collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate utf8mb4_general_ci collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate utf8mb4_general_ci collate gbk_bin); -- do not check collate +-- -- test limit +select 1 from t_collate_expr limit(to_hex('11') collate "binary"); + ?column? +---------- +(0 rows) + +select 1 from t_collate_expr limit(to_hex('11') collate gbk_bin); + ?column? +---------- +(0 rows) + +select 1 from t_collate_expr limit(to_hex('11') collate utf8mb4_unicode_ci); + ?column? +---------- +(0 rows) + +select 1 from t_collate_expr limit(to_hex('11') collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate + ?column? +---------- +(0 rows) + +DROP TABLE t_collate_expr; -- 中文 const charset SELECT CAST('高斯' AS bytea); bytea @@ -2287,18 +2344,16 @@ EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- $1 use collation_connection 高斯DB高斯DB | utf8mb4_general_ci (1 row) -EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate gbk_chinese_ci); -- explicit noneffective, utf8_gen - result | pg_collation_for ---------------+-------------------- - 高斯DB高斯DB | utf8mb4_general_ci -(1 row) - EXECUTE test_merge_collation(_gbk'高斯DB'); -- _gbk noneffective, utf8_gen result | pg_collation_for --------------+-------------------- 高斯DB高斯DB | utf8mb4_general_ci (1 row) +EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate gbk_chinese_ci); -- implicit type cast, keep explicit collation and check it, ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate gbk_ch... + ^ DEALLOCATE test_merge_collation; -- -- -- -- PBE with explicit collation, PREPARE test_merge_collation(text) AS diff --git a/src/test/regress/sql/charset_utf8mb4_b_db.sql b/src/test/regress/sql/charset_utf8mb4_b_db.sql index bf0dd844a..a6ab68d58 100644 --- a/src/test/regress/sql/charset_utf8mb4_b_db.sql +++ b/src/test/regress/sql/charset_utf8mb4_b_db.sql @@ -91,6 +91,42 @@ SELECT '高斯' COLLATE "gbk_chinese_ci"; -- ERROR SELECT '高斯' COLLATE "gb18030_chinese_ci"; -- ERROR SELECT '高斯' COLLATE "binary"; -- ERROR +-- test CollateExpr +CREATE TABLE t_collate_expr( + ftext text collate utf8mb4_bin, + fbytea bytea, + fvbit varbit(8), + fint int +); +-- -- test INSERT +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate "binary"); -- ERROR +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate gbk_bin); -- ERROR +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(ftext) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- only reserve top collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate "binary"); -- do not check collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate "binary"); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate "binary"); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate utf8mb4_unicode_ci); +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate +INSERT INTO t_collate_expr(fbytea) VALUES('01100001' collate utf8mb4_general_ci collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate +INSERT INTO t_collate_expr(fvbit) VALUES('01100001' collate utf8mb4_general_ci collate gbk_bin); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate +INSERT INTO t_collate_expr(fint) VALUES('01100001' collate utf8mb4_general_ci collate gbk_bin); -- do not check collate + +-- -- test limit +select 1 from t_collate_expr limit(to_hex('11') collate "binary"); +select 1 from t_collate_expr limit(to_hex('11') collate gbk_bin); +select 1 from t_collate_expr limit(to_hex('11') collate utf8mb4_unicode_ci); +select 1 from t_collate_expr limit(to_hex('11') collate gbk_bin collate utf8mb4_unicode_ci); -- do not check collate + +DROP TABLE t_collate_expr; + -- 中文 const charset SELECT CAST('高斯' AS bytea); SELECT CAST(_binary'高斯' AS bytea); @@ -544,8 +580,8 @@ DEALLOCATE test_merge_collation; PREPARE test_merge_collation(text) AS SELECT CONCAT($1, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- $1 use collation_connection, utf8_gen -EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate gbk_chinese_ci); -- explicit noneffective, utf8_gen EXECUTE test_merge_collation(_gbk'高斯DB'); -- _gbk noneffective, utf8_gen +EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate gbk_chinese_ci); -- implicit type cast, keep explicit collation and check it, ERROR DEALLOCATE test_merge_collation; -- -- -- -- PBE with explicit collation, PREPARE test_merge_collation(text) AS