修复隐式转换丢失字符序的问题

This commit is contained in:
li-judong
2023-08-02 20:28:02 +08:00
parent 02c4a13d49
commit e8c0b6674f
3 changed files with 114 additions and 20 deletions

View File

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

View File

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

View File

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