diff --git a/src/common/backend/utils/adt/a_compat.cpp b/src/common/backend/utils/adt/a_compat.cpp index eb99d69f3..ca5f2bef5 100644 --- a/src/common/backend/utils/adt/a_compat.cpp +++ b/src/common/backend/utils/adt/a_compat.cpp @@ -932,10 +932,29 @@ Datum chr(PG_FUNCTION_ARGS) wch[2] = 0x80 | ((cvalue >> 6) & 0x3F); wch[3] = 0x80 | (cvalue & 0x3F); } + } else if (encoding == PG_GBK && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + unsigned char bytes[2]; + char* wch = NULL; + if (cvalue > 0xfefe) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("requested character too large for encoding: %u", cvalue))); - } + for (int i = 0; i < 2; i++) { + bytes[i] = (cvalue >> ((1 - i) * 8)) & 0xFF; + } - else { + if (!pg_gbk_islegal(bytes, 2)) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("invalid character length for encoding: %u", cvalue))); + + result = (text*)palloc(VARHDRSZ + 2); + SET_VARSIZE(result, VARHDRSZ + 2); + wch = VARDATA(result); + wch[0] = (char)bytes[0]; + wch[1] = (char)bytes[1]; + } else { bool is_mb = false; /* diff --git a/src/test/regress/expected/chr_gbk.out b/src/test/regress/expected/chr_gbk.out new file mode 100644 index 000000000..02fec7339 --- /dev/null +++ b/src/test/regress/expected/chr_gbk.out @@ -0,0 +1,41 @@ +--test chr function in GBK encoded database +CREATE DATABASE db1 ENCODING 'GBK' TEMPLATE template0 lc_collate = 'zh_CN.gbk' lc_ctype = 'zh_CN.gbk' ; +\c db1 +set client_encoding = 'UTF8'; +select chr(52144); + chr +----- + 税 +(1 row) + +select chr(33088); --0x8140 + chr +----- + 丂 +(1 row) + +select chr(65278); --0xfefe + chr +----- +  +(1 row) + +--error +select chr(32146); +ERROR: invalid character length for encoding: 32146 +CONTEXT: referenced column: chr +select chr(33087); +ERROR: invalid character length for encoding: 33087 +CONTEXT: referenced column: chr +select chr(65279); +ERROR: requested character too large for encoding: 65279 +CONTEXT: referenced column: chr +select chr(33151); --0x817f +ERROR: invalid character length for encoding: 33151 +CONTEXT: referenced column: chr +select chr(65151); --0xfe7f +ERROR: invalid character length for encoding: 65151 +CONTEXT: referenced column: chr +\c regression +clean connection to all force for database db1; +drop database db1; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index 990838a66..95c8b87ee 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -45,7 +45,7 @@ test: spm_adaptive_gplan test: smp test: alter_hw_package test: hw_grant_package gsc_func gsc_db -test: uppercase_attribute_name decode_compatible_with_o outerjoin_bugfix +test: uppercase_attribute_name decode_compatible_with_o outerjoin_bugfix chr_gbk test: replace_func_with_two_args trunc_func_for_date nlssort_pinyin updatable_views test_cursor_arg_defexpr # test multiple statistics diff --git a/src/test/regress/sql/chr_gbk.sql b/src/test/regress/sql/chr_gbk.sql new file mode 100644 index 000000000..50b00631b --- /dev/null +++ b/src/test/regress/sql/chr_gbk.sql @@ -0,0 +1,17 @@ +--test chr function in GBK encoded database +CREATE DATABASE db1 ENCODING 'GBK' TEMPLATE template0 lc_collate = 'zh_CN.gbk' lc_ctype = 'zh_CN.gbk' ; +\c db1 +set client_encoding = 'UTF8'; +select chr(52144); +select chr(33088); --0x8140 +select chr(65278); --0xfefe + +--error +select chr(32146); +select chr(33087); +select chr(65279); +select chr(33151); --0x817f +select chr(65151); --0xfe7f +\c regression +clean connection to all force for database db1; +drop database db1;