From ffbc0ac3b76a16e73ab8d147582ee33b3e74fd1f Mon Sep 17 00:00:00 2001 From: suncan <1006949218@qq.com> Date: Wed, 31 May 2023 11:37:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9MySQL=E5=A4=9A=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/catalog/Makefile | 3 +- src/common/backend/catalog/builtin_funcs.ini | 6 +- src/common/backend/catalog/gs_collation.cpp | 213 + .../backend/catalog/gs_gb18030_collation.cpp | 6881 +++++++++++++++++ .../backend/catalog/gs_gbk_collation.cpp | 2535 ++++++ .../backend/catalog/gs_utf8_collation.cpp | 166 +- src/common/backend/catalog/heap.cpp | 39 +- src/common/backend/catalog/namespace.cpp | 16 +- src/common/backend/catalog/pg_collation.cpp | 66 + src/common/backend/catalog/pg_set.cpp | 27 +- src/common/backend/libpq/pqformat.cpp | 6 +- src/common/backend/nodes/copyfuncs.cpp | 13 + src/common/backend/nodes/equalfuncs.cpp | 11 + src/common/backend/nodes/outfuncs.cpp | 12 + src/common/backend/nodes/readfuncs.cpp | 14 + src/common/backend/parser/analyze.cpp | 62 +- src/common/backend/parser/gram.y | 85 +- src/common/backend/parser/parse_coerce.cpp | 206 +- src/common/backend/parser/parse_collate.cpp | 582 +- src/common/backend/parser/parse_expr.cpp | 83 +- src/common/backend/parser/parse_node.cpp | 6 +- src/common/backend/parser/parse_param.cpp | 6 +- src/common/backend/parser/parse_target.cpp | 17 +- src/common/backend/parser/parse_type.cpp | 39 +- src/common/backend/parser/parse_utilcmd.cpp | 88 +- src/common/backend/parser/scan.l | 9 + .../backend/pgxc_single/copy/copyops.cpp | 22 +- src/common/backend/utils/adt/like.cpp | 6 +- src/common/backend/utils/adt/ruleutils.cpp | 15 +- src/common/backend/utils/adt/selfuncs.cpp | 44 +- src/common/backend/utils/adt/set.cpp | 203 +- src/common/backend/utils/adt/varchar.cpp | 8 +- src/common/backend/utils/adt/varlena.cpp | 51 +- src/common/backend/utils/fmgr/fmgr.cpp | 11 +- src/common/backend/utils/init/globals.cpp | 4 +- src/common/backend/utils/init/postinit.cpp | 12 + src/common/backend/utils/mb/encnames.cpp | 4 +- src/common/backend/utils/mb/mbutils.cpp | 144 +- src/common/backend/utils/misc/guc.cpp | 65 +- src/common/backend/utils/misc/guc/guc_sql.cpp | 20 +- .../interfaces/libpq/frontend_parser/gram.y | 2 +- src/common/pl/plpgsql/src/gram.y | 2 +- src/common/pl/plpgsql/src/pl_exec.cpp | 107 +- .../cbb/utils/partition/partitionmap.cpp | 3 + .../dbmind/kernel/index_advisor.cpp | 6 + src/gausskernel/optimizer/commands/copy.cpp | 115 +- .../optimizer/commands/formatter.cpp | 17 +- .../optimizer/commands/tablecmds.cpp | 55 +- .../optimizer/commands/typecmds.cpp | 11 +- .../optimizer/commands/variable.cpp | 137 + src/gausskernel/optimizer/path/indxpath.cpp | 32 +- src/gausskernel/optimizer/plan/planner.cpp | 46 +- .../optimizer/rewrite/rewriteHandler.cpp | 20 +- src/gausskernel/optimizer/util/plancat.cpp | 25 +- src/gausskernel/process/tcop/utility.cpp | 4 +- .../process/threadpool/knl_session.cpp | 2 + src/gausskernel/runtime/executor/execExpr.cpp | 3 + .../runtime/executor/execExprInterp.cpp | 60 +- src/gausskernel/runtime/executor/execQual.cpp | 72 +- src/gausskernel/runtime/executor/spi.cpp | 16 + .../security/gs_ledger/ledger_archive.cpp | 9 + .../storage/access/common/printtup.cpp | 12 +- .../storage/access/common/scankey.cpp | 1 + .../storage/access/common/tupdesc.cpp | 2 +- .../storage/access/hash/hashfunc.cpp | 5 +- src/gausskernel/storage/bulkload/dist_fdw.cpp | 17 +- src/include/access/printtup.h | 2 + src/include/catalog/gs_collation.h | 64 + src/include/catalog/gs_utf8_collation.h | 39 - src/include/catalog/heap.h | 2 +- src/include/catalog/pg_collation.h | 26 +- src/include/catalog/pg_proc.h | 3 + src/include/catalog/pg_set.h | 2 +- src/include/catalog/pg_type.h | 4 +- .../rollback-post_catalog_maindb_92_903.sql | 20 + .../rollback-post_catalog_otherdb_92_903.sql | 20 + .../upgrade-post_catalog_maindb_92_903.sql | 37 + .../upgrade-post_catalog_otherdb_92_903.sql | 37 + src/include/commands/copy.h | 3 + src/include/commands/sqladvisor.h | 1 + src/include/commands/variable.h | 6 + src/include/executor/spi.h | 1 + src/include/fmgr.h | 3 +- .../knl/knl_guc/knl_session_attr_common.h | 2 + src/include/knl/knl_session.h | 2 + src/include/libpq/pqformat.h | 2 +- src/include/mb/pg_wchar.h | 31 +- src/include/miscadmin.h | 7 +- src/include/nodes/execExpr.h | 1 + src/include/nodes/execnodes.h | 7 + src/include/nodes/nodes.h | 4 +- src/include/nodes/parsenodes.h | 1 + src/include/nodes/parsenodes_common.h | 11 + src/include/parser/parse_coerce.h | 6 +- src/include/parser/parse_collate.h | 2 + src/include/parser/parse_type.h | 6 +- src/include/parser/parse_utilcmd.h | 4 +- src/include/rewrite/rewriteHandler.h | 2 +- src/include/utils/builtins.h | 4 + .../regress/expected/charset_gbk_b_db.out | 3616 +++++++++ .../regress/expected/charset_utf8mb4_b_db.out | 4775 ++++++++++++ src/test/regress/expected/hw_datatype_set.out | 1192 +++ .../expected/test_b_format_collate.out | 24 +- .../expected/test_b_format_gb_collate.out | 1065 +++ .../input/add_b_format_behavior_all.source | 165 + .../regress/input/charset_b_format.source | 23 +- .../input/charset_connection_test.source | 144 + .../output/add_b_format_behavior_all.source | 302 + .../regress/output/charset_b_format.source | 50 +- .../output/charset_connection_test.source | 487 ++ .../regress/output/recovery_2pc_tools.source | 2 + src/test/regress/parallel_schedule0 | 9 +- src/test/regress/sql/charset_gbk_b_db.sql | 999 +++ src/test/regress/sql/charset_utf8mb4_b_db.sql | 1414 ++++ src/test/regress/sql/hw_datatype_set.sql | 382 +- .../regress/sql/test_b_format_collate.sql | 8 +- .../regress/sql/test_b_format_gb_collate.sql | 240 + 117 files changed, 27264 insertions(+), 576 deletions(-) create mode 100644 src/common/backend/catalog/gs_collation.cpp create mode 100644 src/common/backend/catalog/gs_gb18030_collation.cpp create mode 100644 src/common/backend/catalog/gs_gbk_collation.cpp create mode 100644 src/include/catalog/gs_collation.h delete mode 100644 src/include/catalog/gs_utf8_collation.h create mode 100644 src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_903.sql create mode 100644 src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_903.sql create mode 100644 src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_903.sql create mode 100644 src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_903.sql create mode 100644 src/test/regress/expected/charset_gbk_b_db.out create mode 100644 src/test/regress/expected/charset_utf8mb4_b_db.out create mode 100644 src/test/regress/expected/test_b_format_gb_collate.out create mode 100644 src/test/regress/input/add_b_format_behavior_all.source create mode 100644 src/test/regress/input/charset_connection_test.source create mode 100644 src/test/regress/output/add_b_format_behavior_all.source create mode 100644 src/test/regress/output/charset_connection_test.source create mode 100644 src/test/regress/sql/charset_gbk_b_db.sql create mode 100644 src/test/regress/sql/charset_utf8mb4_b_db.sql create mode 100644 src/test/regress/sql/test_b_format_gb_collate.sql diff --git a/src/common/backend/catalog/Makefile b/src/common/backend/catalog/Makefile index 263dfe7fa..c38bf4a48 100644 --- a/src/common/backend/catalog/Makefile +++ b/src/common/backend/catalog/Makefile @@ -24,7 +24,8 @@ OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \ pg_type.o pgxc_class.o storage.o storage_gtt.o toasting.o pg_job.o pg_partition.o\ pg_hashbucket.o cstore_ctlg.o pg_builtin_proc.o streaming_stream.o\ gs_matview.o pgxc_slice.o pg_job_proc.o gs_job_argument.o gs_job_attribute.o pg_uid.o gs_global_config.o\ - gs_db_privilege.o pg_publication.o pg_subscription.o gs_utf8_collation.o + gs_db_privilege.o pg_publication.o pg_subscription.o gs_utf8_collation.o gs_collation.o gs_gbk_collation.o\ + gs_gb18030_collation.o BKIFILES = postgres.bki postgres.description postgres.shdescription diff --git a/src/common/backend/catalog/builtin_funcs.ini b/src/common/backend/catalog/builtin_funcs.ini index cd3ca9af3..a2396fd20 100755 --- a/src/common/backend/catalog/builtin_funcs.ini +++ b/src/common/backend/catalog/builtin_funcs.ini @@ -2009,7 +2009,7 @@ ), AddFuncGroup( "convert_to_nocase", 1, - AddBuiltinFunc(_0(3198), _1("convert_to_nocase"), _2(2), _3(true), _4(false), _5(pg_convert_to_nocase), _6(17), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 25, 19), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pg_convert_to_nocase"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(CONVERTTONOCASEFUNCOID), _1("convert_to_nocase"), _2(2), _3(true), _4(false), _5(pg_convert_to_nocase), _6(17), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 25, 19), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pg_convert_to_nocase"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "corr", 1, @@ -7702,7 +7702,7 @@ ), AddFuncGroup( "opengauss_version", 1, - AddBuiltinFunc(_0(90), _1("opengauss_version"), _2(0), _3(true), _4(false), _5(opengauss_version), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("opengauss_version"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(OPENGAUSSVERSIONFUNCOID), _1("opengauss_version"), _2(0), _3(true), _4(false), _5(opengauss_version), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("opengauss_version"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "ordered_set_transition", 1, @@ -12672,7 +12672,7 @@ AddFuncGroup( ), AddFuncGroup( "version", 1, - AddBuiltinFunc(_0(89), _1("version"), _2(0), _3(true), _4(false), _5(pgsql_version), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pgsql_version"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(VERSIONFUNCOID), _1("version"), _2(0), _3(true), _4(false), _5(pgsql_version), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pgsql_version"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( diff --git a/src/common/backend/catalog/gs_collation.cpp b/src/common/backend/catalog/gs_collation.cpp new file mode 100644 index 000000000..4485bdaec --- /dev/null +++ b/src/common/backend/catalog/gs_collation.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * + * gs_collation.cpp + * common interface for collations in b format + * + * IDENTIFICATION + * src/common/backend/catalog/gs_collation.cpp + * + * --------------------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "knl/knl_variable.h" + +#include "catalog/pg_collation.h" +#include "utils/builtins.h" +#include "utils/syscache.h" +#include "parser/parse_type.h" +#include "access/hash.h" +#include "utils/lsyscache.h" +#include "catalog/gs_collation.h" + +bool is_b_format_collation(Oid collation) +{ + if (COLLATION_IN_B_FORMAT(collation)) { +#ifdef ENABLE_MULTIPLE_NODES + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("this collation is not currently supported "))); +#endif + return true; + } + return false; +} + +bool is_support_b_format_collation(Oid collation) +{ + if (is_b_format_collation(collation) && !DB_IS_CMPT(B_FORMAT)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("this collation only support in B-format database"))); + } + return true; +} + +/* binary collation only support binary string types, such as : blob. */ +void check_binary_collation(Oid collation, Oid type_oid) +{ + if (collation == BINARY_COLLATION_OID && !DB_IS_CMPT(B_FORMAT)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("this collation only support in B-format database"))); + } + + if (IsBinaryType(type_oid) && collation != BINARY_COLLATION_OID) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("binary collation only support binary type in B format"))); + } +} + +Datum hash_text_by_builtin_collations(const unsigned char *key, int len, Oid collid) +{ + Datum result = 0; + switch (collid) { + case UTF8MB4_GENERAL_CI_COLLATION_OID: + case UTF8MB4_UNICODE_CI_COLLATION_OID: + case UTF8_GENERAL_CI_COLLATION_OID: + case UTF8_UNICODE_CI_COLLATION_OID: + result = hash_utf8mb4_general_pad_space((unsigned char*)key, len); + break; + case GBK_CHINESE_CI_COLLATION_OID: + result = hash_gbk_chinese_pad_space((unsigned char*)key, len); + break; + case GB18030_CHINESE_CI_COLLATION_OID: + result = hash_gb18030_chinese_pad_space((unsigned char*)key, len); + break; + case UTF8MB4_BIN_COLLATION_OID: + case UTF8_BIN_COLLATION_OID: + case GBK_BIN_COLLATION_OID: + case GB18030_BIN_COLLATION_OID: + result = hash_mb_bin_pad_space((unsigned char*)key, len); + break; + default: + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("this collation is not currently supported "))); + break; + } + + return result; +} + +int varstr_cmp_by_builtin_collations(const char* arg1, int len1, const char* arg2, int len2, Oid collid) +{ + int result = 0; + switch (collid) { + case UTF8MB4_GENERAL_CI_COLLATION_OID: + case UTF8MB4_UNICODE_CI_COLLATION_OID: + case UTF8_GENERAL_CI_COLLATION_OID: + case UTF8_UNICODE_CI_COLLATION_OID: + result = strnncoll_utf8mb4_general_pad_space((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); + break; + case BINARY_COLLATION_OID: + result = strnncoll_binary((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); + break; + case GBK_CHINESE_CI_COLLATION_OID: + result = strnncoll_gbk_chinese_ci_pad_space((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); + break; + case GB18030_CHINESE_CI_COLLATION_OID: + result = strnncoll_gb18030_chinese_ci_pad_space((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); + break; + case UTF8MB4_BIN_COLLATION_OID: + case UTF8_BIN_COLLATION_OID: + case GBK_BIN_COLLATION_OID: + case GB18030_BIN_COLLATION_OID: + result = strnncoll_mb_bin_pad_space((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); + break; + default: + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("this collation is not currently supported "))); + break; + } + + return result; +} + +int match_text_by_builtin_collations(unsigned char* t, int tlen, unsigned char* p, int plen, Oid collation) +{ + int result = 0; + switch (collation) { + case UTF8MB4_GENERAL_CI_COLLATION_OID: + case UTF8MB4_UNICODE_CI_COLLATION_OID: + case UTF8_GENERAL_CI_COLLATION_OID: + case UTF8_UNICODE_CI_COLLATION_OID: + result = matchtext_utf8mb4((unsigned char*)t, tlen, (unsigned char*)p, plen); + break; + case BINARY_COLLATION_OID: + result = matchtext_general((unsigned char*)t, tlen, (unsigned char*)p, plen); + break; + case GBK_CHINESE_CI_COLLATION_OID: + result = matchtext_gbk_chinese((unsigned char*)t, tlen, (unsigned char*)p, plen); + break; + case GB18030_CHINESE_CI_COLLATION_OID: + result = matchtext_gb18030((unsigned char*)t, tlen, (unsigned char*)p, plen); + break; + case UTF8MB4_BIN_COLLATION_OID: + case UTF8_BIN_COLLATION_OID: + case GBK_BIN_COLLATION_OID: + case GB18030_BIN_COLLATION_OID: + result = matchtext_general((unsigned char*)t, tlen, (unsigned char*)p, plen); + break; + default: + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("this collation is not currently supported "))); + break; + } + return result; +} + +int compare_tail_space(const unsigned char* str_value, int end_space_num, int res) +{ + while(end_space_num > 0){ + if (*str_value++ != ' ') { + return (str_value[-1] < ' ') ? -res : res; + } + end_space_num--; + } + + return 0; +} + +/* bin collation for multibyte charset */ +int strnncoll_mb_bin_pad_space(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2) +{ + int min_length = Min(len1, len2); + + while (min_length > 0){ + if (*arg1++ != *arg2++) { + return ((int)arg1[-1] - (int)arg2[-1]); + } + min_length--; + } + + int res = len1 > len2 ? compare_tail_space(arg1, len1 - len2, 1) : + compare_tail_space(arg2, len2 - len1, -1); + + return res; +} + +Datum hash_mb_bin_pad_space(const unsigned char *key, size_t len) +{ + return hash_any(key, bpchartruelen((char*)key, len)); +} + +int matchtext_general(unsigned char* s, int slen, unsigned char* p, int plen) +{ + return GenericMatchText((char*)s, slen, (char*)p, plen); +} \ No newline at end of file diff --git a/src/common/backend/catalog/gs_gb18030_collation.cpp b/src/common/backend/catalog/gs_gb18030_collation.cpp new file mode 100644 index 000000000..209b24f91 --- /dev/null +++ b/src/common/backend/catalog/gs_gb18030_collation.cpp @@ -0,0 +1,6881 @@ +#include "postgres.h" +#include "knl/knl_variable.h" + +#include "catalog/pg_collation.h" +#include "utils/builtins.h" +#include "utils/syscache.h" +#include "parser/parse_type.h" +#include "catalog/gs_collation.h" +#include "access/hash.h" + +typedef struct GS_UNICASE_CHARACTER { + GS_UINT32 upper; + GS_UINT32 lower; + GS_UINT32 sort; +} GS_UNICASE_CHARACTER; + +typedef struct GS_UNICASE_PAGES { + const GS_UNICASE_CHARACTER **uni_page; +} GS_UNICASE_PAGES; + +/* if gb1803 code length greater than 1,the first or third byte is between 0x81 and 0xFE */ +#define is_gb18030_code_odd(ch) (0x81 <= (GS_UCHAR)(ch) && (GS_UCHAR)(ch) <= 0xFE) + +/* if gb1803 code length is 1, the first byte is between 0x00 and 0x7F */ +#define is_gb18030_mblen_1(ch) (0x00 <= (GS_UCHAR)(ch) && (GS_UCHAR)(ch) <= 0x7F) + +/* if gb1803 code length is 2, the second byte is between 0x40 and 0xFE , excluding 0x7F */ +#define is_gb18030_mblen_2(ch) ((0x40 <= (GS_UCHAR)(ch) && (GS_UCHAR)(ch) <= 0xFE) && (GS_UCHAR)(ch) != 0x7F) + +/* if gb1803 code length is 4, the second byte and the four byte is between 0x30 and 0x39 */ +#define is_gb18030_mblen_4(ch) (0x30 <= (GS_UCHAR)(ch) && (GS_UCHAR)(ch) <= 0x39) + +#define ERROR_INPUT_GB18030 -1; + +/* 2 bytes chinese characters code */ +static const uint PINYIN_2_BYTE_START = 0x8140; +static const uint PINYIN_2_BYTE_END = 0xFE9F; + +/* part 1, 4 bytes chinese characters code */ +static const uint PINYIN_4_BYTE_1_START = 0x8138FD38; +static const uint PINYIN_4_BYTE_1_END = 0x82359232; +static const uint PINYIN_4_1_DIFF = 11328; + +/* part 2, 4 bytes chinese characters code */ +static const uint PINYIN_4_BYTE_2_START = 0x95328236; +static const uint PINYIN_4_BYTE_2_END = 0x98399836; +static const uint PINYIN_4_2_DIFF = 254536; + +static const uint PINYIN_WEIGHT_BASE = 0xFFA00000; +static const uint COMMON_WEIGHT_BASE = 0xFF000000; + +/* min value of the first and third bytes in gb18030 code */ +static const uint MB_MIN_ODD_BYTE = 0x81; + +/* min value of the second and forth bytes in gb18030 code */ +static const uint MB_MIN_EVEN_BYTE_2 = 0x40; +static const uint MB_MIN_EVEN_BYTE_4 = 0x30; +static const uint MAX_GB18030_DIFF = 0x18398F; + +static const uint UNICASE_4_BYTE_OFFSET = 0x80; + +static const uint MIN_2_BYTE_UNICASE = 0xA000; +static const uint MAX_2_BYTE_UNICASE = 0xDFFF; + +static const uint MIN_3_BYTE_FROM_UNI = 0x2E600; +static const uint MAX_3_BYTE_FROM_UNI = 0x2E6FF; + +static GS_UCHAR one_bytes_gb18030_sort_order[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF +}; + +static const uint16 gb18030_2_weight_py[] = { + 15308, 26403, 32018, 10022, 20221, 3853, 26996, 6117, 24523, 17600, 36813, 1796, 14235, 12424, 13777, 9402, + 2763, 40603, 9858, 14080, 7905, 35363, 35610, 31400, 14287, 35292, 36111, 11015, 3298, 36190, 34284, 8336, + 14288, 32020, 11032, 6317, 26965, 21034, 12685, 14582, 26905, 19601, 10824, 40703, 33915, 34465, 8093, 26086, + 20856, 8385, 28328, 36968, 4806, 39018, 39657, 9512, 8396, 19021, 17937, 35820, 14815, 19318, 27011, 36944, + 27705, 28174, 8788, 34234, 23228, 34238, 28437, 35289, 32493, 14027, 35178, 36898, 5148, 17412, 6746, 19824, + 12251, 12677, 30443, 390, 1744, 7812, 25865, 1745, 32053, 30025, 10612, 8417, 1875, 3032, 2888, 26413, + 25300, 12799, 3033, 23732, 31078, 35007, 7689, 2319, 30446, 5510, 39874, 22268, 36947, 5891, 6633, 31310, + 35627, 33157, 12254, 67, 13926, 22418, 5132, 7834, 28854, 4747, 4087, 3046, 32312, 34098, 33161, 38316, + 32145, 21796, 21264, 32938, 33589, 40060, 24677, 999, 22419, 35641, 27710, 35547, 39233, 9928, 19345, 40270, + 2093, 24678, 1114, 38824, 4422, 34815, 38692, 1160, 32059, 24761, 27141, 836, 11661, 10459, 32470, 8674, + 7190, 20501, 1797, 10524, 11958, 9570, 24923, 4440, 33251, 26579, 30035, 8302, 16241, 35382, 9450, 36052, + 20077, 33597, 140, 18699, 7066, 19055, 2584, 3402, 34101, 39979, 25542, 4817, 27715, 38038, 28542, 21673, + 13890, 14207, 3378, 39183, 41281, 3859, 18877, 14460, 27346, 29530, 26697, 29946, 1888, 20980, 32580, 29935, + 37138, 31785, 33547, 9484, 15682, 31258, 35693, 8099, 17572, 11918, 14121, 23841, 25892, 22266, 31436, 8100, + 31944, 33371, 5650, 3048, 39870, 16242, 27774, 11989, 32748, 13106, 1606, 3984, 7498, 34245, 892, 37237, + 33118, 11019, 2865, 39391, 1800, 14322, 34927, 4752, 17397, 30330, 16243, 2324, 40974, 8769, 29294, 27227, + 19842, 28650, 4193, 33295, 22346, 23147, 8458, 14127, 28121, 13647, 7399, 39458, 40890, 19058, 27784, 16841, + 11919, 6133, 40859, 981, 31260, 14609, 20943, 2192, 12988, 35117, 26144, 24201, 36306, 3251, 12864, 25646, + 39954, 4283, 30676, 37153, 1804, 29069, 34605, 7709, 28857, 31088, 6915, 3060, 26776, 15205, 5660, 2503, + 899, 32964, 11480, 35028, 38698, 3861, 34294, 36756, 33565, 38377, 4353, 8174, 1080, 39658, 20235, 12296, + 35570, 32965, 34050, 2170, 6474, 2413, 39078, 29675, 900, 37977, 13654, 30677, 27914, 39690, 27992, 31923, + 37642, 25474, 21810, 37910, 13267, 19294, 5732, 28791, 10270, 13665, 31492, 26308, 23848, 14880, 2326, 3998, + 25868, 910, 32756, 36634, 34937, 28747, 28298, 34830, 7157, 1806, 12717, 38043, 9244, 2230, 16740, 36548, + 38154, 40955, 1018, 27823, 4095, 37171, 38561, 41057, 26371, 4167, 14150, 10086, 38748, 24358, 34624, 5683, + 32990, 18505, 912, 22744, 13898, 17528, 18736, 19379, 23669, 32093, 28750, 36413, 6207, 40425, 26313, 24049, + 14225, 29940, 41219, 23073, 16559, 2936, 9462, 23170, 3260, 2692, 30711, 12159, 1857, 11768, 4114, 29438, + 5197, 13449, 7664, 32371, 14494, 6966, 17963, 1938, 9233, 32428, 32372, 20448, 35207, 13977, 12839, 24105, + 7728, 40097, 96, 25844, 35489, 15081, 21727, 2699, 35875, 5310, 15768, 13028, 4020, 13456, 26138, 38048, + 2316, 1704, 185, 28574, 3820, 2629, 16345, 21283, 13914, 23864, 19866, 31291, 21644, 24493, 21284, 2916, + 17815, 18908, 15848, 822, 37378, 1557, 38076, 39503, 27769, 36698, 10228, 3225, 3227, 17246, 29023, 30738, + 18461, 3959, 2720, 25200, 27273, 11844, 17313, 19124, 38080, 21863, 28868, 34569, 16714, 21054, 38053, 33319, + 6551, 6552, 29838, 2890, 7065, 7067, 13846, 34472, 26974, 0, 23649, 7572, 19563, 26609, 6229, 0, + 17047, 11541, 30444, 21183, 17604, 36970, 10145, 29227, 7568, 12554, 35821, 19615, 25171, 37528, 19598, 2403, + 14185, 9284, 14200, 19620, 40068, 9040, 33561, 36109, 15198, 35373, 19994, 27028, 19847, 14611, 15599, 17874, + 8176, 32930, 20155, 28550, 8488, 11044, 22093, 7913, 20422, 23584, 12852, 27347, 19750, 29765, 9217, 14128, + 24418, 6198, 8459, 36067, 35449, 17155, 4180, 20506, 40564, 4710, 27647, 6702, 13978, 17940, 31579, 6367, + 7229, 7230, 14373, 3945, 39357, 7690, 20833, 39869, 7691, 7696, 15145, 8397, 22878, 15749, 9965, 25297, + 4133, 12085, 23837, 4822, 12089, 5134, 30299, 14823, 16847, 7914, 24880, 14374, 20423, 17997, 39877, 1644, + 13618, 13619, 26205, 2759, 8796, 4177, 15897, 6757, 7135, 13627, 4442, 14090, 18494, 19155, 38233, 37478, + 4870, 15425, 26088, 4178, 4872, 16853, 7499, 2768, 23246, 4179, 40860, 8502, 1837, 6673, 24377, 6323, + 13109, 12513, 34289, 11946, 6690, 6475, 31153, 9292, 26797, 13114, 4938, 15146, 4181, 4081, 2782, 29863, + 18737, 16879, 22405, 26228, 15582, 9267, 11220, 38387, 40699, 17429, 14650, 18240, 9647, 13457, 9648, 13144, + 13145, 28772, 12601, 13158, 13159, 39808, 2721, 13072, 20556, 16996, 40262, 34225, 13927, 15504, 32818, 39529, + 35643, 40128, 20576, 16544, 14751, 15591, 34755, 30179, 32746, 20705, 15810, 13629, 17765, 15426, 13936, 8603, + 20428, 3578, 16464, 36621, 15427, 14754, 24378, 18708, 2110, 3586, 15171, 20237, 6201, 33629, 31403, 35752, + 33996, 31013, 26802, 16555, 18738, 22745, 27083, 12145, 13303, 2982, 25018, 32543, 35854, 14907, 7209, 14717, + 29619, 14651, 5115, 19356, 34002, 34004, 18945, 17208, 3111, 25201, 25022, 37819, 14241, 790, 30908, 1391, + 8337, 8338, 36037, 22312, 14376, 28930, 8675, 6908, 8900, 4939, 14327, 24441, 21109, 14307, 35366, 13288, + 15292, 10825, 24679, 1460, 24142, 38120, 15813, 10842, 37155, 9591, 11753, 5109, 9646, 17421, 17430, 28106, + 6369, 14362, 14973, 31770, 15338, 34473, 24700, 34096, 21418, 41041, 27005, 31771, 30389, 30390, 32824, 5088, + 12297, 27454, 15850, 31426, 32955, 13608, 248, 24442, 26466, 3518, 33599, 25043, 31327, 12278, 6917, 31516, + 25907, 30656, 38918, 10023, 34211, 5605, 38456, 22136, 34182, 10334, 34187, 39617, 22139, 29064, 26524, 29466, + 41140, 7500, 2414, 37551, 17158, 5733, 13899, 291, 9608, 34632, 17171, 2937, 16341, 17187, 34408, 34555, + 37614, 8872, 17870, 25503, 24877, 7102, 16728, 6319, 40375, 2223, 2224, 2227, 90, 5059, 27155, 9330, + 430, 25736, 27012, 40597, 12802, 27910, 8604, 30784, 25713, 4574, 9285, 24567, 3513, 17710, 10568, 20319, + 19474, 33724, 40812, 4825, 35152, 21946, 11945, 35297, 3854, 24319, 13780, 2094, 6820, 10616, 31184, 21164, + 33950, 6223, 10569, 8601, 15050, 18875, 8672, 19687, 23401, 31187, 13504, 10570, 3516, 26733, 29964, 30989, + 6893, 26828, 14729, 22307, 30951, 19245, 25136, 5610, 27019, 40061, 29447, 31778, 35668, 23457, 22842, 40826, + 33557, 35669, 32577, 4925, 24881, 9962, 30036, 23030, 1646, 7920, 34722, 10335, 9862, 4896, 30217, 41308, + 2096, 28543, 32316, 11986, 23464, 7136, 6898, 31786, 40069, 27348, 32747, 15722, 11270, 28932, 6899, 33825, + 9736, 16592, 29584, 33326, 36879, 6040, 21434, 33313, 7566, 10258, 37543, 18475, 23031, 19492, 41047, 10357, + 32333, 16548, 1839, 17622, 411, 20321, 17777, 28122, 7957, 10056, 27572, 36891, 9086, 9144, 956, 9974, + 35726, 12759, 29731, 32153, 30331, 17122, 24594, 3050, 38199, 34214, 6226, 23410, 5552, 24326, 20599, 8969, + 6259, 24886, 17606, 16539, 26091, 41268, 31042, 13950, 23483, 7079, 23979, 191, 38235, 21423, 36930, 29299, + 16290, 31468, 30, 21770, 40611, 5661, 10533, 2193, 32438, 29967, 31263, 30979, 26146, 9149, 23414, 23415, + 5179, 35187, 40840, 1132, 4761, 10369, 34216, 23418, 38948, 17607, 32172, 36309, 9303, 39019, 9851, 19096, + 34296, 5662, 24937, 2770, 14470, 28793, 182, 5187, 37269, 38956, 40001, 2623, 30249, 37248, 37980, 34897, + 20240, 10921, 37876, 11405, 11406, 12129, 39927, 30595, 26153, 33638, 11485, 6693, 21523, 17626, 37270, 25935, + 3415, 24048, 34613, 5102, 22309, 2228, 36541, 30526, 36401, 2076, 31810, 13666, 38209, 11089, 29086, 34946, + 10469, 23903, 26007, 36549, 10707, 32857, 19320, 2507, 9910, 25612, 30190, 12146, 22158, 31159, 23816, 40729, + 19206, 30234, 0, 28344, 39480, 25841, 8773, 20850, 23985, 1249, 294, 17414, 41146, 38912, 20626, 28724, + 13525, 3688, 13357, 15147, 28752, 26236, 35, 32627, 18581, 32628, 10865, 11769, 9750, 21953, 32094, 38252, + 2906, 22935, 5422, 19301, 10940, 8289, 28770, 35159, 25848, 13526, 32766, 11145, 19339, 25152, 16562, 32770, + 12168, 16004, 32639, 10222, 8127, 24052, 4021, 2792, 5202, 34128, 6875, 41221, 7210, 3430, 11633, 38073, + 4154, 4649, 5198, 37341, 29970, 31560, 23519, 10216, 17431, 33509, 11636, 36166, 34071, 21549, 27655, 34538, + 36516, 4911, 38602, 40103, 21730, 11795, 33018, 13537, 37656, 26, 36566, 15772, 37189, 22298, 5396, 10567, + 6613, 5249, 33202, 22585, 36103, 41168, 21648, 5579, 16444, 28413, 11951, 32036, 35241, 6684, 22623, 3824, + 12616, 13995, 2917, 34145, 19683, 29212, 18674, 11826, 1988, 36701, 21571, 36175, 11115, 19685, 10601, 38996, + 16950, 18265, 9927, 21035, 20545, 34675, 17268, 18612, 18397, 20550, 5230, 3229, 22799, 22590, 32558, 20551, + 31887, 6753, 15705, 34420, 2727, 36364, 5784, 16239, 28523, 32678, 4338, 11294, 12062, 40447, 21589, 32679, + 2167, 16978, 2827, 2644, 17328, 36000, 19099, 37998, 27959, 31762, 38335, 12967, 37999, 40263, 16387, 21601, + 16433, 18354, 11657, 36046, 21617, 29859, 15294, 37475, 14202, 22646, 37822, 4475, 11660, 6821, 9771, 29559, + 29762, 9773, 25112, 25376, 9774, 28544, 9777, 36129, 11920, 9975, 19061, 9779, 4093, 30596, 37552, 24909, + 15648, 8197, 37562, 37563, 34270, 29787, 29802, 29803, 29864, 19036, 11782, 35905, 18981, 18999, 34227, 29833, + 29525, 23104, 18694, 15784, 34147, 37215, 23625, 23626, 40589, 5289, 23583, 32049, 26363, 21497, 20577, 12748, + 39535, 33991, 35645, 24291, 19688, 25465, 29982, 978, 1164, 14085, 5641, 14019, 12478, 5606, 14020, 625, + 28766, 24685, 39370, 9300, 28554, 14187, 34816, 7813, 18700, 24526, 9033, 33952, 433, 18000, 40277, 8152, + 10829, 39618, 355, 5015, 22180, 20465, 12495, 10461, 18919, 4372, 3521, 36053, 10801, 6522, 38862, 7940, + 9454, 34922, 6717, 9576, 2533, 34759, 32827, 27167, 1824, 10630, 4988, 15120, 5293, 10191, 188, 33206, + 32334, 653, 7853, 471, 35728, 36257, 10057, 33616, 4194, 24241, 1035, 7381, 25044, 36624, 15056, 12703, + 5653, 16522, 14732, 13854, 38936, 17779, 11244, 2112, 14189, 35156, 5623, 34164, 24938, 28186, 24352, 30335, + 14620, 19082, 39241, 15543, 3740, 6135, 28745, 2209, 3991, 1036, 15207, 6722, 35753, 39463, 40558, 23260, + 14621, 21226, 15440, 16040, 21323, 12865, 8507, 37251, 6918, 9220, 16842, 7413, 34194, 16110, 219, 26725, + 21113, 29742, 3325, 11893, 1226, 17529, 9742, 40418, 766, 37002, 19569, 13574, 25630, 35190, 8855, 40896, + 37003, 11486, 6934, 34939, 806, 4379, 19707, 2934, 30094, 36264, 7763, 39956, 13812, 13858, 10564, 8515, + 4227, 12999, 22902, 16821, 32537, 11465, 6496, 30279, 33737, 12543, 12325, 15762, 36414, 36641, 15150, 28000, + 26935, 20135, 31015, 3340, 29788, 25060, 39930, 17173, 39931, 699, 38147, 6528, 29268, 31356, 39336, 33998, + 39200, 82, 8904, 34387, 15213, 30887, 32991, 18329, 9926, 16513, 2907, 22356, 1060, 3181, 18748, 18659, + 21918, 23857, 19723, 20627, 40385, 27498, 18548, 1539, 2432, 39741, 38752, 15237, 5815, 3204, 39486, 31830, + 9746, 23971, 13969, 5693, 4713, 34633, 28424, 38337, 23766, 30881, 40525, 24012, 26317, 26318, 455, 23076, + 15769, 6169, 7256, 25076, 6609, 41205, 5694, 26809, 6788, 6791, 28670, 5488, 20748, 7618, 11500, 28671, + 4991, 35197, 40361, 13213, 370, 23951, 24017, 15493, 35906, 22541, 5822, 13244, 35162, 33931, 28678, 16412, + 14660, 11274, 5319, 25217, 23872, 34007, 32396, 31755, 99, 34176, 5367, 25637, 14017, 16753, 15875, 18613, + 34421, 28696, 30748, 11276, 18463, 18464, 25718, 17269, 17919, 2862, 34018, 34438, 16715, 493, 30291, 25905, + 40471, 35299, 19346, 40285, 40475, 10912, 16083, 10922, 33640, 16089, 27191, 19530, 41206, 27192, 35337, 9127, + 13289, 7758, 38572, 1474, 28115, 25111, 18001, 4874, 33357, 33104, 21094, 32045, 37628, 19600, 6668, 24374, + 30263, 9042, 23492, 19970, 19972, 3206, 38296, 9329, 8573, 28885, 28590, 34458, 1112, 11198, 37867, 12688, + 396, 7047, 5513, 22207, 14750, 32828, 5764, 34876, 11388, 15123, 38372, 972, 11560, 7464, 5856, 34115, + 1008, 360, 31014, 9857, 31357, 362, 13270, 17422, 6701, 37807, 13271, 27106, 7667, 12027, 1347, 18982, + 6755, 6068, 23627, 14289, 21831, 2580, 32056, 7309, 12429, 10614, 5082, 7837, 14116, 9898, 30974, 39879, + 21976, 15508, 39945, 37823, 7823, 3666, 37693, 40453, 34589, 20867, 33108, 7593, 7692, 30393, 6429, 434, + 40598, 38827, 20940, 37631, 29700, 32149, 39454, 6808, 20579, 1173, 26581, 6809, 10338, 33558, 7164, 39234, + 20372, 627, 7839, 18002, 40817, 25174, 26208, 34723, 19374, 40710, 14587, 25322, 6188, 12280, 8307, 32526, + 11157, 14701, 9038, 12858, 12859, 21422, 39457, 12108, 32325, 10539, 9455, 15024, 15712, 34594, 20502, 17768, + 22277, 6903, 36881, 34359, 26588, 26919, 9577, 24927, 27780, 10631, 32335, 26472, 3300, 32957, 19493, 7854, + 19698, 15434, 4311, 4312, 29532, 33261, 20983, 36982, 23012, 21172, 39639, 9976, 40456, 22788, 29948, 32336, + 31191, 34360, 31265, 15, 34366, 36983, 27725, 17391, 14398, 40512, 23153, 32160, 40612, 6136, 18714, 50, + 6811, 18499, 20191, 4552, 23032, 14471, 2171, 18031, 32600, 27283, 23416, 11608, 7328, 31065, 25676, 28653, + 7420, 7554, 29232, 21227, 24940, 14124, 14034, 23657, 5798, 33299, 11077, 30276, 16249, 36078, 3764, 21143, + 8178, 19062, 220, 16041, 36137, 34249, 14399, 17140, 5769, 32161, 11245, 11209, 5298, 35030, 21028, 4313, + 12810, 29676, 37272, 30597, 5674, 25508, 19755, 5103, 25649, 24214, 11609, 31093, 23754, 4228, 20282, 8182, + 13771, 6476, 35466, 39957, 11487, 20193, 152, 36311, 33738, 13575, 30529, 39265, 24535, 27069, 32980, 30142, + 17531, 19644, 25186, 27635, 22649, 30791, 30188, 14330, 10923, 24202, 767, 33481, 29677, 9522, 3909, 34947, + 37565, 25400, 25613, 18227, 19759, 22062, 340, 19248, 15995, 24256, 39087, 37566, 13576, 25408, 20482, 36321, + 28004, 21454, 28903, 22144, 16473, 21118, 741, 22608, 35856, 37317, 33804, 19372, 35328, 15260, 36556, 21332, + 9532, 13902, 40386, 38253, 9942, 16620, 38913, 11095, 11096, 363, 21199, 19323, 22770, 9109, 31280, 24053, + 30148, 38664, 19576, 32188, 32189, 20645, 17666, 17432, 11228, 9538, 5459, 39494, 33511, 35333, 11214, 31561, + 16005, 25236, 34640, 2700, 13362, 19763, 7348, 7211, 32106, 35907, 11797, 13538, 8233, 27116, 28205, 23952, + 17508, 11338, 33142, 21461, 6170, 35908, 2232, 100, 21436, 21649, 19250, 29415, 3825, 13996, 4404, 37071, + 22795, 25439, 25575, 20948, 34329, 28579, 36350, 2267, 37749, 20203, 1395, 26688, 33311, 21354, 6372, 18320, + 37518, 16420, 34676, 18118, 13491, 21437, 16422, 23714, 36365, 27479, 11848, 24979, 20101, 16988, 18983, 34439, + 40224, 16428, 14818, 19247, 33165, 27718, 28545, 36917, 40401, 28264, 20322, 4553, 23658, 34165, 21279, 40743, + 16904, 33932, 2043, 20932, 21576, 36366, 18984, 25463, 24444, 29724, 25538, 35009, 35375, 14086, 40548, 40236, + 10624, 26914, 35420, 29404, 26975, 3301, 25121, 8893, 32586, 38493, 760, 26664, 11558, 20120, 15600, 2194, + 38067, 37485, 24353, 25050, 39083, 13124, 21634, 1807, 11322, 24299, 26931, 21635, 13960, 21637, 39720, 37172, + 769, 15787, 21638, 14640, 24305, 10866, 26941, 21640, 26676, 30718, 32932, 15788, 11783, 15089, 35936, 35509, + 782, 24229, 3747, 784, 7742, 18917, 6555, 22949, 40378, 7855, 15435, 13230, 40381, 34054, 27369, 6570, + 5364, 13610, 7103, 7104, 27213, 26405, 20698, 17741, 32264, 32265, 16111, 30430, 17735, 19480, 30435, 30432, + 30433, 34918, 6763, 15990, 39928, 8398, 9156, 29914, 8411, 8412, 31774, 1078, 13791, 29248, 5885, 26833, + 39139, 32959, 21221, 31453, 30671, 19418, 18563, 22860, 29223, 7506, 32981, 18899, 2474, 33019, 14674, 14813, + 17688, 14963, 27332, 31901, 21306, 30244, 32054, 17076, 6883, 5418, 11860, 18356, 25304, 31311, 10048, 26574, + 3881, 25305, 37694, 604, 35010, 249, 31315, 13623, 6886, 7594, 30306, 23733, 23225, 13784, 41278, 41279, + 34817, 14588, 8494, 33917, 22909, 17093, 29367, 24688, 7922, 30070, 22489, 356, 15856, 24689, 22963, 29368, + 18003, 3459, 22901, 10054, 33432, 29578, 33918, 1521, 10345, 406, 19187, 6904, 8161, 5942, 18703, 7055, + 7070, 8308, 24902, 35402, 20759, 26920, 141, 30580, 11313, 20118, 17025, 12498, 29585, 30581, 36883, 9242, + 17026, 34924, 13336, 6827, 32829, 2055, 25114, 7705, 21073, 17029, 36746, 32337, 10644, 5353, 26596, 3302, + 29767, 8827, 10259, 31952, 36131, 37149, 16523, 15236, 32249, 25045, 3721, 28451, 17878, 11205, 14402, 16250, + 20386, 16042, 16043, 41050, 9221, 34195, 8527, 19063, 19064, 16826, 6676, 39254, 36139, 6137, 9981, 39255, + 30678, 22511, 13657, 41051, 15646, 6138, 36140, 40885, 38311, 11488, 37004, 34777, 7717, 24622, 34778, 29072, + 35574, 39695, 27070, 6936, 40313, 15190, 18926, 34493, 19756, 9991, 12132, 11407, 29496, 31348, 37005, 40898, + 16333, 15410, 34377, 34378, 30686, 40899, 2544, 28190, 15479, 24215, 29225, 29789, 6530, 31521, 31017, 2328, + 5302, 25409, 13680, 15151, 18228, 31358, 23998, 1019, 5734, 23817, 36642, 21535, 4846, 27147, 25758, 27828, + 40912, 13306, 17657, 15262, 2787, 5988, 2450, 6076, 29748, 18550, 38655, 38656, 295, 2366, 24719, 23908, + 4715, 41159, 5361, 5362, 31688, 37318, 22291, 18381, 32546, 2475, 1859, 24222, 13363, 34531, 16565, 38714, + 17668, 17669, 13864, 6789, 41207, 13533, 9649, 34970, 13364, 34971, 14919, 38603, 35909, 33933, 21087, 35228, + 35229, 35501, 21560, 32277, 12353, 33030, 15415, 31564, 5709, 371, 41166, 30884, 25440, 5368, 18186, 37990, + 37190, 37753, 36230, 25628, 13738, 17230, 9548, 18399, 18400, 25451, 31637, 14531, 2728, 36497, 15914, 34423, + 21098, 24980, 3030, 4690, 18985, 5754, 5755, 21616, 34441, 34440, 34576, 15966, 34577, 15748, 11448, 14021, + 2992, 17811, 14585, 23135, 23136, 24641, 39365, 38828, 35422, 13892, 34102, 14752, 412, 7907, 37951, 6051, + 21494, 7559, 22002, 39536, 11050, 5170, 5017, 20580, 1830, 20591, 35697, 35698, 22849, 23588, 14730, 25545, + 27442, 27530, 24092, 39067, 26840, 25122, 5032, 9506, 22861, 38806, 25893, 30277, 5038, 26148, 23265, 6411, + 10752, 39334, 33482, 30599, 35787, 663, 22866, 6045, 8905, 22063, 28905, 20138, 12837, 29008, 11624, 39904, + 26237, 1540, 9785, 38254, 20811, 666, 14100, 2793, 39763, 10874, 1273, 1393, 38820, 20162, 24018, 2668, + 7619, 19876, 671, 3826, 20343, 3932, 13721, 32287, 16369, 12848, 1798, 8467, 12447, 29458, 38298, 9474, + 20696, 24233, 6636, 34212, 536, 13787, 40490, 34152, 4444, 29580, 35559, 39628, 29351, 39629, 32590, 29768, + 9587, 15684, 19495, 36827, 2056, 1799, 3383, 16251, 12299, 27787, 27362, 24403, 37275, 20314, 27862, 2419, + 32441, 7509, 14332, 6954, 9523, 18330, 26155, 27863, 39721, 23035, 24406, 14343, 14333, 18512, 36271, 5055, + 18750, 35857, 3922, 29804, 27657, 33138, 20316, 2938, 31281, 7522, 9476, 15699, 15774, 1316, 23953, 17942, + 17689, 18615, 12681, 36498, 32125, 29482, 36588, 16990, 29484, 34025, 5545, 22026, 11662, 20941, 11665, 7651, + 14546, 34475, 38144, 35293, 7132, 25852, 7133, 27085, 5890, 11035, 31138, 29902, 13290, 468, 26658, 14830, + 28888, 8096, 5612, 2972, 39135, 35423, 24903, 26415, 33731, 14130, 5857, 38746, 13295, 23940, 22349, 1227, + 26532, 5188, 13013, 8775, 7160, 1250, 15584, 13212, 1676, 32650, 5203, 9751, 13308, 10691, 20028, 9762, + 30290, 14987, 12469, 18701, 11757, 11758, 35502, 35503, 35521, 37679, 37681, 30910, 34595, 37240, 3406, 5858, + 36643, 22732, 3448, 40590, 30134, 12260, 39881, 30447, 5515, 18005, 7925, 30462, 31439, 30465, 3379, 39641, + 14131, 4551, 39871, 4555, 6144, 12531, 39662, 4556, 39992, 16252, 32967, 13806, 13116, 27073, 12811, 1484, + 8184, 30687, 22146, 31524, 39272, 22747, 29105, 5438, 39279, 1658, 3690, 3096, 13459, 11798, 19735, 18486, + 32457, 829, 24831, 16646, 25266, 6087, 8324, 25269, 8368, 23445, 27007, 31415, 7233, 36304, 20374, 30949, + 31323, 12261, 31779, 12749, 30394, 4481, 37224, 23226, 4748, 28591, 29983, 23735, 11887, 33322, 15835, 32060, + 15250, 14589, 35674, 755, 20375, 22232, 14597, 628, 21066, 29429, 11064, 14598, 3783, 5648, 29728, 36739, + 7844, 31780, 1177, 36683, 33847, 4484, 1761, 11553, 33600, 1178, 27350, 31440, 28619, 36673, 20697, 39545, + 27033, 31792, 16594, 10540, 15815, 20707, 39551, 32832, 29353, 5944, 10260, 9578, 31441, 13415, 27775, 10837, + 24530, 11666, 3581, 35405, 33327, 9334, 17958, 3525, 26407, 24904, 37702, 22316, 5426, 11733, 32793, 19488, + 36625, 37482, 22441, 37706, 37254, 29770, 13804, 38949, 17959, 10261, 24148, 29173, 2113, 23845, 31454, 19375, + 35314, 10532, 3380, 31336, 16859, 17623, 4486, 35757, 17124, 21107, 6919, 31338, 4557, 6694, 2953, 19833, + 25895, 9412, 9407, 23155, 15546, 29302, 19065, 31493, 15209, 9696, 21328, 6604, 9819, 38586, 37493, 13857, + 12544, 16331, 37256, 10387, 24941, 28654, 29178, 21515, 4314, 11872, 33125, 6938, 28339, 40951, 12866, 36635, + 5431, 21116, 37913, 5969, 4287, 24465, 2420, 1439, 20438, 40901, 29073, 920, 33740, 30531, 8693, 30688, + 1229, 33741, 11408, 20242, 36636, 15172, 5299, 36080, 3171, 19653, 23604, 15452, 84, 24160, 34495, 21883, + 40952, 25825, 36531, 25068, 8906, 37847, 28018, 23292, 34951, 27824, 11574, 12327, 9158, 14641, 4183, 21333, + 32859, 15152, 39317, 36644, 2391, 34125, 26709, 1928, 15175, 31823, 11930, 36648, 34834, 17175, 25941, 28906, + 36089, 33657, 28606, 37917, 20508, 8984, 4562, 22700, 20812, 9787, 3627, 2282, 2259, 2254, 4717, 20449, + 38756, 29671, 364, 27499, 9419, 25077, 38210, 14347, 17417, 21967, 27830, 24263, 36280, 18937, 26374, 29865, + 19382, 23679, 26545, 24427, 5703, 39495, 18513, 14785, 23182, 23174, 37344, 22881, 17659, 4589, 36695, 3691, + 39765, 29672, 3261, 23520, 24720, 22366, 941, 24494, 13365, 3617, 17435, 22886, 16006, 11785, 3355, 36285, + 36286, 31747, 31581, 5204, 28673, 6737, 6573, 28028, 14939, 2439, 32641, 7213, 7666, 16569, 16621, 32190, + 20450, 17722, 31282, 2285, 14920, 4650, 32388, 28727, 26769, 22476, 35911, 32107, 21088, 5206, 28730, 14102, + 27801, 13471, 30822, 33766, 24280, 24271, 14661, 2393, 15496, 36351, 35912, 17944, 26026, 15090, 11257, 101, + 34334, 16147, 32037, 3650, 37191, 36292, 4999, 19954, 108, 19877, 6584, 23342, 20566, 16351, 19840, 3827, + 39809, 21900, 34330, 34842, 1989, 39828, 15878, 15849, 36860, 7897, 18266, 20344, 3370, 11864, 2844, 16421, + 11261, 33819, 25229, 2848, 12636, 14693, 11295, 26564, 17564, 21024, 20056, 28870, 14989, 8536, 40489, 37687, + 8631, 12854, 6199, 5961, 38319, 12767, 39407, 15939, 38708, 23909, 8655, 13022, 37319, 34532, 10875, 38719, + 31853, 31862, 24834, 11036, 11038, 6884, 27014, 29161, 19603, 5793, 26394, 35424, 35566, 34496, 24569, 16647, + 7297, 25624, 38037, 38799, 5883, 36921, 15628, 8418, 26575, 2492, 30028, 9130, 31313, 5450, 25307, 31416, + 23737, 12750, 36953, 353, 31423, 39539, 39612, 5451, 34462, 15836, 1463, 14375, 30950, 10895, 37695, 24322, + 5136, 39308, 37868, 30308, 21156, 23016, 23017, 432, 334, 38226, 37949, 1762, 39546, 28614, 2102, 35014, + 39132, 38371, 34724, 10310, 21268, 35175, 3575, 22428, 12689, 19771, 24690, 3976, 12693, 38457, 22170, 20840, + 23738, 30038, 537, 5614, 14599, 16116, 23578, 23646, 10519, 21623, 8943, 4819, 35406, 32833, 2408, 11594, + 510, 39630, 16118, 6720, 6721, 21753, 39184, 8677, 13508, 6192, 20844, 17769, 38373, 18878, 5945, 14845, + 17866, 14552, 34243, 32154, 37471, 30042, 1898, 8829, 29151, 3310, 25761, 15513, 19752, 18481, 14388, 22344, + 12989, 26215, 25629, 32837, 2500, 7760, 13421, 14324, 11990, 29771, 23019, 38307, 27357, 35131, 14857, 30312, + 2114, 41227, 35733, 38516, 18879, 27858, 30043, 657, 30878, 30396, 24247, 26518, 20387, 19813, 8109, 5350, + 31066, 14734, 37714, 40950, 3122, 29738, 983, 25735, 41243, 31089, 31476, 3315, 25968, 19049, 24419, 8508, + 5624, 11922, 23266, 27236, 23665, 18034, 34254, 39256, 17608, 9304, 35758, 12001, 26305, 39312, 2197, 1752, + 29175, 39994, 15500, 21994, 13566, 20519, 8867, 19989, 25939, 22408, 21879, 13000, 39266, 14265, 13001, 34388, + 21011, 10578, 22603, 30532, 25826, 21486, 27075, 40953, 39201, 34056, 36603, 1401, 34779, 11409, 34497, 38069, + 33485, 15398, 12288, 29181, 16175, 16189, 3172, 14270, 29783, 11610, 8794, 3752, 32619, 32800, 23749, 2511, + 847, 34940, 30533, 1077, 30982, 40954, 8807, 9052, 24333, 25410, 25061, 3770, 28280, 28266, 25402, 701, + 15363, 34952, 5358, 39415, 21811, 16164, 24663, 32266, 13962, 20334, 6956, 4199, 26229, 28462, 38463, 22066, + 17176, 28907, 10926, 39723, 30193, 11169, 30983, 23967, 29270, 39089, 6957, 21889, 24958, 38502, 31271, 26537, + 15284, 27871, 25788, 2789, 28309, 14272, 3689, 4139, 9321, 7766, 5695, 23511, 27878, 17505, 3262, 3420, + 9420, 18753, 18551, 40960, 8346, 11099, 38389, 4170, 28879, 11222, 20930, 13236, 9533, 36478, 304, 39767, + 21550, 19445, 2840, 15585, 3889, 26546, 29866, 13450, 2302, 15524, 1541, 13307, 36090, 9063, 23682, 12354, + 22760, 16542, 6614, 32381, 25634, 9651, 38074, 35880, 32191, 3268, 21085, 10725, 9491, 4914, 21402, 17941, + 39318, 11634, 13460, 12456, 2355, 5150, 5151, 1860, 3063, 14811, 8128, 993, 8129, 40637, 30712, 23047, + 24337, 6611, 11170, 13461, 28486, 24110, 31053, 13035, 36569, 21047, 18669, 40638, 38269, 23050, 4331, 12201, + 5274, 26027, 24386, 13592, 15745, 5117, 32878, 15114, 377, 14662, 35219, 7043, 19990, 20029, 12458, 28580, + 5369, 16418, 14572, 35145, 25603, 35252, 35245, 21289, 31114, 12382, 1732, 21650, 8666, 39810, 39791, 16141, + 20547, 13174, 32904, 17830, 28640, 533, 27928, 18676, 19045, 25249, 29055, 34843, 16806, 2158, 27274, 38077, + 21409, 32288, 15101, 17274, 16210, 11378, 36443, 18616, 18466, 23709, 23710, 23715, 16371, 32126, 36367, 19741, + 2672, 36534, 4684, 32914, 26565, 19130, 15108, 20057, 16979, 38081, 18988, 28642, 17331, 5756, 30208, 5278, + 13498, 16430, 17359, 9620, 9580, 23160, 34077, 15309, 35550, 8371, 569, 22966, 5728, 15597, 20429, 31330, + 10360, 2411, 3986, 8683, 33627, 13517, 3166, 26605, 6691, 37159, 544, 33628, 6692, 21526, 5773, 6679, + 35790, 15412, 34616, 12134, 29706, 32757, 6696, 34785, 31975, 20399, 36, 37, 5572, 39206, 27392, 17672, + 24731, 33359, 35592, 13472, 26366, 13473, 40661, 35937, 17509, 1332, 16964, 32785, 32786, 33914, 23233, 23249, + 14867, 38520, 16476, 580, 37203, 16379, 30770, 26735, 12805, 12812, 37164, 13527, 29413, 6301, 36119, 23890, + 24764, 38643, 4884, 40622, 40639, 24267, 17901, 40662, 4030, 6512, 40264, 2764, 10159, 22279, 36740, 19774, + 23250, 22448, 18215, 7857, 7400, 14038, 38872, 35575, 26426, 13125, 37030, 39792, 7215, 22707, 7216, 38617, + 15778, 28237, 37098, 12470, 12534, 12007, 32820, 29347, 28552, 5643, 33459, 2762, 34750, 26915, 20376, 20377, + 30019, 4222, 31252, 883, 605, 13626, 26736, 11060, 7394, 9623, 33726, 7563, 24292, 10833, 34354, 38304, + 7395, 26698, 14600, 34763, 1766, 33851, 22967, 39136, 18010, 10256, 20592, 1475, 33608, 11866, 40972, 27037, + 7495, 5946, 30885, 6130, 49, 1767, 251, 18362, 15860, 29405, 26926, 11559, 33828, 15921, 33472, 13422, + 13941, 39645, 29591, 10704, 8310, 32496, 10070, 15063, 32344, 16044, 40080, 31477, 26796, 38950, 38951, 10071, + 10266, 30348, 29306, 40623, 41177, 40052, 26272, 21276, 31495, 23422, 39313, 35791, 225, 30349, 17881, 2871, + 30476, 32726, 7555, 8858, 35468, 37802, 11617, 33569, 20445, 35120, 36509, 27310, 30700, 24385, 19655, 20992, + 13014, 34786, 4229, 34959, 28348, 13972, 13451, 15155, 8583, 31019, 2958, 23512, 10281, 34634, 17189, 12592, + 19836, 38091, 33020, 10284, 20640, 4508, 21340, 38762, 11786, 10108, 33807, 4098, 17676, 5207, 14103, 22761, + 17902, 31751, 35913, 12603, 11579, 5060, 35209, 35210, 17212, 28679, 29633, 32733, 7527, 26682, 38895, 10291, + 35938, 32510, 33233, 26643, 13477, 824, 14165, 34664, 111, 35246, 25582, 19884, 17253, 3195, 15879, 6018, + 17727, 34684, 12063, 18623, 25454, 18411, 19179, 18989, 26199, 28871, 34578, 40226, 37666, 35170, 10834, 27228, + 2360, 26819, 2468, 2280, 33643, 11761, 36219, 24169, 7585, 22556, 7597, 18011, 7460, 29165, 21823, 29406, + 16509, 41142, 20475, 11462, 29968, 12137, 36317, 40908, 30508, 29634, 16521, 16637, 18412, 5476, 27336, 20785, + 25267, 394, 6712, 5341, 17081, 9567, 14244, 1113, 3290, 4436, 25626, 23635, 36955, 31146, 34030, 7234, + 40819, 25313, 30033, 5644, 19481, 3569, 35653, 8342, 8880, 16849, 13325, 26364, 30427, 14370, 19482, 27719, + 37536, 7491, 6128, 32062, 4223, 27220, 11201, 33114, 3856, 3857, 27779, 31083, 13933, 12103, 19555, 1181, + 265, 7598, 35678, 7930, 20978, 11061, 34154, 6254, 33151, 34888, 6870, 38861, 37902, 41202, 6255, 6806, + 18851, 27856, 20979, 32069, 28558, 31722, 9325, 725, 20593, 35705, 35180, 35184, 27038, 21501, 1121, 35407, + 21272, 16160, 10348, 632, 7235, 39890, 5027, 4374, 34821, 7845, 19625, 26445, 27783, 26589, 20982, 36626, + 39631, 38374, 5176, 9084, 2107, 276, 7942, 407, 6765, 1188, 26216, 27727, 3980, 22235, 27021, 9326, + 38375, 35020, 14319, 18302, 19695, 17389, 25387, 38224, 26741, 36622, 34043, 23476, 39068, 35425, 32477, 39192, + 17126, 25997, 15186, 962, 25287, 526, 25288, 1801, 40715, 3788, 35734, 4447, 13110, 41172, 7077, 7111, + 36828, 7174, 8945, 38581, 17782, 36063, 35735, 27047, 7962, 25547, 35426, 15643, 24450, 25909, 33958, 6768, + 40510, 36985, 38066, 0, 36307, 13836, 18353, 38696, 34044, 26099, 39079, 845, 29472, 16121, 14136, 23009, + 984, 25677, 31478, 16477, 18306, 7710, 23156, 30954, 15030, 8427, 27985, 24611, 36832, 18483, 22324, 40459, + 5664, 33734, 29777, 38207, 277, 1213, 5556, 9984, 39402, 25331, 903, 12995, 11400, 30341, 21853, 12709, + 29374, 12535, 32601, 18887, 11891, 2456, 7606, 27789, 16863, 6280, 24296, 36469, 14406, 16084, 40616, 2656, + 30679, 14137, 16864, 1689, 32050, 7816, 28942, 39665, 16253, 17406, 40574, 16874, 23497, 1809, 19068, 4491, + 23850, 23283, 2211, 2682, 5432, 7468, 22015, 697, 11877, 3328, 38182, 17160, 37279, 37280, 9226, 15069, + 6203, 8512, 30477, 4885, 7246, 3246, 38705, 23423, 37499, 34500, 37281, 24911, 35792, 25292, 23162, 40577, + 7997, 16260, 41001, 41002, 7573, 26611, 24382, 21234, 30350, 18730, 10211, 13579, 3799, 14555, 14481, 3329, + 41245, 23900, 34168, 848, 40624, 40733, 1692, 22353, 6099, 3949, 2967, 19843, 11246, 13002, 9524, 31812, + 5420, 9690, 5840, 39408, 25025, 20514, 8281, 8868, 22409, 38647, 36042, 26070, 6733, 8198, 30701, 30541, + 12813, 40909, 12889, 35469, 31683, 34625, 34513, 12890, 37173, 10397, 31101, 22666, 1085, 34902, 12008, 33497, + 25744, 34787, 16190, 34389, 975, 11618, 15941, 13813, 15942, 27641, 7722, 30145, 39666, 20813, 19656, 11087, + 10934, 29503, 37033, 36771, 27827, 33869, 34831, 39091, 22667, 35199, 13683, 35200, 6653, 37012, 30542, 19717, + 29185, 12317, 13684, 25533, 11496, 16657, 25026, 32571, 27148, 28660, 30891, 26726, 4043, 22645, 12818, 35858, + 38657, 8032, 21891, 20147, 9175, 13140, 28409, 35040, 26116, 37577, 40848, 20488, 28019, 12838, 34960, 13701, + 11578, 8469, 23767, 19303, 37578, 25417, 26942, 39423, 37853, 29504, 25411, 28807, 38525, 27649, 26810, 15370, + 31542, 9166, 23176, 8584, 28270, 22067, 28909, 8713, 34061, 5738, 21778, 12338, 9057, 23910, 23819, 19724, + 33669, 8534, 40640, 30107, 24122, 34862, 5739, 12819, 41183, 5421, 18489, 25938, 31694, 12170, 17425, 11787, + 36562, 23866, 9825, 8355, 8360, 29868, 11230, 26071, 4721, 22361, 36850, 13275, 11103, 11429, 9652, 21551, + 35881, 8556, 15266, 9539, 9540, 19453, 5536, 40465, 16659, 16517, 3182, 4509, 16908, 33393, 24387, 27501, + 29665, 9423, 38260, 28030, 16744, 18665, 17587, 20156, 18520, 3002, 28031, 15377, 1547, 18769, 14274, 39038, + 38395, 27264, 19384, 21460, 34869, 29388, 22362, 40335, 26119, 24968, 12903, 4510, 12679, 34717, 33988, 7151, + 34078, 39500, 41150, 4570, 23115, 27397, 11223, 16015, 39112, 26326, 31586, 4234, 5824, 7187, 20539, 31293, + 25238, 17968, 18251, 24060, 32390, 25732, 7261, 38666, 16606, 37859, 27565, 6615, 3273, 28825, 19868, 28056, + 14942, 5825, 11800, 12184, 21872, 30151, 21667, 25688, 29635, 38343, 7626, 24496, 25193, 10551, 23780, 9111, + 18317, 16624, 8558, 31907, 26820, 40886, 25908, 12371, 6243, 14181, 13214, 4044, 28494, 27270, 13249, 17948, + 21734, 36227, 28224, 26248, 41192, 33813, 3277, 8474, 14513, 41196, 35939, 23118, 7733, 11702, 5321, 12619, + 28216, 22890, 3362, 3960, 40365, 9662, 12373, 13776, 12824, 38544, 13040, 23956, 5402, 35597, 1601, 27805, + 26495, 17394, 36176, 28964, 28583, 20208, 23352, 29876, 1710, 12036, 12629, 23706, 21292, 21653, 35345, 8597, + 15227, 36297, 21782, 24413, 34547, 23353, 20175, 38900, 9668, 4241, 12213, 15954, 22942, 5496, 3933, 8776, + 20210, 36705, 39839, 11571, 23711, 16762, 16696, 25812, 18681, 17254, 4689, 18953, 20350, 11837, 21934, 18609, + 39811, 8565, 6376, 37603, 17275, 7540, 40669, 27930, 17456, 13326, 3938, 24438, 40176, 18624, 34430, 17293, + 40175, 3231, 13741, 7020, 27956, 11264, 21585, 37415, 18414, 16314, 13560, 32291, 9556, 14575, 32676, 18125, + 36373, 12958, 36242, 36811, 36450, 32461, 21744, 2011, 2736, 16380, 14577, 27481, 26568, 30650, 4582, 24984, + 24835, 2353, 14372, 37437, 19135, 17349, 4692, 18990, 5282, 14996, 34719, 16434, 16391, 40227, 16721, 17066, + 496, 21043, 37449, 18156, 9496, 35679, 23641, 33468, 2974, 3981, 23488, 15169, 35736, 14858, 31800, 33618, + 10316, 15993, 16470, 15793, 27582, 17, 4047, 3539, 24216, 15210, 15796, 15214, 4113, 9261, 36085, 37035, + 32630, 35211, 31162, 28756, 13983, 21924, 10876, 29191, 11286, 33514, 22300, 31752, 32772, 4049, 26327, 9951, + 4031, 35940, 7010, 37082, 4337, 11447, 2103, 2104, 14601, 23743, 3467, 26005, 3540, 26011, 39933, 28195, + 28196, 17190, 4890, 37057, 17214, 9549, 6885, 38926, 20582, 20583, 34889, 26743, 33619, 14869, 23598, 24612, + 27986, 24380, 35793, 7829, 35193, 2251, 11879, 5983, 39102, 37881, 30892, 3876, 29193, 13984, 26379, 36169, + 5869, 14353, 11801, 4696, 5118, 6463, 13250, 17552, 1734, 6377, 13216, 12959, 40288, 24420, 35759, 26093, + 24096, 15399, 32709, 34119, 11691, 24008, 12163, 21925, 11697, 6509, 35346, 32686, 9401, 19748, 48, 13770, + 22498, 2710, 10206, 2189, 22493, 17864, 12700, 25824, 20795, 30159, 34046, 7112, 25395, 32253, 14467, 24613, + 6281, 26101, 22251, 14482, 6680, 1081, 25906, 19658, 25828, 36935, 30166, 10398, 28474, 25859, 18863, 20747, + 19581, 29636, 25489, 38612, 25982, 38613, 19887, 18682, 6033, 14825, 23447, 34756, 21187, 1741, 26590, 23477, + 31456, 24354, 34264, 6145, 34835, 37806, 39307, 1746, 5287, 27551, 16648, 21308, 7306, 9566, 1679, 38299, + 20222, 5846, 40592, 4117, 30301, 7310, 4980, 30030, 19477, 24573, 22817, 23629, 31139, 31140, 29846, 14369, + 39366, 39540, 23636, 14087, 14088, 25695, 15021, 10620, 24999, 1464, 8455, 39876, 7362, 14832, 11016, 21684, + 33593, 33602, 37824, 34463, 5172, 36726, 11052, 11982, 21819, 19689, 20111, 3671, 22119, 1118, 39541, 22095, + 40507, 37954, 18209, 38227, 7695, 19772, 38065, 30040, 17096, 20078, 35385, 7154, 29250, 27623, 15858, 14204, + 14382, 35681, 12694, 39885, 11720, 959, 38229, 40186, 36684, 9082, 10835, 22845, 4425, 39373, 27968, 3242, + 27713, 14459, 25781, 26737, 14840, 7931, 12432, 9406, 5242, 36126, 22058, 35707, 11596, 38040, 3303, 30582, + 10803, 13101, 27732, 7072, 33256, 7945, 25996, 39554, 36255, 31195, 15314, 19194, 211, 29166, 20708, 16785, + 35309, 20082, 24930, 22968, 32696, 32953, 27971, 15817, 24150, 14591, 22851, 33328, 39633, 9456, 20470, 31148, + 24692, 35708, 14125, 26838, 7168, 2766, 13937, 17783, 24601, 30673, 9979, 19497, 36748, 1899, 6274, 10645, + 35737, 36466, 16402, 10027, 17030, 8799, 17525, 4253, 7761, 35738, 29594, 16554, 12705, 3676, 14212, 28124, + 3247, 22282, 32341, 26700, 16104, 22824, 10062, 14032, 21391, 29735, 32752, 29534, 6828, 29966, 17128, 27531, + 27733, 16788, 27532, 6343, 37837, 10565, 33301, 27186, 4315, 38807, 15547, 31090, 30048, 6141, 31043, 14407, + 26528, 17575, 11873, 28455, 24155, 5429, 14763, 9151, 9820, 34299, 39995, 22402, 10268, 2867, 23157, 7368, + 39468, 18718, 14474, 16792, 39032, 22862, 29303, 37259, 21228, 18719, 20125, 14138, 18036, 19066, 24772, 37260, + 21393, 1531, 10849, 37494, 16254, 24355, 23809, 39558, 36210, 20126, 985, 37487, 30980, 25742, 7421, 37488, + 15409, 12537, 26529, 26066, 23562, 22601, 31906, 37490, 25510, 11410, 13003, 21832, 24625, 29497, 7247, 31044, + 5676, 30535, 25558, 2421, 10373, 34501, 10661, 20089, 19565, 36312, 34502, 10579, 26781, 19757, 38018, 11894, + 20962, 9599, 3600, 6940, 17534, 23499, 23500, 19711, 29264, 4598, 30600, 2229, 11746, 20621, 33486, 12320, + 12997, 7792, 35796, 36266, 26933, 13580, 3256, 28749, 37014, 1233, 20440, 26847, 29744, 26753, 36637, 14483, + 6204, 29893, 13444, 24626, 28768, 18378, 12009, 37554, 21012, 635, 36838, 24952, 40460, 17629, 2683, 34379, + 4262, 21528, 40735, 19421, 36409, 16235, 7808, 18501, 30601, 32051, 36410, 22920, 13964, 34627, 28349, 37570, + 17418, 35036, 19971, 40559, 3342, 28605, 28421, 30194, 9001, 25943, 38498, 26937, 19089, 19277, 30543, 2185, + 31360, 30893, 23901, 38247, 26855, 33, 37849, 36086, 28008, 28390, 26856, 21, 22109, 4008, 30998, 2329, + 20335, 8707, 10274, 11576, 31824, 5561, 39725, 33273, 13685, 8653, 28132, 13522, 11763, 36152, 8549, 18379, + 4264, 32794, 37303, 33426, 11100, 1253, 1542, 39751, 13305, 15611, 26719, 26375, 20148, 297, 18662, 11028, + 36694, 2790, 7346, 36559, 9707, 19426, 24407, 37047, 12575, 34202, 2999, 31743, 12576, 18515, 18382, 13904, + 9789, 4563, 39496, 8358, 23949, 13528, 4501, 4267, 29867, 21920, 29012, 35160, 31689, 20149, 28809, 26376, + 10099, 17419, 30196, 3492, 8405, 7767, 40878, 15264, 22333, 38787, 40483, 33670, 11976, 13141, 34318, 27500, + 17660, 4733, 29106, 13241, 4564, 36483, 10681, 34062, 27387, 9421, 40993, 16112, 33671, 39752, 22614, 37346, + 13535, 23010, 5308, 11788, 13710, 31284, 21998, 12355, 30614, 28044, 23772, 31566, 31843, 34129, 6659, 20451, + 25730, 28032, 39109, 4565, 35860, 39039, 30284, 26319, 34073, 16007, 35122, 29805, 25772, 10513, 1301, 2702, + 27316, 23048, 17895, 30615, 26038, 26019, 3356, 14232, 11231, 13366, 16622, 4814, 10726, 10005, 37856, 18334, + 10727, 8044, 10285, 10399, 32192, 13147, 26245, 31844, 37473, 18854, 21680, 37073, 17946, 20256, 5250, 11434, + 38270, 33035, 37365, 27117, 33934, 18092, 30410, 40773, 36570, 11802, 2306, 17547, 5826, 35232, 11340, 39113, + 19458, 5154, 35919, 28206, 22621, 14663, 28487, 24274, 40653, 21731, 9752, 13991, 7622, 26029, 12356, 11803, + 3957, 28502, 27803, 6079, 26067, 40255, 17447, 20097, 26881, 27398, 20163, 21677, 36433, 36434, 19878, 13999, + 23343, 12620, 4789, 31118, 28920, 36231, 36232, 6580, 4406, 12028, 14169, 16446, 15096, 60, 30624, 1706, + 9195, 23787, 36435, 1742, 16142, 7535, 2351, 19684, 13176, 30739, 19226, 38098, 18951, 17231, 36703, 34871, + 18677, 27770, 39793, 36441, 6374, 30494, 11646, 33056, 22080, 26690, 1564, 2716, 20665, 18269, 12939, 26042, + 3367, 9201, 1716, 12052, 32408, 18617, 24339, 25452, 17276, 14170, 32669, 36446, 28167, 30750, 11262, 33980, + 40170, 18403, 16309, 6588, 7279, 10999, 16310, 27418, 18201, 36447, 20048, 12644, 17558, 13183, 36451, 17920, + 35990, 12953, 2731, 5075, 25203, 13068, 16372, 7280, 27514, 37523, 40682, 7744, 26566, 16769, 16373, 4579, + 24832, 36589, 23792, 7195, 25101, 34705, 36536, 25774, 38109, 18992, 34690, 16980, 20103, 26356, 28643, 5279, + 13499, 2828, 36537, 10306, 40225, 16431, 16388, 21052, 30294, 19000, 34095, 32309, 34708, 8484, 34713, 37462, + 9449, 32573, 32574, 11861, 10571, 40415, 38484, 32940, 3570, 38009, 23460, 39886, 7599, 21697, 30913, 22964, + 35682, 22432, 15167, 22098, 15168, 22163, 20791, 17737, 9451, 33116, 9495, 9452, 1522, 4930, 31948, 39245, + 40190, 15407, 38865, 7946, 439, 32954, 6766, 18191, 40569, 22184, 28560, 34822, 29560, 9930, 30781, 11557, + 40124, 13423, 33620, 10543, 25002, 11396, 33378, 33379, 32255, 36120, 31152, 39987, 34929, 27048, 30519, 29595, + 20327, 38015, 15170, 31956, 33829, 39248, 22972, 11671, 9459, 3079, 11602, 3238, 0, 17867, 7978, 14213, + 32970, 23109, 29473, 40606, 29536, 9888, 16510, 34601, 33630, 3592, 25396, 10915, 31482, 27239, 10466, 33995, + 15689, 14708, 32603, 31483, 40478, 15064, 5665, 32971, 12302, 34302, 18966, 34609, 14475, 17961, 16049, 11924, + 29969, 31499, 4767, 31204, 10580, 3022, 8113, 31098, 4492, 7793, 22867, 24467, 25743, 31500, 24468, 33178, + 35797, 14887, 37283, 8532, 22520, 33354, 30514, 26754, 2954, 26423, 33346, 21394, 8808, 30879, 3178, 10471, + 15977, 39935, 31925, 11619, 7794, 17539, 33215, 13445, 1254, 36318, 40248, 30703, 29851, 26277, 31544, 21835, + 21836, 2689, 34313, 14216, 14226, 19790, 30803, 38428, 33179, 24479, 25512, 11419, 7251, 24635, 28197, 34788, + 17803, 13585, 8615, 9262, 37804, 31926, 27149, 17639, 9058, 28810, 3024, 7053, 1941, 11565, 32871, 31831, + 31367, 37921, 10413, 10473, 31546, 37854, 20927, 26280, 24519, 35083, 20150, 17426, 36420, 31277, 8911, 34716, + 23980, 1276, 1548, 4511, 18771, 12907, 18521, 22363, 28138, 35884, 28999, 14922, 40921, 11104, 35492, 39770, + 30814, 18314, 10109, 21926, 25258, 14230, 16113, 4697, 38344, 12923, 31588, 31589, 35885, 32774, 3639, 11509, + 2802, 35212, 28680, 34656, 32202, 24023, 15092, 5461, 6661, 26636, 13373, 7627, 27669, 37367, 17903, 29637, + 26434, 7587, 34079, 16443, 19765, 28881, 35921, 14104, 19838, 14182, 13474, 36429, 35941, 33935, 16352, 28608, + 2310, 31605, 25089, 4522, 17457, 11703, 40214, 18103, 30560, 35942, 32894, 38897, 11817, 4992, 21735, 16353, + 25583, 15323, 34013, 14003, 3836, 5405, 35096, 10494, 16447, 1569, 25447, 17256, 20673, 25753, 18954, 16211, + 283, 34136, 15880, 27605, 17754, 17296, 18626, 14965, 17731, 34685, 31645, 33069, 18415, 35255, 2317, 25222, + 37770, 16452, 4583, 3737, 9435, 14699, 3115, 20061, 28873, 16457, 40228, 16461, 18157, 37465, 38906, 39238, + 22185, 3244, 30798, 10146, 14923, 35290, 41096, 7119, 4151, 15345, 38122, 5984, 23911, 36606, 23957, 22102, + 2989, 12880, 4138, 37037, 38429, 1406, 682, 1942, 4141, 36919, 6379, 3257, 21718, 14246, 28400, 25314, + 19469, 7365, 8496, 34592, 8634, 886, 27728, 36886, 8639, 20760, 5619, 25016, 24934, 40864, 19499, 15516, + 23660, 16877, 23034, 8513, 39474, 964, 24953, 4263, 12727, 7723, 15364, 14488, 3918, 31833, 928, 19212, + 13817, 19257, 25860, 30815, 19582, 6616, 29638, 24123, 31908, 17257, 6380, 17839, 22024, 22711, 2003, 31646, + 3779, 30644, 15969, 3781, 431, 12430, 2178, 40593, 8628, 15296, 1879, 10789, 34235, 36116, 11283, 40474, + 24343, 39946, 20789, 22433, 14462, 35386, 26738, 30073, 18007, 22495, 21269, 35016, 36877, 33955, 5173, 1884, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17995, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15674, 32244, + 11315, 10350, 38866, 12283, 34105, 26217, 28444, 29588, 16596, 19498, 31459, 31957, 897, 39648, 34362, 26094, + 10063, 14039, 22014, 7427, 32604, 545, 23270, 1534, 36267, 16255, 12868, 23894, 16045, 34309, 40976, 39668, + 39258, 34198, 17868, 5771, 40904, 9635, 7718, 31046, 37555, 4082, 29850, 34265, 32801, 12720, 1402, 36765, + 34954, 28267, 1930, 20484, 27866, 19298, 37572, 4998, 37321, 26857, 10214, 23986, 35829, 39093, 2330, 10225, + 19447, 13276, 20631, 2693, 298, 10218, 4720, 994, 1302, 1279, 11502, 23077, 17896, 33683, 29631, 35087, + 27592, 32643, 27208, 6612, 13539, 8720, 14792, 6362, 11804, 15775, 32278, 32281, 21651, 22796, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12030, 21781, 19955, 17834, + 21135, 9478, 27202, 18618, 28432, 32414, 20049, 25204, 21140, 19132, 32298, 23382, 14991, 20311, 40717, 18598, + 27965, 24571, 8297, 16651, 395, 10621, 5645, 4119, 8374, 36959, 23404, 36960, 2947, 8882, 31256, 7841, + 13795, 34189, 1472, 689, 37700, 14841, 19809, 14842, 12855, 5138, 22786, 23892, 35710, 180, 22852, 7947, + 33793, 4426, 9020, 12803, 26447, 4369, 25182, 26746, 26591, 35412, 41097, 18303, 1192, 39063, 13855, 13511, + 13112, 17130, 9487, 32073, 39988, 34292, 33434, 34770, 33563, 27976, 24242, 36133, 34047, 763, 32533, 31958, + 9509, 3677, 33622, 22283, 16632, 5245, 36530, 30921, 6830, 3316, 5666, 31270, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31202, 3312, 15065, 19703, 905, 29537, + 32346, 3993, 9988, 33801, 34372, 33861, 33438, 7979, 31484, 18038, 16866, 13954, 28395, 7807, 30315, 5805, + 22790, 38648, 26006, 20395, 37284, 16261, 30923, 26806, 30602, 29307, 4000, 1039, 3248, 6959, 2872, 1040, + 18731, 9385, 5861, 915, 25052, 40625, 24250, 7198, 14016, 6413, 13814, 11897, 37174, 19720, 4231, 33749, + 29093, 33216, 5053, 25513, 20400, 12892, 30704, 25651, 11420, 32863, 4084, 13015, 40423, 2955, 17541, 24959, + 6503, 34199, 11499, 18238, 26863, 25423, 28353, 34963, 30894, 31278, 39103, 13973, 36421, 19279, 28910, 18241, + 17191, 16482, 39208, 23912, 4831, 14912, 38855, 1699, 27259, 2912, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16064, 40388, 4512, 35339, 23324, 36484, 28357, 24646, + 307, 17506, 19818, 36171, 11249, 30823, 31222, 5462, 33444, 38346, 34081, 24794, 5322, 17904, 17678, 24497, + 28058, 9542, 14105, 7263, 13985, 18252, 12187, 11863, 14106, 113, 38188, 5254, 13478, 9730, 28735, 11818, + 11347, 26040, 28219, 29283, 4045, 37084, 14004, 18619, 1712, 27297, 41169, 16360, 31760, 40788, 33816, 25666, + 31119, 8364, 16697, 6381, 17279, 39840, 25525, 16967, 38102, 24507, 29213, 9554, 28160, 16217, 18416, 18627, + 17299, 16453, 36375, 20058, 32462, 24516, 9436, 5416, 38112, 11367, 1885, 1900, 39483, 17361, 0, 32469, + 23637, 608, 22301, 7396, 5139, 0, 0, 30245, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10901, 35413, 528, 14709, 2900, 3412, 0, 5300, 19947, 40516, + 22869, 1407, 40089, 0, 4392, 36329, 23513, 32186, 18553, 5705, 21928, 40389, 17970, 31294, 5121, 31034, + 36356, 34562, 29261, 9998, 2904, 24375, 26598, 2773, 2774, 25678, 27942, 26628, 18695, 7790, 38412, 7911, + 22820, 29529, 39181, 19844, 23235, 18323, 34031, 18210, 20761, 37829, 7948, 8798, 13798, 7949, 29256, 20762, + 6671, 13227, 30185, 4936, 20984, 20764, 20765, 2412, 29259, 8313, 1202, 4941, 39669, 19024, 22047, 36040, + 11212, 26489, 37015, 20769, 15071, 35763, 18220, 5974, 11215, 5248, 40520, 13235, 3347, 2959, 30016, 16681, + 2520, 18253, 6046, 17974, 13254, 3840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 22635, 6019, 6024, 13633, 5177, 27245, 39753, 20938, 1119, 8497, 40045, 32024, + 33465, 3216, 14847, 23243, 31915, 4751, 1193, 40973, 33903, 39395, 7169, 39559, 7501, 14390, 26221, 21509, + 29007, 29562, 13568, 30680, 11675, 28625, 3593, 19785, 14147, 32608, 29745, 19504, 32609, 28096, 7864, 6697, + 27189, 35831, 1020, 38810, 9387, 19253, 17885, 12557, 29313, 156, 3609, 1257, 20401, 6532, 6817, 34219, + 4640, 26712, 39937, 3619, 37322, 7726, 34793, 3183, 29794, 9748, 30927, 11426, 15697, 36091, 14925, 31571, + 9361, 35886, 4142, 11775, 21845, 5740, 38816, 26723, 4657, 35922, 40985, 27937, 26031, 5918, 18573, 18574, + 24275, 8068, 17683, 24063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18260, 16573, 32212, 7531, 5122, 36282, 10488, 32213, 9365, 9670, 21755, 37399, 30629, 36579, + 16759, 17236, 27324, 5228, 17950, 17951, 1672, 12637, 3444, 34844, 13596, 39303, 19686, 17314, 12068, 16316, + 12682, 33843, 36503, 36244, 36597, 28644, 5759, 19181, 19006, 19010, 1827, 1834, 440, 7155, 7158, 24128, + 12267, 38196, 19618, 21980, 4427, 18022, 20600, 12285, 22403, 8543, 6835, 10082, 1234, 3806, 23854, 40, + 32732, 10286, 11580, 10287, 38273, 4744, 10294, 32737, 35220, 10297, 13481, 121, 33239, 11584, 17300, 22739, + 10449, 13553, 8421, 22212, 24627, 25063, 38391, 9178, 15035, 15036, 40098, 38399, 9196, 38846, 6384, 23405, + 36395, 841, 8, 1, 14, 16, 10, 12, 11, 32, 42, 56, 52, 66, 86, 75, + 79, 165, 145, 137, 189, 210, 227, 209, 216, 214, 244, 250, 267, 274, 288, 305, + 313, 337, 359, 361, 373, 374, 400, 413, 392, 500, 501, 504, 389, 409, 499, 436, + 449, 465, 461, 472, 467, 491, 506, 469, 516, 525, 523, 531, 524, 540, 542, 549, + 576, 572, 579, 568, 573, 574, 606, 607, 649, 629, 623, 646, 622, 621, 630, 651, + 654, 658, 681, 683, 677, 696, 708, 691, 709, 695, 698, 724, 726, 719, 733, 1838, + 38831, 10351, 10362, 1840, 30334, 36932, 7331, 8115, 24628, 5387, 18741, 38652, 16910, 13905, 33673, 12901, + 22069, 167, 18606, 33583, 40026, 5323, 171, 9202, 17301, 8456, 30503, 23461, 37616, 29257, 33117, 31795, + 7700, 20382, 20471, 27042, 37830, 22045, 7398, 19628, 32328, 27051, 34730, 39249, 35022, 26599, 11991, 4982, + 39142, 15863, 14391, 26701, 19781, 20602, 40299, 39070, 27052, 5957, 21320, 40867, 3019, 1773, 20085, 18367, + 29599, 6043, 5667, 21158, 20476, 33862, 39197, 34774, 20611, 39955, 20603, 19713, 26477, 10084, 11412, 3387, + 4848, 14770, 6836, 19422, 32354, 31503, 16106, 26279, 29314, 9726, 30358, 16844, 27086, 24480, 17804, 39274, + 747, 743, 757, 765, 756, 753, 793, 792, 817, 800, 811, 828, 840, 856, 846, 839, + 867, 917, 889, 873, 891, 893, 876, 880, 913, 914, 898, 958, 971, 969, 986, 1009, + 1037, 1031, 1053, 1070, 1054, 1082, 1105, 1110, 1139, 1128, 1120, 1281, 1261, 1285, 1157, 1199, + 1191, 1153, 1166, 1256, 1159, 1212, 1274, 1154, 22612, 1314, 1339, 1328, 1196, 1419, 1396, 1403, + 1429, 1431, 1473, 1469, 1458, 1505, 1506, 1510, 1490, 1526, 1533, 1549, 1592, 1636, 1628, 1645, + 1671, 1688, 1691, 1705, 1694, 1687, 1728, 1749, 1747, 1768, 1757, 1763, 1770, 1769, 16885, 16293, + 28198, 14778, 1258, 11882, 18742, 35833, 40053, 37049, 11883, 19299, 32034, 33282, 11629, 9729, 38021, 4291, + 12893, 19791, 10767, 33754, 29342, 33674, 7183, 31108, 16003, 19993, 31023, 15616, 5314, 3137, 24488, 20650, + 27542, 38274, 38818, 35923, 5871, 15586, 20651, 27566, 4523, 18492, 3432, 19388, 9613, 11446, 25721, 31608, + 23085, 26687, 17726, 3112, 32214, 35221, 33700, 20725, 9663, 13168, 35250, 122, 11829, 13049, 38901, 19738, + 3867, 25987, 21670, 34016, 35103, 12044, 19896, 20211, 22800, 20212, 17281, 15882, 33777, 20215, 12069, 18633, + 19911, 18418, 9438, 19435, 31767, 28875, 15246, 40267, 17875, 37285, 27586, 38249, 14998, 26660, 1802, 1794, + 1836, 1848, 1861, 1832, 1844, 1833, 1919, 1889, 1929, 1906, 1944, 1877, 1882, 1915, 1914, 2053, + 1922, 22910, 1881, 2075, 2050, 2074, 2073, 2121, 2091, 2092, 2095, 2150, 2118, 2101, 2157, 2172, + 2184, 2180, 2175, 2182, 2203, 2207, 2191, 2195, 2210, 2212, 2233, 2221, 2248, 2246, 2250, 2279, + 2294, 2322, 2325, 2318, 2321, 2343, 2356, 2357, 2373, 2362, 2390, 2406, 2423, 2405, 2404, 2410, + 2471, 2488, 2510, 2489, 2535, 2536, 2534, 2555, 2545, 2553, 2583, 2587, 2585, 2608, 2619, 2620, + 2661, 2297, 2695, 2686, 2680, 2690, 2777, 2758, 2778, 2846, 2864, 2868, 10744, 36464, 39996, 13480, + 38348, 37678, 487, 6090, 23453, 40823, 31325, 38928, 15637, 8498, 5090, 14849, 17110, 7847, 20383, 6872, + 15252, 39555, 13800, 1685, 6896, 38930, 28181, 22046, 14015, 20604, 14392, 37243, 15352, 30086, 6910, 20767, + 40300, 21803, 22825, 18023, 22213, 16655, 1841, 22975, 36674, 15893, 15515, 24946, 40142, 15822, 6922, 23602, + 18722, 30681, 77, 32347, 34373, 22326, 16633, 10654, 24437, 30593, 24046, 35764, 15519, 25057, 2837, 16484, + 10582, 37016, 32612, 31971, 19527, 19201, 36638, 3054, 3089, 34620, 26107, 16086, 37286, 3602, 11247, 18655, + 3202, 21844, 27795, 40631, 15523, 34314, 40521, 15551, 3318, 23294, 40977, 24422, 2929, 2895, 2898, 38781, + 2896, 2892, 2928, 2966, 2948, 2952, 2949, 2980, 2969, 2975, 2993, 3000, 3003, 2991, 3014, 3016, + 3045, 3059, 3097, 3087, 3071, 3098, 3121, 3146, 3152, 3145, 3239, 3149, 3151, 3153, 3220, 3215, + 3269, 3249, 3299, 3361, 3289, 3291, 3306, 3334, 3326, 3357, 3296, 3294, 3381, 3382, 3392, 3400, + 3422, 3462, 27146, 3451, 3457, 3450, 3453, 3530, 3520, 3517, 3512, 3572, 3589, 3566, 3582, 3668, + 3669, 3716, 3720, 3739, 3762, 3879, 3800, 3815, 3807, 3804, 3808, 3782, 3796, 3863, 3852, 3872, + 3882, 3880, 3927, 3902, 3936, 3907, 3916, 3903, 3899, 4042, 17886, 15034, 1855, 20402, 12894, 10472, + 25065, 16830, 36154, 31273, 23295, 19084, 21081, 25656, 34395, 6104, 30103, 36323, 15459, 30808, 27593, 39105, + 6506, 31983, 5309, 29098, 21126, 29345, 23514, 6666, 7727, 25080, 25081, 19280, 8915, 28036, 6844, 18244, + 27661, 28819, 11171, 22467, 30714, 29277, 31987, 31573, 17439, 30616, 37886, 6535, 16176, 40390, 24428, 40393, + 2707, 23533, 310, 22339, 18336, 18671, 15242, 4173, 3207, 36223, 16748, 1551, 23534, 23535, 4724, 40929, + 4333, 19093, 12202, 26335, 16574, 38349, 13169, 31865, 6111, 28687, 22075, 37991, 24028, 5540, 17237, 13215, + 31909, 38791, 24066, 13050, 37385, 40538, 10434, 15472, 38282, 16693, 3948, 3951, 4040, 4007, 4014, 3969, + 4058, 4076, 4080, 4096, 4088, 4092, 4111, 4118, 4135, 4137, 4155, 4150, 4166, 4175, 4186, 4187, + 4196, 4205, 4191, 4224, 4230, 4271, 4252, 4257, 4250, 4296, 4301, 4316, 4349, 4378, 4394, 4395, + 4393, 4391, 4380, 4367, 4421, 4441, 4455, 4437, 4517, 4494, 4476, 4474, 4542, 4543, 4597, 4616, + 4656, 4660, 4631, 4683, 4698, 4694, 4718, 4708, 4709, 4759, 4770, 4775, 4763, 4777, 4809, 4816, + 4824, 4834, 4835, 4829, 4881, 4878, 4889, 4904, 4923, 4948, 4990, 4976, 4978, 4994, 5001, 5004, + 5066, 5024, 5028, 5009, 5031, 5043, 5025, 5003, 15417, 3963, 35256, 25094, 5325, 35599, 22479, 22480, + 37400, 22778, 7016, 127, 15391, 12945, 37401, 25671, 22224, 4412, 1992, 34878, 19314, 32228, 15883, 16704, + 16767, 39850, 17282, 17303, 7282, 25102, 22227, 36376, 17317, 18419, 18420, 20683, 27482, 9439, 16384, 38083, + 34444, 25358, 37696, 28401, 19290, 32946, 34890, 23236, 1004, 6557, 39948, 25323, 35302, 26922, 36888, 39636, + 29373, 8162, 20119, 28107, 19778, 2621, 18888, 37151, 31203, 40301, 9590, 31959, 39396, 8611, 8612, 27535, + 13955, 26704, 8315, 16085, 5668, 28948, 9227, 9413, 41178, 18052, 18733, 5357, 39475, 851, 39020, 11621, + 36843, 36087, 40746, 12010, 39095, 37650, 31208, 32268, 5026, 5094, 5086, 5081, 5085, 5096, 5146, 5142, + 5167, 5189, 5169, 5181, 5184, 5174, 5180, 5186, 5244, 5268, 5269, 5294, 5295, 5336, 5354, 5370, + 5379, 5352, 5356, 5351, 5376, 5397, 5383, 5388, 5385, 5439, 5448, 5446, 5472, 5453, 5454, 5478, + 5493, 5484, 5482, 5527, 5511, 5533, 5551, 5553, 5558, 5546, 5554, 5567, 5565, 5613, 5611, 5445, + 5681, 5669, 5651, 5642, 5658, 5679, 5742, 5730, 5735, 5776, 5765, 5763, 5827, 5792, 5785, 5786, + 5726, 5790, 5799, 5803, 5801, 5807, 5863, 5845, 5872, 5852, 5841, 5900, 5892, 5893, 5899, 5932, + 5931, 5993, 6000, 5938, 5963, 5982, 34789, 39418, 35326, 19721, 27644, 5686, 957, 39106, 36651, 12342, + 8617, 28813, 27650, 19304, 28476, 8283, 33758, 23326, 37386, 12189, 27760, 2708, 5210, 9664, 28220, 17052, + 21736, 20037, 5372, 17259, 37771, 29146, 38113, 16818, 25504, 32972, 29726, 25270, 40824, 2532, 35686, 32065, + 21371, 24532, 7658, 10257, 37832, 39383, 14028, 39384, 37235, 15685, 634, 22443, 21223, 17133, 36749, 22444, + 1902, 18024, 21375, 41241, 39397, 14605, 11961, 29601, 39676, 11963, 10377, 36071, 40723, 39677, 25290, 6440, + 40143, 21725, 8186, 15317, 34120, 27536, 16087, 8429, 14044, 29079, 29786, 34272, 19085, 18744, 9230, 41250, + 40563, 702, 12150, 39419, 16090, 16831, 6048, 6056, 6050, 6057, 6069, 6074, 6103, 6091, 6086, 6118, + 6123, 6124, 6168, 6171, 6182, 6193, 6185, 6191, 6184, 6194, 6228, 6253, 6268, 6258, 6269, 6277, + 6285, 6227, 6330, 6340, 6353, 6341, 6346, 6410, 6419, 6416, 6426, 6456, 6428, 6434, 6446, 6425, + 6479, 6487, 6507, 6491, 6493, 6498, 6525, 6553, 6549, 6550, 6608, 6603, 6623, 6605, 6646, 6635, + 6643, 6639, 6650, 6677, 6670, 6667, 6685, 6716, 6736, 6805, 6785, 6777, 6758, 6778, 6771, 6843, + 6826, 6841, 6823, 6847, 6819, 6825, 6909, 6880, 6889, 6951, 6927, 6914, 7048, 7064, 7063, 7106, + 7105, 7110, 7109, 7130, 22358, 1781, 41179, 37306, 19031, 32448, 35331, 31835, 1443, 12580, 8034, 22616, + 21892, 13590, 39938, 40916, 33575, 3263, 5393, 32193, 40756, 37348, 33687, 39772, 8588, 9186, 25424, 28208, + 25502, 12605, 15273, 2286, 19731, 39814, 12581, 18795, 27949, 12190, 36486, 30968, 24546, 10483, 35925, 11519, + 24179, 12459, 32656, 23087, 13378, 40582, 39942, 41203, 18909, 28230, 21738, 26044, 11830, 25199, 21903, 37402, + 22780, 12638, 29927, 30970, 3279, 12045, 15884, 18912, 1574, 26068, 40587, 17002, 4693, 30178, 36925, 26592, + 14093, 35065, 16547, 35024, 738, 1774, 30186, 40196, 13512, 5896, 31155, 9519, 4136, 35073, 32613, 3320, + 15606, 5194, 40632, 33498, 7138, 7153, 7171, 7178, 7163, 7162, 7173, 7191, 7196, 7220, 7205, 7207, + 7218, 7257, 7236, 7239, 7269, 7228, 7240, 7296, 7299, 7321, 7322, 7307, 7314, 7313, 7412, 7363, + 7360, 7380, 7379, 7376, 7377, 7387, 7388, 7393, 7409, 7423, 7417, 7419, 7415, 7449, 7462, 7463, + 7487, 7494, 7489, 7492, 7497, 7562, 7576, 7558, 7565, 7556, 7561, 7592, 7613, 7595, 7645, 7654, + 7650, 7655, 7660, 7661, 7686, 7698, 7697, 7724, 7706, 7721, 7687, 7699, 7711, 7762, 7757, 7795, + 7778, 7788, 7787, 7912, 7822, 8275, 7879, 7842, 7876, 7917, 7927, 8023, 7995, 7944, 7980, 7909, + 7939, 7929, 27946, 9358, 40701, 31051, 30197, 34275, 24489, 34973, 34974, 29414, 3004, 29278, 5919, 14665, + 17748, 31591, 31377, 15906, 4145, 38841, 15806, 15802, 3278, 4790, 22722, 38218, 4701, 24116, 24508, 6310, + 38223, 18467, 24197, 3973, 27142, 8156, 23881, 3982, 10636, 23244, 10307, 26818, 7684, 20312, 24864, 40302, + 18026, 18369, 1803, 563, 27745, 10663, 14148, 5911, 35836, 27380, 14140, 24870, 22832, 26451, 40406, 2481, + 5464, 4815, 30253, 14176, 15229, 14178, 16653, 22345, 3463, 19489, 40191, 30428, 32698, 28108, 24295, 34192, + 40511, 37545, 10164, 2455, 1206, 35567, 6142, 26225, 4900, 40199, 20890, 9091, 24157, 20437, 727, 2415, + 22285, 18039, 7963, 7977, 8014, 8278, 7908, 8276, 8091, 8112, 8105, 8107, 8098, 23067, 8117, 8095, + 8124, 8165, 8177, 8255, 8192, 8160, 8280, 8146, 8157, 8144, 8201, 8148, 8183, 8145, 8151, 8147, + 8200, 8277, 8292, 8288, 8303, 8326, 8354, 8344, 8345, 8347, 8453, 8366, 8372, 8387, 8388, 8375, + 8425, 8430, 8422, 8426, 8479, 8486, 8489, 8501, 8500, 8493, 8492, 8524, 8529, 8491, 8559, 8539, + 8542, 8552, 8540, 8560, 8580, 8591, 8589, 8602, 8640, 8656, 8649, 8624, 8645, 8641, 8635, 8646, + 8680, 8698, 8686, 9855, 8679, 8702, 8771, 8765, 8766, 8777, 8780, 8781, 8801, 8851, 8797, 8818, + 21793, 7981, 7243, 8428, 7332, 26982, 19612, 29224, 24460, 20466, 19202, 9638, 24710, 3475, 36081, 35076, + 1137, 16125, 32710, 28278, 25559, 12140, 10173, 39960, 16263, 5247, 2429, 7871, 29795, 16886, 16488, 14557, + 9388, 13016, 9999, 29611, 31979, 39729, 3335, 28109, 40326, 41251, 29499, 2430, 8616, 8400, 15895, 37851, + 21909, 32729, 23023, 16270, 41006, 1142, 1283, 8774, 28568, 9328, 36938, 12902, 5394, 3490, 39281, 26164, + 40054, 18759, 17890, 15082, 8036, 38433, 9107, 23685, 15083, 4206, 2436, 41062, 2035, 33760, 1408, 28286, + 32274, 22883, 33226, 10954, 35493, 37676, 4232, 18939, 31167, 6172, 27597, 12360, 13689, 33227, 19796, 7349, + 8826, 8833, 8836, 8869, 8879, 8874, 8894, 8899, 8881, 8895, 8871, 8887, 8870, 8935, 8938, 8941, + 8966, 8965, 8990, 8985, 8988, 9017, 9016, 9037, 9034, 9036, 9041, 9100, 9245, 9241, 9106, 9075, + 9081, 9080, 9079, 9171, 9128, 9154, 9143, 9134, 9136, 9216, 9219, 9215, 9228, 9250, 9247, 9290, + 9294, 9302, 9309, 9313, 9324, 9331, 9355, 9344, 9346, 9347, 9345, 9389, 9384, 9442, 9408, 9434, + 9405, 9448, 9473, 9488, 9528, 9501, 9498, 9517, 9497, 9500, 9505, 9568, 9585, 9573, 9581, 9631, + 9624, 9645, 9629, 9621, 9702, 9703, 9724, 9745, 9741, 9775, 9815, 9829, 9842, 9852, 4101, 7729, + 40212, 11512, 24176, 24543, 20301, 23867, 9246, 27150, 37860, 10424, 28826, 37751, 3775, 25751, 39290, 21561, + 23871, 32734, 18460, 22371, 6423, 40655, 3924, 26184, 40342, 23917, 18391, 12925, 2141, 11820, 1323, 5576, + 4530, 34331, 2288, 40435, 22545, 22735, 37403, 29872, 38280, 26185, 9666, 35511, 11110, 2803, 15620, 22891, + 38216, 12203, 18558, 2445, 21407, 28316, 4699, 5930, 28320, 16661, 17640, 32657, 1994, 20176, 26186, 5326, + 17691, 5126, 8136, 13052, 20456, 16020, 5072, 13388, 28288, 16577, 32670, 18831, 27131, 38058, 23566, 22021, + 23567, 22022, 8443, 14681, 6469, 18819, 34425, 5260, 25846, 40367, 18405, 23712, 17474, 27152, 9876, 9871, + 9885, 9904, 9895, 9903, 9902, 9940, 9948, 9960, 9997, 9959, 9985, 9990, 9961, 10028, 10024, 10117, + 10114, 10060, 10053, 10113, 10059, 10073, 10051, 10046, 10147, 10160, 10166, 10231, 10230, 10219, 10210, 10245, + 10243, 10265, 10247, 10263, 2, 10318, 10366, 10381, 10361, 10329, 10336, 10332, 10331, 10375, 10215, 10355, + 10340, 10372, 10478, 10475, 10481, 10463, 10511, 10510, 10521, 10525, 10526, 10529, 10531, 10530, 10550, 10552, + 10541, 10572, 10573, 10575, 10641, 10660, 10634, 10617, 10613, 10615, 10748, 10742, 10755, 10788, 10800, 10823, + 10797, 10828, 11132, 10831, 10937, 10904, 10931, 10903, 10955, 10899, 11135, 10927, 16374, 16026, 37099, 37762, + 10240, 39121, 28584, 29215, 21586, 3842, 36044, 23568, 29029, 40448, 40116, 7224, 27934, 40115, 23884, 40688, + 29034, 18845, 18634, 13077, 30175, 36458, 37443, 16319, 18426, 24203, 17489, 16389, 23726, 37776, 39922, 24839, + 17490, 1428, 6517, 41133, 17003, 27697, 19143, 36463, 37788, 40697, 37463, 7237, 26584, 38932, 26593, 21817, + 10353, 21219, 4826, 38819, 23648, 38573, 1129, 611, 31340, 26095, 15253, 25531, 1207, 4755, 36301, 38944, + 3528, 28611, 11133, 8395, 14615, 20614, 40081, 16867, 27990, 10664, 29606, 2416, 17884, 40461, 529, 16635, + 7084, 24711, 10507, 32364, 8016, 17038, 37731, 18760, 14496, 23311, 553, 38759, 10897, 11017, 11134, 11051, + 11033, 11053, 11037, 11139, 11141, 11154, 11168, 11167, 11202, 11196, 11195, 11203, 11254, 11252, 11251, 11253, + 11269, 11445, 11308, 11317, 9870, 11372, 11393, 11399, 11391, 11411, 11423, 11401, 11395, 11389, 11382, 11458, + 11466, 11484, 11518, 11515, 11526, 11478, 11481, 11490, 11497, 11585, 11562, 11556, 11561, 11587, 11595, 11614, + 11641, 11593, 11676, 11658, 11692, 11686, 11784, 11714, 11744, 11739, 11736, 11740, 11717, 11734, 11716, 11718, + 11730, 11727, 11867, 11865, 11870, 11899, 11888, 11923, 11953, 11960, 11971, 11970, 11993, 11984, 12005, 12033, + 11985, 12003, 12084, 12091, 12122, 12092, 12149, 12172, 12116, 12165, 9826, 11248, 25875, 28821, 1446, 20270, + 40981, 13151, 16920, 33037, 7888, 21897, 944, 9192, 33428, 12843, 40466, 28832, 25878, 7674, 13311, 20543, + 25880, 25881, 21902, 31620, 17594, 15779, 2045, 11355, 27419, 40991, 32416, 29880, 21596, 17304, 41305, 5596, + 21597, 29426, 16460, 27616, 14252, 8883, 39310, 14255, 36878, 12504, 2589, 40072, 34040, 37669, 10638, 36927, + 10354, 30311, 25324, 30918, 24603, 20884, 40718, 29702, 21704, 7818, 12520, 27232, 4254, 22445, 39193, 26096, + 10647, 39561, 12287, 7569, 37839, 25327, 5145, 13856, 7401, 4756, 14300, 37958, 505, 7861, 39679, 4428, + 3795, 10655, 37959, 31805, 7982, 32973, 26608, 1846, 40308, 24702, 12096, 12087, 12110, 12186, 12083, 12100, + 12113, 12124, 12141, 12257, 12266, 12316, 12678, 12406, 12323, 12252, 12282, 12289, 12262, 12265, 12326, 12263, + 12437, 12422, 12290, 12423, 12562, 12482, 12600, 12489, 12473, 12538, 12488, 12533, 12502, 12528, 12527, 12471, + 12472, 12500, 12480, 12487, 12479, 12521, 12477, 12731, 12698, 12686, 12690, 12704, 12683, 12756, 12772, 12807, + 12798, 12808, 12809, 12842, 12827, 12829, 12828, 12836, 12850, 12863, 12849, 12847, 12869, 12851, 12891, 12861, + 12856, 12857, 12846, 12882, 12987, 12996, 12984, 13026, 13005, 12978, 12990, 13017, 12981, 12994, 12993, 13104, + 15217, 13136, 13132, 13105, 13095, 13137, 13149, 13096, 18040, 40309, 26475, 8463, 34826, 7983, 30092, 39146, + 5039, 3994, 26842, 39899, 32167, 41101, 14191, 636, 24774, 20615, 27363, 41174, 15894, 14040, 25337, 10174, + 32985, 13675, 40148, 3802, 9307, 530, 14890, 15867, 10929, 4451, 11324, 8809, 28900, 13676, 15693, 13438, + 24955, 8331, 19203, 33867, 1015, 32355, 8003, 8778, 6205, 25405, 29420, 36082, 16737, 32986, 14772, 8316, + 5975, 29661, 27637, 13300, 32482, 11748, 14891, 13018, 14779, 3424, 20246, 39156, 18895, 3336, 24637, 27254, + 680, 29662, 32622, 11328, 24219, 8841, 33427, 29094, 29719, 32864, 10674, 31826, 8017, 29475, 28134, 6569, + 16091, 7872, 14050, 11091, 39420, 34384, 14222, 7768, 13108, 13113, 13100, 13099, 13117, 13128, 13111, 13098, + 13239, 13222, 13223, 13226, 13217, 13256, 13268, 13265, 13263, 13262, 13324, 13302, 13291, 13368, 13347, 13377, + 13348, 13343, 13329, 13333, 13337, 13341, 13335, 14974, 13433, 13430, 13428, 13413, 13429, 13418, 13411, 13420, + 13475, 13419, 13441, 13518, 13529, 13515, 13516, 13501, 13520, 13577, 13565, 13564, 13569, 13583, 13562, 13699, + 13620, 13613, 14466, 13631, 13659, 13686, 13704, 13640, 13644, 13772, 13835, 13788, 12387, 13789, 13797, 13803, + 13778, 13799, 13802, 13792, 13837, 13859, 13839, 13847, 13838, 13848, 13877, 13894, 13901, 13887, 13900, 13932, + 13968, 13942, 13965, 13931, 13945, 13943, 12560, 33722, 25350, 40917, 3132, 6738, 17192, 18934, 17584, 3814, + 25010, 26479, 23312, 40560, 23314, 30362, 23861, 32374, 27194, 30609, 28952, 30363, 8518, 30488, 1026, 40547, + 2205, 9827, 4776, 19074, 18312, 23432, 38711, 1284, 4326, 18078, 20197, 23178, 24172, 29274, 40918, 9708, + 41007, 31550, 40757, 33305, 17613, 13906, 7433, 25680, 20409, 37327, 40962, 7255, 18935, 33675, 36332, 26411, + 23564, 33688, 32452, 12910, 15463, 32383, 25659, 20198, 12174, 6508, 3727, 5706, 20412, 20286, 37582, 33023, + 775, 27664, 24544, 1409, 11374, 8812, 4515, 20252, 30818, 8219, 30723, 29690, 9005, 20302, 32879, 17545, + 40923, 1499, 37925, 36094, 29108, 9270, 13888, 13928, 14029, 14051, 14026, 14180, 14042, 14058, 14023, 14036, + 14054, 14049, 14025, 14079, 14110, 14096, 14095, 14158, 14154, 14146, 14167, 14119, 14132, 14153, 14143, 14133, + 14117, 14209, 14217, 14266, 14251, 14243, 14294, 14298, 14286, 14293, 14285, 14301, 14328, 14329, 14309, 14312, + 14339, 14314, 14331, 14315, 14442, 14381, 14383, 14389, 14379, 14386, 14478, 14456, 14545, 14698, 14549, 14547, + 14646, 14590, 14623, 14580, 14595, 14627, 14658, 14638, 14607, 14581, 14622, 14602, 14612, 14706, 14716, 14705, + 14753, 14765, 14728, 14760, 14810, 14990, 14831, 14866, 14855, 14948, 14853, 14822, 14827, 14850, 15019, 15032, + 15027, 15016, 15018, 15057, 39797, 37926, 3270, 2704, 5062, 31989, 37583, 40963, 33517, 36533, 30882, 8813, + 33761, 36430, 13993, 35927, 40529, 21344, 670, 9188, 22073, 40106, 12926, 4357, 24971, 27504, 37811, 31993, + 4725, 31593, 25427, 28917, 8234, 37861, 3140, 8592, 25620, 10972, 38051, 29018, 32392, 28047, 39166, 40986, + 28918, 11586, 2213, 1324, 7803, 4661, 16931, 28321, 34542, 31756, 40988, 16690, 14796, 23873, 19460, 39506, + 18910, 20825, 22736, 17449, 33886, 40965, 12204, 26249, 28231, 18947, 1048, 35343, 25953, 20726, 23973, 11905, + 32429, 12621, 26179, 33449, 25162, 33887, 28240, 24032, 38351, 41272, 39439, 26341, 25882, 17912, 37404, 7217, + 17692, 4336, 41212, 13177, 15051, 15072, 15059, 15053, 15061, 15112, 15111, 15116, 8636, 15122, 15127, 15153, + 15138, 15148, 15184, 15189, 15187, 15199, 15202, 15234, 15254, 15263, 15275, 15283, 15295, 15290, 15297, 15310, + 15312, 15316, 15332, 15402, 15340, 15343, 15356, 15379, 15375, 15347, 15397, 9863, 15401, 15413, 15420, 15421, + 15430, 15438, 15483, 15489, 15485, 15488, 15507, 15506, 15540, 15567, 15561, 15570, 15577, 15588, 15595, 15603, + 15639, 15642, 15653, 15675, 15698, 15681, 15695, 15708, 15723, 15731, 15734, 15732, 15750, 15766, 15753, 15751, + 15785, 15795, 15808, 15823, 15837, 15820, 15859, 15866, 15855, 15854, 15896, 15901, 15898, 15903, 15933, 15919, + 15944, 9513, 25253, 2808, 25691, 33451, 11831, 11237, 41125, 31621, 23975, 37950, 4993, 26771, 11839, 31883, + 26048, 13056, 13257, 11356, 38191, 4535, 33072, 13485, 1364, 5231, 35976, 21750, 28241, 35977, 26189, 33538, + 12646, 1718, 23832, 16375, 23096, 34019, 23371, 22388, 35107, 20685, 16814, 32916, 41131, 15885, 36713, 33713, + 16706, 32130, 2737, 13561, 18635, 2741, 36384, 2188, 25227, 32139, 41155, 41134, 19241, 17008, 16437, 16726, + 17568, 10622, 25315, 40274, 39178, 5947, 31801, 36313, 28945, 37800, 32356, 4711, 32948, 7826, 7827, 23560, + 1847, 22870, 32538, 38907, 8519, 36341, 9429, 41213, 28693, 2352, 23551, 31035, 36369, 16707, 28708, 18636, + 30456, 8487, 16001, 15997, 15998, 16037, 16038, 16081, 16101, 16117, 16115, 16130, 16129, 16157, 16159, 16177, + 16197, 16188, 16200, 16234, 16247, 16240, 16294, 16338, 16330, 16328, 16326, 16347, 16336, 16323, 16342, 16340, + 16404, 16400, 16414, 16405, 16439, 16442, 16479, 16481, 16471, 16474, 16465, 16508, 16524, 16541, 16543, 16545, + 16589, 16590, 16593, 16619, 16616, 16615, 16670, 16644, 16671, 16695, 16749, 16745, 16794, 16750, 16733, 16683, + 16639, 16786, 16784, 16828, 16829, 16840, 16850, 16862, 16865, 16925, 16929, 17392, 16855, 16881, 17034, 17388, + 17022, 17046, 17018, 17136, 17112, 17079, 17125, 17082, 17074, 17085, 17132, 17072, 17083, 17154, 17091, 17101, + 19100, 19997, 9088, 40240, 14393, 19562, 20385, 9305, 29081, 14773, 8004, 26714, 9308, 40633, 37307, 199, + 7184, 27651, 19309, 18315, 508, 7186, 3007, 30824, 1306, 12622, 3699, 18321, 14799, 20177, 38902, 19121, + 22553, 12239, 12248, 18996, 20079, 4932, 34765, 36830, 36826, 7603, 415, 34853, 9147, 23893, 38123, 8541, + 35767, 40311, 35453, 25406, 25125, 23970, 11329, 32366, 35839, 34877, 23913, 23777, 37060, 8814, 37590, 7276, + 26253, 7633, 26255, 17516, 21764, 23983, 8968, 3679, 7570, 10648, 3588, 4757, 7984, 31961, 974, 16161, + 22449, 18327, 39680, 24775, 31677, 32855, 31815, 15400, 11750, 11613, 32614, 26159, 10675, 13238, 5395, 26165, + 17161, 17078, 17148, 17088, 17100, 17070, 16909, 17390, 17396, 17410, 17404, 17399, 17470, 17416, 17402, 17403, + 17401, 17498, 17500, 17536, 17524, 17523, 17522, 17581, 17573, 17574, 17582, 17571, 17601, 17625, 17632, 17628, + 17621, 17624, 17641, 17650, 17654, 17645, 17677, 17656, 17643, 16604, 16667, 17744, 17750, 17743, 17738, 17758, + 17800, 17784, 17759, 17793, 17883, 17872, 17908, 17906, 17873, 17871, 17923, 17880, 17939, 17960, 17954, 17869, + 18015, 18047, 18069, 18073, 18027, 18198, 18043, 18018, 17998, 18028, 18181, 18184, 18189, 18188, 18203, 18216, + 18237, 18222, 18235, 18214, 18207, 18242, 18213, 18301, 18322, 18355, 18374, 18357, 18373, 18490, 3621, 33762, + 3633, 40924, 30323, 11637, 10772, 10484, 22708, 17450, 10778, 388, 17913, 22308, 24117, 319, 11840, 33778, + 5413, 16588, 9021, 9024, 9022, 6042, 25643, 20953, 6473, 29465, 22450, 35446, 24887, 12713, 14617, 3911, + 19086, 12344, 38443, 18527, 12216, 16626, 12055, 36714, 11266, 35659, 24244, 37841, 5093, 10650, 39460, 22105, + 39147, 3085, 39261, 36833, 30232, 29359, 7086, 34266, 29432, 33721, 10275, 26807, 17805, 14055, 1143, 5631, + 9790, 30929, 33677, 22828, 4503, 6116, 21244, 29510, 14568, 4516, 15905, 17570, 17440, 31024, 16010, 17452, + 17460, 4531, 26764, 27831, 29478, 16021, 21572, 39509, 5128, 21658, 24133, 21295, 29481, 29483, 18377, 18455, + 18457, 18454, 18507, 18495, 18546, 18554, 18567, 18561, 18587, 18584, 18602, 18586, 18590, 18653, 18650, 18652, + 18656, 18838, 18743, 18843, 18747, 18710, 18726, 18790, 18732, 18702, 18698, 18768, 18856, 18874, 18892, 18876, + 18885, 18903, 18893, 18896, 18922, 18928, 18920, 18923, 18931, 18924, 18969, 18970, 18968, 18975, 19014, 19016, + 6920, 6921, 19048, 19056, 19051, 19050, 19053, 19054, 19088, 19105, 19116, 19094, 19106, 19110, 19111, 19112, + 19164, 19205, 19188, 19191, 19189, 19246, 19252, 19272, 19273, 19275, 19270, 19292, 19322, 19319, 19325, 19336, + 19347, 19348, 19344, 19349, 19385, 19383, 19378, 19423, 19450, 19437, 19444, 19446, 18428, 38870, 27734, 28012, + 38887, 35622, 24575, 15481, 2395, 8632, 1880, 11384, 35553, 25316, 25595, 37630, 2496, 9963, 7602, 22233, + 22164, 36737, 25138, 30952, 23238, 22496, 31433, 31434, 15484, 5948, 7496, 441, 1892, 24766, 29258, 40825, + 15641, 39386, 21316, 22853, 40874, 8102, 32156, 20763, 24695, 15349, 3523, 34729, 22120, 3409, 33330, 7078, + 10544, 40875, 9510, 3313, 29408, 4758, 19699, 32841, 32842, 19351, 33103, 21624, 30398, 30956, 33384, 14141, + 36834, 10535, 17796, 26222, 29538, 19704, 4258, 26705, 23810, 5449, 14711, 4636, 33382, 33175, 30049, 3321, + 21174, 6282, 21151, 22573, 9153, 17150, 38808, 4768, 13582, 17610, 27518, 1535, 19380, 19478, 19490, 19485, + 19483, 19476, 19525, 19549, 19558, 19575, 19552, 19553, 19611, 19599, 19622, 19623, 19645, 19666, 19629, 19681, + 19693, 19691, 19702, 19725, 19730, 19718, 19690, 19696, 19708, 19762, 19749, 19751, 19775, 19784, 19770, 19783, + 19807, 19829, 19841, 19850, 19861, 19886, 19857, 19950, 19943, 19969, 19967, 19992, 20027, 20041, 20030, 20000, + 20007, 19996, 20075, 20122, 20117, 20115, 20152, 20123, 20130, 20194, 20190, 20192, 20236, 20223, 20230, 20232, + 20244, 20267, 20279, 20283, 20284, 20304, 20294, 20297, 20310, 20309, 20338, 20325, 20371, 20426, 20421, 20436, + 20434, 20432, 20468, 20493, 20469, 20478, 20467, 20512, 20521, 20523, 19070, 22664, 16738, 15999, 4203, 5190, + 21176, 20925, 25338, 26706, 4321, 14411, 6206, 22523, 9783, 31103, 19760, 21242, 40424, 3610, 19108, 21952, + 5687, 158, 21122, 27465, 37918, 39936, 25539, 29796, 30707, 13447, 12729, 6504, 1260, 2905, 23820, 30237, + 27935, 28814, 28023, 40524, 35865, 17661, 12345, 22533, 32872, 18906, 21942, 2913, 18775, 9793, 22128, 4062, + 13280, 7881, 40391, 18940, 13367, 36514, 18865, 33987, 4239, 29639, 21350, 17679, 4787, 9543, 32651, 29000, + 7265, 39501, 13376, 10882, 4782, 25733, 32453, 28168, 7672, 40366, 5158, 15776, 21737, 14950, 4032, 14742, + 16204, 17511, 30010, 23356, 4798, 1735, 34014, 21149, 31120, 38151, 20532, 20552, 20533, 20535, 20542, 20537, + 20555, 20564, 20574, 20609, 20656, 20664, 20585, 20630, 20628, 20589, 20712, 20703, 20735, 20834, 20754, 20753, + 20756, 20752, 20808, 20817, 20810, 20802, 20816, 20782, 20786, 20814, 20792, 20822, 20843, 20858, 21165, 20881, + 20865, 20877, 20868, 20937, 20934, 20935, 20954, 20950, 20981, 20977, 20987, 21039, 21070, 21108, 21104, 21141, + 21144, 21166, 21173, 21184, 21198, 21202, 21210, 21252, 21220, 21216, 21211, 21266, 21265, 21318, 21336, 21317, + 21334, 21368, 21366, 21369, 21404, 21403, 21392, 21421, 21444, 21439, 21445, 21480, 21485, 21510, 21577, 21512, + 21555, 21556, 21508, 21619, 21631, 21628, 21645, 21625, 32410, 1570, 33312, 15790, 16213, 34337, 18628, 12065, + 37968, 19174, 24840, 38152, 18998, 21263, 37973, 23643, 31085, 9490, 17909, 9479, 13410, 12550, 8548, 3874, + 20199, 21562, 8697, 13130, 5977, 39410, 33388, 28569, 32322, 2499, 31816, 37177, 33308, 14570, 14357, 33196, + 26571, 14297, 28626, 27099, 28754, 23128, 23129, 9394, 11238, 29344, 31980, 5343, 7358, 21984, 28597, 7242, + 4091, 18852, 18046, 31962, 24471, 22142, 15738, 8018, 38211, 7769, 16889, 37042, 16489, 37308, 1945, 21430, + 14426, 11514, 15464, 1500, 20819, 5999, 6318, 712, 2519, 35929, 2333, 18528, 5068, 33989, 35098, 5508, + 5262, 23958, 18683, 35601, 12400, 13191, 12056, 23372, 21627, 21674, 21683, 21692, 21703, 21694, 21724, 21722, + 21719, 21752, 21789, 21797, 21807, 21815, 21834, 21841, 21839, 21852, 21899, 21904, 21875, 21908, 21912, 21915, + 21913, 21964, 21947, 21950, 21911, 21985, 21982, 21993, 22003, 22004, 21995, 22007, 22013, 22016, 22012, 22035, + 22031, 22054, 22049, 22059, 22072, 22103, 22104, 22094, 22101, 22118, 22137, 22141, 22159, 22165, 22169, 22179, + 22178, 22210, 22187, 22204, 22209, 22230, 22236, 22248, 22256, 22253, 22247, 22284, 22274, 22273, 22297, 22302, + 22320, 22315, 22325, 22338, 22351, 22359, 22352, 22357, 22416, 22372, 22343, 22360, 22401, 22410, 22424, 22439, + 22482, 22421, 22427, 22466, 22521, 22497, 18687, 18637, 2745, 27488, 12928, 22829, 34677, 34702, 2389, 16649, + 29460, 29364, 13328, 22342, 35640, 2607, 20188, 8369, 37221, 11046, 40855, 11728, 28117, 39609, 29985, 30661, + 23455, 30912, 25271, 7919, 33594, 11140, 14834, 9014, 335, 3900, 19619, 25369, 10157, 36117, 36817, 35661, + 24200, 22570, 29063, 5550, 17099, 36665, 887, 35557, 21629, 21270, 1886, 1764, 33421, 35017, 32066, 10627, + 38458, 6129, 5937, 21487, 10836, 19694, 26740, 9083, 1183, 30779, 7938, 40707, 5616, 12505, 4593, 37558, + 33919, 8678, 17111, 25390, 2631, 3157, 37236, 10193, 40858, 17774, 31198, 12506, 9504, 4446, 9039, 9457, + 13340, 36981, 40714, 7172, 19529, 39950, 22508, 22522, 22504, 22484, 22560, 22575, 22618, 22595, 22636, 22654, + 22647, 22690, 22693, 22704, 22748, 22720, 22743, 22757, 22762, 22773, 22793, 22787, 22812, 22818, 22819, 22843, + 22846, 22864, 22839, 22841, 22858, 22840, 22848, 22907, 23008, 22918, 22932, 22974, 22990, 22965, 22978, 23011, + 23039, 23126, 23037, 23066, 23070, 23068, 23072, 2111, 23105, 23107, 23110, 23108, 23112, 23134, 23133, 23161, + 23163, 23150, 23561, 23144, 23139, 23148, 23177, 23146, 23142, 23229, 23284, 23230, 23234, 23271, 23263, 23253, + 23222, 23309, 23237, 23220, 23282, 23413, 23398, 23392, 23396, 23400, 23465, 23470, 23527, 23443, 23450, 23451, + 23452, 23459, 23444, 23572, 23638, 40193, 11316, 7850, 8309, 4899, 4110, 14030, 7076, 212, 24042, 3465, + 22855, 13851, 16597, 27355, 40455, 4934, 38234, 37472, 6438, 30674, 16856, 6276, 7856, 25289, 36134, 2116, + 37873, 28126, 3304, 3162, 31199, 1650, 31464, 8834, 40304, 20608, 40458, 41242, 30044, 24604, 28297, 3163, + 22347, 19849, 33298, 14033, 3052, 15028, 34365, 4879, 10064, 4880, 12762, 30449, 27979, 21705, 26418, 32342, + 30978, 13652, 20986, 20798, 29848, 8975, 19526, 4449, 5671, 24768, 6143, 41000, 16162, 18724, 30787, 21521, + 16046, 23069, 38016, 8578, 9822, 19067, 3797, 4197, 38703, 19814, 16868, 803, 24329, 14735, 24245, 5625, + 13570, 13896, 24047, 28561, 23589, 23590, 23647, 23628, 23645, 23656, 23622, 23632, 23674, 23623, 23666, 8392, + 23783, 23746, 23747, 23740, 23773, 23818, 23802, 23823, 23846, 23849, 23836, 23860, 23891, 23886, 23902, 23887, + 23944, 23947, 23943, 23964, 24021, 24010, 24006, 23989, 24044, 24065, 24039, 24040, 24077, 24113, 24108, 24099, + 24091, 24088, 24093, 24136, 12696, 24135, 24139, 24144, 24209, 24207, 24206, 24243, 24249, 24254, 24235, 24266, + 24251, 24302, 24323, 24345, 24347, 24346, 24348, 24349, 24356, 24390, 24381, 24383, 24379, 24399, 24401, 24417, + 24469, 24445, 24531, 24522, 24524, 24616, 24576, 24568, 24592, 24579, 24716, 24674, 24707, 24675, 24708, 24686, + 24684, 24773, 8804, 11162, 24248, 149, 30475, 1038, 40049, 12871, 17935, 28718, 29263, 5386, 11022, 10382, + 4226, 2901, 11319, 7507, 16256, 26151, 34487, 35447, 29378, 23273, 30345, 2417, 39230, 30162, 14262, 1392, + 36041, 19851, 2052, 22228, 6115, 24536, 15358, 32539, 30403, 37168, 37019, 8189, 17535, 33746, 21013, 2427, + 31047, 4285, 32615, 1440, 19650, 154, 36412, 16126, 16127, 13234, 20245, 41296, 41297, 41038, 25511, 31734, + 35195, 155, 24778, 12884, 8007, 18930, 14047, 22305, 10665, 10666, 10756, 34621, 29746, 40739, 24384, 20092, + 11492, 26617, 8348, 40085, 13131, 30694, 1924, 30537, 12551, 6499, 35077, 28130, 24957, 39084, 11881, 26849, + 16335, 40906, 24862, 24865, 24873, 24890, 24878, 24907, 24991, 24922, 24972, 24929, 24921, 24944, 24933, 24998, + 25015, 25014, 25029, 9626, 25038, 25040, 25109, 25071, 25058, 25053, 25124, 25126, 25148, 25156, 25172, 25181, + 25208, 25219, 25220, 25218, 25228, 25234, 25243, 25251, 25254, 25256, 25264, 25263, 25261, 25283, 25318, 25302, + 25298, 25296, 25311, 25308, 25352, 25353, 25371, 25384, 25383, 25414, 25391, 25433, 25421, 25413, 25392, 25389, + 25462, 25509, 25505, 25537, 25546, 25586, 25570, 25576, 25541, 25598, 25596, 25594, 25607, 25619, 25642, 25638, + 25686, 25706, 25704, 25724, 25725, 25738, 25740, 25763, 25766, 25786, 25829, 25833, 25827, 25843, 25849, 25853, + 34900, 37496, 19715, 37801, 27364, 40419, 9356, 25198, 33904, 11147, 30695, 36918, 27867, 36273, 26858, 4266, + 26939, 37805, 39097, 25562, 17181, 25031, 37573, 17182, 14562, 31531, 3905, 33552, 29798, 18232, 12016, 5777, + 23855, 41039, 22988, 4850, 37501, 3912, 37309, 22065, 23071, 20908, 31684, 7614, 37852, 25745, 2331, 20012, + 28268, 20486, 27868, 18233, 31685, 9161, 16480, 8356, 4888, 28804, 19163, 33751, 35037, 9643, 40958, 9705, + 41309, 29379, 2431, 22295, 5211, 26621, 16515, 18199, 5912, 29383, 19614, 29565, 4013, 160, 17420, 4505, + 22871, 24540, 13907, 4268, 13706, 30610, 29899, 2369, 37349, 35867, 40809, 1262, 18663, 2132, 38760, 16677, + 25866, 25898, 25910, 25919, 25934, 25942, 25944, 25967, 25970, 26008, 25994, 25998, 26069, 26076, 26098, 26089, + 26080, 26087, 26082, 26085, 26137, 26147, 26110, 26181, 26190, 26218, 26211, 26206, 26200, 26204, 26238, 26212, + 26260, 26263, 26324, 26337, 26330, 26309, 26293, 26301, 26321, 26373, 26367, 26369, 26396, 26395, 26404, 26406, + 26414, 26420, 26416, 26424, 26417, 26443, 26442, 26452, 26454, 26471, 26467, 26468, 26485, 26488, 26505, 26499, + 26516, 26531, 26538, 26525, 26536, 26526, 26523, 26521, 26600, 26573, 26580, 26576, 26578, 26607, 26595, 26585, + 26653, 3150, 26659, 26669, 26652, 26696, 26710, 26703, 26734, 26729, 26755, 26745, 26728, 26767, 23950, 19449, + 34396, 18079, 12552, 1543, 9711, 10030, 5569, 18763, 26550, 26378, 5570, 34001, 1946, 5698, 4853, 26629, + 33875, 10945, 299, 20094, 18517, 39905, 22937, 13273, 20151, 4506, 21457, 11777, 14787, 36162, 13142, 36088, + 9791, 3179, 11102, 26112, 15614, 23863, 19255, 38130, 38317, 16921, 30725, 12363, 23778, 26811, 19870, 21960, + 2798, 5780, 25687, 16746, 37063, 24057, 3920, 11177, 12913, 19341, 37857, 732, 36788, 18797, 25237, 6984, + 29109, 7477, 14927, 7200, 25568, 7623, 16011, 27564, 34223, 33518, 8222, 5317, 31218, 6173, 27666, 32652, + 31848, 18384, 30898, 26484, 12914, 28271, 18093, 37369, 31990, 27767, 21733, 33767, 37931, 37350, 26774, 26799, + 26801, 26795, 26793, 26824, 26823, 26839, 26837, 26848, 26830, 26821, 26829, 26898, 26902, 27144, 26909, 26651, + 26924, 26923, 26913, 27143, 26962, 26964, 26969, 26976, 26973, 26970, 27006, 27002, 26993, 26997, 27039, 27016, + 27035, 27100, 27058, 27018, 27036, 27084, 27115, 27045, 26999, 27017, 27081, 27027, 26994, 27000, 27034, 27030, + 27024, 27025, 27157, 27163, 27169, 27165, 27176, 27184, 27182, 27177, 27193, 27180, 27265, 27221, 27237, 27229, + 27215, 27256, 27219, 27249, 27238, 27246, 27211, 27286, 27284, 27290, 27320, 27309, 27322, 27313, 27314, 27312, + 27315, 27308, 27337, 27345, 27351, 27340, 27338, 27353, 27383, 27361, 27378, 27386, 31698, 10295, 105, 11806, + 11807, 12609, 4407, 32450, 30413, 20340, 16836, 13247, 2308, 26639, 23955, 17453, 15374, 37591, 4960, 29201, + 28778, 38605, 28272, 32108, 7266, 6081, 33038, 9193, 27319, 13162, 10200, 25804, 34005, 35090, 565, 6581, + 22797, 30732, 21652, 3832, 19330, 22723, 12624, 38189, 3192, 39117, 7124, 21290, 36436, 4572, 32658, 23344, + 7188, 13042, 33695, 15955, 1452, 5923, 20170, 16354, 14002, 24503, 24182, 17706, 32219, 28064, 18869, 35960, + 33705, 32934, 35961, 16179, 16760, 13541, 5581, 39597, 862, 35099, 20670, 11439, 1567, 27929, 28695, 29901, + 24512, 24068, 30843, 18270, 11822, 21974, 8598, 37937, 837, 17285, 27327, 3935, 27356, 27424, 27427, 27435, + 27433, 27440, 27441, 27458, 27456, 27474, 27472, 27496, 27517, 27521, 27540, 27537, 27555, 27568, 27557, 27561, + 27571, 27584, 27579, 27576, 27636, 27659, 27654, 27626, 27619, 27614, 27612, 27702, 27749, 27708, 27748, 27706, + 4438, 27003, 27722, 27704, 27778, 27820, 27817, 27844, 27842, 27839, 27838, 27841, 27864, 27884, 27923, 27939, + 27940, 27944, 27961, 27978, 27980, 27995, 28015, 28001, 28007, 27984, 28092, 27969, 28100, 28110, 28111, 28120, + 28153, 28154, 28152, 28173, 28199, 28175, 28228, 28193, 28204, 28184, 28261, 28275, 28276, 28308, 28300, 28294, + 28311, 28336, 28333, 28340, 28327, 28407, 28397, 28398, 28399, 28420, 63, 17981, 33779, 24340, 16313, 30171, + 31394, 25692, 25693, 23362, 18620, 27954, 29928, 19909, 37944, 22894, 37208, 34017, 12639, 14198, 33780, 24673, + 27955, 14199, 7810, 2047, 25205, 35992, 32293, 37106, 14532, 17559, 17518, 36239, 23959, 36370, 18406, 29713, + 30762, 37766, 18122, 35000, 19742, 10136, 15915, 16376, 12649, 5329, 19468, 16817, 16708, 11653, 7745, 39444, + 30855, 15963, 11267, 16982, 12657, 16773, 11281, 19133, 12240, 15967, 18848, 12968, 25821, 29043, 16719, 25012, + 32688, 36026, 19001, 19827, 1642, 27629, 32597, 3995, 10851, 33477, 4844, 7991, 33492, 18658, 11026, 10277, + 13360, 14636, 820, 34409, 38721, 38722, 15908, 1707, 31875, 27417, 28428, 28442, 28504, 28490, 28546, 28557, + 28556, 28551, 28596, 28601, 28589, 28593, 28592, 28612, 28631, 28617, 28636, 28632, 28645, 28684, 28662, 28674, + 28666, 28651, 28713, 28720, 28716, 28753, 28746, 28741, 28743, 28764, 28799, 28801, 28790, 28795, 28822, 28788, + 28827, 28856, 28864, 28858, 28880, 28877, 28897, 28895, 28908, 28896, 28946, 28936, 28935, 28943, 28938, 28972, + 28977, 28984, 29025, 29009, 29006, 29010, 29045, 29044, 29053, 29049, 29074, 29114, 29120, 29071, 29149, 29182, + 29204, 29174, 29169, 29164, 29222, 29226, 29233, 29269, 29247, 29262, 29252, 29316, 29309, 29354, 29365, 29370, + 29417, 29422, 29430, 29436, 29428, 29457, 29462, 29467, 5849, 24582, 6060, 31912, 14852, 38933, 26501, 36928, + 9973, 40831, 32528, 7370, 6913, 416, 3531, 23653, 30919, 37709, 37710, 15029, 23255, 29598, 23256, 37546, + 14861, 11672, 24246, 23257, 39953, 20799, 30450, 7604, 7605, 10167, 8170, 25144, 804, 21231, 28988, 22865, + 3471, 14618, 17151, 8179, 38421, 9025, 22513, 22514, 32169, 5860, 1652, 1777, 38584, 29437, 9155, 36405, + 8699, 4453, 11677, 19509, 8190, 17799, 35324, 32177, 17165, 35807, 22872, 23166, 26509, 35454, 30482, 20622, + 24162, 9602, 24474, 16636, 33218, 13815, 24638, 12775, 29953, 3055, 551, 10090, 33803, 26717, 8120, 32368, + 16490, 1263, 37502, 36844, 13692, 5191, 5812, 11678, 29459, 29486, 29494, 29489, 29490, 29533, 29543, 29561, + 29592, 29616, 29641, 29574, 29603, 29576, 29605, 29659, 29657, 29660, 29655, 29668, 29674, 29683, 29682, 29714, + 29723, 29727, 29730, 29764, 29769, 29773, 29847, 29776, 29832, 29835, 29840, 29849, 29858, 29896, 29908, 29939, + 29954, 29957, 29947, 29963, 29979, 30008, 30039, 30027, 30050, 30089, 30067, 30065, 30176, 30143, 30135, 28439, + 30160, 30181, 30246, 30191, 30182, 30210, 30214, 30229, 30247, 30260, 30285, 30273, 30280, 30309, 30313, 30298, + 30314, 30304, 30359, 30332, 30340, 30353, 30338, 30327, 30336, 30388, 30404, 30434, 30445, 30442, 30513, 30458, + 30461, 30502, 30505, 30499, 30498, 30516, 27798, 14427, 23318, 37332, 15085, 27652, 19076, 17194, 5995, 28953, + 16061, 10003, 10102, 706, 7456, 30548, 6607, 37510, 28392, 23821, 25708, 21246, 30810, 17615, 6152, 6969, + 616, 5699, 30490, 2256, 34836, 6106, 16198, 13693, 29511, 19673, 33519, 20200, 13593, 26944, 33764, 34535, + 25519, 30553, 8223, 37584, 19797, 30883, 25569, 32881, 31932, 36336, 26872, 3728, 28775, 40159, 40925, 29110, + 37585, 19871, 16203, 6361, 24545, 17202, 31054, 37809, 24871, 36425, 13243, 650, 27670, 4463, 31598, 31006, + 17454, 592, 25434, 12377, 31169, 33448, 10119, 35504, 1096, 11178, 35594, 6462, 20971, 10428, 10976, 9541, + 19282, 35931, 30936, 36432, 28994, 39909, 30564, 30540, 30515, 30572, 30578, 30586, 30574, 30589, 30591, 30773, + 30608, 30594, 30662, 30522, 30663, 30657, 30658, 30659, 30660, 30774, 30809, 30777, 30782, 30783, 30789, 30840, + 30775, 30796, 30788, 30786, 30812, 30772, 30896, 30888, 30920, 30909, 30916, 30911, 30948, 30964, 30953, 30972, + 30996, 30993, 31030, 31038, 31052, 31040, 31050, 31059, 31105, 31082, 31095, 31079, 31145, 31144, 31151, 31134, + 31141, 31150, 31147, 31181, 31188, 31200, 31186, 31185, 31182, 31254, 31242, 31262, 31243, 31279, 31402, 31257, + 31314, 31308, 31363, 31342, 31324, 31305, 31401, 31337, 31335, 31427, 31547, 31428, 31904, 31486, 31782, 31494, + 31559, 31413, 31535, 31458, 2334, 25992, 23565, 29427, 26384, 5715, 18813, 30836, 39817, 3189, 24802, 22546, + 37087, 13170, 18529, 24309, 36234, 13252, 30940, 32659, 30416, 38993, 39044, 19261, 9764, 18261, 4533, 16945, + 19432, 32660, 2968, 20671, 41153, 27678, 24554, 28996, 39510, 22380, 13483, 24814, 1633, 17694, 9617, 31758, + 12461, 40395, 7457, 16578, 14959, 14960, 36177, 2717, 13390, 21093, 32671, 31232, 3731, 34088, 27679, 4046, + 3280, 5263, 17058, 26346, 35602, 14109, 4964, 23552, 4364, 32513, 26559, 24283, 36535, 2641, 17261, 38325, + 33781, 40217, 38287, 32813, 19538, 33076, 23373, 25457, 13069, 10241, 40685, 13756, 22802, 10325, 7287, 16709, + 13753, 16226, 20461, 17305, 31504, 31905, 31421, 31473, 31574, 31405, 31474, 31545, 31481, 31526, 31417, 31501, + 31700, 31678, 31672, 31668, 31682, 31731, 31730, 31723, 31775, 31820, 31772, 31783, 31931, 31917, 31938, 32003, + 31985, 31976, 31946, 31940, 31950, 32019, 26152, 32025, 32021, 32076, 32091, 32055, 32427, 32099, 32058, 32152, + 32151, 32170, 32168, 32148, 32155, 32150, 32182, 32246, 32248, 32320, 32359, 32314, 32367, 32351, 32357, 32326, + 32343, 32323, 32321, 32434, 32437, 32464, 32435, 32451, 32454, 32442, 32431, 32483, 32478, 32472, 32501, 32494, + 32492, 32530, 32527, 32551, 32542, 32523, 32536, 32606, 32611, 32648, 33901, 32585, 32663, 32616, 32593, 32587, + 32705, 32724, 24563, 21598, 18638, 6470, 32683, 40183, 18430, 17323, 18431, 7747, 35129, 1075, 21040, 9209, + 36385, 27420, 31660, 2276, 24850, 24990, 2277, 19415, 13767, 40231, 40588, 11459, 21714, 22237, 39961, 19354, + 7143, 15113, 20360, 31902, 15235, 37639, 24900, 18049, 33864, 27365, 29670, 32540, 32184, 10957, 30821, 5398, + 3694, 30826, 5403, 40556, 8423, 36966, 35389, 7851, 7567, 13636, 39893, 5143, 35718, 39951, 13801, 39556, + 32844, 25140, 39389, 15025, 2635, 11599, 25141, 30088, 18183, 805, 35072, 41290, 1208, 26473, 14619, 10465, + 33921, 39145, 35437, 22005, 1842, 5521, 8171, 9698, 39653, 39685, 25145, 35747, 30045, 20887, 8994, 33857, + 38945, 24698, 32721, 32742, 32751, 32745, 32754, 32753, 32750, 32804, 32795, 32805, 32808, 32882, 32819, 32834, + 32861, 32821, 32848, 32825, 32851, 32927, 32968, 32949, 33075, 33034, 32944, 32945, 32987, 32958, 33145, 33110, + 33133, 33115, 33111, 33134, 33109, 33105, 33169, 33176, 33205, 33217, 33210, 33209, 33288, 33244, 33253, 33248, + 33246, 33245, 33284, 33291, 33289, 33292, 33290, 33317, 33316, 33331, 33320, 33323, 33342, 33344, 33369, 33372, + 33380, 33422, 33441, 33439, 33430, 33436, 33435, 33501, 33458, 33505, 33478, 33500, 33471, 33548, 33554, 33663, + 33636, 33605, 33588, 33592, 3988, 33607, 33648, 33641, 33631, 33632, 33725, 33736, 33729, 33799, 33800, 33789, + 9699, 21365, 1904, 1849, 3542, 3537, 15690, 25333, 13297, 13119, 1917, 13661, 7082, 25555, 40144, 9520, + 36072, 15121, 33314, 33493, 16047, 21455, 27374, 12770, 16088, 17041, 14715, 26618, 8701, 39149, 18224, 12563, + 35845, 2079, 40463, 27538, 25127, 17393, 7820, 2664, 16056, 28951, 37653, 18065, 3546, 2874, 3810, 17611, + 22257, 7431, 37503, 34517, 6357, 39757, 35581, 12564, 39478, 15502, 23563, 29189, 29100, 8210, 3725, 33016, + 5996, 16062, 6480, 33445, 33446, 37654, 8211, 37054, 29894, 34530, 11630, 22229, 5111, 37882, 28412, 9006, + 11255, 25429, 37655, 20970, 14233, 28355, 593, 25925, 21463, 36342, 13821, 11258, 15700, 17441, 16922, 26878, + 33827, 33841, 33855, 33854, 33906, 33908, 33916, 33913, 33944, 33948, 33993, 33999, 34055, 34027, 34032, 34026, + 34029, 34028, 34110, 34099, 34143, 34097, 34107, 34100, 34148, 34153, 34157, 34162, 34285, 34146, 34186, 34180, + 34193, 34196, 34201, 34197, 34218, 34213, 34230, 34233, 34301, 34593, 34306, 34290, 34300, 34368, 34346, 34364, + 34385, 34353, 34345, 34350, 34406, 34376, 34357, 34356, 34467, 34483, 34486, 34478, 34522, 34602, 34614, 34657, + 34587, 34597, 34623, 34598, 34596, 34618, 34599, 34611, 34604, 34728, 34720, 34732, 34731, 34751, 34746, 34754, + 34757, 34747, 34764, 34749, 34823, 34814, 34825, 34819, 34850, 34864, 34910, 34903, 34885, 34964, 18907, 35932, + 5935, 33049, 32112, 30837, 1599, 2379, 12195, 26072, 734, 1394, 8070, 13043, 40437, 13044, 4792, 12388, + 5123, 37992, 7270, 1983, 32557, 33154, 1660, 25239, 19429, 16355, 345, 38283, 9671, 2398, 28233, 21739, + 2670, 17513, 5259, 27329, 28736, 1367, 16364, 23095, 39599, 6518, 27331, 30241, 27136, 534, 32912, 2015, + 3233, 16318, 18423, 31714, 32134, 16385, 39025, 5077, 14700, 38115, 26894, 13084, 36020, 16462, 34232, 31418, + 7780, 8282, 7811, 484, 10443, 12242, 12250, 13097, 9348, 1480, 34603, 9521, 14872, 22685, 19643, 20128, + 20129, 20331, 27062, 27746, 2662, 19109, 14893, 20144, 29421, 17427, 35084, 39758, 15037, 31691, 34953, 34917, + 34956, 34933, 34943, 34923, 35018, 35026, 35067, 35068, 35106, 35119, 35121, 35130, 35288, 35157, 35153, 35150, + 35167, 35118, 35164, 35165, 35166, 35194, 35173, 35188, 35291, 35319, 35296, 35321, 35318, 35301, 35294, 35295, + 35478, 35369, 35460, 35444, 35365, 35435, 35482, 35377, 36039, 35398, 35520, 35576, 35563, 35565, 35542, 35541, + 35552, 35543, 35617, 35652, 35677, 35663, 35630, 35613, 35650, 35946, 35778, 35840, 35711, 35625, 35844, 35825, + 35882, 35616, 35612, 35740, 35828, 35689, 35623, 35748, 35662, 35633, 35945, 35769, 35687, 36059, 36060, 36047, + 36064, 36061, 36049, 36055, 36114, 36145, 36142, 36138, 36198, 36193, 36194, 36209, 26285, 30555, 31849, 29321, + 37075, 16415, 6997, 6421, 24223, 22161, 12625, 20495, 36437, 9070, 24744, 38726, 14006, 9366, 5470, 13186, + 19122, 24897, 12947, 30641, 14977, 24750, 19125, 16426, 26693, 5597, 9378, 34591, 29310, 24588, 13853, 4617, + 39686, 3038, 12293, 5192, 5628, 11216, 24961, 8710, 27088, 9605, 13773, 11933, 24642, 33224, 21249, 12175, + 18778, 38397, 1327, 33235, 26385, 8927, 39844, 33940, 4037, 31629, 35530, 17343, 14983, 31656, 34694, 31663, + 34715, 6093, 8163, 24589, 24590, 13509, 12508, 7206, 34111, 5898, 10716, 2636, 28974, 33475, 13653, 35438, + 25328, 34144, 36135, 26303, 23480, 30046, 12524, 34112, 36136, 6832, 7574, 34258, 36251, 36305, 36338, 36310, + 36358, 36303, 36333, 36400, 36402, 36403, 36399, 36532, 36396, 36439, 36398, 36482, 36477, 36510, 36506, 36539, + 36543, 36542, 36576, 36544, 36546, 36554, 36650, 36646, 36617, 36618, 36627, 36614, 36629, 36620, 36662, 36685, + 36676, 36687, 36679, 36719, 36720, 36731, 36755, 36727, 36735, 36764, 36818, 36812, 36916, 36868, 36871, 36901, + 36889, 36866, 36870, 36923, 36931, 36945, 36963, 37034, 37043, 37028, 37053, 36950, 36969, 37021, 36967, 37010, + 37013, 36993, 36998, 37129, 36984, 37137, 37128, 37132, 37143, 37131, 37144, 37134, 37212, 37250, 37220, 37230, + 33456, 37294, 37271, 37239, 37276, 37301, 37258, 37234, 37229, 37313, 34895, 27846, 26672, 36143, 33127, 14874, + 32707, 21159, 3168, 36759, 39569, 33332, 7403, 33177, 2976, 26530, 32081, 25767, 40561, 33566, 35772, 35773, + 28093, 3417, 10319, 26619, 10390, 33651, 39151, 40317, 39335, 9044, 40846, 38588, 9162, 8191, 13008, 5978, + 18053, 5629, 34855, 21080, 22108, 40087, 8465, 35810, 14626, 35078, 38500, 35456, 35457, 24869, 38875, 22873, + 1238, 33355, 24715, 446, 4949, 41103, 28902, 40249, 4388, 38959, 36639, 33571, 34064, 35846, 11563, 10402, + 27089, 2552, 32764, 26860, 10527, 2594, 9053, 9606, 24962, 11765, 13694, 11217, 8318, 32485, 30546, 26622, + 40090, 29614, 20017, 20515, 6962, 11623, 34393, 33335, 9310, 7145, 37241, 37273, 37291, 37246, 37351, 37213, + 37484, 37489, 37480, 37527, 37538, 37548, 37542, 37553, 37581, 37533, 37532, 37544, 37571, 37569, 37556, 37615, + 37633, 37652, 37634, 37635, 37665, 37668, 37727, 37717, 35069, 37699, 37726, 37684, 37707, 37713, 37840, 37818, + 37833, 37820, 37872, 37865, 37899, 37927, 37909, 37798, 37920, 37897, 37952, 37976, 37974, 38014, 38012, 38010, + 38025, 38042, 38035, 38036, 38063, 38078, 38086, 38093, 38124, 38146, 38148, 38158, 38163, 38170, 38192, 38174, + 38173, 38184, 38179, 38222, 38215, 38205, 38197, 38195, 38217, 38231, 38228, 38225, 38230, 38318, 38331, 38339, + 38341, 2472, 38361, 38368, 38379, 38382, 38411, 34229, 1810, 29410, 35472, 16741, 40154, 15826, 15715, 31214, + 12585, 39760, 25345, 4647, 16518, 6845, 15843, 7046, 29548, 5195, 931, 2696, 36907, 15525, 24103, 24220, + 27432, 161, 37182, 32767, 3345, 13818, 32375, 31165, 31368, 8619, 27853, 2061, 11778, 14156, 27573, 39209, + 27574, 6359, 11250, 2962, 27519, 13716, 15466, 24733, 4566, 32716, 28210, 30491, 32195, 7478, 3433, 28489, + 35891, 21345, 36173, 5916, 22580, 40646, 2799, 3138, 40555, 12597, 23188, 28676, 40530, 30726, 14502, 24409, + 6174, 39338, 38265, 41008, 23691, 40647, 17636, 13152, 4023, 10226, 19091, 26679, 1596, 11273, 22675, 37066, + 6005, 33524, 22689, 27119, 33769, 27120, 11937, 11232, 38423, 38418, 38459, 38491, 38504, 38004, 38483, 38492, + 38485, 38524, 38517, 38540, 38548, 38556, 38563, 38614, 38578, 38594, 38583, 38576, 38641, 38638, 21399, 38642, + 38640, 38737, 38694, 38691, 38693, 38697, 38706, 38702, 38763, 38747, 38754, 38757, 38744, 38786, 38785, 38801, + 38796, 38800, 38805, 38797, 38804, 38817, 38811, 38829, 38830, 38850, 38852, 38867, 38879, 38881, 38859, 38886, + 38858, 38914, 38921, 38934, 38958, 38986, 39017, 39021, 39051, 39026, 39029, 39062, 39090, 39071, 39094, 39073, + 39116, 39054, 39056, 39057, 39133, 39141, 39130, 39215, 39190, 39214, 39176, 39273, 39244, 39259, 39236, 39246, + 39232, 39237, 39321, 39311, 39323, 39329, 6998, 39968, 5710, 32889, 8059, 23114, 29512, 13163, 23439, 37371, + 40776, 40394, 31754, 11809, 36097, 168, 32207, 20999, 3190, 7783, 40163, 34796, 34658, 11520, 33770, 8733, + 21895, 23193, 20724, 35235, 30827, 33315, 29021, 40027, 26336, 22941, 16017, 11570, 12038, 8667, 36438, 20026, + 32736, 20172, 31757, 23921, 3142, 33977, 29124, 28069, 714, 3501, 23700, 27125, 13284, 37595, 33051, 10491, + 28921, 34984, 34985, 39872, 37092, 1568, 4592, 16946, 20544, 20667, 26386, 39000, 20522, 13058, 38284, 13597, + 17463, 18531, 2312, 21935, 9731, 31703, 40672, 317, 318, 13921, 39001, 35523, 10889, 13319, 19399, 3013, + 10131, 11184, 2816, 33536, 38354, 26057, 39328, 39331, 39327, 39325, 39362, 39371, 39359, 39363, 39426, 39374, + 39377, 39399, 39361, 39358, 39376, 39470, 39456, 39472, 39473, 39451, 39459, 39453, 39534, 39552, 39526, 39570, + 39527, 39532, 39542, 39610, 39644, 39664, 39608, 39651, 39731, 39620, 39627, 39616, 39700, 39650, 39728, 39623, + 39622, 39670, 39702, 39621, 39678, 39873, 39892, 39883, 39894, 39897, 39888, 39924, 39923, 39952, 39943, 39944, + 39977, 39981, 39976, 39984, 39978, 40003, 40040, 40044, 40123, 40062, 40078, 40063, 40071, 40110, 40138, 40137, + 40150, 40127, 40140, 40139, 40130, 40197, 40184, 40194, 40247, 40238, 40258, 40254, 40234, 39050, 40287, 40272, + 40312, 40282, 40323, 40315, 31630, 38402, 6589, 39350, 21095, 16365, 6860, 36371, 14967, 12225, 41225, 13488, + 2046, 11843, 40442, 31236, 38333, 38449, 27153, 24118, 28699, 38334, 23120, 26772, 33783, 38220, 28704, 5275, + 28246, 32295, 12230, 13548, 38732, 21038, 35353, 130, 38622, 11711, 11242, 35993, 35994, 26347, 25230, 21785, + 23833, 40543, 28530, 11120, 40034, 10242, 131, 36378, 13197, 37427, 13078, 11854, 6392, 39006, 33896, 38110, + 16774, 26694, 30865, 2829, 17352, 35533, 1518, 39012, 34695, 7033, 3847, 30869, 3848, 35115, 2750, 25231, + 36246, 16392, 3236, 32924, 21606, 11302, 38117, 36030, 5285, 38637, 34709, 6408, 30026, 25301, 33321, 33347, + 1168, 39985, 26667, 33480, 40271, 40280, 40291, 40284, 40362, 38848, 40371, 40374, 40380, 40400, 40429, 40427, + 40431, 40457, 40452, 40462, 40451, 40484, 40470, 40472, 4202, 40498, 40492, 40527, 40509, 40546, 40552, 40557, + 40571, 40568, 40567, 40572, 41246, 40599, 40608, 40610, 39049, 40594, 40602, 40708, 40709, 40720, 40711, 40736, + 40722, 40704, 40843, 40811, 40829, 40845, 40884, 40853, 40866, 40852, 40938, 40903, 40927, 40888, 40892, 40948, + 40971, 40995, 41023, 41027, 41028, 41037, 41043, 41044, 41052, 41098, 41092, 41093, 41094, 41116, 41130, 41164, + 41189, 41176, 41180, 41204, 41208, 41239, 41264, 41265, 38490, 41291, 41274, 41275, 41287, 0, 0, 0, + 0, 0, 23654, 10656, 31922, 12306, 10676, 9945, 10592, 31610, 31611, 17695, 10037, 6393, 18434, 23412, + 17042, 5455, 1093, 27396, 32398, 7736, 39853, 39867, 34710, 34712, 3979, 11607, 29991, 35774, 35775, 12872, + 421, 10809, 6948, 3906, 12897, 15490, 8319, 14637, 7877, 31554, 1700, 40164, 12738, 7629, 31612, 1984, + 30899, 11349, 5587, 40935, 7635, 35982, 218, 22515, 20894, 22451, 9029, 20899, 36900, 20623, 27751, 11330, + 16057, 10404, 10104, 16913, 21250, 1146, 37195, 12739, 29853, 19551, 31613, 7004, 14679, 3893, 28700, 11303, + 15003, 878, 39065, 37541, 8164, 2183, 8970, 28985, 35439, 10172, 30400, 22789, 12004, 7336, 28627, 9411, + 38244, 39471, 3968, 12081, 31304, 8335, 21419, 25777, 22417, 8787, 3288, 8688, 21063, 6995, 9691, 36974, + 22766, 1109, 30024, 34880, 34915, 39360, 5509, 33162, 36256, 15929, 37320, 8551, 28968, 40233, 12268, 20968, + 20318, 12088, 23216, 20076, 875, 26000, 9173, 38297, 26520, 4873, 34482, 14881, 27648, 35226, 34660, 7359, + 22947, 9571, 15992, 1433, 38266, 9299, 36814, 5337, 35615, 30947, 14083, 15632, 9622, 15139, 16173, 12111, + 26298, 30274, 15743, 22699, 14905, 24005, 11949, 35903, 14184, 30463, 25262, 6049, 38779, 16641, 25759, 8625, + 20783, 25299, 37130, 22563, 34181, 30215, 31244, 2863, 2320, 15291, 40269, 21672, 15117, 36680, 35642, 8986, + 7142, 40319, 27079, 1239, 40751, 7144, 9639, 22688, 1437, 19338, 5049, 26804, 15868, 7513, 29434, 35459, + 3477, 19651, 10468, 1240, 18746, 17962, 11766, 8320, 22669, 40752, 12816, 33666, 38320, 13448, 8357, 38126, + 13135, 36337, 34126, 39210, 26492, 1701, 1702, 24643, 26493, 4126, 38131, 40017, 16297, 38092, 4464, 3139, + 26397, 29323, 22263, 8815, 32196, 19360, 13153, 28212, 8226, 28757, 4567, 4568, 39779, 12177, 38815, 6422, + 13994, 33338, 4292, 37890, 778, 38022, 16300, 7804, 2350, 12208, 26815, 35949, 40438, 8244, 9071, 25845, + 38285, 17696, 35964, 559, 3211, 30419, 39833, 40539, 1571, 37815, 38363, 5232, 38103, 34678, 23138, 26348, + 29575, 30066, 21309, 12687, 12269, 7134, 36874, 15721, 15200, 40129, 35665, 29348, 2616, 13412, 21720, 20704, + 3785, 34471, 17102, 24584, 17024, 37139, 22821, 36619, 23240, 7791, 23843, 25739, 22011, 40570, 27226, 19156, + 31039, 1127, 29167, 9349, 15542, 14608, 7659, 34481, 32845, 12525, 30520, 40949, 18498, 28859, 1690, 21854, + 3606, 31536, 14098, 13138, 13356, 14341, 29618, 33755, 5114, 29573, 30011, 26500, 23633, 41095, 37755, 4678, + 5548, 31406, 34118, 10694, 9800, 2806, 15962, 718, 23062, 10574, 7972, 7910, 27966, 27711, 29681, 34466, + 1895, 9694, 19642, 32976, 18973, 23021, 1780, 36427, 19172, 16698, 1743, 11043, 17763, 32243, 30422, 36453, + 14009, 8478, 32234, 38136, 1379, 6394, 27300, 34691, 26401, 33898, 18488, 8482, 38138, 37530, 1241, 40006, + 7796, 37812, 31489, 29615, 31828, 3259, 3275, 31995, 28835, 41022, 17115, 26304, 24462, 36206, 32262, 4351, + 14875, 24298, 3472, 4352, 3221, 5979, 5528, 31819, 38589, 14894, 12337, 3487, 3914, 9266, 33972, 29386, + 6734, 8433, 28313, 4648, 31692, 38889, 28026, 36224, 14504, 13154, 25082, 4328, 4738, 18780, 5318, 24548, + 40777, 29119, 24741, 3652, 11535, 24069, 24033, 13543, 38221, 29217, 7128, 38084, 15686, 15353, 14876, 3200, + 7410, 37716, 475, 23276, 30164, 35812, 21395, 18055, 19786, 15650, 4355, 23580, 40320, 14417, 27785, 20107, + 39926, 20473, 34344, 13614, 10714, 26291, 21910, 14586, 21153, 9133, 10309, 5607, 38860, 24682, 35379, 15811, + 16731, 9301, 12274, 11590, 26586, 9035, 24925, 39239, 11917, 33559, 24089, 8606, 15838, 7045, 40997, 40607, + 30675, 36988, 26666, 2769, 28185, 3169, 13121, 33965, 35189, 6925, 37266, 33735, 150, 5672, 40726, 22686, + 20524, 5271, 27996, 27078, 20134, 38963, 13019, 38332, 24050, 14915, 34644, 38600, 3230, 13607, 13891, 8143, + 31309, 23624, 14082, 601, 5788, 41276, 838, 33249, 8305, 39637, 21503, 40999, 4195, 22507, 30525, 11483, + 15926, 31699, 9956, 24443, 15851, 19473, 31143, 7361, 1759, 22423, 879, 35172, 5774, 22061, 14631, 21238, + 35474, 12154, 6783, 6784, 40155, 24963, 40372, 32487, 3611, 22670, 39736, 12776, 2204, 28469, 14499, 27261, + 29808, 4018, 14157, 21547, 32636, 2136, 4813, 20776, 27262, 13452, 24009, 20717, 13155, 23331, 31055, 30727, + 13717, 12365, 21554, 14431, 14432, 19078, 18782, 16845, 30372, 24970, 41065, 24177, 35588, 4655, 40926, 22411, + 39276, 37077, 6662, 4116, 36656, 5711, 38473, 3208, 9271, 28831, 8061, 41068, 21896, 2576, 29942, 23922, + 21408, 5744, 29125, 12391, 18205, 38101, 1341, 3705, 18824, 17697, 28781, 5074, 28074, 31759, 15985, 12220, + 39511, 23927, 5588, 22082, 40936, 17464, 38165, 21412, 29929, 14527, 32122, 39916, 5608, 28553, 12755, 39626, + 40131, 15754, 24141, 11310, 37903, 17118, 36465, 8607, 31447, 7955, 22506, 28652, 34489, 14767, 34316, 36156, + 38750, 22938, 26315, 41010, 18116, 7740, 3897, 11383, 19343, 24762, 26464, 10333, 8762, 19942, 33626, 32875, + 27911, 33046, 14976, 36192, 23798, 5288, 2951, 27610, 1459, 973, 24623, 979, 6902, 7167, 27287, 12182, + 36567, 10487, 30573, 31136, 8627, 39175, 15852, 22564, 35368, 17087, 23223, 602, 8376, 18456, 5789, 18588, + 3072, 3458, 30069, 21213, 20755, 354, 34156, 5941, 6187, 15141, 26214, 26393, 21102, 8306, 36124, 3308, + 26925, 9740, 33994, 17778, 37636, 39462, 192, 35754, 22510, 21424, 1869, 4667, 14970, 17983, 28419, 24034, + 14814, 17642, 6624, 15881, 4969, 1374, 1375, 14687, 24120, 6632, 3844, 12235, 31303, 37772, 21414, 39520, + 17345, 39861, 3943, 6516, 30866, 18435, 17990, 32135, 30871, 16393, 25213, 25775, 21607, 28539, 24854, 13833, + 4685, 4867, 31768, 15971, 15005, 17992, 5100, 7685, 29153, 6735, 8909, 16493, 25351, 19167, 59, 12178, + 14505, 15575, 16623, 34540, 19806, 15278, 24746, 18535, 16629, 6752, 39514, 34718, 29158, 5415, 36538, 37453, + 3047, 34241, 9583, 15026, 37711, 33174, 5034, 33733, 7327, 25330, 26223, 15840, 27243, 29993, 3170, 5044, + 6926, 20896, 23278, 19567, 25648, 25334, 23750, 40403, 10576, 10857, 22348, 29841, 25975, 5037, 15645, 5965, + 36077, 16827, 10808, 8706, 37564, 19441, 36555, 17583, 3491, 33146, 22557, 36013, 2400, 13327, 20936, 6424, + 23631, 12097, 30303, 24439, 23399, 32432, 7918, 34349, 37826, 7488, 12485, 17090, 6890, 14592, 22488, 39543, + 25696, 32318, 2893, 4478, 24234, 31319, 23839, 23227, 26207, 1466, 40275, 15579, 35554, 20587, 8383, 22767, + 18359, 437, 20793, 14384, 25175, 24398, 3461, 7937, 18008, 21447, 36254, 19559, 36397, 24448, 20378, 26444, + 23842, 29065, 25233, 1195, 4377, 14551, 29590, 11668, 40135, 29491, 24043, 7954, 25286, 33294, 24931, 11729, + 34041, 20472, 12507, 13339, 3675, 13225, 19190, 33258, 24782, 15869, 5630, 18057, 5050, 278, 39153, 7339, + 15829, 34833, 22330, 916, 9098, 9099, 22191, 40322, 25480, 6949, 450, 40042, 39576, 34944, 15360, 35813, + 39714, 27092, 22876, 7087, 8954, 14493, 13524, 9463, 10406, 15154, 24964, 40010, 38046, 39737, 26491, 17634, + 37335, 26430, 36782, 30408, 36220, 38970, 30367, 8126, 24362, 40019, 21251, 16834, 38978, 38717, 17637, 40769, + 11639, 30492, 4329, 9830, 15220, 35589, 22369, 23869, 9715, 21405, 22884, 9392, 937, 19079, 22018, 17590, + 25664, 25521, 12680, 34797, 32208, 4104, 4607, 4238, 8734, 36793, 10598, 27268, 8236, 40778, 8062, 30900, + 998, 38672, 37088, 30901, 28922, 9198, 39119, 32001, 34042, 8792, 13938, 19337, 28263, 10640, 40074, 15204, + 1104, 26928, 31041, 36831, 6829, 19700, 36752, 17135, 29772, 32075, 7968, 28125, 36753, 5555, 26602, 9382, + 16525, 36308, 4255, 14041, 23272, 31488, 27791, 13895, 20958, 23159, 444, 27242, 2869, 29431, 36995, 11320, + 1221, 7990, 29781, 5185, 4764, 34304, 14408, 5297, 12870, 30344, 36404, 9094, 10075, 23574, 7720, 25339, + 32445, 30538, 2780, 15149, 23501, 16000, 31735, 6944, 768, 21987, 29500, 18503, 22037, 33745, 12721, 39098, + 26859, 25616, 20632, 7052, 923, 31018, 10196, 12335, 16890, 703, 12896, 27588, 16529, 36418, 37310, 28024, + 19863, 6237, 31745, 17507, 4645, 17965, 37596, 18825, 13391, 3011, 40410, 30844, 11906, 33990, 39004, 13544, + 38728, 2067, 16611, 7636, 7221, 17918, 8745, 26055, 15230, 11359, 35604, 12408, 40544, 7100, 37428, 13198, + 10608, 16713, 22294, 17346, 17357, 18640, 17993, 5013, 39990, 17580, 30895, 4389, 41181, 1496, 16199, 4400, + 33909, 643, 1504, 33910, 596, 4415, 1515, 1517, 21726, 21729, 2818, 4308, 36036, 25356, 1397, 26903, + 25625, 2651, 8370, 36924, 35372, 23141, 37955, 30501, 29839, 40549, 29163, 10158, 4924, 6822, 39974, 3074, + 21312, 39624, 3155, 40283, 28931, 30075, 24899, 11669, 6196, 36890, 20942, 35417, 13645, 17775, 34106, 6642, + 14210, 36686, 24605, 5659, 14134, 35568, 24789, 15615, 33723, 17721, 11791, 34130, 14928, 25681, 41188, 12364, + 19869, 7214, 23329, 10692, 33039, 10597, 30557, 35930, 31033, 27926, 1326, 10199, 28582, 25578, 34010, 32282, + 8595, 16953, 12057, 24824, 10560, 7283, 21587, 20059, 8934, 35701, 15847, 17398, 4898, 35696, 31450, 38143, + 22189, 36718, 17734, 8298, 8399, 27207, 19808, 29860, 3117, 8097, 22096, 336, 13639, 13416, 37957, 35732, + 18884, 15058, 29338, 35134, 31, 20889, 12443, 9318, 527, 14405, 23020, 17788, 23748, 9409, 5970, 38381, + 34262, 24330, 37011, 195, 33742, 1779, 15932, 37646, 27252, 7058, 4059, 12888, 27587, 38651, 21886, 25920, + 19210, 36327, 39488, 10096, 39031, 31341, 17405, 28388, 11673, 9243, 16257, 988, 4882, 14879, 1055, 36761, + 39998, 13956, 37267, 4299, 29176, 4945, 37619, 21881, 5301, 28155, 34508, 3478, 29082, 26934, 39085, 36768, + 37916, 6950, 9846, 4950, 30603, 21032, 34955, 3875, 34124, 28470, 5690, 3488, 37622, 28013, 19321, 9422, + 38761, 27102, 2165, 3623, 28027, 6657, 5700, 18518, 3496, 4833, 25252, 23692, 33836, 37355, 35495, 31374, + 17675, 27121, 19361, 9877, 38607, 29016, 7125, 1414, 1418, 16957, 37604, 35003, 19134, 17062, 29485, 23394, + 26202, 36946, 25540, 30426, 7835, 15293, 1680, 33107, 26657, 37531, 4808, 11973, 662, 14593, 1169, 30216, + 15812, 9502, 26831, 15638, 38966, 32876, 18583, 41222, 4680, 8437, 11433, 22583, 33285, 40660, 11955, 41138, + 21051, 35614, 28981, 5018, 27072, 2069, 3563, 12086, 15594, 5338, 16645, 38369, 34149, 34883, 7836, 8089, + 35644, 4995, 17086, 6888, 1116, 955, 9735, 24320, 36197, 37956, 15110, 8287, 9077, 18190, 6125, 21626, + 6669, 21065, 36682, 27620, 15814, 12105, 26661, 11591, 4897, 17865, 35397, 32581, 1185, 4346, 9453, 11723, + 33373, 35303, 22030, 15756, 6715, 12494, 20320, 19991, 38489, 21721, 8782, 20701, 19293, 3405, 16549, 8825, + 31190, 38376, 28330, 38200, 31449, 41285, 12112, 7781, 38236, 21878, 20278, 17876, 40417, 38834, 28939, 10844, + 4760, 26145, 8304, 10343, 12275, 10799, 33252, 31669, 9531, 21850, 16540, 34358, 3297, 6270, 18857, 8103, + 31189, 16466, 12757, 8824, 1893, 31796, 890, 32701, 23152, 24350, 39991, 40998, 22847, 16248, 21224, 36754, + 2138, 32436, 14479, 36573, 23994, 35317, 19705, 25741, 908, 27244, 37161, 37908, 10746, 15925, 32439, 32440, + 27860, 28796, 20481, 31513, 25599, 4006, 40741, 41004, 35196, 31158, 32446, 37844, 10273, 36553, 19652, 2994, + 7875, 17719, 40384, 11092, 24001, 19440, 24002, 33576, 5486, 1358, 34068, 1286, 38338, 30611, 39340, 19668, + 17892, 5112, 19872, 35225, 2396, 15771, 7730, 19873, 15873, 17512, 38097, 2712, 36700, 12210, 34668, 2724, + 4860, 11293, 36540, 5178, 2051, 6096, 16463, 17139, 27426, 4065, 5964, 4902, 20990, 16872, 15930, 13572, + 36602, 15994, 14264, 27861, 36076, 3597, 13573, 18580, 15691, 21906, 11742, 24255, 293, 27999, 6329, 15362, + 21532, 10320, 3129, 28396, 8704, 7, 20835, 10213, 5724, 22, 81, 28306, 9867, 29563, 3418, 22288, + 16822, 2364, 22746, 23172, 36326, 1023, 27920, 5564, 20146, 22335, 14809, 17664, 23046, 4066, 13531, 21907, + 24265, 18582, 2469, 5458, 10198, 13988, 14938, 35335, 25830, 22471, 25574, 2156, 12050, 21033, 30571, 12977, + 20974, 19052, 10894, 17999, 36880, 37148, 24351, 37156, 11337, 30575, 39619, 22275, 28855, 3786, 38239, 9780, + 31648, 38107, 17324, 36991, 34490, 41175, 19568, 39199, 6284, 39082, 37663, 8279, 29237, 23581, 7159, 3811, + 38047, 4325, 36904, 36278, 23074, 41185, 9890, 30618, 18787, 16411, 34326, 28956, 38665, 28677, 40531, 32209, + 6331, 28734, 24653, 4274, 37933, 22995, 15387, 27891, 3865, 4838, 37935, 36671, 273, 38514, 13312, 22737, + 3212, 37408, 16947, 38166, 35350, 13317, 28702, 7161, 21742, 35995, 34686, 35996, 21440, 25590, 3845, 34697, + 18138, 20068, 20069, 21442, 33200, 13557, 26187, 20074, 34706, 1468, 27067, 27137, 16958, 14014, 24593, 35564, + 17718, 5344, 38833, 6062, 22977, 24609, 417, 39076, 39461, 418, 19020, 8108, 20944, 5904, 26307, 24081, + 30590, 31094, 19443, 38814, 8043, 7212, 12259, 23397, 23634, 23224, 24680, 34183, 32317, 352, 2452, 16325, + 397, 11057, 15404, 6127, 12800, 33431, 5016, 9015, 19605, 20373, 35671, 6189, 13507, 34034, 39242, 16551, + 16244, 27786, 34297, 9222, 32703, 9743, 15544, 14864, 25401, 35031, 30257, 38027, 30598, 37006, 4845, 18545, + 40731, 19709, 26805, 27794, 12452, 38813, 17894, 5489, 1708, 35510, 5746, 3562, 7391, 4623, 34104, 34762, + 10802, 16245, 31726, 2899, 11489, 34950, 39288, 13470, 24851, 26201, 25024, 24570, 206, 9475, 19288, 21693, + 37869, 31943, 22183, 7493, 25388, 15757, 27179, 28262, 1201, 14758, 17129, 36986, 32256, 36132, 15605, 4122, + 40839, 7303, 11163, 11164, 10076, 8510, 23279, 19502, 25379, 5673, 27743, 31807, 35779, 2611, 26843, 29837, + 31491, 21818, 23662, 24672, 13122, 22605, 35137, 13860, 464, 7371, 3176, 33271, 6263, 37729, 23667, 7868, + 22452, 20900, 33132, 6839, 14896, 6652, 8998, 36211, 23757, 615, 25787, 25273, 2981, 21707, 7577, 37878, + 12451, 24252, 22453, 9744, 10669, 36150, 15033, 26853, 35815, 39901, 31736, 8349, 25380, 11975, 28603, 15300, + 37664, 18853, 6952, 30990, 6698, 40761, 21280, 29800, 27093, 20404, 9105, 15367, 18066, 1782, 27752, 9170, + 1934, 22460, 37314, 27753, 41252, 2060, 36776, 29272, 12817, 39099, 26986, 27094, 39485, 14633, 28095, 35315, + 9821, 19103, 21229, 26486, 4635, 20004, 10928, 2546, 30692, 30880, 19712, 21078, 38758, 14155, 14924, 17673, + 33036, 34008, 11296, 4107, 11978, 28265, 36160, 39525, 26899, 28786, 29986, 31776, 25319, 37225, 3573, 35391, + 32495, 1845, 36992, 11892, 2512, 27869, 20528, 33391, 13908, 25876, 40432, 21042, 22561, 31248, 9569, 22182, + 33375, 32474, 30140, 147, 37157, 1211, 8810, 296, 13903, 2701, 33032, 17943, 36352, 33201, 5339, 4823, + 2835, 31250, 39611, 21965, 3670, 31249, 15166, 2945, 4176, 27777, 1462, 21691, 11058, 3975, 22314, 4927, + 34848, 41280, 21215, 7926, 2973, 35675, 35384, 29667, 34288, 2407, 15142, 34036, 2665, 26861, 26862, 33871, + 38836, 810, 10407, 1267, 26759, 3915, 26940, 1935, 40327, 3612, 37961, 22922, 29617, 23765, 8024, 38552, + 18310, 23676, 8025, 17184, 37733, 22461, 34735, 639, 1856, 13696, 9002, 27382, 39277, 20774, 31737, 31738, + 5691, 12730, 20815, 28722, 11332, 35577, 27645, 15871, 15119, 871, 29624, 33274, 10684, 13454, 3550, 7148, + 19213, 1783, 27103, 20718, 12732, 36163, 15038, 40015, 3755, 32507, 29625, 20641, 16799, 12167, 37336, 33679, + 25276, 41229, 39761, 26311, 3624, 32273, 33275, 24967, 22464, 29439, 40160, 32548, 20489, 15725, 34966, 32097, + 32187, 33397, 15039, 2517, 16603, 12348, 22579, 25565, 20095, 35332, 36093, 9465, 15431, 37904, 896, 27819, + 23650, 15900, 16080, 35731, 29168, 24906, 24154, 33300, 7465, 2933, 30471, 3792, 10846, 4762, 37914, 15996, + 6939, 16843, 40514, 24083, 1230, 28005, 23852, 36558, 14101, 24056, 3692, 4026, 17945, 19957, 29292, 11642, + 27455, 34588, 30579, 10623, 20425, 15251, 28447, 18858, 16082, 14260, 16472, 37268, 2870, 31808, 30922, 11875, + 6928, 24888, 25059, 10408, 29273, 25032, 10031, 23937, 22056, 23888, 27550, 23448, 27709, 2582, 7694, 37535, + 20788, 20224, 6637, 20110, 9132, 1465, 30975, 10184, 30576, 16652, 8379, 27343, 18358, 18589, 34725, 27720, + 30072, 18006, 19607, 19184, 33848, 22097, 30071, 10626, 20427, 14024, 200, 6122, 36848, 26012, 15331, 23771, + 27776, 24, 5913, 10111, 25711, 27110, 15528, 24649, 32646, 38979, 33447, 38150, 29112, 4892, 9272, 10729, + 39908, 29679, 18902, 19729, 16497, 30373, 33139, 37858, 938, 28038, 37358, 2698, 6107, 1959, 10112, 12783, + 10690, 4681, 7731, 2667, 30374, 39784, 27667, 33765, 11179, 37185, 29391, 8957, 40650, 19038, 33278, 24307, + 26722, 10007, 19039, 35141, 3926, 38359, 14434, 32385, 29440, 19512, 23130, 16923, 22112, 25712, 3353, 8620, + 17044, 28993, 1826, 40338, 39231, 29757, 18316, 41194, 14669, 2941, 37624, 13164, 8521, 5920, 28960, 2915, + 19080, 9832, 18094, 861, 18799, 16936, 23919, 23025, 14743, 20413, 11314, 30668, 17770, 12701, 39061, 36058, + 11667, 40133, 12501, 33610, 11726, 28933, 34038, 13293, 18211, 11018, 34039, 25609, 27975, 31196, 16246, 30587, + 40605, 14707, 2454, 659, 31457, 19753, 11394, 40242, 23269, 31480, 27790, 6347, 40575, 22600, 20238, 8461, + 7450, 4558, 26670, 9410, 18720, 27464, 32983, 34308, 20243, 13435, 27865, 11491, 33645, 22304, 12879, 33866, + 31097, 19710, 34628, 24258, 15453, 26540, 19531, 36416, 23111, 17178, 25614, 28410, 11927, 1252, 33442, 8118, + 28802, 22126, 20483, 11501, 36419, 32631, 16409, 2367, 10868, 19211, 11424, 17542, 40158, 35330, 18755, 33805, + 8432, 27393, 27660, 26244, 26482, 29630, 2703, 16299, 41195, 22373, 232, 22472, 32394, 34173, 40500, 16803, + 15385, 15557, 28500, 16066, 6366, 21192, 4209, 40780, 39286, 966, 21563, 40987, 4275, 28682, 6109, 23338, + 23782, 40534, 12196, 37373, 13915, 9395, 19588, 2878, 29326, 31599, 17551, 28961, 9236, 4893, 27402, 39118, + 18800, 19956, 18801, 11148, 1600, 8294, 16278, 15495, 7414, 31404, 20972, 30414, 11136, 5443, 32109, 22657, + 11952, 17638, 7204, 19820, 15161, 36345, 5541, 17553, 9760, 32283, 6465, 29822, 30626, 40933, 8245, 25523, + 12393, 7005, 15043, 3210, 29126, 38444, 11114, 34800, 6511, 32002, 37089, 15533, 33237, 11528, 30745, 8246, + 38843, 2523, 24183, 26883, 10603, 15956, 29327, 24030, 28141, 17048, 5209, 2706, 17446, 25577, 23084, 1336, + 10234, 40664, 10134, 33067, 36445, 37765, 7681, 10302, 494, 20187, 9564, 5291, 20113, 36882, 3159, 21636, + 23677, 23681, 31365, 17667, 23695, 11339, 13047, 13046, 4306, 34237, 31320, 14206, 38232, 35390, 7108, 12697, + 14120, 5021, 10804, 22140, 2057, 17031, 24606, 32598, 29171, 25115, 15924, 30523, 11404, 18725, 4094, 11493, + 24632, 31973, 300, 9055, 28471, 18234, 32102, 17899, 14668, 33041, 20305, 28234, 16169, 12468, 11738, 29892, + 39697, 15304, 39549, 12114, 6813, 2299, 31740, 14652, 2851, 14118, 21799, 20080, 7988, 1228, 37441, 3069, + 27575, 7416, 34347, 31247, 37222, 1117, 24031, 10780, 29680, 4534, 11351, 35251, 20415, 13171, 6482, 13165, + 27809, 15957, 10985, 33772, 6747, 13733, 39120, 1415, 39912, 40785, 33407, 35144, 19767, 22042, 27, 13830, + 23882, 19737, 28369, 4965, 715, 32005, 17469, 28373, 15181, 34994, 35258, 21783, 31007, 25450, 28842, 28374, + 23929, 17264, 27603, 4210, 1995, 22083, 4919, 1099, 25928, 8522, 40787, 31174, 36442, 11583, 29397, 18273, + 15162, 28289, 26129, 27896, 30420, 10299, 39224, 39225, 16500, 35966, 37602, 28867, 21573, 31704, 12742, 8669, + 19284, 14723, 27857, 41114, 28375, 32043, 7809, 30991, 20854, 18685, 28376, 21936, 41083, 29879, 33412, 9433, + 33894, 17555, 27203, 19434, 20672, 19123, 13930, 40818, 9499, 21681, 36951, 27712, 4926, 40038, 26209, 24138, + 34242, 25232, 27224, 18967, 13334, 22772, 2586, 17028, 22823, 30184, 32157, 28296, 5654, 30670, 6812, 14135, + 1593, 13655, 2866, 1210, 2679, 21804, 339, 37643, 29495, 31347, 9047, 20526, 22607, 83, 22791, 3419, + 16903, 34317, 23945, 22719, 2908, 16673, 38753, 31562, 26322, 1315, 21465, 19251, 27476, 8296, 8291, 7915, + 21790, 40730, 13609, 14819, 722, 38140, 27723, 8158, 40996, 35690, 21792, 5022, 32584, 11159, 22660, 16858, + 23281, 15445, 40494, 2226, 39716, 31355, 365, 18236, 26312, 1545, 4507, 2801, 12642, 32458, 27611, 36922, + 40058, 8629, 30302, 15853, 1359, 30847, 18280, 5593, 25883, 40969, 35525, 18832, 15537, 23933, 4732, 23207, + 2921, 28782, 19464, 36584, 2819, 7737, 14175, 1572, 27413, 18578, 33452, 4538, 18407, 38104, 13188, 2385, + 16969, 32046, 31632, 15280, 27516, 1073, 38821, 23883, 3283, 18842, 11188, 12409, 23097, 11846, 23976, 22930, + 17921, 26056, 33453, 25886, 3284, 16029, 27684, 18346, 21097, 11537, 22768, 28248, 7285, 24071, 24917, 34807, + 28783, 32563, 14978, 13394, 41214, 17703, 24194, 16584, 6592, 33155, 38060, 12231, 13071, 39917, 5499, 34179, + 36526, 6543, 14979, 21784, 38061, 23122, 29443, 7286, 38822, 6085, 26349, 15137, 12956, 7544, 28253, 18688, + 14726, 11850, 37429, 17486, 37825, 22422, 27216, 8457, 32947, 7933, 40066, 7934, 3978, 5020, 15683, 10162, + 13294, 8832, 32596, 29068, 18041, 23419, 7422, 26409, 9697, 6723, 27188, 18307, 25005, 30342, 40724, 15450, + 32444, 29080, 20298, 11749, 27638, 1488, 8997, 40517, 20396, 13966, 39157, 25615, 8582, 16888, 35838, 12895, + 1696, 22701, 19448, 16676, 20716, 25949, 32880, 17674, 38342, 13245, 23826, 24025, 11341, 41128, 34879, 12171, + 4075, 38011, 36545, 6054, 12094, 30667, 1683, 30914, 14846, 15346, 18364, 5795, 5029, 22969, 20381, 12702, + 7113, 8946, 33476, 34191, 10163, 34930, 19195, 31725, 11603, 17499, 23286, 36319, 23285, 11025, 16050, 34504, + 4559, 30352, 40678, 24036, 13201, 40687, 16710, 1380, 29444, 11361, 35270, 6710, 9835, 5334, 14695, 7638, + 4971, 36005, 132, 40945, 34141, 5927, 40359, 10563, 40545, 12241, 21599, 10451, 12070, 24368, 1720, 36383, + 16032, 21662, 33543, 13203, 13204, 23885, 2579, 39865, 20363, 16999, 16716, 12243, 41139, 15889, 26402, 22398, + 16231, 6400, 27608, 4342, 18964, 1585, 834, 18690, 32430, 15807, 18440, 7037, 18641, 13206, 16458, 2027, + 12971, 35116, 2751, 32467, 13208, 31665, 9444, 2347, 21609, 16779, 4686, 24856, 22116, 19146, 41122, 19005, + 38172, 21612, 15007, 28876, 27335, 16398, 12276, 34758, 33259, 802, 33266, 19503, 34260, 39688, 32082, 31206, + 23299, 2875, 3124, 14410, 19660, 37039, 37649, 31978, 21121, 94, 28812, 13912, 11510, 36339, 4736, 4513, + 33808, 38765, 23081, 2311, 24812, 18803, 1351, 38105, 30988, 30709, 37919, 28912, 31317, 1525, 23403, 2494, + 19289, 17095, 22492, 20292, 35015, 25697, 12979, 3947, 3295, 4482, 32579, 7364, 21992, 40279, 20952, 39632, + 39027, 18363, 14318, 22850, 18594, 31947, 32582, 36885, 39553, 30157, 39379, 18012, 9019, 5618, 17107, 6764, + 3243, 15315, 16598, 34159, 25235, 39646, 39069, 9458, 23151, 29535, 9255, 14325, 11206, 10542, 9632, 13651, + 18971, 14757, 144, 33562, 7329, 9224, 7975, 14868, 40836, 28299, 18035, 3952, 7610, 6350, 23851, 38873, + 39738, 36324, 11508, 40762, 1960, 28865, 25430, 1066, 18259, 11353, 16221, 2744, 38784, 2894, 14302, 338, + 5980, 24734, 17730, 20053, 19811, 19291, 27457, 26270, 11994, 19812, 34375, 1223, 10077, 1224, 26365, 15130, + 15301, 1017, 10670, 25727, 25900, 32178, 32179, 12886, 20442, 31924, 27552, 6288, 38430, 21146, 38596, 22332, + 32017, 18068, 1495, 1268, 25728, 95, 9360, 8715, 8716, 7185, 4019, 10724, 9535, 20447, 25993, 16096, + 16534, 18861, 29508, 26171, 14500, 37746, 37747, 2800, 24891, 17973, 2879, 26194, 16097, 34328, 30937, 34410, + 7000, 11885, 37374, 30938, 32560, 735, 10731, 24896, 35054, 30941, 620, 233, 30627, 36104, 16144, 25093, + 19107, 4201, 17578, 9824, 13126, 5675, 14409, 41029, 26711, 20993, 38384, 17538, 16407, 12329, 22814, 14560, + 24538, 6500, 4204, 3222, 18859, 2550, 14559, 33870, 19716, 36415, 39101, 7473, 28472, 28282, 33003, 8550, + 4719, 8585, 27590, 1698, 25416, 40157, 33002, 13910, 23948, 23184, 3891, 28816, 40162, 10952, 8435, 37750, + 24391, 30116, 14941, 24059, 24273, 18670, 41209, 31584, 14509, 37589, 16688, 34411, 17949, 2044, 2567, 36772, + 306, 20584, 4624, 26368, 29293, 37875, 17527, 22730, 5104, 12318, 1729, 35916, 25317, 6897, 9085, 15350, + 18596, 39557, 35720, 39138, 10841, 17117, 34926, 27057, 39656, 24936, 18711, 38954, 21397, 30483, 16357, 6334, + 25027, 7735, 29286, 21574, 28514, 15163, 10437, 25095, 4174, 9368, 6307, 23442, 15911, 28846, 9370, 22725, + 15244, 31890, 11847, 2823, 22638, 5330, 11362, 28525, 30945, 28417, 10052, 15143, 6326, 11751, 4953, 11345, + 16643, 33160, 8339, 39605, 36048, 34748, 6251, 6887, 26731, 22243, 15505, 37866, 39533, 22486, 3240, 6891, + 24683, 5609, 18180, 30068, 1760, 6759, 27223, 6760, 7068, 9574, 36926, 15055, 24090, 33260, 4251, 8172, + 31951, 26268, 26747, 23042, 39188, 32332, 5419, 7504, 35750, 6564, 19059, 36066, 14396, 3165, 18712, 26750, + 32261, 36074, 40241, 34776, 25366, 31966, 3722, 34612, 36075, 27367, 5526, 30524, 21522, 6565, 4322, 40740, + 4602, 18786, 17905, 30785, 12845, 23889, 12763, 12450, 12314, 15192, 5479, 8352, 13023, 38129, 21914, 18016, + 2124, 1063, 38360, 22625, 23038, 8286, 16172, 8454, 10254, 28649, 8576, 38303, 33113, 37828, 14205, 10347, + 38064, 19609, 37233, 2931, 21315, 23252, 3311, 35183, 2990, 34600, 11601, 2058, 9983, 9598, 33747, 15940, + 93, 20487, 29972, 34012, 35095, 31641, 21049, 961, 27044, 15862, 35416, 39655, 40719, 8312, 13949, 39198, + 16291, 24617, 12142, 5147, 8212, 2655, 12523, 31679, 5559, 37044, 9062, 13987, 24889, 13103, 13310, 22816, + 19557, 9139, 31267, 9225, 12138, 14629, 12881, 22652, 15329, 24149, 25762, 512, 194, 13571, 8350, 34509, + 11615, 37879, 31353, 28806, 12568, 5359, 292, 31829, 36215, 25823, 25245, 17893, 29913, 5487, 13468, 28157, + 369, 32275, 7617, 21286, 7092, 12197, 5366, 36229, 6849, 18462, 31633, 17220, 17242, 10909, 39401, 35780, + 24253, 23668, 11325, 9056, 14775, 10872, 37986, 37067, 3823, 28144, 10132, 31121, 27475, 9431, 3937, 37993, + 36582, 12222, 31622, 18345, 16959, 21002, 33942, 38002, 12420, 12421, 20860, 7831, 26004, 20807, 7579, 22125, + 37845, 3613, 34736, 183, 31362, 5813, 5306, 11094, 5914, 20820, 3188, 38511, 18086, 23194, 40024, 10693, + 38608, 36100, 40343, 30007, 18200, 6215, 36347, 31385, 18106, 18107, 10696, 36105, 8712, 515, 19635, 20744, + 4766, 13127, 25856, 27253, 2940, 18855, 23116, 24836, 22754, 5342, 32061, 4079, 6131, 34247, 36065, 15443, + 37803, 28116, 3591, 13443, 6352, 5985, 36853, 37539, 9795, 37688, 31081, 25386, 11453, 14089, 25640, 28594, + 8884, 40550, 20874, 34920, 23803, 18365, 6195, 15118, 18595, 12804, 26699, 40073, 41284, 9253, 39064, 24765, + 39387, 14126, 9460, 6200, 34293, 15760, 25785, 9887, 22661, 39191, 20086, 29992, 19104, 4868, 22172, 30343, + 21483, 14046, 34311, 7451, 37017, 40905, 6100, 13129, 4600, 21015, 20247, 30236, 6960, 27381, 3339, 36512, + 8714, 18900, 1730, 29013, 39775, 4070, 9197, 19885, 25954, 26251, 19362, 19363, 37891, 18342, 19979, 1717, + 31392, 30848, 16149, 31705, 35983, 5234, 29042, 37430, 18408, 5076, 12410, 22134, 34810, 30648, 7746, 31898, + 12658, 19926, 19927, 16717, 17367, 12076, 65, 7553, 5079, 18441, 18139, 135, 7751, 17380, 787, 10508, + 10504, 10506, 1823, 24344, 29238, 39100, 3266, 24426, 14163, 14168, 29245, 7429, 20264, 813, 29328, 11852, + 35278, 6063, 2549, 23760, 25340, 5560, 6448, 31354, 25341, 24260, 21711, 36216, 25768, 20911, 20642, 41105, + 640, 35871, 35085, 28954, 934, 12780, 10685, 22193, 1825, 36096, 8726, 28958, 13719, 164, 10523, 8958, + 23621, 29477, 36519, 28143, 29392, 33884, 15574, 1050, 28506, 26412, 17461, 17971, 36956, 31479, 35322, 26157, + 33135, 26556, 1527, 25784, 14634, 27875, 1555, 1556, 27212, 9050, 9168, 10982, 7467, 12180, 16346, 36961, + 22281, 19560, 38580, 14037, 21275, 18229, 35583, 34752, 30666, 6638, 23978, 26921, 10839, 40289, 33853, 28559, + 35185, 34768, 31344, 9987, 19831, 2978, 34619, 10936, 37304, 30544, 6502, 730, 33748, 1405, 29952, 18204, + 19454, 26380, 37923, 35883, 37368, 7262, 28218, 32285, 14982, 4706, 1524, 5384, 33658, 31587, 17094, 11059, + 14188, 11078, 7425, 26995, 27714, 32064, 39548, 24694, 11065, 7951, 41283, 19999, 39382, 4376, 39074, 29355, + 23287, 2684, 31825, 40641, 31753, 25207, 28980, 28712, 1789, 16145, 16237, 33061, 674, 7062, 24555, 24556, + 10438, 32779, 20829, 12933, 5542, 30903, 28925, 28515, 32910, 22084, 8746, 1368, 16151, 28784, 18538, 9682, + 24073, 33911, 12236, 12964, 13260, 2854, 4972, 11124, 32306, 23728, 6402, 30242, 12973, 16399, 30583, 25342, + 8038, 19793, 25020, 8727, 30728, 24114, 10015, 2964, 16154, 25534, 37939, 26560, 30755, 8743, 561, 28926, + 9012, 37942, 8623, 1369, 30761, 28257, 6397, 30243, 6403, 7956, 14306, 32105, 33044, 32113, 12228, 37985, + 16658, 22374, 11536, 36354, 37945, 22392, 176, 36108, 32517, 11125, 35182, 6071, 24404, 15928, 32541, 27562, + 9941, 33495, 35477, 33499, 6874, 27848, 15980, 23302, 6561, 12760, 11732, 21822, 21194, 34849, 40861, 25051, + 23671, 20443, 28991, 23529, 6575, 19677, 19839, 8537, 37211, 37219, 4929, 33920, 20296, 12099, 8382, 5292, + 11987, 3049, 6640, 34244, 40601, 1399, 7701, 7176, 76, 17131, 18368, 38460, 29597, 5622, 16174, 30085, + 7964, 33265, 19501, 31960, 23992, 38558, 6202, 21075, 8770, 31099, 23506, 6566, 922, 6102, 3203, 6356, + 13702, 5697, 33874, 1442, 38975, 9714, 25924, 24429, 24800, 6619, 5494, 13255, 2163, 19897, 2017, 15188, + 39578, 8072, 8140, 33466, 20231, 15581, 6629, 20293, 5089, 26775, 37483, 35432, 28129, 40868, 3413, 20711, + 16292, 13004, 5678, 28303, 34200, 21335, 10177, 37315, 30320, 582, 6655, 5571, 5113, 22111, 22924, 18185, + 3095, 14099, 16800, 10421, 24015, 6992, 6846, 30729, 32883, 16136, 26680, 35507, 26685, 9874, 6548, 37186, + 22835, 16801, 8130, 12784, 29692, 11813, 15952, 12790, 19097, 29553, 3276, 36488, 37813, 10979, 10120, 14107, + 29919, 29920, 22794, 16301, 29921, 40794, 40793, 4211, 6112, 16302, 28688, 10129, 23705, 15388, 4793, 33839, + 24226, 35516, 25834, 29135, 6853, 7013, 34417, 30986, 15228, 36609, 40396, 34418, 32286, 33193, 35603, 37660, + 25931, 5747, 5748, 13285, 15909, 16810, 16585, 22740, 30268, 19405, 4670, 35004, 10303, 24074, 9239, 34139, + 34573, 11855, 2855, 25591, 19931, 1722, 28133, 22611, 25709, 27922, 15945, 19664, 15378, 20491, 22733, 3274, + 15241, 17907, 9203, 29463, 1182, 25001, 29255, 7323, 39140, 26490, 30357, 29889, 7953, 8505, 9146, 17166, + 34516, 22532, 16410, 16933, 12205, 38350, 10363, 9427, 14727, 13841, 8290, 35546, 22904, 38825, 17715, 29836, + 4121, 26213, 19810, 2610, 21816, 2109, 28595, 14606, 610, 23741, 7367, 15298, 29701, 11974, 462, 37245, + 39253, 9148, 6814, 22953, 2119, 1905, 37712, 20800, 28717, 5797, 27581, 27059, 33858, 28404, 1209, 21225, + 22447, 6689, 15326, 16600, 7114, 36835, 3323, 12766, 21076, 35135, 5333, 5905, 36073, 15144, 40145, 6097, + 6121, 11165, 24948, 9853, 32307, 22809, 18643, 16435, 21611, 24995, 29546, 14218, 11767, 36476, 36607, 16808, + 7702, 1536, 9311, 8028, 31927, 38662, 1544, 25792, 452, 28570, 17813, 9274, 33885, 26436, 14676, 1562, + 27680, 30756, 34806, 34997, 27900, 15164, 27901, 7222, 18281, 31710, 18347, 22712, 22713, 18287, 1579, 1580, + 1581, 17707, 1615, 26062, 7752, 33420, 34753, 38639, 27646, 34967, 18239, 7418, 7226, 7447, 26918, 2225, + 12120, 6095, 27735, 30051, 38585, 29997, 25343, 37295, 14783, 3605, 36217, 7342, 7343, 28269, 36212, 29707, + 35479, 41299, 1270, 13774, 28913, 18311, 4401, 29450, 27754, 770, 27096, 6787, 9913, 25346, 29320, 13455, + 12781, 1784, 34968, 29626, 26104, 5906, 39263, 26003, 3751, 28767, 193, 25556, 16558, 16264, 28990, 15522, + 38358, 17037, 8613, 6840, 4887, 19029, 18309, 15129, 13009, 16487, 24301, 14418, 4, 23907, 21888, 965, + 5436, 15455, 16058, 9232, 11948, 22254, 14737, 28663, 40755, 24174, 15157, 27653, 6972, 2518, 27881, 11334, + 25, 18570, 23914, 7520, 19726, 20652, 8725, 14721, 20852, 18247, 35894, 12736, 1703, 1554, 28779, 19459, + 19114, 36574, 41070, 33882, 5539, 2713, 14952, 23090, 18673, 6583, 16356, 23119, 4682, 23924, 5495, 12047, + 40674, 35967, 2578, 1575, 39906, 26663, 4849, 39739, 1124, 40827, 20606, 27282, 18890, 12133, 7866, 16485, + 15365, 25293, 4402, 32508, 34837, 14789, 7121, 16669, 31558, 1863, 21177, 6994, 2139, 15091, 6299, 28039, + 37068, 27112, 34981, 11904, 9833, 27113, 13166, 40535, 1786, 32395, 2144, 35240, 28683, 7439, 38767, 30831, + 9396, 7001, 21837, 37936, 10987, 11530, 11825, 12934, 10782, 116, 28838, 7588, 30839, 9199, 2524, 27855, + 28844, 1996, 8564, 31878, 16019, 18343, 27897, 28965, 35262, 37862, 20549, 28848, 19402, 1360, 37419, 33413, + 13924, 25890, 16030, 40446, 26351, 3656, 5235, 35998, 12232, 25241, 3286, 30862, 32519, 38627, 7589, 9925, + 19928, 34698, 20561, 2752, 32520, 19148, 38118, 21046, 6088, 30031, 6761, 10356, 16668, 31448, 6278, 15060, + 9823, 9164, 39162, 12594, 26032, 21381, 8256, 25210, 9503, 13426, 10271, 31529, 22940, 5956, 11079, 36616, + 14253, 37477, 758, 39189, 9090, 6134, 18597, 24769, 3411, 27631, 7083, 39689, 9260, 33385, 18972, 1926, + 16878, 9165, 37297, 32180, 29085, 31274, 20285, 159, 858, 4297, 10951, 6975, 4397, 19727, 31369, 35088, + 12919, 36349, 39042, 18338, 17687, 13385, 14360, 37397, 11117, 18828, 9440, 21152, 6055, 13563, 17097, 26297, + 17109, 36742, 8389, 15351, 5144, 38494, 22211, 40297, 33796, 12706, 34217, 35443, 39706, 16557, 31351, 4847, + 32175, 26106, 40203, 7516, 9229, 30705, 37175, 36937, 5107, 16194, 35862, 10766, 2638, 18568, 12820, 25980, + 35205, 1937, 7616, 1950, 21282, 1290, 1975, 29821, 9950, 7440, 12935, 170, 125, 32123, 37814, 7640, + 22783, 33149, 19276, 37296, 7765, 10092, 5562, 30105, 38964, 3489, 34066, 40328, 39430, 22290, 33187, 25381, + 25789, 37884, 30930, 39493, 5200, 18862, 36783, 1951, 773, 14917, 30113, 35872, 24728, 23137, 24735, 14195, + 22958, 38840, 37513, 22264, 40102, 14649, 40339, 21794, 14436, 22468, 38141, 12840, 18087, 39163, 28573, 8228, + 34840, 26988, 1312, 30177, 30115, 27762, 18248, 19311, 22681, 28963, 39804, 25436, 29019, 6213, 34006, 24914, + 26641, 14196, 7123, 9917, 1976, 40167, 36102, 19221, 40125, 5214, 33052, 18264, 14517, 27832, 24227, 19517, + 3629, 20649, 585, 12358, 11517, 1550, 19168, 36485, 38565, 18390, 36228, 3774, 595, 16306, 35956, 5830, + 22588, 5753, 24842, 35768, 27821, 31432, 24447, 40551, 1432, 35025, 29409, 6290, 15366, 37052, 34000, 14645, + 37184, 36038, 2572, 20880, 25325, 13852, 19779, 22106, 5246, 12765, 8643, 15501, 17411, 3337, 17504, 13007, + 1594, 3953, 29186, 1264, 14423, 6681, 4910, 930, 771, 18901, 1444, 16343, 3551, 39023, 23974, 25584, + 22115, 22562, 33469, 15031, 4810, 13849, 16729, 40830, 3035, 27742, 11947, 16618, 28771, 21959, 18522, 13279, + 21780, 20688, 5976, 6058, 5098, 18045, 21633, 9263, 16009, 314, 28659, 9931, 23258, 10169, 16502, 10130, + 29824, 33773, 29962, 15097, 6879, 3389, 33238, 44, 18826, 40502, 40031, 26561, 22683, 16070, 28966, 16279, + 40937, 15473, 23358, 23359, 34671, 7441, 25958, 34552, 8748, 35057, 31396, 22695, 4539, 22696, 23789, 7442, + 11538, 23786, 11956, 37103, 29140, 24978, 32011, 40939, 15959, 25526, 27683, 9280, 30126, 9553, 27904, 23717, + 3373, 39847, 18283, 22396, 29028, 31711, 2394, 6389, 34687, 37606, 41017, 25960, 26352, 16984, 39857, 27480, + 18844, 31712, 19126, 38774, 20680, 384, 2242, 1582, 4541, 24753, 1377, 39858, 37440, 33542, 11190, 1871, + 28088, 32684, 17925, 38738, 6627, 18293, 30129, 2485, 5839, 13401, 29446, 34699, 19139, 38629, 13677, 10393, + 36474, 15361, 10091, 6993, 40392, 21564, 19373, 25926, 10300, 25587, 22803, 10826, 23745, 24577, 12435, 2634, + 11597, 8767, 19846, 7969, 22505, 25699, 32259, 10209, 13805, 8983, 6261, 36203, 3410, 9936, 9095, 10383, + 17152, 36758, 25147, 38497, 24534, 18048, 3253, 36897, 24473, 12769, 21079, 39712, 27639, 24713, 29501, 16128, + 23288, 13351, 34782, 20715, 26716, 38911, 26429, 31213, 16892, 3913, 8020, 23906, 24361, 23319, 31552, 37333, + 7434, 9828, 9753, 35868, 22534, 29389, 24966, 30283, 16492, 19953, 4233, 25428, 21021, 8049, 15948, 15382, + 8224, 27886, 37064, 36789, 18523, 24648, 1410, 19584, 24278, 315, 19428, 19536, 14076, 36021, 35279, 30062, + 22784, 40121, 34707, 18448, 18873, 29040, 32468, 12673, 27493, 14542, 31720, 11304, 17015, 1588, 25375, 36062, + 1528, 33207, 24212, 40895, 27991, 15937, 27478, 30682, 30697, 30698, 37024, 8466, 35819, 246, 815, 935, + 4358, 29155, 24016, 15736, 29943, 8848, 22677, 37095, 28170, 2009, 32675, 685, 2010, 4362, 20554, 17705, + 18541, 32681, 38137, 29160, 1739, 15792, 18644, 8546, 24104, 15306, 24086, 16586, 25990, 16055, 5563, 7405, + 33398, 25151, 5201, 16063, 1731, 7199, 22469, 7201, 29197, 818, 1313, 19586, 8053, 7093, 25437, 24738, + 8923, 16139, 22377, 40368, 26439, 28322, 29211, 17245, 1733, 5589, 22386, 27812, 19324, 37592, 31597, 3435, + 28830, 22151, 27123, 11527, 2383, 22709, 28833, 31609, 32559, 39911, 38769, 27451, 19589, 22381, 11833, 22081, + 26342, 12058, 19961, 2722, 17476, 20359, 16983, 6472, 24855, 7821, 36334, 24432, 32038, 27056, 40187, 36976, + 12286, 6409, 12118, 12992, 38869, 40835, 11074, 24461, 22955, 4944, 26751, 38242, 9023, 17147, 27739, 29377, + 12711, 1400, 3414, 15607, 1236, 32263, 34383, 24954, 39268, 37850, 27087, 8533, 21996, 26427, 32728, 24425, + 38258, 24171, 40330, 25747, 23769, 30168, 1282, 5110, 15555, 37506, 32634, 39110, 16008, 11511, 10770, 9007, + 7480, 17215, 1322, 3497, 28060, 20348, 6244, 18804, 6510, 9614, 39292, 40940, 27569, 13063, 30155, 11002, + 16215, 23376, 17484, 39170, 22397, 19315, 25863, 19407, 19408, 26078, 33544, 17853, 23722, 23721, 21041, 16153, + 21665, 1740, 25215, 6279, 6298, 21147, 10734, 31879, 6311, 10041, 6314, 6313, 14283, 37454, 37458, 34662, + 8135, 24284, 9551, 40942, 18348, 9555, 26389, 19787, 12569, 23305, 8301, 33508, 37395, 29925, 23199, 17620, + 8414, 22714, 1371, 12465, 33540, 3871, 34579, 38630, 37001, 5346, 25275, 13697, 507, 10686, 30054, 5915, + 12455, 33691, 6848, 6974, 26121, 10179, 30003, 20655, 13824, 26681, 619, 37586, 22538, 18666, 30933, 10963, + 18605, 37965, 7383, 7624, 20916, 36790, 22697, 20699, 10431, 31997, 5831, 38057, 5467, 2037, 16311, 40113, + 36965, 36980, 3681, 31817, 21511, 21826, 4090, 26219, 35562, 1130, 39896, 612, 7402, 8763, 18599, 40200, + 38243, 31509, 26428, 30708, 19952, 27173, 2382, 3703, 19907, 24211, 21452, 12715, 24639, 26114, 1366, 5524, + 23966, 28307, 13713, 28774, 31594, 32071, 20083, 414, 17149, 29419, 31505, 40738, 2301, 17891, 40979, 25873, + 10771, 38055, 4399, 33577, 25518, 24665, 13316, 8783, 12571, 35714, 18044, 31506, 40331, 7474, 13033, 22655, + 10426, 35944, 20109, 39476, 23313, 23431, 34982, 5417, 7863, 24748, 14256, 14416, 17806, 40753, 38082, 21010, + 39022, 13229, 27065, 6061, 8391, 40079, 35569, 9101, 24739, 10012, 22474, 18097, 30121, 1868, 24656, 22889, + 8067, 1330, 4434, 30832, 14439, 5873, 483, 36797, 9720, 22475, 21379, 33232, 28576, 821, 8240, 38476, + 14659, 9115, 27151, 6221, 5080, 28509, 13734, 27271, 10817, 32514, 7095, 235, 30628, 38899, 40168, 36289, + 17824, 19223, 29642, 29156, 35953, 1816, 30746, 13381, 15668, 9545, 32115, 8740, 11682, 16638, 8284, 15333, + 33455, 6708, 15044, 29136, 20259, 26441, 38477, 28323, 24228, 37096, 21180, 39002, 9723, 8850, 28094, 31233, + 24659, 26252, 23056, 11441, 29396, 17056, 26130, 26131, 15336, 19903, 3399, 17395, 41036, 31910, 36658, 21256, + 40797, 23364, 39302, 32515, 21181, 4279, 12643, 5878, 4639, 30102, 32090, 20509, 39582, 34638, 26182, 3352, + 29809, 16798, 16065, 22241, 10978, 29121, 33582, 9893, 28837, 16579, 2068, 13546, 31631, 14688, 17059, 34022, + 26968, 4858, 6630, 24482, 33930, 4663, 1665, 801, 28403, 12998, 7862, 23898, 39479, 7867, 26227, 17167, + 30098, 12723, 2034, 28562, 15979, 24000, 1265, 32270, 32089, 12155, 13354, 17585, 12586, 4300, 11256, 3495, + 39780, 5781, 1958, 39498, 13156, 6006, 4071, 39940, 14571, 6705, 4837, 22679, 25520, 21567, 22076, 23197, + 3940, 14969, 23121, 7278, 4666, 40220, 17985, 2743, 17851, 41120, 33095, 39614, 5862, 20633, 33390, 20668, + 22547, 10914, 14873, 26370, 9097, 40748, 24192, 9238, 40057, 6162, 16280, 7542, 21258, 35985, 16071, 18835, + 14364, 2883, 14067, 19081, 18117, 41015, 16970, 19962, 40943, 39849, 21382, 11138, 37474, 5723, 26886, 26646, + 11915, 29142, 10784, 33241, 40178, 16222, 40944, 38324, 1420, 1421, 11442, 24981, 38328, 30565, 30566, 37107, + 4242, 25528, 6021, 11543, 17561, 34563, 24557, 24558, 13064, 1102, 7022, 34809, 8264, 25836, 8445, 31937, + 30156, 11005, 27154, 25754, 33899, 30905, 23876, 10304, 31176, 7386, 25963, 18290, 19285, 26955, 26890, 9373, + 40801, 29032, 28435, 35005, 6868, 36612, 23794, 23378, 30906, 25756, 26727, 17487, 327, 16666, 11654, 20462, + 12659, 29403, 24756, 12965, 26648, 19412, 8908, 28025, 39776, 40750, 24435, 14149, 37000, 17169, 30924, 29509, + 12588, 22292, 7437, 26174, 36182, 64, 25888, 19335, 3218, 14563, 731, 29387, 40764, 15491, 37187, 4330, + 31123, 20229, 37561, 30127, 40491, 28277, 14761, 14424, 19214, 24818, 3839, 24486, 18977, 31375, 38094, 20727, + 380, 18272, 953, 33148, 36769, 7382, 479, 22877, 21376, 18603, 27945, 8202, 10811, 28566, 9537, 13707, + 30717, 7090, 12589, 13361, 32509, 34070, 8847, 16924, 17443, 12917, 26948, 29394, 9716, 26123, 11432, 12599, + 24364, 18098, 41012, 7438, 16067, 2880, 9237, 21253, 21380, 5874, 26880, 40783, 7676, 6011, 7008, 24553, + 8248, 11531, 1417, 25956, 31715, 24661, 1614, 12660, 12652, 40222, 13261, 33418, 40398, 36595, 38775, 15282, + 33947, 1639, 37445, 24757, 32567, 1873, 13500, 34093, 28089, 11549, 41216, 26359, 26360, 7227, 9687, 17926, + 34094, 20291, 31766, 38367, 32572, 7683, 9379, 10821, 15783, 38329, 25965, 38632, 8450, 9689, 36528, 17065, + 2925, 16823, 27421, 136, 25593, 12671, 33719, 11129, 27422, 17374, 17863, 17379, 20368, 39123, 32521, 7041, + 18646, 9445, 17016, 32142, 5345, 12445, 29998, 426, 10409, 36777, 38464, 480, 22529, 15322, 29627, 38321, + 10814, 15767, 38468, 15040, 36653, 23340, 26642, 1098, 2919, 29128, 30902, 30562, 24975, 13253, 22153, 12943, + 30850, 31707, 11122, 8447, 320, 23360, 28431, 9369, 34995, 16664, 1613, 33946, 19404, 20460, 36585, 9680, + 26353, 41215, 17061, 4955, 34738, 4961, 24058, 19395, 12942, 14445, 25524, 9011, 950, 13816, 29689, 15659, + 9182, 5632, 10776, 8729, 15390, 1345, 18536, 23613, 15791, 1737, 6399, 19795, 454, 34537, 17617, 32653, + 30495, 3445, 32500, 34649, 29454, 28929, 36594, 1530, 16059, 19580, 25155, 29393, 12615, 40782, 33404, 24977, + 14279, 1738, 11366, 17861, 20536, 11640, 20032, 12454, 15041, 40257, 20035, 23370, 321, 26567, 17928, 5071, + 4034, 36859, 32009, 35352, 24749, 6390, 16977, 24394, 2292, 242, 7631, 36911, 31238, 34580, 31658, 24657, + 9952, 38408, 38628, 9399, 21453, 35578, 8030, 17185, 14271, 2065, 34631, 8104, 5864, 12158, 7797, 25627, + 8406, 26868, 7799, 20490, 774, 37508, 39434, 11106, 24269, 7884, 587, 30934, 12918, 26875, 37362, 7833, + 34907, 14936, 14937, 22582, 11288, 39220, 777, 34650, 34171, 39346, 7374, 7800, 30935, 21929, 5065, 8662, + 25573, 18099, 20341, 8054, 30122, 20414, 17227, 1448, 39806, 8663, 37514, 4411, 24806, 32654, 3438, 5216, + 14440, 35051, 9116, 6156, 37376, 34743, 25501, 34175, 29442, 37377, 29346, 36348, 6539, 31171, 7096, 9278, + 106, 39437, 34667, 10557, 32662, 12792, 17825, 40169, 34801, 29129, 10697, 19224, 25581, 20729, 8668, 25279, + 13382, 33409, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40029, 39438, 19225, 10566, 21435, 7044, 18979, 12793, 12634, 29826, 11292, 30153, 2085, 31234, 14724, 37412, + 1998, 15099, 34135, 1097, 31624, 15100, 14523, 29759, 14066, 29137, 6856, 6857, 15846, 10996, 31301, 26645, + 16307, 13559, 22117, 18836, 22550, 27277, 8081, 175, 40680, 22394, 24285, 23713, 863, 5879, 18837, 25110, + 12949, 14530, 29845, 34178, 37520, 23367, 16971, 35267, 40504, 15559, 6800, 16072, 26766, 23368, 14068, 35986, + 35987, 14069, 40798, 16281, 6163, 23208, 4298, 8819, 14448, 14971, 36043, 41234, 12229, 27414, 36362, 3657, + 20289, 25529, 177, 24560, 29143, 11006, 29144, 7024, 13602, 19593, 8083, 4244, 29828, 34564, 10448, 37608, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22659, 16075, + 19743, 11007, 36363, 4132, 31398, 14533, 6222, 2338, 7408, 10501, 36379, 37609, 32131, 31011, 26891, 10502, + 3941, 28852, 32013, 25757, 18291, 12415, 9126, 12963, 28290, 10141, 4416, 4417, 36010, 35108, 34689, 12237, + 17326, 29289, 15623, 29059, 29060, 36011, 29830, 19286, 13399, 8570, 29290, 3199, 12416, 29883, 39048, 328, + 35059, 35358, 21939, 3660, 39863, 18350, 36596, 18872, 1381, 27484, 40690, 37117, 31240, 14995, 36187, 29148, + 27691, 13402, 36022, 11192, 1384, 36387, 28090, 11550, 7292, 13403, 17709, 34700, 8572, 14368, 32237, 32238, + 29831, 19342, 41217, 37447, 36389, 18849, 29884, 32239, 33943, 36028, 22640, 3966, 19142, 31662, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35537, 12249, 38294, 37124, + 38633, 35282, 34813, 22641, 21666, 11130, 20073, 36392, 19938, 5601, 37787, 37448, 16781, 835, 18647, 10505, + 18449, 27494, 37792, 36393, 9446, 24860, 17017, 19012, 26832, 2323, 32599, 18029, 33922, 10547, 40000, 31207, + 16060, 23678, 8811, 37505, 28014, 10416, 24541, 35900, 31004, 18250, 12368, 35901, 35342, 11354, 38616, 19904, + 27485, 18654, 13868, 18100, 13065, 32232, 4863, 13075, 13088, 34445, 36693, 4619, 22196, 4620, 22198, 40345, + 12936, 20034, 37204, 18276, 3194, 15045, 17915, 21261, 14365, 15046, 14072, 17290, 32460, 32233, 12744, 20051, + 17327, 38777, 14077, 23387, 18161, 34452, 4621, 19353, 10417, 3027, 7886, 20271, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20255, 7892, 22222, 24895, 24742, 20730, + 7896, 32406, 16282, 20277, 3667, 7754, 24736, 20274, 19682, 20700, 41016, 21847, 7642, 11495, 13869, 9467, + 29242, 29710, 11236, 15876, 10701, 3449, 10509, 35902, 5156, 31861, 29975, 20648, 23785, 5783, 34553, 19769, + 34565, 37769, 5276, 34340, 34436, 34570, 5164, 39173, 5078, 2293, 35360, 19747, 38689, 34586, 6407, 18648, + 7649, 20249, 37598, 4665, 24898, 3012, 30206, 40179, 39445, 19935, 330, 1640, 30133, 1389, 2995, 20154, + 6078, 40770, 9172, 6161, 7634, 37524, 2887, 8571, 23556, 37525, 28785, 29004, 27305, 7534, 30943, 459, + 5877, 30125, 39914, 24823, 26765, 26951, 26954, 29519, 21433, 14075, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11912, 14540, 34575, 29760, 27694, 32423, 16727, 35053, + 31389, 31393, 10739, 33091, 7036, 33454, 31036, 38409, 21756, 21062, 23322, 38528, 12635, 40799, 12238, 12246, + 3553, 3224, 3226, 10441, 34205, 36183, 33078, 736, 38291, 33083, 2630, 3446, 34566, 14576, 29401, 18123, + 18108, 3895, 24985, 33087, 15498, 21591, 14367, 35058, 4340, 16100, 37209, 3965, 35608, 21262, 38293, 41020, + 24876, 37896, 34584, 21943, 7039, 31132, 36032, 4365, 41021, 5760, 3967, 14013, 34282, 10385, 36151, 18392, + 22154, 8928, 22155, 34567, 18425, 18468, 8932, 15196, 4974, 18176, 4975, 9547, 24565, 1643, 4220, 10453, + 15000, 32926, 37452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2943, 0, 0, 0, 34283, 40083, 40059, 5335, 13769, 0, + 30248, 10042, 10036, 32719, 33204, 40088, 40064, 0, 8490, 15739, 27837, 27816, 0, 0, 8495, 15765, + 28443, 21682, 0, 0, 0, 18491, 2281, 27009, 3767, 0, 25309, 25349, 0, 490, 481, 37470, + 40377, 24481, 16023, 16013, 0, 33128, 34696, 14161, 24389, 0, 26344, 35138, 22923, 26345, 40586, 26350, + 15008, 30967, 39341, 4069, 39342, 0, 0, 37116, 36290, 4243, 24559, 37115, 29033, 26876, 13384, 17826, + 14071, 14534, 29061, 22643, 34568 +}; + +static const uint16_t gb18030_4_weight_py_p1[] = { + 36865, 34286, 36250, 25280, 14183, 0, 5349, 2049, 32720, 31179, 30440, 30441, 31180, 27773, 34914, 12676, + 12467, 33203, 27209, 28151, 0, 25382, 25370, 37683, 5007, 0, 20420, 27553, 27554, 1590, 38908, 38905, + 23963, 25028, 0, 20832, 27001, 27140, 27700, 27701, 8523, 30497, 30496, 0, 0, 0, 37469, 25536, + 14543, 2399, 2401, 2402, 11031, 36045, 31667, 31911, 13211, 0, 0, 34455, 954, 3057, 4305, 4307, + 4344, 8141, 13886, 2926, 2927, 38795, 19828, 0, 8142, 37136, 24373, 30655, 35287, 7756, 7448, 26958, + 0, 26959, 26960, 0, 19287, 9142, 9618, 37127, 21479, 18693, 19371, 11552, 20260, 23390, 23391, 3560, + 3561, 18452, 18453, 9563, 9562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24521, 29334, 0, 0, 15728, 31241, 36195, 0, 0, + 0, 0, 0, 35364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32822, 0, 0, + 0, 0, 0, 3784, 0, 0, 0, 0, 21876, 0, 0, 5101, 0, 0, 0, 33596, + 33250, 0, 33318, 18208, 17932, 32447, 36575, 33159, 39126, 5008, 31306, 22044, 0, 0, 19271, 23838, + 35626, 36112, 21185, 3391, 7688, 0, 0, 0, 40566, 7389, 331, 31246, 41273, 0, 6183, 27967, + 35664, 24446, 15809, 16783, 21101, 40276, 27217, 0, 0, 0, 33556, 0, 0, 26587, 13796, 5939, + 21851, 27970, 35692, 18472, 36505, 1032, 0, 0, 0, 16329, 20281, 35724, 17119, 12512, 37146, 19102, + 2618, 0, 0, 0, 11890, 33564, 11737, 25244, 0, 0, 10079, 31809, 28602, 34936, 11741, 15068, + 19296, 19030, 28797, 34945, 38877, 38522, 37170, 40635, 7147, 25190, 23428, 3615, 31275, 10093, 28860, 26009, + 0, 24484, 16672, 25790, 0, 0, 15981, 23075, 28485, 27288, 34740, 21957, 28571, 0, 20201, 36284, + 5917, 37188, 20342, 15095, 21468, 33053, 36804, 0, 0, 3114, 7739, 16764, 17312, 0, 19178, 0, + 12474, 0, 0, 0, 0, 24920, 0, 2177, 17602, 9131, 19616, 0, 9288, 28180, 0, 0, + 19637, 19377, 24908, 27082, 16987, 0, 30455, 15596, 6442, 39213, 29456, 0, 0, 1795, 11983, 6186, + 8967, 3241, 0, 24208, 14208, 18707, 33296, 0, 20988, 32977, 0, 1247, 13698, 27982, 0, 8873, + 0, 36867, 33243, 23582, 22487, 5787, 8094, 19183, 23585, 23586, 28765, 509, 8386, 4370, 33727, 16507, + 0, 0, 26502, 0, 16852, 11204, 29685, 22648, 5522, 25647, 6916, 24152, 35782, 40576, 25702, 12874, + 0, 3607, 3724, 31537, 0, 19034, 5456, 17887, 14904, 28016, 32765, 38088, 0, 0, 40251, 38663, + 12920, 41030, 4048, 33045, 17228, 0, 3655, 31708, 12976, 0, 12256, 0, 7486, 3971, 1002, 13628, + 0, 438, 17605, 15759, 0, 31919, 1618, 14906, 16686, 33192, 556, 34841, 18949, 901, 6930, 18657, + 0, 0, 3081, 21864, 33791, 10537, 37154, 0, 9603, 35822, 33832, 8982, 18560, 29048, 16642, 27004, + 0, 28279, 35062, 32052, 41026, 0, 25041, 36113, 31410, 39530, 12747, 11047, 16155, 35555, 15424, 7843, + 24240, 73, 0, 15446, 3908, 32931, 3917, 30550, 0, 0, 11381, 27973, 36893, 0, 15088, 38847, + 33587, 26966, 0, 27425, 15989, 27473, 10410, 8359, 34456, 24566, 26572, 11197, 31412, 7308, 22162, 5135, + 7390, 8878, 275, 8088, 21154, 33949, 36722, 11155, 0, 3147, 9770, 20836, 11199, 17092, 7165, 32576, + 23029, 0, 27716, 0, 0, 16654, 17956, 35694, 10790, 0, 33606, 24763, 7069, 0, 0, 34033, + 0, 0, 0, 0, 21504, 30669, 32956, 29066, 10643, 30012, 21505, 21506, 36128, 39066, 0, 0, + 0, 0, 0, 27181, 21877, 35186, 23259, 29715, 9980, 15062, 6166, 11869, 18713, 14397, 11996, 18030, + 0, 29298, 19060, 0, 0, 0, 0, 0, 0, 8689, 34307, 26930, 33926, 22296, 4284, 21686, + 6725, 38245, 6932, 32852, 36688, 6933, 26778, 30958, 15647, 10920, 8691, 31968, 19438, 19028, 12309, 10747, + 39691, 0, 0, 30250, 0, 564, 80, 40497, 23670, 9046, 5193, 852, 1927, 3888, 17172, 32763, + 33440, 0, 0, 0, 0, 0, 10680, 29187, 4641, 16133, 16560, 39740, 32807, 31539, 0, 24167, + 38388, 31540, 0, 0, 4561, 12349, 12022, 28425, 34399, 33682, 22926, 25838, 0, 0, 0, 9757, + 35227, 32511, 33907, 10422, 41301, 35904, 4403, 0, 16824, 32211, 28587, 25438, 35935, 39825, 31615, 32218, + 14677, 12395, 0, 22223, 17267, 0, 16368, 25840, 10040, 34431, 24752, 0, 34443, 15197, 3559, 21492, + 11979, 0, 1172, 31941, 31012, 33794, 30282, 36805, 24230, 33590, 21496, 1163, 10248, 14084, 350, 351, + 0, 0, 39055, 28613, 14457, 0, 41277, 2097, 13637, 72, 38142, 4371, 7166, 0, 0, 0, + 0, 21507, 18325, 19697, 6562, 656, 1197, 759, 0, 3990, 32027, 29300, 2897, 0, 0, 6674, + 30527, 8181, 6726, 37162, 35158, 15931, 30683, 15761, 0, 30528, 34898, 18458, 33213, 40382, 3480, 32858, + 21533, 16512, 35327, 40911, 19381, 38812, 32033, 9727, 32868, 0, 12590, 17665, 35876, 12350, 36167, 0, + 4912, 35877, 33029, 10289, 36654, 15221, 2841, 28575, 28824, 39505, 823, 19881, 15953, 2715, 16752, 0, + 31881, 0, 31636, 24121, 21055, 37799, 0, 18361, 8159, 40889, 0, 9135, 15124, 5866, 11221, 15984, + 0, 8574, 28976, 0, 26261, 16285, 21498, 7921, 8575, 24130, 626, 12691, 15541, 31787, 37252, 40493, + 26668, 4317, 32618, 12457, 21788, 32693, 35629, 36948, 35370, 34459, 26656, 25173, 10249, 25779, 15020, 36724, + 0, 33150, 22231, 24528, 2652, 0, 2098, 6126, 27717, 7107, 0, 19604, 37900, 12101, 0, 24079, + 33324, 22181, 3898, 22313, 21867, 13638, 35306, 7137, 6762, 0, 0, 0, 6718, 0, 0, 24146, + 18881, 24595, 27912, 2296, 6272, 31452, 7703, 35729, 28295, 24125, 22971, 33120, 29656, 33172, 36745, 895, + 18476, 0, 0, 0, 0, 37836, 16854, 28450, 16403, 19420, 23965, 40041, 34606, 31471, 18715, 31472, + 25969, 7337, 0, 30684, 7197, 35784, 21114, 3254, 28748, 12131, 27368, 22663, 151, 15714, 2508, 0, + 32173, 39694, 0, 0, 7716, 17530, 34053, 33655, 20136, 11755, 20809, 36550, 38650, 35823, 21775, 28800, + 31519, 37846, 27377, 8010, 35824, 4952, 0, 17423, 2365, 2231, 14639, 18749, 28017, 21197, 366, 198, + 23858, 0, 4714, 4498, 0, 25153, 21401, 19327, 33153, 37744, 20929, 375, 26635, 19310, 0, 0, + 16445, 31603, 37756, 39827, 31026, 11259, 19980, 21470, 30387, 20046, 21583, 24828, 38108, 17567, 39523, 40813, + 9869, 33591, 10252, 33728, 39640, 20233, 4260, 9048, 0, 4272, 18997, 40268, 27164, 17711, 14310, 32928, + 6089, 13783, 25385, 19479, 0, 15429, 35019, 21630, 35399, 16467, 36600, 36130, 34367, 27983, 0, 17877, + 34166, 19564, 20474, 41173, 37163, 35785, 9049, 20093, 15076, 30962, 0, 15261, 5816, 18380, 0, 33283, + 4778, 24054, 20207, 19982, 24314, 0, 30305, 5423, 74, 0, 1478, 21759, 17424, 13909, 36920, 4190, + 41266, 2032, 11592, 35064, 29936, 12529, 146, 19197, 12441, 30685, 1850, 37960, 33656, 21385, 37898, 0, + 460, 38925, 14378, 30664, 32951, 23466, 35400, 32952, 4373, 24596, 6325, 21482, 23493, 12446, 29898, 0, + 27814, 5818, 16564, 38678, 0, 0, 36110, 2451, 12425, 11715, 40815, 16324, 21064, 14584, 24318, 5011, + 0, 13616, 33555, 4477, 36663, 6252, 3455, 0, 20424, 11476, 28176, 15403, 41045, 10253, 3293, 33953, + 21214, 3574, 17400, 208, 20757, 27621, 32473, 34760, 11158, 4875, 24597, 16550, 7959, 6563, 19494, 16468, + 30137, 9977, 19524, 1897, 25113, 23247, 9978, 0, 18478, 0, 29375, 38237, 23261, 38085, 20003, 22249, + 38699, 32534, 8526, 0, 23262, 0, 18716, 0, 37912, 6935, 6477, 20392, 30530, 24950, 27918, 20393, + 29743, 0, 20507, 35034, 14897, 17174, 15763, 8530, 37567, 4989, 0, 16561, 18510, 23859, 302, 1595, + 36557, 19532, 5360, 0, 303, 0, 31687, 8042, 5116, 14346, 25729, 29629, 24729, 6977, 23181, 12351, + 12352, 11174, 13532, 41190, 1597, 19875, 555, 30730, 35591, 376, 37199, 10232, 6579, 31117, 21355, 4687, + 0, 16951, 18614, 21471, 11260, 17272, 0, 18958, 7743, 20102, 37455, 0, 14579, 0, 0, 38646, + 22337, 35545, 0, 12530, 1111, 0, 25306, 11449, 7232, 8673, 15680, 13786, 26081, 0, 27617, 29579, + 37476, 40706, 1174, 15724, 17103, 11457, 34035, 21868, 0, 38940, 30977, 32162, 23597, 35133, 19638, 0, + 0, 27370, 0, 23997, 40553, 16048, 31349, 36316, 4153, 29087, 17415, 1084, 8999, 19508, 33000, 7798, + 18511, 38156, 39343, 3921, 19456, 18389, 0, 36291, 22776, 39352, 12952, 18986, 21490, 35789, 0, 12570, + 12370, 38541, 37133, 14291, 11307, 39537, 16158, 18004, 39544, 970, 38487, 14380, 5171, 17736, 35700, 38864, + 32327, 3580, 4445, 3522, 34474, 16469, 6273, 18479, 2678, 0, 29904, 2541, 51, 3534, 0, 36470, + 38957, 29687, 0, 29907, 2554, 35039, 40959, 0, 22048, 24107, 17433, 24270, 18668, 34652, 15303, 27951, + 35988, 2650, 14203, 13272, 0, 14164, 0, 6190, 0, 14747, 10050, 5640, 0, 0, 10619, 0, + 3460, 5847, 1176, 0, 34103, 18591, 0, 32831, 1186, 0, 1198, 0, 32163, 25700, 1674, 7115, + 14769, 0, 39204, 919, 6955, 37181, 24793, 38090, 20052, 35673, 27763, 0, 0, 0, 26295, 28555, + 20801, 14145, 1483, 25415, 2487, 2305, 6052, 0, 0, 0, 0, 5547, 29654, 28441, 33255, 27781, + 6687, 31791, 28889, 0, 29067, 26300, 13115, 39661, 30521, 36259, 0, 0, 11371, 39929, 23494, 40900, + 0, 32993, 33001, 38255, 30607, 0, 0, 28492, 38604, 21676, 0, 0, 0, 35635, 25282, 27339, + 2581, 40591, 0, 20227, 12270, 7378, 22271, 71, 7312, 333, 24321, 23569, 32744, 7560, 8378, 23987, + 8637, 29582, 2653, 36875, 8538, 980, 8154, 3974, 40278, 0, 0, 10161, 21618, 14844, 3672, 2588, + 15566, 17780, 17104, 37232, 0, 36971, 9900, 17105, 10743, 8940, 15436, 37638, 5425, 11725, 0, 9489, + 14211, 41293, 8167, 24153, 868, 3077, 4383, 19496, 9932, 31797, 24599, 11555, 0, 0, 3787, 25894, + 34298, 39467, 5430, 28986, 19830, 18033, 27183, 29949, 2249, 5968, 3082, 22350, 35320, 14473, 12532, 16259, + 29301, 37645, 0, 2196, 23154, 37255, 17409, 4490, 0, 0, 0, 37008, 12313, 30794, 20088, 28191, + 32853, 33483, 3598, 24624, 11759, 0, 37009, 24163, 27559, 27539, 6728, 18500, 0, 22147, 28604, 36218, + 25946, 7469, 3131, 37568, 35467, 11925, 26010, 35208, 20446, 7647, 10395, 0, 36274, 2433, 21339, 372, + 7770, 17434, 2911, 2788, 19256, 5933, 10867, 18752, 0, 35878, 11175, 38393, 10880, 6978, 12023, 28284, + 21342, 32379, 16915, 32380, 34653, 18386, 19835, 13870, 12200, 0, 1453, 37202, 12035, 20306, 3833, 19331, + 0, 16662, 13739, 30853, 35989, 33776, 31882, 2289, 16370, 36241, 33081, 37971, 19177, 18153, 23736, 11981, + 12853, 31060, 0, 0, 8682, 40136, 5953, 36630, 12449, 34784, 25617, 31693, 27512, 37380, 35376, 23801, + 12271, 24882, 29253, 27156, 23799, 20784, 13843, 19602, 36196, 8341, 22903, 33824, 19617, 7392, 34184, 11589, + 37227, 9252, 9332, 18300, 6895, 40822, 40857, 1180, 30219, 0, 17766, 0, 0, 0, 9901, 36056, + 40132, 3748, 32245, 33850, 0, 24586, 22278, 9579, 7071, 8942, 24452, 10838, 16595, 17106, 3217, 25867, + 40698, 31063, 23018, 15512, 30020, 22318, 28987, 28453, 40614, 1607, 9223, 10847, 0, 1776, 39663, 6167, + 6545, 39993, 21189, 17934, 22933, 12442, 20394, 30689, 3061, 9051, 665, 25557, 28628, 2077, 40902, 15902, + 16556, 10081, 36408, 39699, 13667, 33281, 32860, 34059, 26275, 23763, 32803, 28006, 9868, 20140, 11895, 22457, + 0, 11760, 20902, 27825, 990, 3769, 13681, 11575, 16406, 0, 11098, 6235, 12018, 9706, 34958, 2434, + 9609, 13139, 13024, 5363, 13970, 19302, 11772, 20250, 2260, 19037, 22613, 34861, 14642, 14643, 25070, 0, + 23689, 26183, 0, 14348, 12024, 37885, 4956, 33757, 32642, 7523, 2440, 35218, 0, 5452, 0, 24272, + 11701, 30006, 0, 23954, 31696, 21285, 25831, 19883, 29871, 16417, 10233, 4467, 38567, 281, 19170, 20349, + 0, 7893, 0, 32902, 1990, 11828, 24412, 32903, 0, 0, 2001, 23790, 22944, 13492, 14981, 16099, + 14535, 7032, 21600, 23725, 6029, 6030, 0, 23149, 39393, 23267, 40515, 15630, 36954, 24236, 15635, 10346, + 7941, 0, 5617, 32339, 9630, 10359, 25123, 10069, 29658, 1907, 26271, 1135, 18727, 35192, 21233, 4061, + 25896, 5908, 18728, 29705, 17502, 15411, 25897, 39154, 4064, 17537, 19654, 0, 23683, 15177, 26459, 32629, + 1296, 38394, 36281, 31582, 26325, 28041, 25799, 25716, 4302, 18622, 18124, 2531, 0, 11416, 0, 0, + 12753, 631, 10905, 6262, 0, 18552, 14441, 14803, 15406, 28329, 19192, 38942, 6073, 6505, 40334, 34461, + 22138, 2540, 0, 0, 0, 0, 35571, 0, 0, 36762, 11635, 35044, 35008, 39531, 8937, 23402, + 8790, 0, 0, 10798, 20114, 7928, 10832, 9485, 28715, 5517, 0, 34361, 0, 0, 24883, 0, + 2930, 20503, 28894, 798, 143, 0, 0, 32251, 0, 0, 0, 19639, 16526, 21009, 902, 3167, + 0, 7426, 40051, 12135, 13578, 27371, 0, 16105, 5971, 18729, 0, 0, 0, 0, 37032, 28563, + 2839, 19439, 20444, 11417, 30890, 21833, 11418, 10757, 14151, 1939, 32272, 17188, 13971, 0, 19534, 22749, + 10223, 34795, 0, 32389, 28042, 30731, 3102, 31583, 13990, 2477, 10482, 7584, 26195, 18101, 0, 6585, + 23201, 23132, 37757, 1991, 0, 11836, 6017, 34683, 14696, 13552, 21030, 17859, 36949, 29198, 29243, 31253, + 10705, 32697, 10267, 0, 29358, 39269, 0, 11472, 8218, 0, 0, 29974, 0, 25357, 13405, 0, + 33166, 0, 0, 37632, 14839, 11156, 0, 688, 20706, 0, 30665, 0, 19776, 27726, 1476, 18593, + 24691, 0, 0, 8685, 38943, 18886, 22032, 25393, 24600, 17781, 8944, 32252, 31799, 33123, 0, 21451, + 0, 0, 0, 32849, 17791, 7858, 4843, 40615, 420, 41294, 38952, 41143, 10371, 12301, 0, 12867, + 0, 0, 0, 29784, 32174, 34499, 28794, 28459, 5627, 14886, 254, 9992, 32708, 14480, 30534, 678, + 40495, 21527, 29340, 20960, 0, 0, 36842, 20195, 0, 0, 20964, 26782, 2513, 34312, 8795, 3754, + 25650, 12773, 24257, 19571, 6958, 17177, 3482, 38125, 10396, 13682, 21398, 0, 9416, 10758, 8353, 0, + 991, 28352, 31161, 12572, 31541, 24485, 10412, 31000, 32185, 13700, 11900, 22530, 26627, 3771, 39207, 0, + 38597, 27589, 12162, 27850, 39585, 977, 0, 0, 0, 16519, 1297, 33879, 22260, 5061, 0, 39431, + 22535, 2794, 1298, 28029, 12025, 10522, 14229, 4099, 13274, 21200, 9183, 7407, 0, 0, 28493, 4784, + 31585, 5442, 32200, 15801, 38981, 28414, 10967, 4785, 18788, 14790, 18789, 23865, 22219, 39222, 0, 17213, + 2375, 23333, 0, 0, 29199, 18102, 24810, 17510, 18672, 27296, 8979, 38989, 22174, 13997, 24392, 0, + 0, 40930, 23091, 13918, 1603, 13175, 9721, 0, 0, 38168, 17837, 16965, 19171, 26691, 20209, 13182, + 5592, 949, 0, 17514, 0, 32227, 22801, 25099, 18413, 41200, 0, 14975, 26256, 33939, 0, 33084, + 0, 16423, 23381, 35532, 21866, 16997, 37775, 0, 35551, 3401, 12491, 10149, 32943, 15509, 40712, 10313, + 31793, 24884, 9864, 31913, 9865, 9508, 2657, 34045, 33473, 26702, 15604, 31920, 26149, 36933, 34263, 23033, + 41054, 36836, 40863, 17503, 32085, 32031, 35579, 26156, 34626, 13521, 31543, 3547, 27097, 15267, 36222, 10514, + 35915, 31604, 26037, 13998, 35247, 36706, 25100, 35149, 18991, 16078, 39324, 0, 0, 0, 0, 32797, + 0, 4765, 33394, 236, 33423, 2244, 4108, 38415, 0, 35706, 22434, 15640, 26749, 16478, 29938, 31496, + 18051, 23164, 31096, 17533, 6351, 19834, 16441, 30702, 6501, 38, 38029, 11773, 35859, 20646, 40879, 7668, + 22370, 0, 1334, 17295, 18625, 19235, 9861, 39134, 8311, 25046, 39081, 15549, 3330, 14335, 14898, 12573, + 18091, 0, 26453, 25088, 25717, 4310, 21209, 39372, 18493, 22171, 0, 0, 796, 25394, 32077, 16790, + 32602, 7859, 24771, 0, 26100, 39574, 28656, 25479, 27941, 36475, 19572, 20965, 1493, 0, 27436, 28808, + 10097, 25979, 25418, 0, 5460, 23079, 13372, 28731, 0, 25159, 21654, 17838, 6032, 5955, 39947, 0, + 18938, 5208, 31408, 9565, 12255, 21307, 35621, 21420, 37135, 30457, 9843, 38302, 34348, 4749, 32147, 13407, + 29699, 8150, 22272, 0, 36681, 24529, 34155, 2105, 1470, 27022, 38417, 35680, 1471, 0, 6556, 16327, + 35308, 2633, 3673, 33852, 33609, 36972, 33376, 0, 0, 0, 9739, 0, 0, 0, 18482, 32961, + 3078, 12991, 28620, 22598, 38068, 33795, 32158, 21481, 0, 0, 0, 0, 0, 20124, 12536, 21774, + 10848, 11144, 30472, 36757, 38240, 1232, 20087, 23896, 32969, 7330, 35760, 28624, 16791, 36631, 0, 13953, + 26533, 36260, 12444, 0, 27987, 0, 0, 0, 30478, 20268, 27994, 35795, 26180, 31498, 12319, 19200, + 36691, 19649, 38462, 28192, 39701, 1486, 16876, 0, 0, 0, 0, 0, 0, 0, 24100, 9415, + 31525, 39205, 36552, 21536, 15077, 32995, 35035, 32996, 39416, 21204, 0, 27642, 18459, 3177, 20142, 25062, + 5106, 26276, 0, 0, 0, 28020, 33005, 1940, 6077, 41061, 0, 27385, 26513, 10098, 28633, 8586, + 0, 0, 0, 20914, 20157, 34072, 19837, 13146, 4735, 14921, 10479, 7524, 26945, 3065, 26721, 21829, + 22882, 19457, 0, 0, 0, 0, 35917, 3821, 0, 15665, 746, 16685, 15416, 26172, 1319, 28158, + 8730, 22624, 35918, 32201, 21348, 36428, 40256, 4273, 7774, 33699, 22734, 31296, 17682, 2342, 41032, 41237, + 1507, 35093, 11346, 22041, 33405, 0, 16757, 24434, 32777, 13387, 9802, 0, 0, 34424, 33938, 40177, + 10559, 36444, 31627, 0, 0, 17481, 32292, 11358, 36107, 0, 17557, 26288, 2345, 952, 13073, 27416, + 7357, 5836, 0, 492, 37119, 0, 0, 21050, 16778, 36033, 5012, 0, 2677, 3015, 8373, 13934, + 21193, 0, 0, 0, 17717, 20595, 36825, 0, 18324, 9971, 0, 36666, 13944, 3526, 25326, 21723, + 0, 0, 10717, 29339, 0, 18, 9259, 1532, 1909, 24458, 0, 27372, 4215, 11690, 3021, 8185, + 11611, 6941, 30797, 7612, 28657, 0, 19069, 10470, 36645, 11693, 0, 37036, 40956, 34629, 24634, 38878, + 14221, 28564, 0, 0, 0, 0, 0, 0, 29956, 17889, 14227, 38465, 33219, 11101, 0, 33672, + 0, 0, 0, 4774, 24408, 20647, 0, 38161, 1062, 3431, 0, 0, 34654, 8731, 20657, 942, + 14740, 6003, 38896, 0, 31221, 34655, 0, 14947, 32111, 28581, 10035, 0, 5782, 12630, 13744, 0, + 41126, 0, 33068, 16315, 7281, 12064, 31892, 21595, 20060, 25166, 4705, 36121, 20116, 0, 14911, 24693, + 29596, 30397, 38910, 17023, 26446, 15571, 32063, 38927, 39394, 29407, 27230, 927, 35249, 22694, 2850, 11039, + 15499, 14245, 139, 4248, 23739, 885, 403, 7600, 15339, 30078, 30079, 41240, 18014, 0, 9589, 34291, + 27050, 10793, 17792, 26103, 27737, 0, 904, 25332, 6348, 1910, 17579, 23814, 7510, 12577, 40957, 11620, + 10400, 16882, 37579, 37735, 33395, 2795, 5574, 16680, 13911, 3726, 27766, 23117, 35050, 13251, 11291, 11435, + 28923, 25622, 31027, 36454, 25242, 36122, 27015, 36115, 14833, 29984, 33792, 12695, 39887, 24140, 40281, 5848, + 0, 36876, 0, 0, 35410, 26977, 35709, 20596, 0, 0, 25047, 32594, 31197, 8800, 36467, 29492, + 26979, 21222, 8803, 28456, 31045, 14476, 2772, 22731, 40618, 10850, 21117, 34380, 9027, 37166, 10754, 0, + 27643, 3421, 11090, 34857, 30999, 32360, 22792, 25422, 18516, 16602, 26239, 32632, 38257, 9916, 7258, 10033, + 2666, 38715, 0, 28427, 40341, 21732, 10124, 37083, 40666, 36910, 17278, 12053, 31647, 32128, 2732, 17482, + 0, 27615, 14311, 23060, 24574, 8939, 40820, 36958, 0, 0, 25364, 21698, 19692, 404, 14284, 0, + 33611, 22856, 1477, 19626, 0, 0, 0, 0, 35431, 36987, 0, 22857, 24697, 762, 11735, 0, + 0, 0, 2122, 19500, 16184, 29780, 31201, 17142, 18037, 0, 12545, 15070, 41003, 6729, 14888, 5048, + 921, 0, 0, 0, 0, 0, 16192, 1695, 28156, 29793, 33905, 0, 0, 0, 0, 0, + 6790, 0, 0, 28202, 1303, 29754, 26021, 2304, 29810, 20251, 13865, 18904, 0, 0, 38720, 1147, + 12374, 38330, 33771, 17232, 0, 0, 28225, 36577, 27323, 0, 0, 6851, 0, 0, 0, 0, + 24515, 19136, 39185, 29987, 9087, 37150, 16735, 1911, 21175, 22672, 17543, 28861, 17436, 30897, 5256, 17375, + 29487, 30220, 40065, 8499, 33257, 266, 7324, 22407, 1901, 30083, 27240, 35442, 1912, 24156, 29703, 8948, + 29604, 9993, 3332, 13671, 11421, 33302, 5809, 2613, 6208, 22526, 25653, 17809, 26784, 21954, 5696, 37048, + 4097, 25425, 15268, 28818, 4571, 22721, 4172, 18791, 29640, 39347, 17234, 25808, 22050, 27671, 0, 5257, + 10991, 35974, 32409, 33088, 19140, 18351, 0, 28661, 8471, 0, 28686, 0, 0, 0, 36728, 20976, + 0, 8525, 15052, 3583, 8992, 30333, 17143, 18218, 17797, 31970, 854, 197, 37305, 14489, 25516, 34074, + 40765, 4855, 2307, 38357, 36578, 8250, 25669, 0, 31718, 27379, 13408, 13409, 33464, 38803, 0, 0, + 27529, 3156, 7300, 12284, 39380, 0, 9218, 31339, 0, 24151, 27358, 9866, 30084, 6344, 40833, 25143, + 20796, 8168, 18021, 12303, 33383, 33830, 20924, 34167, 13808, 17144, 4942, 25552, 37495, 18894, 26673, 17036, + 17630, 8839, 33180, 32802, 24300, 24161, 3088, 36766, 2125, 15841, 25055, 85, 24218, 23904, 4009, 22287, + 16131, 35325, 9319, 26785, 22653, 0, 40092, 11503, 11627, 10943, 929, 0, 0, 38390, 12579, 9185, + 31570, 8587, 2627, 19307, 40336, 29941, 40528, 32103, 16495, 0, 0, 0, 39796, 102, 32279, 9758, + 31697, 0, 29944, 2287, 25986, 32117, 13831, 7677, 25133, 0, 35101, 5373, 12794, 16766, 34433, 18631, + 29931, 36457, 22639, 19237, 17362, 1673, 0, 19627, 519, 11573, 0, 35081, 10322, 4290, 10418, 21675, + 3841, 17315, 28874, 11309, 1194, 410, 3080, 34851, 4943, 290, 33928, 0, 40745, 4909, 25191, 668, + 4856, 30375, 28511, 750, 8381, 34363, 31443, 40298, 34215, 7325, 36894, 148, 29906, 19856, 26542, 13975, + 9191, 12604, 24064, 13484, 34434, 31895, 15248, 20225, 33845, 26210, 31084, 23642, 11387, 25320, 39186, 29230, + 14848, 32835, 23468, 252, 19777, 9140, 0, 28892, 7241, 14614, 2836, 27558, 1204, 19633, 27580, 9145, + 10706, 11211, 19199, 10170, 12764, 24945, 8314, 11464, 2078, 9159, 7719, 20804, 78, 36471, 27560, 17631, + 13672, 3601, 13673, 3768, 22900, 3125, 34381, 6414, 5677, 0, 17633, 32361, 1538, 33303, 19949, 35201, + 20143, 23504, 23505, 31107, 33006, 37324, 23608, 3348, 35041, 36330, 34794, 12340, 40913, 33753, 20407, 15159, + 35045, 34534, 28285, 9654, 11581, 36423, 26786, 2561, 17438, 0, 33810, 4103, 3105, 21349, 24892, 20287, + 12031, 37074, 38667, 10980, 2480, 1558, 23784, 31607, 13281, 15587, 19329, 19537, 38673, 1454, 12214, 14956, + 21036, 1352, 27130, 27606, 20676, 17842, 20356, 20682, 31652, 2740, 24843, 13555, 12077, 32141, 33604, 21700, + 29600, 10769, 37383, 0, 3697, 2014, 41132, 5853, 40573, 12115, 23601, 0, 33304, 11776, 26906, 15631, + 0, 6521, 34925, 36973, 690, 13641, 39028, 12707, 26980, 5621, 6165, 4381, 8169, 20384, 39072, 39144, + 0, 34610, 24080, 10151, 8949, 23991, 19025, 9339, 16187, 25703, 7194, 4869, 34382, 8901, 13674, 9320, + 9784, 28350, 31069, 39337, 21537, 5910, 16286, 28466, 4771, 34170, 9704, 0, 0, 5530, 0, 20196, + 13589, 20408, 14565, 37050, 39104, 38884, 38505, 33220, 0, 586, 10419, 9065, 10689, 16567, 31371, 1862, + 15530, 18794, 4658, 17448, 35340, 24112, 27292, 0, 33881, 13873, 24225, 11704, 28059, 4158, 6618, 18393, + 0, 21092, 28689, 5161, 30751, 8441, 4963, 17258, 2159, 32415, 22086, 16219, 40182, 21474, 11265, 36455, + 32419, 16456, 20560, 497, 0, 9582, 1123, 7848, 11988, 35742, 18326, 0, 36070, 14766, 11962, 3333, + 6286, 6837, 0, 34515, 40522, 38503, 23426, 37041, 25019, 11965, 21538, 11505, 14566, 26548, 0, 0, + 22367, 20492, 2377, 18525, 16927, 4143, 0, 4728, 26340, 5125, 23361, 0, 16317, 18163, 17713, 25361, + 36964, 35685, 5884, 23406, 35388, 21370, 7849, 12986, 34190, 7366, 25698, 32070, 0, 0, 1205, 26927, + 22976, 21374, 39675, 28944, 29304, 29305, 25611, 35765, 17794, 222, 10376, 24459, 17146, 9518, 40869, 27989, + 37640, 34257, 2542, 30354, 14714, 29542, 36840, 11747, 13006, 25679, 19506, 14556, 40747, 14420, 157, 28200, + 16267, 11928, 25007, 2873, 6781, 15552, 21160, 29099, 33574, 14344, 11506, 23516, 13703, 19577, 34320, 0, + 39588, 29912, 0, 97, 22149, 2349, 28820, 7057, 11934, 23327, 3923, 28360, 40644, 21779, 29817, 26637, + 18556, 1552, 16928, 19390, 33144, 2462, 11525, 19766, 8563, 17467, 5407, 38674, 40789, 0, 0, 39851, + 488, 4805, 24562, 0, 18421, 32133, 7549, 9814, 3292, 14317, 6907, 3674, 37705, 10635, 35023, 34161, + 34931, 29602, 38496, 36896, 33963, 35029, 15444, 11403, 16486, 37725, 3173, 0, 0, 26713, 0, 21639, + 20485, 10589, 4140, 37887, 33759, 13986, 40654, 36942, 28638, 15274, 24498, 0, 3366, 14276, 33979, 39293, + 3698, 22053, 24115, 0, 24819, 16363, 35975, 25455, 27687, 23630, 27721, 0, 7170, 0, 19848, 11207, + 0, 0, 9907, 24098, 4003, 25066, 6567, 17180, 476, 13826, 33527, 19227, 0, 37871, 39895, 11073, + 36201, 0, 39560, 23805, 0, 8394, 13118, 40305, 40306, 15676, 21517, 25701, 38241, 260, 39708, 8973, + 35801, 3416, 12139, 40147, 16601, 25335, 25403, 39267, 20897, 2422, 0, 0, 35471, 14900, 1655, 3343, + 15079, 6291, 30706, 35837, 38960, 34391, 0, 25857, 19073, 22879, 38856, 10000, 37325, 5057, 38885, 7455, + 26163, 18076, 28477, 24721, 19511, 35222, 745, 9655, 9295, 21019, 8722, 0, 26946, 15380, 28361, 4398, + 40099, 28572, 15770, 24338, 33516, 6420, 2441, 11373, 4514, 25839, 39344, 23775, 13866, 40922, 30720, 0, + 0, 31855, 20918, 23082, 27888, 14666, 39115, 26435, 28916, 590, 28496, 23870, 31005, 25431, 19220, 10981, + 27927, 39910, 23088, 20347, 13874, 26437, 20167, 27406, 18104, 16751, 13282, 16837, 39815, 5888, 0, 25879, + 9119, 7353, 19801, 28239, 13051, 28840, 33071, 15669, 31231, 7273, 19228, 2236, 2483, 18109, 35347, 4575, + 37863, 19898, 37416, 39841, 35600, 5163, 12054, 30637, 28697, 26047, 33058, 27931, 27835, 23718, 18285, 36003, + 0, 16813, 16981, 7546, 17845, 17988, 32420, 32790, 21938, 20062, 32137, 25212, 40449, 27487, 34447, 1520, + 18168, 10637, 23251, 17739, 613, 1215, 10916, 10917, 0, 2425, 22286, 24470, 20479, 14337, 2129, 19722, + 25871, 30804, 0, 0, 16911, 25009, 0, 11901, 32505, 0, 27107, 36424, 0, 21020, 11513, 14349, + 34323, 0, 25800, 29873, 33047, 38990, 19821, 31866, 19397, 0, 11532, 28690, 32778, 35257, 1354, 19117, + 7274, 17283, 4745, 4051, 5411, 5595, 15886, 3942, 32138, 2857, 20071, 23879, 24580, 39187, 0, 0, + 0, 11075, 8390, 3529, 9337, 20797, 1903, 11208, 8830, 34932, 19634, 30468, 0, 0, 0, 25554, + 33924, 39260, 20389, 13266, 0, 38701, 41244, 37715, 17795, 0, 40082, 1216, 25336, 37287, 0, 4320, + 7116, 35802, 20091, 24421, 0, 30479, 12559, 2080, 0, 1623, 7252, 37732, 16887, 7253, 24788, 8123, + 7089, 6818, 39282, 29240, 37326, 13976, 23430, 14497, 16271, 3064, 872, 21716, 35888, 33578, 20720, 34075, + 8045, 0, 21622, 29476, 1046, 38469, 30551, 15381, 34904, 21970, 32644, 8845, 28828, 9659, 11805, 28415, + 0, 34979, 4916, 23541, 13917, 19041, 20168, 20169, 12927, 18806, 7268, 21931, 20031, 13746, 8137, 1677, + 11582, 27950, 34991, 21579, 13878, 17515, 2005, 12946, 29157, 18113, 41129, 26887, 36243, 5412, 3843, 2161, + 20361, 34571, 16427, 3738, 13400, 27486, 24918, 21604, 19238, 0, 26895, 19240, 40230, 0, 14759, 14214, + 7117, 35804, 25707, 2206, 25277, 8046, 16348, 28245, 36977, 36750, 5772, 18042, 40310, 28457, 22863, 38549, + 13350, 4207, 2134, 15619, 4827, 0, 10025, 10026, 20736, 11066, 8889, 5520, 7966, 33856, 20006, 19714, + 16527, 9231, 38880, 28467, 37329, 40980, 16932, 18796, 31227, 16694, 12463, 17321, 17004, 0, 22914, 34824, + 30231, 30093, 22327, 0, 38874, 9601, 0, 33551, 20928, 25074, 30715, 39283, 6151, 30724, 1968, 0, + 11436, 33888, 38059, 17337, 34480, 11479, 33964, 10918, 764, 25185, 32605, 22979, 17740, 40005, 35805, 33649, + 19204, 15327, 4011, 0, 20907, 10001, 3025, 18761, 38659, 28478, 7889, 10596, 38352, 24067, 28072, 22781, + 9437, 0, 11880, 3904, 0, 7074, 7075, 25645, 23409, 27741, 14491, 0, 34527, 705, 35215, 40758, + 21161, 4185, 2358, 29206, 10126, 41257, 38922, 30228, 8802, 1217, 7141, 40316, 31361, 30925, 39756, 40094, + 18762, 30928, 9710, 24647, 16202, 38032, 27924, 20202, 5635, 23542, 2381, 22750, 17468, 26888, 18427, 28011, + 23449, 37629, 7759, 33460, 14843, 5656, 22692, 9381, 21699, 25321, 39182, 8343, 22597, 28714, 3017, 4281, + 10311, 20598, 1648, 23471, 27043, 1125, 14851, 27730, 0, 9257, 20885, 11687, 31461, 7140, 33381, 20709, + 0, 31673, 39681, 25726, 14477, 5962, 39034, 26476, 19945, 1218, 10074, 36994, 32348, 22122, 21203, 2252, + 2126, 0, 23424, 12548, 40626, 18735, 15073, 32358, 31507, 2201, 30961, 39477, 40876, 16052, 4493, 29308, + 4012, 5531, 4289, 24539, 38961, 38385, 25514, 1726, 12334, 31530, 40153, 14901, 8709, 12151, 4907, 3134, + 28391, 25748, 32506, 11566, 23336, 40332, 28283, 2614, 31021, 15373, 15330, 9180, 8321, 7347, 4518, 2374, + 39774, 2796, 16682, 33399, 38564, 38977, 37061, 9656, 8919, 38056, 5119, 12032, 27889, 28758, 9112, 31859, + 19392, 6707, 378, 22626, 31381, 62, 19899, 22633, 19900, 34845, 39842, 2006, 36452, 30640, 25223, 16381, + 34339, 2825, 24987, 39148, 23093, 0, 28565, 7503, 27307, 0, 5316, 4857, 28622, 29260, 3536, 28488, + 12821, 27567, 11545, 17716, 0, 0, 3119, 13948, 6912, 8995, 7986, 6776, 0, 6943, 1016, 28901, + 5680, 0, 5688, 2131, 30364, 38888, 19075, 23315, 20818, 23862, 0, 40919, 27883, 0, 36785, 40022, + 28499, 0, 28062, 2145, 31701, 13283, 2397, 8243, 29020, 3113, 8252, 7536, 31302, 31446, 34827, 20516, + 22160, 19539, 26077, 19930, 2388, 29369, 15140, 539, 32723, 33171, 23473, 0, 0, 26456, 11397, 21685, + 32700, 3161, 5095, 7708, 36202, 253, 25183, 25378, 19376, 7334, 24705, 26983, 10380, 1481, 5041, 20618, + 5477, 0, 0, 15824, 0, 2593, 6731, 36841, 10272, 0, 9264, 33966, 16795, 13897, 23425, 24712, + 30481, 35323, 17651, 0, 0, 34392, 35841, 36155, 23296, 38962, 31827, 35842, 35139, 31212, 39421, 39733, + 10029, 4324, 7874, 4265, 22875, 15741, 3809, 0, 30149, 4504, 8553, 15718, 24723, 24724, 39424, 19973, + 17193, 40014, 28482, 39425, 9234, 17614, 10871, 16196, 5779, 4460, 36335, 0, 0, 23317, 0, 2595, + 19672, 6360, 36095, 2628, 25710, 10528, 25660, 7882, 16295, 33306, 12912, 35889, 19764, 0, 19515, 12607, + 28317, 10118, 0, 17218, 40849, 41108, 34980, 8660, 16934, 23438, 8978, 17219, 1753, 28318, 0, 0, + 28063, 3878, 12929, 32896, 946, 33584, 14171, 23089, 18105, 32491, 41302, 5922, 4277, 24411, 21000, 38527, + 18948, 35514, 26461, 37085, 11182, 16943, 21991, 0, 0, 16944, 0, 0, 27507, 0, 35947, 21678, + 27676, 15704, 8253, 35348, 5468, 25163, 2447, 0, 29132, 24282, 1604, 28242, 30630, 6622, 26045, 123, + 23546, 41223, 15803, 7482, 0, 36299, 0, 25973, 6308, 11841, 33073, 38286, 28698, 28845, 39843, 35979, + 8078, 6858, 0, 15102, 12743, 2569, 32229, 19466, 0, 1373, 18121, 13755, 16027, 12795, 0, 3282, + 16538, 33242, 7547, 18871, 38479, 10450, 12234, 21297, 36459, 32791, 29036, 16612, 38292, 15965, 0, 23795, + 14536, 22726, 7289, 29696, 17952, 20064, 40692, 32920, 11127, 20065, 13604, 38001, 4587, 17369, 25168, 40229, + 36188, 10144, 0, 36035, 19008, 37794, 25170, 18171, 21443, 37467, 21840, 0, 35744, 21842, 35745, 23744, + 31963, 3950, 36148, 20132, 31532, 20909, 15215, 41104, 31981, 34403, 29818, 29056, 31172, 28372, 36181, 3717, + 40047, 19523, 37540, 21824, 20280, 38180, 30346, 16869, 24706, 20893, 26929, 1222, 40725, 694, 0, 14774, + 32499, 15934, 22038, 15825, 34057, 38499, 34942, 16053, 11622, 31533, 6842, 34790, 29384, 36775, 14902, 16891, + 0, 16912, 3264, 12583, 11029, 38712, 8125, 2909, 9390, 14498, 19865, 2876, 28755, 20721, 33231, 17043, + 34325, 27885, 26871, 35890, 1813, 4519, 10774, 30365, 5707, 12194, 8732, 10010, 1969, 33402, 18257, 2263, + 2264, 35948, 33814, 34416, 38190, 10127, 36608, 40932, 0, 15276, 37086, 23196, 39043, 19263, 0, 0, + 27508, 14005, 9432, 23094, 17977, 0, 29518, 13258, 16214, 35980, 36583, 4470, 34559, 13752, 34020, 30856, + 32294, 21659, 8262, 8750, 0, 20686, 40355, 20933, 32299, 30946, 17340, 2273, 20366, 12969, 21361, 2648, + 30296, 33614, 21825, 19352, 41144, 15238, 15115, 10168, 0, 0, 37370, 30857, 40189, 0, 0, 35717, + 0, 5854, 7970, 1131, 40244, 40838, 27366, 31965, 21232, 0, 13439, 34058, 3683, 21777, 25407, 39713, + 25911, 0, 26232, 37311, 0, 13863, 0, 18766, 9944, 1625, 35869, 41184, 38713, 37334, 30366, 21247, + 9391, 14914, 1044, 2257, 0, 6793, 23523, 34906, 16012, 25636, 10775, 34076, 33024, 0, 0, 32888, + 1970, 15468, 4726, 33696, 532, 21932, 40966, 0, 29207, 3961, 3500, 21466, 9430, 7775, 33048, 5469, + 30631, 14961, 38362, 25814, 6750, 18114, 19917, 0, 9839, 19918, 18422, 0, 36527, 0, 9443, 4676, + 17011, 6406, 0, 1529, 0, 31510, 0, 5427, 5428, 32349, 17408, 0, 26478, 32856, 26850, 30799, + 0, 0, 10476, 36781, 18777, 16296, 36487, 26790, 14793, 23538, 13045, 37934, 0, 23547, 0, 17982, + 12405, 19333, 4161, 21411, 1719, 17376, 18173, 8509, 3344, 33752, 32269, 10947, 1091, 41064, 5005, 5006, + 11935, 25832, 3106, 29118, 0, 21901, 39818, 18271, 7541, 13487, 9371, 31709, 17916, 33788, 25365, 28973, + 22572, 33173, 26302, 39687, 30233, 29704, 29235, 35316, 32974, 22574, 34934, 34935, 21827, 10269, 21620, 36261, + 7301, 20989, 34894, 30399, 37620, 31972, 40086, 37621, 27077, 20269, 31511, 12553, 28949, 7512, 33968, 21236, + 4387, 20133, 1489, 0, 20851, 37312, 6961, 39581, 25274, 33664, 19032, 11764, 34123, 21084, 10103, 12779, + 6295, 11226, 29750, 22833, 4646, 31553, 27852, 20022, 33186, 31373, 24490, 38766, 28955, 33307, 14351, 14657, + 11936, 29111, 19386, 34642, 12176, 27197, 16747, 30370, 3100, 2309, 13827, 36908, 11699, 38474, 28068, 8737, + 21133, 31868, 0, 6541, 3506, 30632, 38999, 9722, 2987, 3440, 38164, 11842, 18980, 17699, 16581, 30060, + 11650, 31395, 381, 26563, 28161, 19366, 28763, 33197, 14112, 187, 28529, 2738, 30861, 29890, 12654, 3197, + 3116, 37438, 32304, 0, 0, 0, 21134, 0, 24591, 13228, 27822, 15074, 17662, 14503, 0, 19433, + 17849, 0, 3996, 3543, 32486, 24221, 19761, 27389, 2632, 3554, 9123, 37076, 36098, 0, 18262, 16576, + 27407, 39007, 27490, 11606, 0, 0, 6947, 0, 26168, 40983, 14931, 15094, 29852, 18533, 30638, 3706, + 40356, 17850, 0, 39014, 38854, 0, 35776, 3886, 21237, 1852, 28099, 35587, 10288, 34276, 11350, 19461, + 19462, 24825, 16610, 10239, 39915, 20391, 32171, 39202, 27311, 41247, 40318, 9045, 33868, 35811, 39735, 32867, + 13967, 2258, 0, 2135, 17589, 39432, 12598, 30371, 9426, 14430, 98, 8225, 9657, 10816, 34659, 25663, + 39799, 1610, 35515, 28367, 6013, 9675, 26816, 34140, 3235, 26512, 0, 0, 4293, 10652, 6209, 3265, + 30716, 25589, 27306, 2169, 12295, 37979, 23274, 34305, 8180, 37292, 8008, 22985, 39411, 28721, 41248, 3062, + 24781, 36903, 10405, 10810, 9607, 6963, 13301, 37883, 29720, 4812, 29752, 8213, 41254, 10948, 0, 1957, + 38839, 15013, 28776, 14933, 8227, 11521, 4236, 36655, 4216, 28368, 3502, 23701, 2174, 32718, 19401, 2238, + 23548, 13179, 1357, 12226, 39516, 40219, 24826, 38682, 12413, 1426, 0, 17344, 17354, 37781, 24992, 3245, + 8166, 2592, 28878, 27066, 10187, 24159, 23275, 1918, 20895, 29717, 3901, 4638, 37728, 39412, 3174, 4005, + 1242, 19854, 448, 29265, 20397, 17757, 7782, 3258, 24668, 29380, 8022, 16132, 13020, 0, 0, 0, + 39211, 24645, 41300, 3622, 15946, 17810, 933, 6455, 31286, 0, 40649, 18781, 28777, 0, 3925, 17616, + 29324, 16095, 2914, 14934, 29814, 11431, 7525, 1310, 0, 31934, 31116, 12613, 24893, 15982, 10977, 24549, + 28222, 2173, 0, 24670, 22628, 22152, 30240, 34987, 25441, 34011, 4662, 6014, 3653, 4859, 19977, 33842, + 6751, 1666, 39045, 3939, 2849, 9679, 6515, 41034, 5503, 16284, 29037, 37782, 24993, 40232, 18056, 3126, + 39152, 8193, 26535, 29411, 15716, 34, 0, 24491, 27401, 9882, 26287, 30267, 38683, 18469, 14257, 17116, + 0, 4225, 25398, 37718, 14877, 15286, 7302, 23277, 10657, 7993, 18601, 10668, 30101, 20398, 29266, 14782, + 23427, 39315, 24423, 8953, 29275, 16494, 19667, 36277, 18784, 37511, 14506, 22620, 0, 32890, 1503, 11884, + 40166, 25444, 25927, 31170, 2599, 15532, 26338, 22383, 19463, 33411, 0, 4536, 15536, 40409, 2723, 27681, + 3707, 28247, 951, 15183, 0, 39856, 30867, 20418, 18137, 41121, 21610, 18174, 23482, 37720, 0, 35892, + 31761, 3180, 0, 25487, 3196, 21741, 36729, 12486, 1887, 7397, 0, 0, 4625, 5620, 13344, 36990, + 10367, 33625, 37244, 24699, 0, 546, 8806, 14215, 0, 34268, 27375, 36767, 27847, 35204, 2348, 34965, + 27390, 34397, 27449, 17745, 4520, 37354, 1971, 28159, 0, 34661, 16804, 17914, 29057, 6383, 37783, 12427, + 0, 37827, 0, 0, 14385, 14548, 3884, 3158, 8892, 32545, 32247, 142, 9584, 37145, 16734, 0, + 29774, 3164, 33264, 24607, 10189, 0, 5270, 2199, 5626, 34488, 40728, 0, 36320, 2685, 0, 16896, + 28351, 19278, 19283, 0, 28815, 22259, 18519, 23180, 4854, 29815, 6989, 2261, 13718, 35506, 12392, 5281, + 14993, 1126, 16787, 35749, 4256, 4259, 22980, 16870, 38026, 28600, 22986, 4627, 14632, 33667, 7340, 0, + 33668, 7146, 11967, 40156, 25188, 7182, 14718, 9947, 17591, 39433, 20161, 36941, 0, 2461, 19734, 36099, + 20257, 29819, 15951, 0, 0, 20173, 25445, 37390, 23923, 20038, 14528, 22591, 13923, 30511, 12640, 19925, + 13200, 33984, 833, 8449, 2831, 17382, 17035, 24608, 6647, 36511, 37877, 3175, 39577, 25189, 0, 19033, + 15133, 9610, 37739, 11780, 22617, 2556, 6740, 2705, 26120, 27108, 26555, 33277, 36426, 27109, 3634, 35236, + 10011, 7530, 35237, 34545, 41137, 27895, 13875, 6797, 32401, 9367, 28924, 24189, 2810, 10018, 19978, 37758, + 4664, 23874, 13922, 20780, 37519, 0, 22341, 39351, 39845, 4278, 37205, 20732, 30423, 13320, 23206, 28079, + 22769, 29288, 15804, 4669, 28252, 0, 13601, 13194, 324, 13495, 35271, 0, 35272, 18424, 38171, 751, + 17485, 0, 11363, 18963, 30652, 32300, 29445, 2020, 39355, 40223, 866, 19933, 32937, 21940, 36716, 0, + 32740, 17365, 38455, 20072, 0, 0, 0, 32929, 0, 0, 0, 0, 12542, 13587, 0, 21458, + 322, 3997, 31346, 9386, 32988, 29544, 33969, 5305, 38595, 28723, 22334, 32874, 33680, 32377, 27756, 15735, + 31219, 11950, 25731, 6333, 11344, 16138, 8237, 4072, 32210, 24279, 24132, 16349, 0, 34277, 36353, 25092, + 10155, 4294, 39823, 0, 30763, 34435, 32565, 36006, 21301, 0, 26904, 6053, 40816, 14836, 33595, 37549, + 0, 0, 33560, 5377, 29251, 8768, 35418, 10642, 35310, 0, 17033, 15644, 32260, 28127, 31803, 33859, + 0, 0, 5525, 16258, 39999, 21426, 3324, 13123, 1245, 40420, 18059, 10279, 704, 28805, 3425, 19300, + 32370, 27466, 36560, 24726, 0, 23078, 11792, 30619, 35595, 35238, 0, 3108, 10236, 1709, 0, 32411, + 2735, 11943, 0, 10078, 4385, 39414, 23289, 15935, 25515, 0, 36325, 33343, 0, 10960, 4739, 0, + 25086, 5577, 31384, 24552, 0, 34679, 17704, 1107, 0, 1721, 0, 37526, 21843, 739, 36473, 10678, + 4396, 23609, 29101, 37337, 16678, 744, 0, 12587, 8052, 32386, 2460, 10883, 26035, 1029, 24363, 37200, + 30203, 61, 10014, 5224, 8739, 5582, 12048, 22130, 0, 40501, 18110, 19332, 19364, 17478, 32673, 33945, + 39228, 23004, 8263, 21767, 31897, 6599, 5240, 37894, 32425, 36248, 27281, 6602, 1076, 11123, 7466, 7508, + 37983, 939, 7444, 32092, 27095, 20248, 38660, 38661, 38598, 11812, 8132, 30381, 20570, 24072, 17733, 0, + 20367, 10860, 10671, 37022, 23300, 6786, 256, 0, 477, 5692, 33877, 5701, 1287, 40095, 22192, 29435, + 35496, 0, 12789, 39801, 29820, 32892, 5213, 29395, 33043, 2963, 37625, 9397, 17618, 1049, 0, 18816, + 12402, 33889, 27410, 6337, 27898, 10993, 37938, 2820, 675, 25453, 6862, 31008, 485, 7777, 36943, 39046, + 7639, 9398, 2086, 8753, 6626, 11546, 6396, 29159, 2022, 23877, 17857, 18443, 30874, 38742, 16396, 28149, + 20912, 1288, 30111, 40333, 5934, 2083, 14516, 23000, 32006, 30754, 23002, 4922, 7225, 2674, 11128, 37984, + 0, 0, 0, 0, 0, 7288, 33093, 10672, 3479, 740, 36157, 0, 14057, 1972, 25668, 3869, + 36361, 35357, 8332, 16054, 37880, 39158, 34221, 14428, 10813, 20411, 513, 8718, 1497, 40580, 10282, 39159, + 26789, 8784, 1311, 6745, 4276, 4057, 25901, 3363, 25157, 3209, 19676, 22265, 30561, 22586, 8134, 40583, + 23198, 17910, 35344, 19822, 31228, 23549, 6016, 3213, 32007, 10439, 25929, 9279, 10783, 282, 8138, 24035, + 11942, 22481, 34428, 27682, 31706, 20498, 15986, 8747, 0, 382, 25889, 27511, 18540, 39171, 11853, 2739, + 0, 17986, 20855, 10142, 6398, 14012, 20218, 7293, 7040, 2977, 10673, 10679, 37316, 33973, 22173, 1089, + 2985, 36849, 35485, 33975, 25791, 33690, 17204, 17221, 37657, 6577, 12034, 26175, 16838, 23015, 10887, 9799, + 2146, 25683, 30845, 27899, 238, 37094, 32455, 10558, 34805, 32674, 34996, 0, 1376, 0, 10562, 28971, + 18295, 0, 40346, 0, 31821, 38087, 35818, 6293, 37576, 14340, 0, 1936, 29102, 36481, 0, 35488, + 21378, 26481, 992, 9003, 618, 20644, 8322, 7059, 26519, 0, 39787, 34870, 13157, 37658, 27544, 29122, + 30736, 34133, 39803, 35934, 25294, 27127, 10986, 21163, 35125, 13180, 28169, 36495, 781, 10994, 10995, 35261, + 0, 34874, 17479, 31635, 7060, 6542, 38079, 40354, 36500, 36502, 13925, 4164, 5238, 0, 15781, 36016, + 35277, 13079, 7061, 21663, 4420, 23834, 33985, 1874, 20106, 27549, 20563, 17598, 23436, 23437, 27174, 8080, + 1949, 1068, 1664, 35598, 30877, 11327, 7254, 23303, 19579, 772, 258, 261, 8216, 23320, 25128, 30112, + 35898, 1962, 22676, 457, 0, 33809, 0, 0, 37375, 3499, 18607, 35508, 17222, 0, 21464, 31873, + 31229, 0, 16805, 23053, 40585, 41151, 40675, 2881, 239, 7097, 37411, 16846, 8257, 38450, 11909, 4295, + 27903, 1101, 1370, 38451, 0, 10447, 17309, 0, 10137, 38033, 9125, 3375, 18542, 20687, 20181, 19368, + 386, 39008, 40221, 11548, 7291, 5505, 29650, 0, 6401, 31131, 30872, 12667, 3664, 17929, 1586, 18447, + 13093, 21613, 19151, 26650, 0, 9277, 21588, 35781, 15652, 30321, 30199, 23611, 1963, 15305, 18088, 8472, + 9276, 9878, 15832, 10554, 15907, 38277, 29479, 16503, 1344, 11437, 22997, 35055, 30421, 29214, 28171, 15720, + 6591, 347, 13195, 20558, 16033, 15782, 243, 19317, 24405, 24004, 0, 15324, 10305, 6756, 32084, 20926, + 28314, 13820, 22465, 21990, 27800, 2910, 21558, 19387, 27807, 4466, 32114, 16146, 0, 5583, 23026, 29398, + 41082, 31076, 7538, 2216, 22385, 25835, 0, 25527, 23363, 4862, 22087, 2016, 19406, 40970, 4473, 16034, + 12668, 16394, 0, 19937, 20220, 22091, 18645, 41136, 0, 18289, 35584, 30932, 17206, 17223, 38364, 40265, + 11902, 26654, 3635, 33310, 30493, 6160, 12049, 22589, 10890, 19802, 3066, 19804, 2988, 14539, 21786, 0, + 36027, 25592, 18178, 34269, 0, 23518, 40763, 0, 710, 8917, 38267, 13823, 37069, 24268, 940, 428, + 30120, 34742, 24062, 36857, 39805, 13829, 20661, 26770, 26332, 23339, 26333, 20098, 8961, 35518, 8863, 8864, + 29712, 7894, 33937, 35263, 29517, 29399, 20731, 18275, 2239, 16960, 27276, 18834, 12061, 4894, 22025, 18282, + 14684, 38729, 14529, 39301, 41084, 32412, 39848, 0, 0, 16216, 0, 0, 16223, 33541, 8865, 6865, + 20751, 39973, 29141, 37607, 38624, 8866, 31010, 16506, 27908, 38480, 9883, 11191, 38687, 0, 18543, 2856, + 39862, 30868, 33822, 38194, 20419, 9558, 27960, 0, 0, 27690, 6804, 2465, 15805, 29038, 21182, 16587, + 18692, 35535, 33097, 34581, 24396, 23058, 3849, 32240, 9400, 13765, 16321, 19941, 35286, 0, 17226, 0, + 0, 5058, 6458, 10687, 0, 31841, 0, 23332, 0, 37587, 12367, 37928, 7406, 8918, 10180, 39219, + 25083, 0, 0, 13825, 22544, 8473, 33812, 26762, 26950, 24085, 4408, 6007, 1977, 5875, 30376, 4409, + 39594, 521, 31295, 780, 5215, 458, 29643, 0, 8926, 14359, 9667, 4468, 36858, 37597, 16607, 14519, + 8076, 21575, 6854, 6855, 33287, 15243, 34673, 29825, 23036, 1052, 20499, 27547, 34681, 23366, 37605, 1637, + 0, 33785, 10785, 11544, 34913, 14801, 15961, 7023, 12411, 20681, 3735, 785, 31399, 39229, 33715, 28532, + 3659, 31653, 4585, 19267, 15624, 34692, 2274, 0, 10503, 5475, 25167, 29652, 37446, 32568, 21100, 27570, + 7641, 23100, 18141, 349, 11368, 35536, 11369, 19939, 36391, 16780, 34711, 788, 6038, 18179, 8531, 32666, + 30255, 4074, 5602, 11335, 35049, 17207, 20024, 10885, 26763, 12741, 36179, 30563, 0, 22727, 18850, 18142, + 35874, 2187, 26316, 10879, 27291, 30058, 20663, 11180, 29453, 1791, 22387, 11908, 7895, 9838, 2152, 16972, + 2847, 22554, 4864, 19929, 28384, 23984, 39522, 15890, 1108, 329, 19940, 32387, 15706, 29694, 29854, 30757, + 32124, 0, 29857, 16614, 2833, 21346, 21352, 16937, 6179, 14691, 23875, 2019, 26198, 38407, 28975, 23878, + 21751, 35851, 14159, 8436, 5584, 13039, 19800, 4962, 13059, 37413, 33062, 38052, 19520, 16973, 9733, 34021, + 28526, 39047, 34875, 29891, 26391, 31903, 24038, 30875, 36529, 4052, 24822, 30205, 0, 39449, 29554, 9212, + 26392, 2166, 8077, 29455, 28521, 28533, 40659, 10016, 22893, 10445, 40506, 40119, 2025, 18294, 21830, 31625, + 22225, 5722, 10326, 29219, 30272, 29221, 23349, 12628, 3507, 486, 14008, 15476, 17311, 14692, 24875, 16228, + 9208, 23619, 23386, 32424, 13089, 26957, 12970, 47, 11193, 38410, 38295, 35060, 38636, 12674, 2606, 34714, + 12966, 0, 0, 13396, 29649, 21004, 37773, 0, 3511, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26273 +}; + +static const uint16_t gb18030_4_weight_py_p2[] = { + 10308, 23140, 0, 24134, 0, 9894, 0, 0, 0, 24520, 2354, 0, 0, 26998, 0, 0, + 0, 0, 0, 27613, 14821, 0, 0, 0, 0, 0, 0, 37216, 0, 15539, 0, 0, + 0, 0, 40702, 0, 0, 0, 33247, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 20734, 0, 0, 0, 0, 0, 12106, 35177, 15023, 0, 0, 23742, 18706, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3887, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27114, 0, 0, 0, 0, 0, 0, 0, 0, + 24193, 0, 0, 0, 0, 8295, 0, 0, 0, 0, 0, 0, 0, 23239, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2786, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11285, 0, 35611, 41263, 13605, 0, 0, 0, 0, 0, 0, 0, + 0, 40994, 0, 0, 40810, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13840, + 0, 0, 22027, 0, 6519, 4545, 0, 26695, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11477, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36191, 0, 9692, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14237, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26577, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14321, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 35206, 0, 0, 0, 6214, 0, 0, 14816, 13606, 0, 5880, + 0, 14817, 4189, 0, 0, 0, 17996, 0, 0, 0, 29471, 0, 0, 0, 0, 0, + 0, 0, 0, 8789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34239, 0, + 0, 35392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30606, + 0, 0, 13612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35381, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6041, 0, 0, 23245, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 728, 0, 0, 0, + 0, 32979, 0, 0, 0, 0, 0, 0, 0, 38809, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36565, 0, 0, 0, + 33692, 0, 0, 0, 0, 0, 0, 0, 0, 6044, 0, 5124, 0, 0, 0, 30769, + 0, 0, 0, 9283, 0, 0, 0, 0, 0, 7305, 0, 0, 0, 0, 20573, 0, + 0, 31409, 34457, 0, 0, 21212, 5168, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5133, 0, 0, 0, 28886, + 0, 0, 8875, 0, 0, 0, 0, 15710, 3970, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24879, + 0, 20575, 0, 26825, 0, 8419, 0, 26732, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 30032, 0, 0, 0, 27158, 0, 0, 0, 0, 21491, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37901, 9289, 0, 0, 0, 0, 0, 0, 32575, 16546, 0, 0, + 5175, 28291, 0, 0, 0, 19522, 35393, 0, 28983, 0, 1184, 0, 0, 0, 0, 0, + 0, 0, 28440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 19186, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 31721, 11868, 4935, 0, 0, 14610, 0, 6342, 0, 0, 190, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19780, 0, 0, 25142, 0, 28, 37238, + 0, 0, 13107, 0, 23475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20433, + 0, 0, 0, 40075, 39638, 39925, 21105, 1805, 0, 40416, 27359, 34114, 14863, 23807, 0, 0, + 9293, 0, 29737, 0, 0, 0, 36508, 39659, 0, 0, 0, 0, 0, 0, 15923, 0, + 0, 0, 0, 0, 0, 0, 3219, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17526, 34163, 0, 0, 0, 0, 9844, 20295, 26503, 37147, + 0, 27736, 27913, 0, 39660, 0, 0, 24126, 0, 8175, 0, 0, 14469, 911, 0, 1225, + 0, 0, 28337, 0, 0, 23812, 20505, 2779, 0, 0, 25940, 12128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8971, 24463, 0, 0, 0, 25500, 0, 0, 0, 27917, 27919, + 34938, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3765, 0, 0, 27443, 38909, 17170, + 8351, 28131, 38590, 0, 40481, 0, 0, 0, 0, 0, 0, 0, 0, 8196, 0, 0, + 0, 0, 0, 12144, 6233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11752, 0, 0, 13010, 34510, 39717, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19758, 35079, 5529, 35463, 0, 0, 0, 1657, + 0, 0, 24785, 35853, 0, 34858, 0, 0, 0, 38431, 0, 0, 0, 26160, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16268, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14903, 0, + 23171, 0, 0, 37045, 0, 0, 38028, 25793, 26013, 0, 0, 6658, 0, 0, 0, 13775, + 15376, 0, 0, 37674, 0, 0, 0, 13029, 34969, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32101, 0, 32769, 24011, 0, 0, 0, 37340, 24791, 0, 0, 0, 0, + 0, 32100, 19216, 0, 9477, 0, 0, 3267, 4171, 35499, 0, 39320, 0, 40984, 6574, 0, + 38554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7479, + 35500, 19874, 0, 0, 0, 0, 0, 0, 1413, 13728, 27404, 17681, 1149, 27963, 0, 0, + 0, 5713, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 945, 30985, 0, 0, 0, 0, 19893, 0, 2805, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5371, 0, 0, 0, 0, 22798, 13060, 17978, 9673, 23203, 10606, + 0, 0, 0, 12404, 33063, 39300, 2813, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34998, 2821, 0, 0, 0, 0, 0, 0, 5751, 3760, 21169, 21170, 0, 0, 38570, 1423, + 0, 2824, 0, 0, 0, 0, 0, 0, 0, 0, 32685, 0, 0, 0, 0, 4675, + 33147, 14114, 23731, 0, 24372, 0, 0, 0, 0, 9129, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37618, 1775, 0, 0, + 0, 0, 30319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21459, 0, 0, 0, 0, 17544, 0, 0, 25247, 0, 0, 0, 0, 0, 7351, 5578, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11644, 35971, 32222, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16386, 8272, 0, 33367, 0, 0, 17599, 28883, 12253, 0, + 0, 0, 13779, 38413, 26826, 0, 0, 0, 0, 0, 23241, 1430, 0, 16401, 17933, 0, + 0, 0, 0, 0, 0, 0, 39718, 1246, 26808, 0, 0, 0, 0, 26813, 0, 24286, + 0, 0, 1523, 31407, 0, 0, 0, 0, 0, 14749, 0, 12098, 0, 31419, 24290, 0, + 0, 9899, 0, 0, 0, 19057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37722, 0, 0, 0, 0, 0, 0, 0, 17413, 0, 0, 0, 0, 0, 0, 583, + 0, 0, 10548, 0, 0, 0, 23200, 0, 0, 0, 23708, 39356, 19597, 0, 0, 0, + 0, 4544, 0, 0, 20864, 0, 0, 0, 0, 0, 29524, 0, 40887, 0, 0, 0, + 0, 0, 0, 0, 0, 14186, 38851, 0, 0, 0, 0, 0, 0, 0, 0, 21390, + 3314, 0, 0, 23603, 0, 0, 37298, 13440, 0, 0, 0, 0, 0, 38893, 0, 0, + 0, 0, 0, 5544, 14238, 0, 0, 0, 28165, 0, 0, 34881, 0, 0, 0, 30431, + 0, 0, 17644, 0, 29577, 0, 19966, 0, 0, 0, 0, 36821, 0, 0, 0, 0, + 0, 0, 0, 27632, 0, 0, 0, 0, 0, 0, 0, 18564, 0, 0, 0, 36092, + 0, 0, 0, 0, 0, 3746, 0, 0, 0, 0, 0, 8448, 14236, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24316, 14201, 0, 32823, 0, 0, 0, 0, 0, 0, + 0, 0, 10460, 0, 0, 0, 28887, 0, 24585, 32826, 14122, 21387, 14123, 0, 0, 12277, + 0, 0, 0, 0, 0, 0, 0, 0, 29295, 0, 4753, 5950, 0, 24400, 0, 0, + 0, 0, 0, 0, 0, 22899, 22859, 0, 5960, 18562, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17501, 9989, 22123, 28792, 0, 0, 0, 35464, 33802, 28389, 18226, 27497, 26708, + 0, 2128, 27870, 0, 0, 24262, 26675, 0, 0, 0, 21754, 29551, 13240, 0, 0, 0, + 0, 0, 0, 0, 0, 31580, 39807, 0, 0, 0, 0, 0, 0, 16303, 17247, 17248, + 0, 0, 10442, 13542, 0, 34437, 0, 27210, 0, 0, 26961, 0, 0, 0, 0, 0, + 0, 39127, 0, 36675, 0, 0, 0, 0, 0, 0, 28387, 31183, 0, 0, 0, 0, + 0, 2891, 4548, 0, 0, 0, 14596, 0, 0, 0, 0, 0, 0, 0, 27218, 0, + 0, 0, 0, 0, 14323, 30584, 0, 0, 0, 0, 0, 0, 0, 0, 11995, 0, + 0, 0, 0, 0, 13584, 0, 0, 0, 0, 0, 0, 0, 38183, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21945, 0, 0, 0, 0, 0, 9286, 0, 0, 0, + 0, 0, 0, 10205, 17019, 39606, 32313, 0, 0, 2054, 2944, 0, 0, 0, 0, 0, + 0, 0, 0, 37797, 10368, 0, 0, 0, 0, 0, 0, 0, 28914, 0, 0, 0, + 1573, 0, 0, 0, 0, 5842, 0, 7131, 14239, 0, 0, 0, 0, 5637, 35618, 16035, + 0, 38917, 0, 16114, 39975, 14583, 0, 0, 0, 26292, 26140, 5844, 566, 12090, 0, 0, + 39875, 0, 0, 35367, 0, 15576, 31135, 0, 0, 0, 8626, 393, 0, 0, 8987, 0, + 0, 32146, 9248, 18299, 3515, 9312, 4078, 0, 16848, 4629, 27423, 0, 0, 0, 0, 0, + 0, 1115, 0, 0, 0, 1758, 17084, 0, 0, 14295, 29349, 6713, 0, 34287, 24901, 0, + 0, 17764, 0, 15422, 0, 8779, 39058, 0, 7596, 0, 0, 0, 0, 0, 0, 0, + 0, 35383, 0, 14313, 33598, 13414, 0, 0, 18918, 14296, 0, 3855, 0, 0, 32319, 0, + 15755, 6559, 0, 0, 0, 0, 19095, 31437, 24324, 2106, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 22440, 34158, 1005, 9817, 9254, 0, 0, 0, 14464, 0, 0, 23570, 0, 14856, 0, + 0, 0, 0, 0, 17120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11142, 13342, 0, 0, 0, 0, 0, 0, 23591, 0, 38419, 23571, 0, 38947, 2504, 36468, + 0, 0, 34295, 0, 3680, 0, 0, 0, 3533, 0, 30275, 0, 27859, 0, 0, 0, + 0, 0, 15206, 37550, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3790, 0, 28338, + 29740, 0, 0, 38955, 29047, 0, 31156, 0, 4901, 17156, 2506, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 25399, 8972, 25054, 0, 16871, 0, 0, 0, 0, 28899, 0, + 0, 0, 0, 0, 17157, 0, 0, 20014, 0, 3608, 0, 0, 9725, 18506, 4168, 28343, + 13442, 13958, 0, 0, 0, 7179, 38523, 0, 0, 0, 0, 0, 0, 0, 13959, 4769, + 0, 0, 2486, 41220, 0, 38882, 0, 0, 22755, 38654, 31538, 35082, 8122, 3687, 0, 0, + 0, 0, 0, 4773, 0, 0, 0, 9268, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12160, 0, 0, 26014, 38599, 18194, 26015, 35217, 0, 0, 0, 0, 0, + 14429, 0, 0, 0, 0, 0, 29753, 0, 0, 0, 25571, 38268, 11336, 0, 0, 0, + 0, 32276, 0, 23693, 38894, 0, 0, 0, 0, 0, 0, 2265, 0, 0, 16140, 17229, + 25522, 0, 0, 0, 6368, 0, 0, 17816, 0, 0, 0, 0, 36355, 17249, 0, 0, + 6371, 0, 18112, 0, 0, 0, 0, 0, 0, 0, 30289, 0, 0, 0, 0, 6028, + 0, 0, 0, 14240, 0, 17071, 15627, 15503, 0, 39129, 0, 0, 0, 0, 0, 0, + 10458, 0, 1161, 0, 22420, 0, 0, 0, 0, 0, 10148, 0, 0, 0, 0, 0, + 0, 40596, 6544, 0, 35666, 0, 0, 0, 0, 0, 0, 0, 15423, 35667, 20590, 0, + 0, 2245, 0, 8823, 15428, 27029, 0, 0, 0, 0, 0, 0, 0, 18019, 1006, 0, + 0, 6492, 0, 0, 0, 0, 14704, 21106, 40832, 0, 0, 40975, 0, 0, 0, 0, + 0, 0, 0, 28789, 0, 0, 31967, 10080, 0, 0, 0, 0, 19027, 23752, 0, 0, + 0, 0, 0, 20625, 21917, 10212, 0, 0, 0, 38426, 14776, 4560, 0, 0, 0, 0, + 17186, 38432, 36846, 5814, 14908, 925, 0, 0, 0, 35038, 22756, 0, 0, 0, 0, 0, + 0, 13979, 15158, 26016, 34838, 13980, 0, 0, 0, 15470, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2671, 0, 0, 21413, 0, 30424, 18965, 0, 0, 0, 0, 0, + 37821, 34882, 720, 0, 0, 15017, 33790, 0, 39980, 0, 0, 0, 0, 0, 0, 0, + 15988, 7789, 0, 0, 0, 0, 0, 0, 0, 0, 24767, 26470, 28274, 0, 0, 0, + 6324, 0, 15740, 22214, 0, 0, 0, 0, 0, 0, 808, 0, 0, 0, 8203, 14342, + 25150, 0, 0, 0, 14437, 0, 0, 0, 0, 0, 24501, 0, 0, 40033, 11194, 752, + 0, 0, 0, 0, 0, 35374, 0, 35394, 35395, 0, 0, 0, 0, 19624, 0, 0, + 0, 0, 0, 0, 0, 0, 25654, 0, 0, 0, 0, 4414, 0, 0, 9957, 0, + 4546, 0, 0, 0, 31773, 0, 0, 0, 0, 24924, 29366, 0, 5894, 0, 9966, 0, + 0, 0, 0, 0, 0, 0, 0, 35155, 0, 0, 0, 0, 0, 6810, 30588, 0, + 2327, 5907, 0, 0, 0, 6931, 5684, 0, 28105, 24965, 0, 0, 6976, 21922, 33806, 0, + 0, 0, 31292, 0, 0, 0, 35972, 0, 20733, 0, 0, 0, 0, 0, 0, 0, + 10827, 0, 0, 0, 9967, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26900, + 0, 0, 0, 25778, 0, 0, 0, 0, 1156, 0, 9958, 14115, 0, 0, 24317, 4842, + 4435, 0, 567, 0, 0, 0, 0, 6520, 0, 0, 0, 0, 31777, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39392, 19017, 0, 10843, 12298, 9316, 0, 0, 0, + 0, 0, 22124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40161, 0, 0, 0, 0, 1150, 0, 37079, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 23393, 0, 0, 10330, 3946, 0, 0, 26465, 3568, 1878, 0, 0, 0, 25362, + 36732, 0, 0, 0, 20939, 0, 0, 0, 0, 11722, 29371, 609, 0, 0, 0, 0, + 33467, 0, 0, 0, 36744, 3587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10545, + 0, 0, 0, 30264, 0, 0, 32999, 0, 0, 0, 14918, 0, 28150, 24342, 40414, 0, + 0, 0, 0, 0, 0, 12475, 0, 0, 1162, 0, 31438, 0, 0, 0, 0, 0, + 12308, 0, 15075, 0, 0, 17655, 36699, 0, 0, 0, 0, 0, 0, 14453, 0, 0, + 0, 0, 37685, 0, 0, 687, 0, 0, 22485, 0, 0, 38300, 0, 0, 35628, 5604, + 0, 0, 24137, 0, 28326, 0, 4439, 0, 40273, 37690, 0, 0, 0, 0, 0, 13332, + 0, 0, 0, 0, 26911, 0, 0, 35396, 31945, 0, 0, 0, 0, 0, 0, 0, + 37537, 0, 0, 0, 0, 9776, 0, 15432, 0, 0, 4754, 35725, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17121, 0, 5766, 0, 0, 31467, 0, 0, 0, 0, 1248, + 0, 0, 1434, 19701, 17138, 0, 0, 27916, 0, 0, 0, 0, 0, 0, 0, 0, + 18219, 9642, 15451, 0, 0, 0, 0, 35465, 0, 31739, 36158, 0, 0, 0, 0, 15456, + 0, 0, 0, 26544, 0, 0, 0, 31070, 0, 0, 0, 0, 0, 0, 22619, 0, + 0, 0, 0, 0, 0, 0, 37742, 10688, 0, 0, 17209, 8232, 0, 0, 0, 0, + 0, 0, 0, 14955, 32116, 0, 0, 0, 0, 5752, 0, 0, 17348, 0, 0, 0, + 0, 0, 0, 29722, 0, 0, 0, 0, 12844, 0, 0, 522, 5638, 38782, 0, 0, + 0, 0, 0, 37214, 0, 0, 0, 0, 6554, 0, 0, 0, 0, 2222, 29763, 0, + 0, 0, 0, 0, 0, 0, 28618, 12279, 23242, 26299, 21373, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9414, 0, 1138, 0, 0, 33212, 0, 0, 0, 0, + 0, 0, 0, 39165, 0, 0, 0, 0, 0, 25765, 0, 20572, 0, 7906, 0, 0, + 0, 0, 28884, 686, 0, 0, 0, 0, 0, 0, 1605, 0, 31411, 0, 13615, 0, + 0, 0, 0, 0, 0, 0, 13929, 0, 0, 0, 0, 0, 0, 0, 23640, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27724, 14091, 0, 3524, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14094, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38383, + 16880, 0, 0, 0, 40579, 0, 0, 0, 0, 1492, 0, 0, 0, 0, 0, 30001, + 0, 0, 0, 1292, 0, 0, 7521, 0, 0, 0, 5441, 0, 40211, 0, 0, 0, + 0, 14446, 0, 0, 0, 0, 0, 0, 0, 35544, 0, 0, 34226, 0, 0, 3564, + 9287, 39528, 0, 0, 0, 0, 0, 0, 25355, 0, 0, 36677, 0, 1876, 0, 12428, + 22811, 0, 0, 36302, 34721, 19546, 0, 0, 0, 0, 0, 0, 0, 18471, 20837, 25822, + 4077, 0, 4366, 31245, 25303, 0, 0, 0, 5010, 12258, 0, 35548, 0, 25135, 0, 0, + 11980, 9249, 0, 38920, 22593, 0, 0, 37953, 624, 13621, 0, 0, 10737, 0, 0, 32315, + 11588, 0, 0, 0, 0, 0, 0, 0, 0, 38370, 4996, 8630, 0, 22594, 0, 22691, + 26907, 17603, 37691, 11048, 1461, 0, 0, 25359, 0, 25360, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 35298, 39364, 0, 13844, 30992, 2970, 0, 24525, 0, 40235, 0, 38414, + 22948, 207, 0, 10337, 0, 3883, 34352, 0, 0, 0, 27020, 11056, 6894, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26912, 0, 0, 0, 0, 30037, 5014, 30261, 22906, 25466, 14377, 0, + 1829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37140, 6225, 0, 9575, 27178, 0, 0, 28292, 21313, 39982, 18473, 1765, 41226, 35179, 25178, 0, + 18009, 25782, 0, 0, 16732, 6900, 0, 39949, 12436, 0, 0, 6901, 0, 0, 0, 41282, + 0, 0, 20876, 37870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32950, 41157, 27349, 6119, 7203, 25285, + 0, 652, 9968, 10629, 35304, 0, 35305, 0, 0, 15341, 35695, 11663, 39240, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14129, 0, + 0, 8681, 0, 0, 21757, 24145, 0, 5951, 0, 12514, 35727, 35419, 0, 7958, 27577, 27578, + 36623, 15487, 11160, 10715, 0, 0, 0, 10358, 0, 0, 10315, 23804, 23592, 0, 27731, 0, + 655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14031, 15433, 0, 0, + 0, 0, 0, 13, 18496, 0, 29732, 0, 0, 4152, 0, 0, 27843, 3307, 0, 30517, + 0, 0, 21801, 0, 14299, 0, 0, 1686, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32749, 26748, 10792, 0, 0, 40296, 0, 9351, 12121, 0, 12526, 0, 31469, 0, 26527, + 21951, 10910, 28449, 32702, 0, 38206, 0, 0, 2039, 23484, 30187, 30047, 5382, 0, 20888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38519, 0, 0, 34248, 0, 0, 31264, 39125, 5447, 10317, 0, 245, 22509, 26001, 7646, 9258, + 0, 0, 0, 22954, 0, 0, 0, 33860, 9934, 8506, 419, 40891, 19968, 0, 11997, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5729, 31470, 0, 0, 4983, 21053, 0, 0, 0, + 5855, 19196, 15439, 0, 0, 0, 0, 35783, 14882, 10386, 0, 12310, 0, 0, 10467, 21524, + 25723, 23753, 5046, 26422, 15447, 40201, 0, 26844, 18925, 12718, 22662, 10807, 12130, 28458, 3798, 31048, + 14144, 22919, 38521, 33130, 0, 0, 1482, 0, 0, 33639, 0, 0, 0, 0, 9096, 13811, + 0, 0, 32181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6834, 0, 1920, 22698, 0, 0, 0, 38005, + 0, 22034, 29741, 0, 36314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32497, 0, + 0, 21882, 8647, 1921, 32978, 0, 0, 0, 39086, 37027, 21330, 0, 0, 0, 0, 0, + 34121, 30235, 0, 268, 10087, 10585, 5105, 0, 21857, 0, 2392, 12324, 21207, 36640, 32617, 0, + 4053, 35080, 0, 8705, 28798, 809, 2783, 0, 33654, 0, 0, 9872, 0, 3803, 0, 13011, + 41235, 0, 0, 0, 30802, 4905, 22454, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11414, 0, 31517, 0, 22310, 18202, 20773, 20323, 16528, 29951, 578, 0, 0, 8652, 0, 15696, + 0, 0, 12725, 1854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11415, 0, 41058, + 19207, 0, 0, 0, 0, 0, 0, 16901, 0, 10411, 20529, 0, 27541, 26626, 15288, 3616, + 18074, 19165, 0, 0, 34519, 38883, 4055, 9174, 24304, 0, 28665, 7665, 29801, 0, 0, 0, + 0, 18075, 0, 0, 16516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16339, 38089, 31364, 0, 0, 0, 0, 16902, 5, 19035, + 39583, 3812, 13304, 0, 12899, 0, 0, 0, 0, 19072, 35480, 0, 26372, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12161, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35855, 21621, 0, 0, + 0, 11781, 0, 38392, 0, 0, 10032, 0, 36221, 1293, 163, 31929, 21248, 0, 0, 0, + 5535, 13030, 22068, 0, 0, 37342, 4067, 37964, 0, 2558, 0, 38971, 26017, 0, 22299, 9108, + 38972, 0, 0, 0, 0, 0, 16914, 6239, 0, 3816, 0, 41163, 22991, 0, 0, 26494, + 18385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 27391, 0, 13981, 18084, 0, 0, 15265, 16201, 0, 33510, 13982, 0, 4085, 0, + 0, 0, 37743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19340, 33028, 14275, 12602, 0, 37748, 0, 0, 0, 12921, + 0, 10008, 0, 25797, 11796, 24109, 0, 26025, 41165, 0, 0, 18667, 11234, 3892, 26286, 31113, + 12369, 40651, 32198, 35336, 9796, 16014, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 40020, 0, 0, 18767, 0, 1864, 26949, 36517, 15662, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39788, 32884, 0, 0, 35242, 7002, 18946, + 10122, 35243, 0, 0, 0, 0, 19222, 4334, 7352, 39504, 36520, 30969, 30201, 107, 37080, 0, + 0, 11149, 0, 17817, 14059, 37989, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38132, 6578, 0, 12617, 0, 0, 0, 31057, 0, + 12381, 31602, 0, 38723, 29870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37081, 0, 0, 0, 0, 17827, + 0, 0, 39826, 26885, 0, 16609, 16304, 30747, 22201, 3505, 36490, 6304, 0, 6305, 0, 827, + 24184, 27408, 0, 39508, 0, 0, 0, 0, 0, 17828, 0, 22379, 0, 38915, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21933, + 0, 0, 33054, 12396, 16305, 36440, 2470, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16640, 0, 0, 0, 0, 0, 0, 19092, 0, 0, + 0, 18398, 31880, 0, 0, 0, 17979, 0, 0, 9552, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33240, 0, 0, 0, 16963, 4363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24414, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12951, 5410, 13066, 24436, 33079, 36525, 0, 0, 0, 0, 0, 0, 0, 0, 9856, + 0, 39052, 26498, 20045, 11357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4673, 25588, 25773, 12067, 35354, 0, 5543, 0, 19023, 0, 35999, 0, 0, 0, 0, + 0, 0, 2048, 22156, 28705, 6866, 38135, 4578, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38533, 0, 31763, 19544, 0, 16229, 37948, 0, 0, 0, 0, 0, 0, + 0, 7027, 0, 0, 0, 6023, 0, 0, 0, 0, 0, 0, 0, 9374, 0, 0, + 0, 11443, 0, 0, 0, 27139, 13081, 0, 0, 38631, 12419, 11444, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30425, 19180, 0, 0, 0, 0, 0, 0, 0, 0, 6315, + 0, 0, 0, 0, 0, 17566, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21493, 21006, 14308, 37686, 0, 0, 34884, 4134, 0, 0, 0, 2278, 17020, + 6634, 21007, 21008, 0, 0, 0, 0, 0, 25372, 0, 0, 0, 0, 37692, 0, 0, + 36723, 0, 36050, 0, 9772, 0, 0, 0, 5290, 0, 0, 0, 0, 0, 0, 0, + 0, 39059, 19998, 5940, 0, 0, 39060, 0, 0, 0, 15711, 0, 9969, 27840, 10344, 12107, + 38935, 0, 0, 0, 1771, 0, 30585, 29673, 0, 29766, 0, 0, 8503, 18497, 24932, 11921, + 40402, 25049, 0, 10653, 0, 5296, 10370, 28599, 9317, 0, 37249, 0, 34261, 0, 0, 30278, + 25116, 0, 0, 0, 0, 14883, 21916, 0, 0, 24910, 39481, 0, 0, 18060, 31160, 33182, + 4951, 0, 37497, 37647, 0, 0, 0, 20636, 0, 36778, 0, 0, 0, 0, 31276, 0, + 38751, 0, 0, 33756, 0, 0, 25246, 9713, 37343, 0, 0, 0, 0, 0, 31998, 1449, + 36799, 0, 36106, 0, 33817, 36806, 16701, 0, 0, 0, 0, 0, 29523, 0, 0, 39053, + 0, 0, 0, 0, 38034, 8285, 16171, 0, 0, 25039, 0, 0, 0, 0, 14454, 0, + 4221, 4895, 29981, 9, 0, 0, 0, 40814, 0, 0, 11475, 35646, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 791, 3454, 0, 0, 25373, 0, 0, + 0, 0, 0, 0, 18585, 0, 0, 13622, 27013, 0, 41115, 0, 0, 0, 0, 0, + 0, 35647, 0, 0, 7652, 7653, 0, 0, 0, 20578, 0, 0, 0, 27341, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 22571, 22844, 22908, + 12751, 40037, 0, 24527, 0, 0, 0, 36819, 28648, 0, 0, 25467, 0, 20112, 0, 0, + 0, 0, 0, 0, 0, 0, 35670, 0, 25470, 0, 0, 17767, 24449, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11664, 12496, 0, 0, 0, 0, 8605, + 0, 0, 0, 0, 0, 0, 0, 36738, 2497, 5424, 36054, 0, 37231, 894, 0, 1896, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23988, 0, 0, 0, 0, 0, 2574, 0, 33119, 0, 3466, 0, + 0, 0, 0, 38201, 15920, 0, 7505, 0, 0, 28405, 9338, 0, 0, 6675, 0, 0, + 0, 0, 9514, 0, 39464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2771, 21110, 0, 0, + 10911, 0, 28940, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 35755, 0, 0, 21525, 38559, 11321, 0, 6443, 0, 23491, 2418, 0, 0, 4198, 0, + 0, 0, 4903, 0, 0, 0, 39692, 8856, 0, 0, 0, 31031, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6444, 0, 0, 0, 3474, 0, 0, + 0, 223, 16124, 0, 31092, 0, 0, 0, 36315, 0, 22687, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38424, 40370, 0, 28002, 0, + 0, 0, 0, 21331, 0, 0, 0, 0, 0, 0, 40202, 2687, 0, 0, 1056, 21241, + 39482, 11754, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32029, 0, 39719, 31518, 0, 0, 13269, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6529, 7870, 0, 0, 13358, 2996, 552, + 0, 0, 0, 0, 0, 17807, 0, 0, 0, 0, 0, 0, 301, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38155, 4016, 0, 0, 30147, + 0, 0, 10217, 15259, 36159, 0, 32373, 0, 0, 0, 0, 0, 0, 8204, 1627, 0, + 15904, 0, 0, 0, 24175, 25794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4913, + 35161, 0, 0, 0, 38788, 0, 17586, 0, 6547, 0, 0, 0, 0, 16563, 34003, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39762, 0, 15661, 0, 0, 0, 28213, 31056, + 0, 0, 0, 15663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13034, + 0, 0, 0, 0, 0, 0, 13277, 0, 0, 0, 0, 40533, 0, 27502, 37070, 0, + 0, 25798, 0, 37363, 16413, 0, 0, 0, 0, 0, 37379, 0, 23828, 14673, 0, 17818, + 0, 0, 27295, 32397, 0, 0, 8362, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 28578, 0, 0, 0, 0, 29329, 0, 0, 0, 0, 0, 0, 0, 19976, + 0, 5585, 0, 20206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11645, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6798, 0, 0, 0, 17829, 0, 0, + 0, 0, 16308, 36180, 16419, 0, 13392, 0, 12051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9766, 0, 0, 38730, 0, 0, 0, 0, 0, 0, 20100, 0, 0, + 15912, 0, 0, 0, 0, 0, 0, 6803, 0, 0, 0, 0, 0, 0, 0, 36184, + 0, 0, 0, 0, 0, 0, 0, 16816, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8981, 0, 0, 0, 0, 0, 29526, 34916, 0, 30459, 0, + 0, 0, 0, 13648, 0, 0, 0, 0, 33377, 0, 27360, 0, 0, 0, 0, 0, + 0, 30790, 0, 0, 37299, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 38611, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 25933, + 3846, 0, 15729, 0, 0, 0, 14544, 9897, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 20226, 0, 0, 0, 0, 10186, 0, 0, 3791, 0, 0, 0, 18061, 0, + 40907, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16036, 0, 0, 39878, 0, 38826, 0, + 6039, 9018, 37835, 5091, 21869, 0, 0, 0, 0, 0, 0, 1772, 0, 25146, 2658, 0, + 0, 0, 25475, 36068, 2659, 0, 0, 39693, 0, 0, 9340, 21855, 26610, 0, 0, 28003, + 0, 0, 31068, 3545, 0, 0, 0, 0, 0, 0, 20337, 39487, 0, 0, 23173, 0, + 0, 9004, 0, 0, 0, 0, 18557, 0, 40784, 0, 0, 0, 0, 5277, 0, 32308, + 0, 25535, 0, 0, 0, 0, 0, 22399, 0, 0, 0, 0, 0, 0, 31414, 0, + 0, 0, 15709, 0, 9619, 4247, 13781, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13782, 31420, 0, 15629, 0, 9078, 38486, 7315, 0, 0, 32941, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11311, 0, 21448, + 31788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4612, 0, 9693, 0, 0, + 0, 31451, 0, 0, 0, 0, 0, 23579, 0, 0, 19470, 0, 0, 38937, 0, 0, + 14755, 0, 0, 0, 1616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1617, 0, 0, 0, 0, 24939, 0, 0, 0, 0, 0, 31811, 0, 0, 13432, 0, + 24949, 39571, 29236, 15125, 0, 0, 0, 0, 25869, 0, 0, 40742, 0, 0, 0, 0, + 0, 0, 0, 13678, 0, 0, 0, 0, 0, 0, 1654, 0, 6294, 41147, 0, 0, + 0, 0, 0, 0, 0, 0, 34520, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1294, 0, 0, 0, 15744, 0, 34651, 30620, 0, 11290, 0, 10290, 0, 0, 0, + 0, 8924, 0, 0, 19882, 0, 0, 16754, 0, 5719, 0, 1793, 11298, 0, 0, 30207, + 14986, 0, 0, 0, 0, 0, 0, 0, 3565, 0, 0, 0, 0, 391, 14290, 0, + 0, 0, 0, 0, 0, 0, 0, 5639, 0, 38798, 0, 4979, 26908, 10250, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35168, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1165, 22568, 35012, 0, 0, 5514, 2295, 22785, 37698, + 24124, 22425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30136, 32942, 0, 0, 0, 0, 0, 0, 35174, 0, 0, + 7316, 9251, 11063, 25597, 0, 0, 0, 0, 0, 25179, 7824, 11456, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25544, 0, 0, 0, 0, 0, + 0, 0, 19608, 0, 0, 6523, 11724, 31789, 33374, 0, 0, 25180, 35307, 0, 0, 38938, + 0, 12515, 8608, 36892, 0, 23043, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3985, 4613, 38939, 21449, 0, 24147, 0, 0, + 2537, 0, 21450, 28123, 0, 0, 0, 0, 0, 2538, 3309, 34928, 6436, 30436, 0, 21425, + 20002, 0, 0, 0, 0, 0, 21771, 31804, 0, 34892, 0, 2660, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32966, 20330, 15538, 0, 4637, 0, 26779, 22107, + 11086, 0, 15448, 32353, 0, 10749, 24464, 40897, 0, 0, 7994, 20959, 0, 21327, 0, 15677, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21196, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8648, 0, 0, + 0, 10750, 0, 19, 0, 26845, 0, 0, 0, 0, 0, 0, 0, 0, 33386, 4487, + 13346, 0, 38425, 32607, 17532, 24868, 0, 0, 26274, 32992, 0, 8974, 20332, 2624, 0, 7051, + 0, 0, 0, 6289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 15608, 0, 0, 0, 29381, 26854, 0, 0, 0, 25912, + 0, 0, 9357, 0, 0, 0, 10283, 39742, 34867, 29568, 1271, 0, 20530, 0, 8031, 0, + 0, 0, 0, 0, 0, 23946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39743, 0, 0, 27877, 0, 0, 21456, + 14784, 0, 34859, 0, 11471, 0, 0, 0, 1024, 20531, 2997, 0, 0, 0, 18898, 26433, + 2081, 38340, 27656, 0, 41186, 37675, 38054, 19015, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 24792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20300, 0, 0, 0, 0, 0, + 40428, 0, 0, 0, 0, 0, 0, 0, 5311, 0, 37509, 0, 0, 0, 0, 0, + 0, 0, 14569, 0, 0, 11696, 23528, 0, 37929, 0, 19455, 0, 20565, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 22705, 0, 13989, 0, 0, 0, 0, 0, 34908, 0, 0, 0, 0, 0, 0, + 3636, 21347, 27887, 0, 0, 0, 0, 0, 27405, 0, 0, 22706, 0, 0, 0, 0, + 0, 0, 0, 0, 10123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34911, 0, 21168, 0, 0, 0, 0, 0, 0, 0, 27128, 0, 37516, 0, 2214, 13737, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33055, 0, 0, 0, 34422, 32667, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33064, 17270, 0, 7355, 0, + 0, 0, 0, 0, 0, 0, 0, 40350, 0, 20921, 0, 40411, 0, 0, 15910, 0, + 0, 0, 19128, 0, 0, 0, 0, 0, 0, 0, 0, 23577, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30292, 0, 0, 0, 0, 0, 0, 27302, 0, 3390, + 0, 35619, 0, 0, 0, 0, 10244, 0, 13505, 0, 0, 11719, 0, 32743, 4368, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12497, 0, + 0, 0, 0, 0, 0, 0, 21271, 0, 21274, 29150, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14628, 0, 20513, 0, 0, 0, 0, 16873, 0, 39958, + 0, 33642, 0, 24476, 8011, 0, 1727, 0, 0, 0, 12555, 0, 0, 23290, 31822, 0, + 0, 0, 0, 0, 5485, 7088, 0, 0, 0, 0, 0, 27289, 29628, 32715, 0, 22542, + 0, 0, 0, 0, 0, 0, 0, 0, 5152, 0, 12397, 0, 0, 0, 0, 0, + 0, 0, 0, 32784, 0, 0, 0, 4581, 0, 0, 0, 1678, 25464, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20261, 0, 0, + 0, 0, 20262, 0, 27214, 32694, 754, 30225, 0, 22208, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8327, 0, 10830, 10538, 0, 40185, 9314, 0, 0, 0, 9628, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5023, 0, 0, 1684, 11554, 0, 0, + 2539, 0, 0, 0, 32026, 14465, 0, 35021, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7643, 38202, 0, 0, 0, 7704, 0, 0, 0, 0, + 0, 0, 14400, 37253, 0, 0, 0, 0, 0, 11871, 0, 0, 0, 0, 0, 0, + 0, 0, 13656, 33352, 0, 20957, 0, 0, 0, 0, 0, 21772, 0, 26780, 0, 37274, + 0, 0, 11323, 8838, 30347, 0, 30095, 23996, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36265, 0, 12719, 0, 0, 0, 0, 0, + 0, 28345, 0, 13679, 31520, 31016, 0, 0, 0, 19507, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34783, 0, 34948, 0, 0, 0, 0, 19510, 21919, 0, + 0, 184, 0, 0, 0, 18566, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6967, 40847, 0, 0, 0, 0, 6968, 0, 228, 0, 0, 0, 0, 12017, 0, + 2473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 33358, 12591, 0, 41255, 0, 23323, 0, 0, 0, 0, 39287, 0, 0, 0, 0, 0, + 12183, 23191, 14738, 21646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26041, + 0, 0, 0, 0, 0, 10493, 25494, 24310, 0, 0, 0, 0, 14447, 0, 0, 17271, + 0, 0, 0, 0, 0, 26952, 0, 0, 21357, 32226, 7902, 0, 0, 25604, 0, 0, + 0, 33366, 9681, 0, 12656, 0, 19964, 7904, 0, 25847, 37436, 13551, 19985, 18439, 23936, 0, + 20067, 0, 0, 35538, 0, 0, 9955, 21363, 16631, 26079, 0, 0, 17953, 0, 37217, 0, + 0, 0, 0, 0, 0, 21848, 0, 0, 0, 0, 0, 31328, 0, 0, 0, 1435, + 0, 0, 1436, 33739, 0, 12875, 0, 0, 1438, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5437, 0, 0, 0, 0, 40387, 0, 0, 0, 25488, 0, 0, 0, 0, + 27468, 0, 0, 0, 0, 0, 0, 0, 12684, 0, 0, 11685, 0, 0, 38574, 0, + 0, 0, 535, 17762, 0, 32796, 0, 0, 0, 0, 0, 0, 0, 12982, 27168, 0, + 0, 0, 0, 15325, 0, 0, 0, 9350, 19018, 0, 0, 0, 0, 0, 21773, 2932, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17577, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 20963, 25600, 0, 0, 0, 39744, 0, + 0, 0, 0, 0, 0, 0, 2371, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16358, 0, 0, 0, 2673, + 0, 30429, 0, 0, 17075, 0, 0, 31307, 22177, 36869, 0, 8367, 0, 0, 0, 138, + 33370, 27522, 25685, 0, 0, 0, 0, 0, 603, 36725, 0, 0, 0, 0, 0, 0, + 0, 0, 11959, 0, 0, 11598, 0, 0, 41286, 32588, 0, 20189, 0, 0, 0, 0, + 8299, 37617, 0, 2040, 3037, 29937, 0, 2041, 0, 0, 0, 0, 0, 8300, 0, 29356, + 20846, 0, 0, 0, 0, 10933, 21534, 0, 0, 0, 0, 11679, 18549, 0, 29096, 0, + 24106, 24055, 39939, 0, 0, 0, 5537, 0, 0, 0, 17900, 0, 0, 24982, 40397, 0, + 16711, 0, 32923, 0, 0, 25265, 0, 0, 5243, 0, 6320, 21386, 0, 0, 0, 26967, + 0, 0, 32144, 0, 0, 0, 0, 0, 0, 39452, 0, 0, 0, 68, 4345, 23061, + 0, 26971, 0, 0, 0, 24687, 27304, 5727, 0, 32722, 27525, 0, 11312, 0, 0, 0, + 35401, 14702, 0, 0, 39550, 0, 0, 0, 0, 0, 0, 0, 38863, 0, 0, 0, + 0, 0, 0, 33617, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18477, + 0, 40293, 0, 28331, 0, 0, 0, 5952, 0, 0, 24770, 0, 15441, 10845, 14401, 0, + 24402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1751, 0, 0, + 0, 0, 0, 0, 0, 29177, 0, 14884, 0, 0, 24621, 0, 0, 0, 0, 0, + 0, 0, 0, 13298, 0, 0, 0, 0, 0, 0, 37911, 0, 0, 19789, 22455, 0, + 24784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20137, 0, 0, 29183, + 0, 0, 15174, 0, 1140, 0, 24718, 0, 0, 0, 0, 0, 0, 0, 0, 29363, + 0, 4022, 0, 0, 0, 0, 0, 0, 14501, 0, 31563, 0, 0, 0, 17967, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3557, 12223, 0, + 0, 0, 0, 0, 18621, 0, 0, 0, 17329, 0, 0, 0, 0, 0, 14820, 0, + 0, 0, 0, 0, 0, 40126, 18696, 0, 0, 0, 0, 0, 0, 0, 21499, 0, + 0, 0, 0, 0, 24928, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34228, 0, 6881, + 0, 11040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19475, 0, 0, 0, 0, 0, 0, 0, 0, 31312, 0, 0, 2491, 0, 0, 0, + 0, 24204, 13617, 10618, 0, 5083, 7054, 38301, 11049, 263, 13785, 8149, 36664, 0, 7693, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20787, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25995, 4549, 0, 0, 0, 15249, 0, 0, 0, 0, + 0, 0, 35061, 70, 723, 0, 22950, 0, 26972, 7317, 0, 14458, 22490, 0, 30778, 15633, + 24131, 8377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15857, 28178, 1003, 12692, 34240, 0, 0, 0, 15231, 21500, 0, 33254, 0, 31790, + 0, 17957, 6719, 0, 2765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27031, 0, 0, 6560, 0, 13224, 37141, 18704, + 7056, 0, 0, 9138, 0, 30672, 3051, 11392, 1649, 0, 0, 10058, 29903, 20882, 23411, 0, + 29684, 37481, 30448, 0, 31192, 8609, 0, 0, 15511, 0, 35421, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32589, 0, 9586, 34246, 28183, 27818, 0, 40604, + 0, 0, 29733, 32250, 0, 0, 0, 0, 38306, 17123, 0, 0, 40294, 0, 13649, 0, + 0, 29172, 0, 0, 32846, 24457, 0, 34250, 14403, 0, 0, 36141, 39465, 0, 15208, 40721, + 0, 15354, 0, 21513, 23939, 30337, 38238, 0, 14404, 0, 40865, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 34251, 0, 0, 17879, 0, 23264, 0, 0, 0, 0, 11674, 0, + 0, 0, 0, 23485, 0, 34772, 28187, 0, 23417, 9515, 0, 0, 0, 0, 0, 0, + 0, 0, 24328, 6815, 0, 41292, 0, 0, 38308, 23486, 12311, 0, 30096, 5966, 0, 11743, + 19570, 0, 33567, 0, 0, 10751, 34494, 32481, 4488, 10924, 0, 0, 224, 0, 1778, 0, + 0, 0, 0, 0, 0, 0, 0, 6727, 0, 0, 0, 0, 0, 0, 0, 0, + 40245, 5967, 36689, 23421, 26932, 33997, 36690, 15191, 24082, 0, 0, 23899, 22303, 0, 0, 24951, + 0, 36407, 0, 0, 0, 0, 0, 26105, 0, 0, 0, 28904, 0, 10720, 22577, 34949, + 0, 0, 0, 0, 29790, 2625, 0, 32030, 23291, 0, 24477, 0, 0, 13961, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39088, 0, 0, 0, 40151, 0, 31522, 0, + 30997, 39932, 0, 0, 0, 28194, 0, 0, 15368, 16134, 15289, 0, 0, 2998, 1272, 20637, + 40329, 10094, 37180, 35481, 19254, 0, 0, 23509, 9728, 19442, 17658, 17888, 41059, 16742, 11097, 4169, + 23510, 16674, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3426, 0, 22936, 5989, 0, 0, 0, 0, 0, 16743, 0, 0, 0, 35586, 0, + 0, 0, 0, 5819, 0, 0, 6610, 8555, 10873, 0, 32640, 8293, 22336, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26677, 0, 0, 0, + 0, 30613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6572, 3001, 36226, 15773, 15664, + 0, 41191, 9189, 0, 0, 37930, 39789, 0, 0, 12618, 3272, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 33031, 0, 0, 0, 0, 41167, 186, 10201, 0, 0, + 22960, 0, 5580, 35244, 0, 0, 0, 21090, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13729, 713, 16416, 2340, 0, 1331, 0, 0, 0, 0, 38669, 23539, 0, 0, 0, + 0, 0, 21091, 0, 0, 18950, 0, 15877, 0, 20546, 0, 16755, 22202, 0, 0, 0, + 0, 0, 17250, 2482, 0, 5324, 16756, 0, 0, 7014, 0, 1072, 14964, 0, 0, 0, + 0, 0, 0, 0, 0, 33818, 21578, 0, 9918, 0, 0, 0, 0, 0, 32289, 0, + 13067, 20047, 21584, 0, 0, 0, 0, 0, 0, 0, 0, 2341, 27836, 38356, 36001, 0, + 0, 0, 3736, 0, 2344, 0, 0, 0, 0, 16771, 21865, 17330, 0, 0, 16989, 19129, + 0, 0, 0, 28869, 0, 0, 21602, 21603, 0, 12247, 0, 16777, 0, 21056, 0, 0, + 17930, 18151, 0, 0, 32241, 37460, 0, 38006, 24997, 17760, 0, 0, 0, 0, 0, 37223, + 11451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21103, 0, 34108, 0, 14472, 11998, + 0, 35786, 0, 0, 0, 0, 0, 0, 0, 0, 31626, 26053, 13496, 36592, 0, 0, + 0, 0, 0, 0, 0, 26822, 14018, 30391, 35151, 14242, 0, 0, 8936, 0, 0, 0, + 0, 11600, 0, 0, 0, 0, 0, 0, 0, 0, 7122, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10045, 0, 0, 0, 0, 0, 0, 7960, 0, 0, 0, + 7973, 40613, 12123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 669, + 0, 0, 23219, 26963, 0, 5882, 22269, 32242, 25851, 0, 0, 0, 0, 2889, 37667, 0, + 8876, 0, 31137, 0, 7557, 0, 0, 2760, 0, 21186, 14828, 0, 38849, 0, 23734, 0, + 0, 332, 0, 0, 0, 0, 30460, 39880, 0, 11452, 0, 2099, 40237, 1175, 2971, 39235, + 7923, 15580, 0, 41238, 33846, 0, 8153, 0, 0, 0, 35013, 0, 0, 1831, 0, 881, + 32830, 27032, 35403, 0, 10632, 4750, 0, 35699, 40379, 0, 0, 0, 0, 3579, 0, 0, + 0, 0, 0, 0, 22911, 0, 0, 0, 36125, 0, 0, 0, 0, 0, 0, 0, + 0, 37637, 0, 0, 0, 0, 14190, 0, 0, 19630, 23844, 0, 35730, 0, 0, 0, + 31193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 844, 11999, 4554, + 15545, 0, 0, 0, 0, 28452, 0, 10067, 23847, 0, 0, 0, 39466, 0, 0, 0, + 0, 0, 26002, 0, 0, 23659, 9818, 0, 0, 9695, 0, 0, 12876, 39900, 20241, 9597, + 27071, 20713, 6937, 463, 16185, 0, 0, 0, 40084, 0, 12312, 0, 0, 0, 0, 0, + 38181, 0, 0, 0, 38380, 35788, 0, 9026, 0, 0, 9527, 36322, 26188, 10394, 700, 20629, + 19855, 0, 0, 31359, 5051, 0, 0, 14219, 0, 0, 0, 0, 10088, 0, 0, 29569, + 15583, 16905, 39745, 11770, 38071, 0, 5886, 4642, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 39746, 0, 15726, 0, 32549, 11229, 17670, 4779, 24013, 13458, 0, 33512, 7149, 0, 30056, + 28672, 39764, 0, 0, 0, 0, 0, 0, 21128, 19670, 5702, 2476, 0, 0, 13469, 17444, + 0, 26124, 5205, 0, 0, 28214, 17445, 9848, 0, 0, 1598, 0, 4465, 5823, 18942, 21287, + 34541, 16350, 0, 0, 8363, 3930, 0, 0, 0, 1348, 41077, 11827, 0, 16289, 32221, 7678, + 10497, 0, 0, 0, 0, 0, 0, 0, 0, 35104, 38681, 0, 21171, 0, 19176, 0, + 37611, 0, 21206, 0, 0, 0, 0, 0, 0, 25281, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8692, 0, 13012, 22874, + 0, 0, 0, 1675, 0, 0, 13160, 0, 0, 1815, 0, 0, 0, 0, 0, 20108, + 11034, 0, 0, 0, 5881, 0, 36678, 34886, 1000, 0, 3148, 12102, 0, 34887, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9352, 34607, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3556, 0, 26141, 34460, 35631, 35632, 3070, 0, 0, 10049, 11450, + 0, 0, 0, 0, 27528, 28177, 25268, 28646, 39538, 0, 7311, 7779, 0, 0, 0, 0, + 28647, 0, 19995, 22491, 2100, 20871, 29249, 435, 35672, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 34468, 0, 29350, 0, 34919, 26662, 15342, 29586, 0, 33826, 0, 0, 0, 0, + 0, 0, 0, 36884, 0, 541, 0, 0, 0, 31953, 18882, 16103, 38121, 24598, 0, 0, + 4632, 41141, 18544, 0, 31954, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26597, + 0, 0, 23064, 0, 14035, 23895, 35756, 0, 21514, 6526, 0, 13658, 28188, 38700, 4594, 0, + 0, 1010, 9353, 26517, 0, 13951, 5663, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5097, 0, 20945, 0, 21758, 0, 12300, 34369, 0, 21776, 0, 6445, 30792, 22650, 0, + 0, 0, 10925, 0, 12832, 35191, 15049, 16334, 16186, 36079, 0, 0, 0, 29905, 0, 0, + 0, 0, 0, 0, 0, 21115, 0, 0, 0, 0, 41102, 0, 0, 0, 0, 19297, + 27640, 39722, 0, 0, 11616, 40519, 0, 11756, 0, 0, 0, 0, 0, 3910, 0, 3090, + 0, 0, 33389, 16337, 0, 4499, 26718, 20638, 35329, 34957, 31741, 41160, 1812, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37046, 0, 18751, 0, 0, 0, 0, 29915, 30719, + 0, 7620, 26678, 0, 0, 0, 0, 0, 0, 0, 0, 17671, 0, 0, 0, 0, + 0, 0, 27317, 5153, 14739, 37072, 33189, 34977, 27948, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11968, 0, 23697, 0, 0, 0, 0, 0, 19262, 0, 0, 15160, 0, 0, + 0, 18675, 0, 36702, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32407, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31235, 0, 36240, 31638, 0, 0, 38532, + 33080, 0, 0, 0, 24829, 0, 0, 0, 16991, 0, 0, 0, 0, 23724, 0, 0, + 0, 0, 0, 0, 18152, 19004, 0, 0, 0, 0, 2649, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 39330, 0, 34370, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 36252, 15918, 0, 0, 0, 24681, 0, 7916, 0, 37226, 0, 0, 0, 0, + 0, 23231, 0, 0, 0, 0, 23467, 12499, 37479, 0, 0, 0, 0, 0, 8610, 14756, + 0, 23248, 0, 8328, 0, 25017, 0, 0, 0, 0, 30793, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39747, 0, 0, 0, 13021, 0, 27755, 0, 0, + 35910, 23694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17073, 0, 0, 38119, + 35648, 0, 2179, 35649, 8633, 0, 5943, 0, 39378, 35702, 0, 38013, 5033, 0, 27993, 0, + 0, 0, 0, 0, 13730, 3228, 24830, 0, 10044, 32143, 0, 0, 0, 0, 0, 0, + 24919, 13611, 0, 0, 0, 14748, 0, 0, 0, 0, 5166, 0, 0, 13842, 0, 0, + 0, 0, 0, 0, 1748, 10893, 0, 0, 0, 14829, 0, 36952, 0, 0, 0, 0, + 0, 0, 0, 17021, 23938, 27523, 15634, 0, 39131, 0, 0, 0, 0, 7924, 26582, 0, + 0, 0, 4192, 0, 0, 29587, 0, 35703, 0, 34761, 0, 0, 30077, 39983, 12281, 0, + 0, 0, 0, 0, 34109, 0, 26665, 33732, 0, 0, 0, 0, 0, 18212, 37486, 10913, + 39332, 0, 0, 22323, 0, 0, 0, 14865, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 39696, 22651, 37644, 0, 12877, 0, 0, 0, 22145, 0, 0, 0, 40421, 0, + 32183, 0, 1025, 0, 4500, 0, 20639, 0, 0, 0, 9786, 0, 0, 0, 3354, 24014, + 0, 0, 0, 0, 0, 0, 1317, 0, 0, 23972, 0, 40021, 0, 0, 0, 0, + 0, 0, 7272, 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2000, 25497, + 0, 0, 0, 0, 0, 6084, 24983, 14366, 35002, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 31939, 0, 0, 38175, 0, 0, 0, 0, 0, 0, 5092, 0, 31266, + 30090, 0, 10852, 0, 0, 0, 0, 31523, 0, 0, 0, 0, 16269, 0, 7435, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10998, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32057, 0, 0, 26262, 0, 0, 0, 7490, 0, 0, + 4876, 0, 7961, 0, 3992, 0, 0, 0, 0, 0, 0, 0, 0, 6120, 16440, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31742, 0, 0, 0, 0, 0, 1546, + 37364, 28215, 31750, 0, 0, 0, 0, 23027, 0, 0, 0, 0, 0, 0, 13502, 0, + 35634, 0, 0, 30300, 12431, 0, 30307, 29945, 0, 0, 0, 264, 0, 29228, 3456, 0, + 0, 0, 25137, 0, 25780, 36118, 22426, 4423, 29581, 36199, 0, 0, 8676, 29352, 39243, 40070, + 0, 35404, 15730, 27782, 0, 0, 0, 5652, 0, 0, 0, 0, 32836, 0, 32591, 9486, + 30138, 7707, 31194, 0, 0, 33433, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36747, + 0, 18032, 34608, 0, 0, 6139, 23487, 28941, 9982, 0, 3470, 27788, 0, 0, 0, 0, + 0, 25004, 0, 0, 10068, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25532, + 23495, 15126, 37007, 2509, 3393, 37277, 0, 1808, 0, 4489, 40146, 0, 37290, 0, 0, 0, + 0, 14885, 18331, 25945, 37300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 27444, 0, 0, 0, 0, 0, 37648, 0, 0, 38749, 0, + 0, 27445, 0, 3954, 38755, 25872, 32095, 0, 4716, 19951, 5566, 0, 0, 0, 39748, 367, + 0, 0, 0, 0, 0, 0, 33392, 0, 22671, 0, 13534, 15798, 25795, 32378, 38509, 5820, + 0, 0, 0, 0, 0, 0, 0, 35490, 0, 0, 11799, 26323, 0, 0, 0, 0, + 0, 0, 0, 0, 3729, 35505, 33033, 39790, 29424, 0, 22838, 32216, 0, 0, 32110, 28070, + 0, 4688, 0, 0, 0, 0, 0, 27833, 0, 0, 0, 10516, 0, 32413, 0, 36807, + 0, 37426, 0, 0, 28585, 0, 14988, 21057, 0, 5725, 0, 35620, 1155, 0, 0, 0, + 0, 0, 0, 33457, 35636, 25608, 0, 8877, 0, 0, 35637, 0, 0, 0, 0, 39607, + 33106, 0, 12476, 0, 32022, 0, 0, 0, 38823, 21155, 32939, 0, 0, 0, 35651, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8090, 0, 26522, 0, 37534, + 7298, 0, 7838, 31316, 31422, 10702, 0, 0, 0, 12481, 2946, 0, 0, 0, 0, 20581, + 22276, 0, 0, 20743, 24578, 19621, 0, 4928, 0, 31942, 26583, 28982, 10625, 1179, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21267, 0, 24041, + 0, 0, 0, 0, 0, 0, 0, 25639, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13292, 2498, 20081, 0, 0, 35704, 0, 28293, + 0, 31329, 33730, 0, 0, 31670, 0, 35560, 0, 0, 0, 0, 0, 0, 0, 0, + 21069, 0, 0, 30780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15233, 0, + 0, 18480, 18883, 40469, 0, 0, 0, 0, 0, 0, 39642, 0, 33297, 0, 8828, 13939, + 32338, 12516, 4877, 0, 16552, 7644, 14613, 0, 0, 0, 0, 20313, 31955, 0, 0, 0, + 0, 27974, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39643, 0, 11071, 15601, 0, 28332, 21319, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28998, 40295, 0, 0, 0, 0, + 0, 4940, 0, 24610, 34252, 0, 32164, 0, 0, 21188, 0, 0, 0, 39562, 1651, 0, + 0, 0, 3741, 16332, 6140, 25117, 32535, 0, 32704, 30339, 25610, 30504, 21324, 0, 511, 34253, + 0, 0, 0, 0, 0, 27633, 36204, 0, 37257, 0, 0, 0, 0, 0, 16860, 12000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 692, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 31475, 0, 14261, 0, 0, 32982, 23664, 21884, 33280, 6695, 12448, 31269, 20745, + 34615, 23496, 20847, 3599, 10753, 0, 25977, 0, 21077, 0, 0, 3384, 3385, 15976, 0, 12833, + 29782, 0, 6349, 0, 0, 31969, 39959, 12006, 3723, 4946, 0, 0, 19646, 35075, 0, 0, + 0, 0, 0, 14713, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27074, 0, 0, 36146, + 0, 0, 0, 9157, 31350, 0, 0, 0, 9847, 29179, 0, 10577, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25255, 0, 35450, 0, 30014, 0, 0, 0, 24478, + 9911, 0, 23503, 0, 0, 12012, 29184, 22456, 0, 0, 8840, 0, 32994, 0, 20139, 8614, + 28408, 32502, 0, 27251, 0, 0, 8012, 0, 0, 0, 0, 0, 40383, 18332, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36770, 0, 0, 0, 0, 3388, 6531, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16906, 34860, 16907, 0, 0, 18660, 20775, 28201, 91, 0, 0, 15610, 0, 38965, + 92, 29011, 0, 18933, 29910, 1088, 0, 0, 0, 0, 0, 0, 0, 0, 11771, 11333, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16135, 0, 33136, 0, 0, + 0, 25978, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27384, 25069, 427, 29955, 0, + 0, 0, 8217, 1629, 0, 28863, 0, 32550, 0, 27658, 1952, 0, 19328, 5312, 0, 9650, + 10512, 31565, 5313, 35879, 0, 1090, 0, 9110, 4780, 26018, 0, 0, 0, 8719, 37345, 20861, + 0, 17195, 39766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38890, 0, 0, 0, 12169, 25657, 0, 0, 0, 3756, 0, 0, 0, 0, 0, 0, + 0, 0, 13708, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2960, 38973, 0, 0, + 0, 0, 28040, 36568, 0, 0, 23530, 40652, 0, 0, 15179, 0, 35230, 0, 23531, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33362, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35338, 3864, 0, 0, 0, 29888, 109, + 22777, 0, 0, 17819, 20204, 110, 0, 20567, 30833, 36521, 21288, 0, 0, 0, 1978, 0, + 18339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25715, 0, 0, 0, 0, 0, 0, 0, 18867, 2566, 0, 0, 4035, + 0, 25985, 16952, 0, 27811, 0, 17251, 0, 0, 0, 0, 31874, 0, 34335, 4839, 0, + 18267, 0, 0, 0, 0, 0, 0, 0, 19894, 0, 38725, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40486, 0, 0, 20307, 0, 17273, 0, 14573, 0, 0, 0, 33065, + 33066, 18465, 18401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29027, 40348, 0, 0, 0, 0, 0, 0, 0, 2729, 32290, 0, 0, 36449, + 22293, 0, 0, 0, 0, 0, 0, 0, 32913, 0, 13550, 0, 0, 0, 3708, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30018, 0, 0, + 0, 0, 0, 0, 0, 10713, 0, 0, 19416, 0, 13885, 0, 24760, 6250, 24572, 38007, + 0, 26730, 38008, 0, 0, 35549, 0, 0, 0, 0, 11200, 0, 0, 0, 0, 15185, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37703, 21314, 27627, 0, 31061, 0, 0, 0, 2247, 0, 12862, 0, 20326, 26448, 0, 25476, + 8393, 0, 0, 0, 0, 23941, 0, 27285, 40620, 0, 0, 0, 0, 0, 0, 26846, + 0, 29180, 0, 0, 0, 0, 38427, 38591, 0, 0, 0, 0, 0, 7662, 20333, 0, + 38313, 0, 0, 0, 39749, 23680, 10095, 8711, 0, 0, 0, 0, 0, 0, 2255, 0, + 9788, 13359, 0, 36561, 308, 0, 0, 0, 0, 0, 0, 38435, 0, 31842, 0, 0, + 0, 33513, 31283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14940, + 12181, 0, 3637, 0, 30378, 0, 20345, 38322, 0, 0, 0, 0, 13751, 26953, 0, 31639, + 0, 7025, 0, 0, 0, 11041, 11045, 0, 17080, 0, 0, 3972, 0, 0, 35300, 19606, + 33462, 39884, 0, 35676, 0, 0, 0, 0, 0, 0, 17647, 0, 0, 0, 0, 12860, + 12983, 14461, 0, 0, 40286, 0, 0, 0, 31261, 0, 0, 0, 0, 0, 0, 15442, + 15408, 17159, 1134, 8694, 0, 33484, 26109, 18062, 15369, 0, 0, 0, 0, 0, 1953, 1412, + 27460, 23351, 26354, 0, 0, 0, 12082, 0, 24078, 0, 0, 0, 0, 0, 35638, 14824, + 38783, 0, 33163, 0, 0, 0, 0, 30029, 9896, 32023, 0, 30064, 35371, 0, 0, 0, + 0, 0, 0, 4630, 0, 0, 0, 13219, 20975, 0, 0, 22400, 0, 13624, 33900, 10896, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36815, 21798, 35169, 0, 0, 36253, 0, 15562, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32578, 32433, 0, 0, 0, 0, 21067, 0, 38802, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13630, 0, 0, 21800, 26296, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12752, 0, 0, 0, 0, 40046, 25471, 0, 0, 18705, 25783, 21808, 0, 1890, + 38929, 0, 24293, 0, 4347, 41046, 0, 31062, 31259, 0, 0, 21488, 0, 0, 0, 32068, + 10633, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29556, 13893, 0, 0, 0, + 0, 13650, 10464, 29734, 38941, 22774, 13940, 21026, 0, 0, 0, 0, 6644, 0, 31455, 32960, + 0, 31798, 16553, 6486, 12517, 2501, 3763, 0, 8504, 0, 0, 0, 0, 0, 32476, 5355, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1479, 32592, 33121, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37158, 32165, 16861, 23808, 0, 0, 19754, 0, 23990, 34255, 0, 23573, 24517, 0, 693, + 39257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38309, 27463, 0, 0, 25976, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18717, 0, 0, 0, 32847, 0, 8110, 38557, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 38312, 0, 6497, 0, 5483, 37278, 0, + 18927, 0, 30401, 33927, 13434, 37682, 39698, 30690, 0, 8695, 14554, 0, 34498, 4883, 19647, 0, + 0, 0, 0, 0, 0, 0, 7996, 20, 0, 0, 33743, 0, 8511, 153, 0, 0, + 0, 0, 12315, 0, 0, 0, 0, 0, 22517, 39572, 0, 0, 21856, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22110, + 0, 35451, 0, 0, 13668, 0, 40732, 0, 12834, 30258, 0, 0, 12835, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2784, + 0, 28346, 28347, 12328, 27826, 0, 29050, 22458, 22934, 0, 0, 0, 0, 0, 20141, 0, + 0, 0, 0, 0, 35198, 0, 24334, 13963, 0, 0, 14807, 0, 0, 37498, 25631, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1693, 0, 0, 0, 30807, 38212, 24168, 27879, 18661, 0, 0, 0, 5990, 4060, 1275, 40205, + 19249, 7517, 22758, 36275, 33873, 0, 368, 40636, 41060, 0, 0, 1141, 0, 0, 0, 0, + 0, 16531, 0, 29188, 0, 0, 0, 0, 0, 29412, 12900, 0, 0, 0, 0, 29664, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6682, 6210, 0, + 0, 0, 1441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39768, 0, 7621, 0, 0, 0, 15285, 39769, 38526, 1295, 15799, 0, 641, 14812, 24730, 0, + 23183, 16679, 32877, 28773, 0, 0, 0, 0, 0, 0, 0, 0, 27882, 0, 936, 0, + 0, 0, 0, 0, 0, 0, 0, 34868, 13031, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 38213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40373, 0, 0, 7260, 0, 26514, 0, 24495, 0, 22992, 0, 29441, 26125, 37988, 0, 0, + 0, 21462, 9341, 4741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 24111, 0, 6002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 22775, 4405, 0, 711, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36293, 0, 0, + 0, 32280, 0, 0, 35596, 20303, 6489, 40107, 0, 15558, 0, 0, 0, 0, 0, 0, + 0, 0, 38768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 18268, 0, 39596, 2807, 6373, 37600, 0, 0, 28393, 13740, + 17252, 8962, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9801, 17690, 26689, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21472, 0, 4702, 30758, 0, 30059, 0, 0, 27952, 0, 18402, 0, 0, + 0, 0, 0, 32668, 34556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 24415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31640, 0, 37105, + 0, 39353, 33082, 2615, 7680, 0, 9806, 0, 14111, 16449, 32127, 0, 0, 18119, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16768, 0, + 0, 0, 15105, 32789, 0, 0, 0, 0, 0, 0, 0, 0, 37996, 0, 0, 0, + 0, 0, 0, 0, 9375, 24196, 19231, 35109, 18987, 28535, 0, 0, 0, 0, 0, 0, + 0, 19232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 466, 2858, + 0, 40694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29416, 0, 0, 0, 30293, + 18154, 0, 0, 0, 37461, 23446, 0, 23232, 0, 0, 0, 0, 12490, 1883, 0, 26834, + 8101, 0, 9507, 0, 0, 5767, 0, 10194, 0, 8329, 0, 23268, 0, 0, 0, 0, + 0, 0, 0, 3327, 11745, 0, 0, 31974, 26936, 39724, 23306, 0, 9914, 0, 0, 13462, + 17211, 0, 17724, 0, 24019, 0, 0, 0, 25806, 0, 23209, 26827, 0, 0, 13625, 0, + 0, 0, 0, 0, 0, 882, 1398, 402, 15022, 22429, 0, 0, 5137, 0, 0, 28787, + 15973, 15636, 0, 15592, 0, 0, 0, 0, 0, 26835, 26836, 12109, 795, 0, 0, 0, + 15405, 15816, 0, 0, 0, 0, 20430, 0, 0, 17648, 6905, 8684, 0, 0, 0, 30466, + 6688, 0, 0, 23593, 11161, 0, 10703, 0, 0, 22319, 0, 13510, 0, 0, 0, 0, + 24696, 40862, 40076, 15819, 0, 26092, 0, 12518, 30518, 23044, 33923, 0, 26419, 0, 0, 0, + 0, 0, 16475, 39563, 29539, 0, 0, 4984, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34773, 13952, 39564, 0, 0, 40621, 0, 37978, 2681, 0, 0, + 0, 0, 19648, 0, 0, 0, 15548, 40002, 10853, 22329, 0, 0, 0, 14334, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4318, 20439, 0, 0, 0, 0, 32758, 0, + 6417, 30604, 0, 2253, 37029, 6449, 15131, 22609, 0, 0, 3341, 0, 0, 0, 4288, 0, + 26458, 34511, 15764, 0, 37672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23307, 39280, 0, 15457, 23308, 39584, 18754, 0, 0, 0, + 0, 22462, 21890, 22206, 0, 0, 0, 0, 0, 0, 7472, 0, 0, 0, 0, 30926, + 0, 0, 19862, 0, 0, 0, 0, 0, 26283, 0, 0, 0, 33360, 0, 6792, 1609, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36696, 0, 19451, 0, 17725, 0, + 0, 32885, 19022, 24020, 5491, 0, 3359, 3360, 0, 0, 0, 0, 0, 4332, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2442, 0, 0, 0, 0, 0, 0, 0, + 16687, 38670, 17051, 17455, 25132, 0, 0, 0, 0, 0, 0, 0, 0, 3191, 0, 3364, + 9118, 0, 40989, 3834, 4130, 0, 0, 0, 0, 0, 0, 0, 16809, 27604, 18952, 0, + 0, 0, 0, 8082, 0, 17291, 0, 25904, 0, 0, 0, 25862, 0, 0, 0, 25817, + 0, 0, 0, 21592, 0, 0, 41118, 17064, 0, 0, 0, 27334, 0, 0, 8085, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1187, 0, 0, 0, 5380, 0, 0, + 0, 0, 26841, 0, 0, 0, 8464, 28751, 0, 0, 0, 0, 19452, 0, 0, 16916, + 0, 0, 1318, 0, 0, 0, 22079, 0, 36709, 0, 0, 0, 0, 14248, 0, 9737, + 17646, 0, 0, 31087, 23594, 6260, 0, 17789, 0, 13424, 0, 17790, 0, 0, 0, 0, + 0, 29360, 0, 0, 9747, 0, 22127, 24007, 0, 5573, 37922, 0, 0, 0, 0, 0, + 0, 0, 16650, 0, 0, 0, 27622, 33112, 0, 0, 0, 0, 33122, 32531, 19158, 0, + 0, 0, 0, 0, 1012, 29357, 0, 0, 0, 0, 0, 0, 32759, 0, 6234, 0, + 0, 0, 0, 5303, 29502, 40422, 0, 0, 0, 0, 0, 21923, 0, 31111, 0, 0, + 0, 0, 0, 0, 33143, 25661, 0, 0, 40663, 5320, 0, 0, 0, 4794, 0, 0, + 0, 40676, 0, 0, 0, 0, 0, 4547, 2761, 0, 0, 0, 0, 34820, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34479, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 34484, 0, 39195, 0, 0, 0, 0, 0, 0, 0, 21871, 34617, 0, + 0, 0, 0, 0, 0, 7404, 0, 0, 0, 34512, 37031, 0, 0, 29088, 8205, 976, + 0, 34521, 0, 11625, 0, 0, 0, 0, 0, 11569, 0, 0, 9658, 34663, 0, 10989, + 1563, 0, 0, 0, 0, 0, 0, 28258, 0, 0, 0, 0, 0, 0, 40856, 12483, + 6871, 12519, 15974, 0, 17627, 0, 0, 0, 12013, 0, 30621, 40565, 0, 0, 0, 29527, + 0, 0, 0, 38023, 36872, 0, 0, 0, 0, 25312, 0, 0, 0, 20263, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20872, 0, 0, 29729, 0, 5087, + 0, 14838, 0, 0, 33463, 5516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32525, 0, 0, 0, 0, 0, 0, 33349, 0, 0, 36822, 9291, 0, 0, 31442, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10462, 0, 0, 0, 0, 6070, 0, 0, + 18592, 0, 33549, 0, 40077, 32340, 11460, 2502, 26978, 8460, 21870, 213, 0, 0, 0, 32798, + 0, 0, 0, 0, 0, 0, 0, 10262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 24213, 8835, 26224, 7974, 0, 0, 0, 0, 0, 0, 0, 38310, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5182, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5770, 26606, 0, 41100, 0, 0, 0, 0, 0, 0, + 0, 0, 1619, 0, 0, 0, 4200, 39036, 5047, 0, 0, 31067, 24466, 0, 0, 0, + 17882, 0, 11876, 12136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2363, 0, 0, 0, 0, 20803, 0, 0, 5972, 30795, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1485, 29152, 0, 0, 0, 29791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8859, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3481, 4599, 29154, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12019, 23175, 25948, 25936, 33833, 270, 20967, 0, 34792, 27258, 26115, 0, 0, 0, + 0, 29547, 0, 0, 0, 0, 0, 0, 0, 34274, 11564, 0, 0, 0, 1697, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21968, 2372, + 0, 309, 0, 19671, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 19867, 0, 29241, 0, 0, 0, 0, 0, 0, 25937, 33693, 15240, + 0, 0, 0, 0, 0, 0, 0, 16520, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1632, 4569, 0, 0, 32199, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 29973, 0, 0, 0, 0, 37381, 5217, 36522, 0, 38844, 0, 23131, + 0, 0, 0, 0, 0, 0, 0, 0, 11815, 0, 0, 0, 0, 0, 117, 20569, + 0, 0, 14063, 16359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17836, 22738, 0, 2002, 24513, 0, 0, 1361, 0, 0, 0, 0, 0, 36586, + 0, 0, 0, 0, 0, 17292, 0, 0, 0, 0, 0, 0, 0, 21593, 0, 5444, + 0, 0, 0, 11299, 0, 0, 0, 37778, 0, 0, 4246, 0, 17368, 0, 38778, 18155, + 4280, 0, 0, 0, 0, 0, 0, 2409, 34037, 0, 0, 0, 14550, 11862, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29564, 0, + 0, 0, 0, 0, 0, 0, 21641, 14653, 0, 0, 0, 0, 0, 0, 0, 2598, + 0, 0, 0, 0, 0, 0, 38167, 0, 0, 0, 0, 37456, 0, 0, 0, 15482, + 0, 0, 0, 0, 0, 0, 15861, 7461, 0, 0, 0, 0, 0, 0, 0, 37907, + 23806, 0, 0, 0, 24942, 0, 0, 0, 22981, 0, 22267, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8860, 35826, 19208, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15789, 0, 33834, 21431, 0, 0, 0, 0, 0, 10966, 14508, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35253, 0, 0, 0, 0, 31642, 0, + 0, 37774, 28872, 22815, 6628, 874, 0, 0, 17712, 0, 0, 0, 0, 0, 0, 0, + 36615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34150, 0, + 0, 13406, 0, 0, 16102, 0, 39180, 27342, 0, 0, 26916, 0, 0, 0, 36733, 22029, + 32695, 12272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23145, 10339, 0, 0, 15563, 0, 0, 0, 0, 0, + 0, 0, 35176, 3576, 0, 0, 0, 0, 0, 0, 15313, 37704, 0, 0, 30221, 21388, + 0, 4375, 0, 35408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14371, 0, 0, 0, 0, 0, 0, 34727, 16851, 0, 4997, 3718, + 0, 0, 0, 0, 0, 35427, 0, 0, 0, 0, 10061, 0, 0, 0, 0, 35311, + 0, 3749, 11072, 40369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24453, 6767, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 29593, 32072, 0, 0, 0, 0, 0, 7976, + 0, 0, 5800, 31676, 32799, 39196, 24095, 29739, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10072, 15865, 28301, 0, 27185, 29376, 0, 0, 0, + 39080, 0, 0, 21190, 0, 23813, 36147, 0, 17609, 26154, 40870, 22518, 8547, 0, 0, 13957, + 36763, 0, 26310, 0, 20131, 21966, 0, 10854, 0, 0, 0, 36899, 0, 19946, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39573, 0, 0, 1136, 0, 0, 0, 26612, 23498, 32083, 22060, 15287, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27459, 22519, 0, 38017, 40246, + 0, 27872, 14220, 0, 0, 2688, 7250, 32711, 36214, 10759, 19657, 29792, 0, 12556, 0, 0, + 0, 35470, 0, 37302, 14192, 22217, 0, 32620, 0, 9030, 0, 0, 9000, 28281, 32267, 40405, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3805, 0, + 0, 0, 0, 0, 23999, 29089, 37848, 0, 0, 26230, 17802, 0, 39579, 0, 0, 0, + 22009, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14487, 16265, 0, 0, 0, 40844, 0, 24786, 9176, 14909, 39489, 271, 24336, + 22531, 41148, 0, 23768, 0, 4851, 0, 12339, 29097, 25563, 0, 9889, 34067, 0, 926, 39490, + 0, 6656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5273, 0, 0, 0, 0, + 25367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8404, 0, 0, 8535, 28473, 0, 30167, 34863, 15655, 39750, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12904, 21343, 26631, 707, 27447, 6240, 0, 23690, 10004, 23576, + 8434, 0, 0, 4269, 2559, 1299, 35334, 7880, 6876, 0, 16566, 10224, 16917, 0, 0, 0, + 0, 28992, 26632, 0, 36168, 0, 0, 12905, 0, 0, 0, 2560, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 21552, 4603, 0, 0, 35491, 0, 0, 0, 28817, + 0, 0, 14788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3628, 9031, 0, 0, 13709, 38974, 10953, 19513, 0, 0, 0, 41009, 27764, 0, 0, 7528, + 40771, 40772, 0, 13722, 27668, 0, 4235, 22220, 0, 0, 0, 35143, 5538, 0, 16684, 33522, + 25572, 0, 21999, 14791, 31854, 35231, 166, 0, 35914, 12922, 0, 0, 27804, 31074, 0, 26028, + 39592, 1095, 40433, 0, 0, 0, 13309, 10292, 0, 3638, 6660, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1964, 12372, 4056, 0, 19219, 0, 0, 25689, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10968, 0, 0, 0, 0, + 0, 5218, 0, 0, 10034, 25087, 26127, 38671, 38279, 4105, 23195, 6008, 0, 38513, 29721, 0, + 0, 4361, 25807, 0, 19115, 0, 0, 12383, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 19169, 24281, 0, 0, 0, 24502, 14794, 0, 0, 0, 112, 13041, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 29205, 30939, 0, 0, 24027, 0, 0, + 0, 22020, 11907, 0, 0, 118, 0, 27601, 17465, 6586, 0, 28510, 13919, 1349, 34548, 8621, + 22724, 37398, 26558, 0, 0, 12938, 0, 10990, 0, 0, 17831, 0, 1511, 28071, 13386, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40540, 0, 0, 0, 0, 9953, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6663, 0, 0, 0, 0, 0, 0, 0, 0, + 32935, 19905, 7898, 18829, 28761, 0, 0, 18278, 32119, 25930, 0, 0, 4609, 40467, 0, 3143, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17556, 0, 0, 0, 16966, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22413, 30154, 0, 0, 30172, 0, 17701, 32787, 4219, 11277, 21473, 23716, 17294, 0, 0, 22175, + 29400, 18279, 31237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 36499, 0, 38452, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37111, 0, 32296, 33820, 27461, 31649, 0, 0, 19745, 26074, 17562, 0, 14280, 16630, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32680, 41018, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18292, 0, 38904, 0, 39009, 0, + 16772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6490, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13082, 27462, 41259, 24198, 0, 16613, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37442, 36019, 21303, 0, 0, 2467, 0, + 0, 0, 0, 0, 0, 34701, 0, 25672, 0, 0, 0, 0, 0, 0, 34446, 6031, + 20219, 0, 0, 0, 0, 0, 0, 16722, 0, 30295, 0, 0, 0, 0, 0, 0, + 20863, 0, 0, 0, 0, 0, 34450, 0, 0, 0, 16782, 0, 0, 26136, 10891, 0, + 0, 31424, 31425, 0, 36816, 9929, 0, 9860, 0, 30180, 33601, 22430, 28615, 31429, 31430, 1682, + 24205, 31431, 36962, 31781, 0, 4443, 23840, 31914, 0, 0, 30211, 6906, 36823, 33293, 21217, 9970, + 1189, 26742, 0, 0, 38577, 5794, 37142, 0, 21949, 0, 9588, 30467, 23651, 35428, 0, 0, + 41048, 0, 23652, 6094, 15514, 0, 3987, 35312, 0, 0, 9935, 15794, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5804, 31813, 40734, 18050, 40871, 0, 37282, 11878, + 0, 27703, 15211, 0, 0, 0, 0, 0, 0, 0, 226, 0, 36837, 12330, 11926, 23575, + 10760, 10761, 0, 5806, 0, 0, 0, 0, 0, 32806, 0, 0, 0, 26539, 26158, 0, + 0, 0, 32869, 34961, 4986, 0, 33004, 3427, 36847, 10321, 26161, 0, 0, 0, 0, 28567, + 0, 40206, 0, 54, 0, 0, 0, 25072, 38261, 0, 16165, 18571, 4068, 0, 36851, 0, + 0, 0, 0, 0, 0, 0, 29192, 0, 26877, 0, 0, 0, 0, 0, 0, 0, + 0, 32773, 31863, 0, 0, 0, 0, 0, 12041, 3651, 35955, 0, 0, 0, 0, 27298, + 37760, 2730, 7021, 31643, 31650, 36501, 41088, 37969, 0, 0, 37972, 0, 0, 0, 0, 0, + 0, 0, 28438, 30392, 0, 0, 0, 33167, 0, 0, 30500, 8092, 0, 0, 0, 0, + 18651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12980, 0, + 0, 34355, 0, 1190, 15486, 9404, 0, 0, 40716, 0, 0, 0, 0, 0, 15975, 40048, + 39647, 0, 0, 29778, 0, 0, 0, 28454, 0, 3999, 3255, 3386, 40314, 0, 4985, 0, + 0, 0, 0, 0, 0, 0, 0, 1251, 0, 12814, 0, 0, 35827, 0, 0, 37730, + 8517, 0, 0, 0, 0, 0, 8407, 0, 0, 0, 0, 0, 24022, 0, 0, 0, + 3928, 3931, 1333, 0, 0, 0, 9669, 0, 0, 9200, 1792, 36298, 40542, 9206, 0, 17332, + 0, 0, 0, 0, 0, 6882, 5002, 0, 0, 0, 0, 0, 2243, 0, 0, 0, + 0, 0, 29162, 6427, 35654, 0, 0, 0, 5936, 0, 21695, 0, 33954, 21157, 9625, 15311, + 0, 0, 4109, 0, 0, 0, 38416, 36734, 0, 538, 26917, 5791, 21978, 24587, 0, 0, + 0, 33956, 0, 20594, 15344, 36824, 13417, 1891, 0, 0, 0, 0, 33424, 0, 0, 0, + 0, 0, 20084, 19193, 0, 33959, 0, 6769, 0, 7139, 26220, 0, 15991, 21142, 20234, 17127, + 19019, 0, 5954, 0, 23595, 16789, 0, 19640, 0, 10534, 3083, 39667, 0, 9150, 4828, 0, + 0, 0, 0, 31343, 28978, 0, 0, 31497, 34899, 30691, 0, 41055, 19295, 37165, 22404, 35794, + 24331, 37723, 15014, 13299, 33644, 1013, 0, 0, 0, 0, 19160, 40496, 0, 0, 0, 0, + 0, 0, 6450, 32544, 0, 0, 11762, 0, 0, 0, 9167, 15320, 0, 0, 33214, 11896, + 1404, 0, 0, 0, 15458, 15321, 0, 0, 4852, 0, 0, 0, 0, 0, 0, 18770, + 0, 41187, 38160, 13463, 9424, 0, 0, 0, 0, 34321, 7091, 0, 24388, 0, 0, 5492, + 27765, 28217, 17746, 0, 0, 0, 0, 26328, 0, 1335, 30834, 35248, 0, 38568, 0, 35146, + 5926, 119, 0, 0, 13315, 0, 0, 27953, 0, 11278, 37424, 0, 0, 25221, 0, 0, + 5757, 41119, 570, 0, 24237, 0, 0, 12699, 0, 22502, 0, 0, 29686, 0, 0, 0, + 3793, 0, 0, 0, 0, 9592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12147, 0, 0, 0, 0, 0, 0, 0, 33970, 0, 5808, 0, 0, 1494, 38030, 29620, + 0, 0, 0, 0, 0, 0, 26284, 0, 9235, 25078, 0, 0, 0, 0, 0, 0, + 9190, 0, 0, 0, 0, 0, 0, 0, 10969, 15746, 0, 0, 9068, 0, 28057, 0, + 3835, 0, 15534, 0, 6335, 0, 0, 0, 0, 35973, 0, 0, 5409, 23932, 0, 0, + 0, 0, 0, 18433, 0, 16998, 0, 17360, 24370, 0, 30570, 0, 20702, 0, 0, 0, + 0, 23458, 0, 13264, 32838, 0, 0, 0, 0, 5052, 0, 18514, 0, 0, 0, 0, + 0, 0, 9403, 0, 0, 0, 22244, 0, 0, 22503, 0, 14762, 0, 853, 14910, 14786, + 27098, 0, 0, 0, 0, 32933, 0, 0, 25684, 14177, 23007, 25850, 0, 0, 0, 0, + 12093, 0, 0, 0, 0, 0, 0, 0, 0, 7564, 884, 13793, 25760, 0, 22431, 0, + 0, 0, 0, 0, 5649, 19556, 502, 503, 29372, 18013, 26744, 39137, 22435, 31331, 0, 38305, + 797, 0, 0, 0, 0, 0, 0, 18880, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10192, 6256, 7943, 21218, 0, 0, 0, 8687, 0, 0, + 25548, 32254, 0, 0, 1200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19561, 0, + 0, 0, 25477, 24614, 0, 0, 0, 1908, 0, 10195, 21111, 34371, 0, 0, 0, 0, + 0, 0, 0, 22190, 28128, 0, 30161, 0, 24709, 16875, 5433, 0, 13669, 13670, 9700, 12878, + 1231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25899, 664, 4261, 0, 0, 0, 20961, 679, 0, 0, 25412, 12726, 27873, 0, 0, 0, + 5434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32086, 38592, + 19659, 0, 0, 40744, 0, 12574, 23310, 0, 0, 0, 0, 25618, 28310, 25483, 31366, 25419, + 25420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28475, 0, 27880, 0, 0, 0, + 0, 0, 0, 0, 16918, 0, 0, 4734, 40920, 19817, 31748, 0, 19535, 21553, 0, 28137, + 0, 22261, 0, 0, 1300, 5704, 0, 0, 24799, 24061, 0, 7586, 28043, 0, 0, 0, + 0, 0, 0, 33523, 0, 0, 0, 25490, 12185, 0, 0, 24811, 17820, 0, 0, 0, + 0, 0, 0, 0, 0, 25983, 0, 0, 16107, 0, 4795, 35254, 1817, 0, 13742, 0, + 24816, 24817, 0, 0, 0, 19895, 25160, 0, 1711, 3009, 0, 0, 6378, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25206, 32129, 0, 0, 28969, 24837, 21594, 0, 0, 27278, + 18689, 0, 16109, 0, 0, 0, 0, 0, 20379, 20431, 0, 0, 0, 5183, 0, 0, + 36276, 0, 0, 32776, 0, 0, 0, 12484, 0, 0, 0, 0, 36057, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7580, 39962, 0, 0, 0, 9184, 0, 0, 0, 0, + 0, 2530, 0, 18206, 0, 0, 2070, 0, 0, 0, 21975, 27707, 5340, 39128, 0, 0, + 26203, 0, 4063, 0, 14292, 0, 0, 0, 0, 0, 15419, 3452, 0, 0, 0, 0, + 0, 11054, 17089, 26083, 0, 0, 22028, 30577, 31251, 0, 0, 0, 36394, 0, 0, 0, + 0, 26084, 5512, 0, 0, 5084, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29725, 10341, 22951, 0, 39547, 21696, 21311, 0, 0, 0, 0, 0, 25468, 9333, 0, + 39455, 0, 0, 12273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7318, 0, 0, 13632, + 9884, 0, 0, 0, 38695, 0, 31794, 0, 0, 40713, 0, 0, 31671, 22742, 0, 0, + 960, 0, 12985, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13102, 0, 0, 37975, 0, 0, 0, 0, 0, 0, 0, 982, 19631, + 0, 0, 38203, 40476, 0, 15839, 0, 0, 1103, 0, 22033, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19632, 28744, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30013, 19157, + 0, 0, 28621, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 181, 0, 0, 0, 0, 0, 9986, 40198, 0, 6772, 6773, 8462, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24518, 0, 30473, 0, 20610, 39033, 30955, 40477, 0, 13567, + 22215, 0, 0, 0, 0, 0, 0, 0, 27988, 0, 0, 0, 0, 14624, 0, 0, + 23158, 2298, 0, 29861, 26102, 0, 30091, 0, 0, 11210, 0, 35761, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20388, 39898, 0, 0, 0, 27583, 0, 0, 0, 35762, 30474, 289, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27964, 0, 0, 0, 0, 0, 0, 0, 9600, 30144, + 11689, 0, 0, 33646, 38070, 0, 40841, 1487, 0, 4947, 36069, 25006, 0, 0, 11271, 20848, + 37981, 0, 29075, 0, 0, 0, 0, 0, 35452, 28629, 26508, 27585, 0, 33267, 0, 0, + 36839, 0, 0, 7611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15449, 0, 0, 0, 7998, 0, 0, 0, 0, + 0, 0, 20441, 0, 0, 0, 0, 0, 0, 0, 22604, 0, 12321, 24101, 39934, 8468, + 37500, 3483, 0, 0, 0, 23853, 0, 41249, 0, 32862, 19573, 0, 10935, 0, 22610, 34122, + 0, 31977, 29090, 0, 0, 20903, 4054, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11468, 33971, 28979, 0, + 24102, 0, 0, 13352, 0, 0, 0, 0, 0, 0, 0, 0, 5272, 547, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5307, 15612, 0, + 14425, 26117, 14052, 0, 0, 20534, 21761, 0, 27591, 0, 27388, 40464, 8033, 0, 0, 38127, + 32870, 16532, 29570, 0, 0, 0, 0, 0, 0, 38967, 0, 0, 2303, 0, 37734, 0, + 0, 40091, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28634, 0, 0, 0, 34394, 18756, + 34523, 0, 0, 0, 0, 0, 38256, 27446, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9755, 40208, 0, 25566, 25567, 0, 0, 15219, 12593, 8557, 0, + 0, 0, 33021, 0, 0, 21969, 12906, 0, 0, 0, 39497, 38436, 0, 10708, 0, 15800, + 0, 1954, 0, 0, 26020, 230, 13148, 0, 29014, 0, 0, 27802, 0, 19974, 36170, 28635, + 9756, 0, 0, 25635, 30813, 0, 0, 27759, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23521, 0, 38789, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6176, 8055, 26683, 28045, 35920, 17548, 0, 10423, 0, 39114, 0, + 38271, 0, 4742, 4743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7801, 17049, 15617, + 0, 0, 0, 32771, 36855, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10229, 0, 0, 0, 0, 0, 10115, 15494, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37366, 0, 0, + 0, 0, 0, 11377, 28319, 0, 16206, 0, 6302, 13167, 22928, 1450, 0, 0, 0, 0, + 33978, 0, 1508, 0, 0, 0, 0, 30835, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5227, 13743, 560, 0, 21410, 32403, 26043, 0, 0, 11186, 4050, 0, 0, 21971, 17832, + 5586, 2215, 0, 38447, 0, 18868, 0, 0, 0, 12042, 0, 0, 17255, 36491, 0, 30749, + 1350, 9803, 0, 22631, 0, 0, 1565, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34549, 0, 0, 0, 40439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10698, 0, 0, 0, 17980, 7015, 0, 36236, 16448, 0, 35100, 0, 0, 33892, + 17277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16450, 18120, 31644, 10607, 0, 13493, 40681, 0, + 0, 0, 39515, 0, 0, 2012, 29003, 204, 0, 0, 34089, 16765, 38134, 11710, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31891, 10700, + 0, 7356, 13074, 4580, 37997, 0, 2160, 0, 36711, 0, 0, 6596, 22055, 0, 0, 0, + 0, 0, 0, 0, 0, 28527, 0, 22114, 0, 0, 0, 7223, 31651, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 35110, 19131, 0, 0, 1425, 0, 14010, 17333, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34693, 6312, 0, 0, 19467, 0, + 8933, 25226, 2313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19826, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9214, 27471, 0, 0, 0, 0, 0, 34448, 1390, 0, 0, 0, 0, 0, 0, + 1589, 3377, 15987, 0, 11972, 0, 0, 0, 0, 0, 0, 0, 0, 3571, 0, 31080, + 0, 4596, 39613, 0, 0, 0, 0, 0, 0, 27524, 0, 0, 9297, 23040, 33603, 27624, + 0, 31255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7840, 0, + 27023, 0, 0, 11721, 11454, 21979, 0, 0, 0, 0, 0, 0, 40239, 0, 35409, 0, + 0, 0, 0, 17108, 26266, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20380, 0, 8638, 0, + 10840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7049, + 7175, 0, 0, 33621, 35429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36507, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3468, 0, 0, 0, 0, 35430, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5557, 11688, 10374, 0, 38461, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37842, 32078, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32166, 16617, 26474, 27060, + 40617, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1620, 14304, 31049, 13436, 7999, 0, 32443, 15173, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21119, 0, 12014, 12331, 16191, 0, 0, 0, 0, 7817, 26278, 17742, 20336, 3091, + 0, 0, 20527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18508, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6779, 0, 0, 21120, 0, 12148, 0, 0, + 40324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 28009, 6780, 0, 0, 0, 14228, 0, 0, 38031, 11694, 36479, 10941, 17964, 31020, + 10100, 0, 0, 0, 20995, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31832, 0, 8470, 0, 0, 0, 0, 10474, 12164, + 32504, 26118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29958, 0, 38838, 27394, 0, 36852, 12908, 0, 0, 0, 0, 0, 38214, 0, 0, 0, + 0, 0, 0, 0, 38764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25750, 0, 0, + 0, 0, 0, 0, 34322, 0, 0, 0, 0, 0, 0, 4781, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12357, 26381, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6996, 16570, 28732, 0, 40340, 0, 0, 0, 0, 0, 17947, 0, 38345, + 0, 14741, 10881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 26684, 12029, 0, 0, 0, 16016, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4027, 40104, 0, 0, 0, 280, 0, 40665, 0, 0, 0, 0, 33234, 0, 20346, + 10886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28685, 0, 0, 0, 0, 1337, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6082, 0, 0, 0, 0, 0, 15180, 0, 1566, 0, 0, 0, 0, + 12043, 17833, 4700, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32404, 25259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37761, 0, 34015, 0, 17728, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 26133, 0, 0, 27134, 0, 0, 0, 33070, 0, 0, 0, 0, 0, + 0, 0, 0, 32677, 0, 0, 0, 35147, 16424, 35991, 0, 0, 0, 0, 0, 17517, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2013, 2359, 0, 0, 0, 0, 0, 0, 0, 35105, 0, 0, + 0, 0, 0, 0, 0, 0, 17563, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28536, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12662, 0, 0, 31657, 39864, 0, 0, 0, 0, 31659, 0, 0, 37785, 0, 0, + 0, 0, 0, 0, 32310, 0, 40700, 0, 0, 0, 0, 0, 0, 0, 0, 38780, + 0, 0, 0, 0, 0, 41091, 0, 20839, 0, 0, 0, 0, 0, 0, 5378, 17771, + 20841, 0, 0, 0, 0, 0, 0, 0, 0, 22186, 0, 14603, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19161, 0, 0, 27428, 26410, 0, 0, 19162, 0, 7581, + 0, 0, 0, 812, 0, 0, 0, 0, 17196, 0, 0, 33361, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5252, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3398, 0, 0, 0, 38794, 0, 0, 27933, 0, 0, 26655, 0, 0, 0, 0, 0, + 0, 0, 8761, 0, 0, 0, 0, 0, 36936, 0, 11626, 3103, 0, 13506, 40290, 27225, + 0, 0, 32706, 0, 0, 0, 21642, 0, 0, 0, 0, 0, 0, 13218, 0, 13220, + 0, 0, 0, 0, 0, 0, 0, 5895, 0, 0, 0, 0, 0, 23942, 24615, 0, + 7712, 0, 0, 0, 0, 0, 38707, 15357, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5991, 38262, 0, 0, 9468, 26030, 7669, 0, 0, 13278, 0, 34412, 39812, 0, + 0, 0, 17297, 0, 0, 0, 18158, 0, 0, 0, 35378, 0, 24863, 22057, 8989, 0, + 12801, 10349, 0, 22406, 0, 14604, 0, 3075, 0, 0, 17785, 27049, 22973, 32532, 0, 22599, + 19159, 4634, 0, 37160, 0, 0, 0, 15572, 32984, 0, 0, 0, 0, 30351, 34503, 22252, + 0, 0, 0, 3331, 0, 0, 0, 0, 29091, 3092, 1255, 17540, 12815, 0, 29505, 0, + 0, 0, 29051, 0, 0, 0, 0, 0, 5998, 0, 27395, 16919, 18864, 31930, 0, 4722, + 0, 0, 0, 1865, 29917, 23080, 0, 17969, 7670, 0, 1979, 2843, 0, 0, 5253, 28588, + 5406, 0, 0, 17298, 0, 34185, 34188, 38579, 0, 0, 35441, 0, 23165, 0, 0, 0, + 0, 0, 0, 0, 11042, 0, 29461, 0, 15590, 0, 0, 4249, 36736, 7656, 0, 21849, + 29336, 13935, 22494, 3154, 22596, 0, 13794, 9572, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 40473, 0, 0, 10898, 3858, 27344, 28890, 22499, 25472, 25473, 0, 10791, 22317, 0, + 0, 0, 0, 0, 0, 543, 0, 31949, 0, 0, 0, 24294, 21273, 0, 28891, 24885, + 0, 0, 32839, 0, 38868, 11143, 33124, 0, 27159, 0, 0, 29779, 0, 17576, 1214, 3885, + 0, 33208, 0, 33126, 7860, 0, 0, 0, 0, 13807, 0, 0, 0, 8111, 0, 0, + 28989, 26534, 0, 0, 2979, 4188, 0, 0, 0, 0, 0, 0, 25149, 10795, 1014, 0, + 2200, 0, 0, 0, 0, 20746, 0, 0, 0, 33487, 5973, 0, 0, 2785, 37038, 39963, + 0, 0, 0, 16883, 27162, 0, 0, 0, 0, 0, 6354, 0, 19550, 11498, 0, 28950, + 0, 6451, 29092, 26756, 19719, 0, 0, 0, 39092, 24264, 22615, 28811, 2332, 34962, 0, 33443, + 667, 9177, 0, 0, 0, 2133, 0, 0, 0, 0, 0, 0, 9059, 1943, 0, 0, + 0, 30984, 0, 0, 12578, 0, 0, 0, 0, 0, 16166, 0, 0, 4723, 20452, 4628, + 21927, 36563, 0, 0, 0, 0, 19583, 15460, 19471, 6080, 11287, 6742, 13242, 28033, 0, 0, + 0, 0, 2478, 28495, 0, 11516, 14943, 34080, 0, 0, 33363, 0, 20164, 25131, 16571, 0, + 0, 39813, 30740, 0, 0, 0, 0, 26039, 0, 0, 0, 38133, 0, 0, 0, 0, + 0, 203, 30854, 0, 11279, 0, 0, 38735, 0, 36374, 8670, 11849, 0, 24986, 0, 0, + 0, 0, 0, 17854, 14541, 495, 16723, 0, 19414, 18159, 0, 0, 17077, 12426, 0, 0, + 0, 11659, 33164, 27008, 38919, 0, 0, 1828, 0, 0, 0, 2493, 0, 0, 0, 2495, + 14022, 398, 877, 0, 0, 34590, 0, 11055, 0, 36957, 0, 1167, 4089, 0, 12433, 0, + 0, 0, 20790, 0, 19554, 39882, 0, 35171, 6224, 35154, 0, 0, 0, 25374, 36051, 0, + 10255, 0, 20873, 29448, 8155, 20758, 38024, 0, 10900, 0, 3118, 30074, 0, 0, 3977, 7932, + 0, 0, 0, 0, 0, 0, 0, 794, 0, 0, 0, 0, 5615, 2190, 18697, 22952, + 4931, 35181, 0, 35561, 0, 0, 0, 32475, 1079, 40134, 0, 35411, 0, 18921, 0, 15818, + 0, 0, 39634, 0, 0, 0, 0, 30212, 5518, 27352, 17772, 38177, 39635, 21071, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2617, 0, 0, 32595, 38145, 0, 0, 37242, 6275, + 2591, 32840, 34769, 0, 32257, 761, 0, 0, 0, 0, 0, 0, 0, 0, 38518, 0, + 24602, 0, 10906, 38041, 14859, 0, 9933, 0, 0, 0, 0, 0, 0, 0, 0, 215, + 38204, 0, 0, 26150, 0, 32345, 3535, 34485, 0, 221, 0, 0, 0, 38953, 14870, 0, + 0, 17141, 0, 16656, 0, 0, 2198, 0, 18721, 0, 12710, 0, 0, 32028, 32760, 34310, + 33488, 0, 6648, 36411, 11612, 29076, 21760, 31732, 0, 0, 29785, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30251, 3123, 0, 0, 0, 10581, 0, 29077, 33744, + 37982, 0, 0, 0, 0, 0, 0, 8696, 0, 0, 0, 18502, 2622, 22064, 12332, 0, + 28463, 0, 0, 31527, 0, 0, 32621, 0, 25947, 12728, 28010, 11469, 0, 4830, 0, 28464, + 27434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8013, 17179, 0, 26541, 0, 28803, + 0, 0, 0, 0, 0, 0, 5736, 0, 0, 0, 1277, 0, 9060, 4643, 0, 23684, + 0, 0, 16675, 28021, 0, 0, 40978, 10197, 0, 0, 0, 0, 0, 0, 0, 3618, + 2368, 0, 0, 31106, 32633, 17808, 34319, 0, 0, 0, 0, 0, 0, 1278, 0, 11425, + 0, 31548, 3428, 33515, 21086, 34400, 0, 33022, 38437, 0, 28207, 0, 31845, 1027, 25154, 27596, + 584, 9653, 15134, 3136, 0, 0, 33684, 0, 0, 0, 0, 0, 0, 0, 6979, 17197, + 31567, 11430, 28034, 0, 2939, 0, 0, 0, 0, 0, 18772, 34401, 0, 0, 5251, 5155, + 34741, 0, 38555, 14664, 0, 6703, 25951, 16277, 28046, 0, 0, 0, 0, 0, 0, 38272, + 0, 0, 0, 1320, 0, 0, 36294, 0, 10202, 0, 17821, 0, 0, 10235, 34798, 0, + 0, 0, 0, 0, 27602, 120, 24506, 0, 0, 16758, 32905, 0, 27129, 0, 0, 0, + 0, 0, 0, 18678, 0, 25097, 17472, 0, 0, 0, 0, 0, 32781, 0, 36368, 0, + 0, 32915, 0, 0, 0, 0, 0, 0, 18127, 36715, 0, 0, 0, 0, 5280, 16432, + 32687, 0, 0, 0, 0, 0, 0, 0, 35861, 0, 0, 0, 31142, 0, 35655, 30034, + 2071, 0, 33168, 0, 0, 27618, 13845, 0, 399, 7192, 0, 20586, 25737, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4981, 12492, 0, 0, 0, 0, + 27972, 24451, 408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 29254, 36741, 0, 30080, 0, 30262, 36887, 0, 6132, 0, + 0, 31724, 15564, 0, 0, 0, 24454, 6524, 6770, 0, 35739, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 31460, 24210, 27977, 0, 0, 18217, 0, 30316, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3053, 40141, 0, + 19641, 0, 0, 0, 0, 0, 0, 24943, 0, 0, 0, 0, 0, 36934, 0, 35798, + 20008, 0, 0, 16262, 39703, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21235, 0, 577, 0, 0, 0, 6146, 0, 0, 0, 39704, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 35830, 0, 0, 18063, 37040, 4495, 5685, 39726, 0, 0, 0, + 25652, 0, 0, 13133, 0, 0, 0, 0, 0, 30406, 0, 13974, 0, 22148, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18757, 24787, 0, + 31744, 4954, 0, 0, 0, 0, 11105, 19166, 0, 16660, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8956, 0, 0, 0, 0, 18195, 0, 0, 0, 0, + 0, 0, 16572, 0, 40434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38185, 10293, 32554, 0, 0, 10296, 17233, 0, + 0, 5828, 8736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11348, 0, 0, + 0, 0, 0, 0, 7003, 0, 31999, 0, 0, 0, 0, 12940, 23354, 32004, 36861, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 39298, 0, 0, 0, 0, 0, 0, 0, 0, 40441, 0, 0, 0, 2845, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33085, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 21099, 0, 0, 0, 0, 0, 0, 0, 12663, 29291, 0, + 0, 0, 0, 34585, 0, 0, 0, 10246, 33156, 18160, 0, 571, 1033, 0, 0, 0, + 0, 8991, 18020, 0, 0, 16122, 23599, 13519, 0, 7050, 34941, 6327, 0, 0, 0, 0, + 0, 11977, 6418, 22239, 0, 0, 0, 0, 0, 0, 0, 0, 37580, 0, 0, 18524, + 33276, 0, 0, 17437, 34972, 31568, 34978, 0, 31616, 0, 0, 18629, 0, 34688, 0, 0, + 24988, 0, 0, 0, 0, 25216, 30224, 41042, 7319, 35683, 6430, 28179, 0, 22436, 0, 9972, + 0, 33612, 0, 8947, 0, 5655, 0, 20883, 0, 0, 0, 0, 0, 0, 6774, 30189, + 0, 0, 21516, 0, 0, 0, 0, 0, 5901, 11463, 0, 0, 29078, 7338, 0, 0, + 0, 31205, 255, 0, 22868, 0, 0, 0, 0, 9994, 0, 8516, 16884, 0, 6606, 8199, + 20904, 0, 2449, 0, 0, 0, 0, 13588, 0, 24424, 0, 36328, 32489, 0, 0, 0, + 0, 10942, 0, 0, 28022, 0, 0, 0, 0, 0, 0, 8658, 6980, 33685, 0, 0, + 0, 0, 0, 0, 0, 0, 31590, 0, 0, 0, 15270, 9797, 13595, 4102, 16689, 10555, + 41210, 0, 0, 0, 0, 22771, 0, 0, 5466, 31617, 16692, 0, 26339, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18630, 0, 6597, 15106, 0, 0, 2852, 0, 32918, + 30209, 39010, 0, 40399, 0, 0, 0, 18352, 16725, 0, 0, 0, 5019, 8380, 0, 0, + 0, 0, 0, 0, 27040, 0, 0, 34514, 0, 0, 0, 0, 8410, 0, 0, 0, + 34432, 0, 0, 0, 0, 0, 28118, 0, 0, 0, 39891, 0, 27041, 0, 0, 0, + 0, 26798, 0, 0, 0, 2775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11524, 36295, 0, 0, 19959, 0, 0, 0, 0, + 0, 0, 25209, 0, 0, 32471, 0, 0, 906, 0, 0, 0, 4100, 0, 0, 0, + 0, 23099, 0, 0, 0, 0, 0, 0, 0, 15337, 16156, 0, 0, 25000, 0, 10185, + 3577, 19484, 0, 0, 0, 0, 38488, 0, 0, 0, 7657, 0, 3034, 0, 0, 0, + 0, 0, 0, 14092, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17773, 0, 20878, 20879, 29589, 0, 0, 0, 25139, 41099, 22442, 36829, 0, + 27231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17786, 27160, 29887, 0, 8577, + 26449, 30082, 0, 20985, 0, 0, 0, 30141, 8897, 5902, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 19944, 660, 0, 32850, 27738, 29540, 9633, 0, 0, 8000, 9636, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9637, 0, 0, 0, 0, 0, 0, + 0, 40250, 0, 16266, 0, 19083, 29312, 25187, 0, 0, 6148, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14777, 34390, 0, 0, 25632, 5149, 0, 0, + 19663, 0, 0, 0, 0, 0, 18976, 0, 33686, 0, 31569, 0, 0, 0, 0, 0, + 0, 0, 19258, 23185, 0, 2596, 0, 0, 26383, 10116, 22887, 0, 0, 0, 12188, 0, + 0, 0, 0, 17235, 0, 37382, 594, 0, 29001, 0, 0, 0, 0, 3828, 0, 0, + 3829, 0, 0, 0, 23202, 31618, 948, 0, 0, 0, 35264, 0, 0, 9480, 0, 40349, + 0, 0, 0, 16702, 16703, 2527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6034, 0, 0, + 0, 0, 0, 34210, 0, 0, 0, 0, 21502, 27247, 0, 39705, 0, 0, 0, 39794, + 0, 0, 39795, 22587, 0, 14247, 14249, 35656, 36873, 0, 14250, 0, 0, 0, 0, 11385, + 0, 6431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28934, 24143, 24238, 33170, 2654, + 12503, 0, 24325, 0, 0, 0, 0, 0, 0, 0, 6435, 39381, 0, 0, 21948, 0, + 31332, 0, 30915, 0, 0, 0, 0, 0, 1203, 0, 0, 842, 0, 20766, 13946, 28937, + 17649, 0, 0, 0, 0, 2361, 38420, 0, 0, 0, 0, 0, 3527, 34160, 15922, 36258, + 0, 0, 0, 0, 0, 0, 0, 0, 18372, 23600, 0, 10150, 26408, 9906, 2505, 0, + 13425, 16599, 0, 0, 0, 0, 0, 0, 31485, 0, 0, 1913, 0, 0, 0, 0, + 0, 0, 0, 39565, 0, 30021, 8001, 0, 10855, 0, 21529, 35799, 40480, 0, 0, 0, + 2547, 0, 0, 0, 28097, 0, 0, 37915, 0, 0, 0, 0, 0, 0, 6447, 0, + 31502, 4123, 33268, 13437, 26613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30437, 849, 7453, 13134, 24960, 35832, 6149, 33659, 20905, 12333, 0, 0, 39155, 23293, 6533, 36153, + 0, 14338, 22527, 33183, 19071, 2202, 18192, 1622, 5390, 5435, 0, 0, 0, 0, 0, 16236, + 0, 31528, 14635, 0, 32712, 0, 14048, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30265, 0, 21125, 32449, 25073, 24170, 29749, + 33573, 11774, 0, 0, 0, 20406, 30713, 0, 36779, 29911, 5056, 0, 0, 0, 15414, 20913, + 0, 8206, 37323, 39586, 0, 9943, 23, 8207, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 34737, 0, 0, 26943, 0, 2694, 0, 0, 0, 3630, 37924, 27437, 0, 28035, 25923, + 0, 6981, 39319, 39, 28358, 2137, 0, 25129, 35887, 34533, 0, 20915, 31285, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17198, 17199, 0, 31572, 14926, 26869, 0, 34222, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3186, 36422, 1321, 3104, 0, + 0, 38398, 30152, 11107, 29017, 36518, 1148, 21647, 17549, 33190, 37192, 0, 0, 0, 0, 0, + 0, 0, 943, 0, 20540, 6538, 0, 5365, 23334, 0, 0, 0, 0, 0, 0, 0, + 27438, 0, 0, 32655, 39941, 40537, 0, 1509, 0, 30741, 31606, 0, 5463, 0, 32811, 22051, + 21565, 0, 0, 1661, 26557, 7532, 20454, 23540, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26334, 28366, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12384, 0, 0, 5160, 14798, 18818, 0, 379, 0, + 0, 0, 35957, 27325, 28238, 30841, 30326, 3962, 0, 0, 0, 0, 31124, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1362, 0, 36237, 11969, 0, 0, 15182, 21656, 0, 0, + 0, 0, 126, 0, 17280, 0, 38529, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18840, 0, 0, 0, 0, 1514, 22085, 0, 0, 0, 0, 0, 0, 0, 9678, + 27957, 19920, 32297, 18487, 0, 23553, 0, 0, 0, 0, 0, 2853, 36014, 10183, 0, 17520, + 9441, 0, 30768, 0, 0, 0, 0, 14992, 16718, 18995, 17363, 0, 22559, 0, 0, 0, + 0, 0, 11380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9516, 0, + 0, 0, 0, 14490, 0, 0, 5457, 0, 0, 0, 7529, 0, 0, 0, 0, 0, + 0, 39367, 0, 19773, 0, 11386, 0, 0, 0, 21981, 1122, 0, 22912, 0, 0, 0, + 0, 0, 0, 7073, 0, 11390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2950, 0, 19198, 7828, 0, 0, 0, 0, 0, 0, 0, 0, 3801, + 0, 41056, 20991, 32727, 0, 0, 0, 0, 0, 548, 18739, 0, 19209, 0, 0, 21427, + 38248, 0, 0, 0, 40325, 10938, 0, 0, 11628, 28862, 3813, 0, 0, 0, 0, 0, + 0, 11504, 6236, 0, 0, 0, 0, 0, 0, 0, 0, 20317, 0, 1965, 0, 0, + 5714, 0, 5480, 23051, 0, 27808, 3830, 0, 0, 0, 0, 35102, 19960, 18404, 0, 0, + 0, 0, 17473, 0, 0, 1667, 0, 0, 0, 0, 18913, 0, 0, 0, 0, 26064, + 41260, 0, 0, 0, 4821, 18162, 39309, 22569, 737, 0, 0, 25042, 0, 0, 22437, 21025, + 22438, 2033, 888, 7156, 0, 20435, 20601, 30226, 38832, 39649, 4614, 0, 0, 0, 0, 34051, + 12304, 9634, 0, 3317, 0, 0, 0, 10083, 32761, 25056, 0, 4319, 0, 8114, 0, 0, + 0, 0, 0, 24303, 18740, 25064, 5775, 23672, 0, 0, 0, 0, 2935, 28465, 855, 0, + 0, 6454, 1043, 10812, 0, 0, 0, 0, 38466, 38467, 0, 0, 0, 0, 25079, 19259, + 10006, 0, 0, 18243, 18792, 0, 40774, 0, 22584, 40105, 0, 38162, 0, 21712, 0, 0, + 11819, 0, 0, 33936, 0, 16208, 0, 0, 0, 0, 0, 21763, 34557, 25196, 21137, 0, + 16218, 9481, 6385, 0, 0, 18632, 0, 0, 0, 13086, 33094, 23559, 0, 0, 32570, 0, + 0, 9816, 13634, 19547, 0, 0, 31916, 15899, 0, 0, 0, 0, 0, 0, 36667, 0, + 9886, 20121, 35070, 0, 0, 30886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17145, + 14764, 31154, 24045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5909, 4001, + 0, 0, 28302, 0, 0, 3682, 0, 0, 24912, 26543, 0, 0, 0, 0, 0, 0, + 0, 0, 19948, 14644, 0, 0, 0, 0, 0, 0, 0, 29811, 0, 0, 0, 0, + 0, 0, 21728, 20541, 0, 0, 0, 0, 0, 7671, 0, 0, 0, 0, 0, 0, + 0, 0, 312, 9759, 10970, 2268, 6617, 9892, 13479, 0, 0, 0, 0, 0, 0, 0, + 9117, 0, 0, 0, 0, 13872, 0, 0, 34802, 0, 0, 0, 0, 0, 0, 0, + 2600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11652, 0, 0, 0, + 0, 0, 0, 0, 24838, 15394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24371, + 36029, 0, 0, 15165, 13404, 0, 0, 3761, 2072, 8791, 13331, 39368, 0, 0, 30976, 0, + 1681, 0, 0, 0, 33348, 7320, 0, 0, 35387, 4120, 35063, 0, 0, 34726, 6432, 34469, + 0, 19845, 0, 0, 0, 0, 0, 3403, 20794, 13338, 0, 21821, 0, 9778, 33957, 0, + 0, 7950, 33902, 7846, 22280, 20597, 31444, 31086, 26267, 0, 0, 31445, 23469, 20265, 0, 0, + 0, 0, 0, 0, 0, 0, 5140, 0, 3860, 0, 0, 0, 0, 0, 0, 0, + 0, 7502, 20324, 0, 33960, 33623, 27630, 14553, 19610, 799, 0, 35433, 9256, 21321, 0, 35434, + 0, 41288, 0, 0, 21802, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5796, 7326, 35741, 27053, 0, 0, 4615, 39143, 0, 0, 0, 0, 0, 27061, 13427, + 10805, 7080, 0, 0, 0, 0, 16793, 33962, 8854, 0, 27161, 0, 14710, 0, 0, 0, + 0, 0, 0, 0, 13660, 30592, 0, 27171, 14139, 0, 33550, 3750, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13231, 20741, 0, 0, 37261, 0, 0, 14889, 0, 0, 0, + 0, 29557, 0, 0, 32610, 0, 6230, 0, 9782, 19505, 30438, 33647, 30506, 28304, 14771, 37724, + 0, 9995, 0, 26614, 0, 32854, 18221, 25720, 0, 0, 0, 0, 0, 0, 0, 1235, + 0, 0, 21145, 0, 0, 0, 30402, 14336, 25030, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21329, 0, 20009, 28305, 0, 23968, 0, 0, 10089, 40630, 20015, 33660, + 0, 16514, 13687, 6101, 2956, 39727, 7430, 12774, 15078, 12015, 23167, 14419, 40554, 0, 5810, 13446, + 34169, 0, 38653, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39417, 0, 19355, + 10861, 32997, 26938, 9529, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33661, + 0, 0, 12341, 0, 4184, 0, 19665, 25633, 33502, 11427, 26162, 14564, 0, 0, 0, 15872, + 0, 10768, 9359, 9269, 0, 20018, 5992, 1280, 17612, 16195, 26281, 18758, 31834, 0, 0, 27921, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21921, 0, 16832, 0, + 0, 0, 0, 0, 0, 0, 0, 15656, 9534, 0, 0, 31549, 22070, 26022, 15015, 10728, + 9425, 14654, 0, 20969, 11176, 8721, 17200, 9064, 29194, 0, 19308, 29015, 4957, 0, 0, 0, + 23186, 37347, 13464, 20339, 8844, 19975, 30816, 0, 29107, 23325, 0, 0, 3187, 6241, 0, 22071, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10110, 0, 0, 0, 20165, 19260, 18793, 23192, 15529, 0, 6004, 23532, 13374, 15271, 24024, 20166, + 26246, 0, 0, 0, 0, 0, 0, 12909, 16926, 15467, 33694, 0, 0, 0, 0, 0, + 0, 19389, 7802, 2842, 11698, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15618, 0, 0, 30742, 9428, 12385, 41230, 12037, 32895, + 0, 0, 0, 0, 28226, 0, 25665, 0, 28995, 0, 0, 0, 39348, 16068, 32512, 20205, + 0, 31864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25764, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7011, 20351, 40260, 41014, 19958, 0, 31619, + 0, 28839, 0, 12841, 2920, 12398, 0, 0, 0, 0, 0, 0, 0, 0, 40670, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10498, + 2568, 23550, 20213, 39169, 15670, 35265, 40032, 0, 12944, 0, 22113, 0, 0, 11649, 0, 20497, + 18344, 0, 0, 0, 0, 0, 0, 0, 27546, 0, 19365, 16974, 0, 0, 27607, 35528, + 0, 0, 0, 0, 17302, 0, 0, 0, 32815, 28997, 33416, 0, 0, 33895, 17316, 19921, + 30645, 19922, 0, 0, 0, 0, 0, 0, 0, 0, 35111, 16383, 18128, 36380, 36381, 17334, + 13076, 9557, 0, 0, 0, 9376, 33089, 0, 0, 26569, 0, 41154, 0, 0, 0, 0, + 0, 0, 0, 15247, 16724, 0, 0, 0, 0, 0, 1519, 0, 0, 27303, 21820, 33613, + 0, 0, 0, 10264, 0, 0, 0, 0, 9593, 0, 38560, 16483, 4679, 39707, 7764, 24217, + 0, 38246, 20906, 21709, 35834, 0, 0, 4502, 26864, 13025, 40914, 34524, 36331, 0, 0, 0, + 25655, 0, 25426, 31846, 0, 9362, 15178, 0, 31370, 0, 24276, 4524, 0, 38275, 33057, 0, + 37384, 38096, 4147, 17054, 17055, 33704, 20040, 33706, 25670, 0, 0, 9674, 25496, 0, 0, 19594, + 0, 24287, 4703, 4704, 4707, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31149, 0, + 7193, 443, 0, 0, 0, 0, 0, 0, 23596, 39671, 29418, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39672, 39469, 0, 11402, 3794, 0, 39673, 0, 0, 0, 36472, 0, + 0, 0, 31352, 850, 0, 10662, 26674, 0, 14899, 16002, 0, 0, 35580, 34271, 0, 0, + 1086, 0, 0, 0, 15733, 23673, 0, 0, 38835, 0, 15156, 26377, 0, 0, 229, 38968, + 39754, 0, 0, 0, 0, 0, 0, 39771, 0, 13465, 0, 0, 0, 0, 0, 0, + 27672, 23086, 21962, 0, 0, 0, 0, 0, 0, 0, 40671, 0, 0, 0, 0, 0, + 0, 36382, 0, 11301, 0, 34231, 0, 0, 26910, 21977, 23106, 0, 0, 0, 19486, 2609, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37831, 0, 0, 9141, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5141, 0, 21072, 0, 38931, 0, 10902, + 0, 0, 0, 0, 0, 15510, 0, 5958, 29470, 0, 0, 9335, 0, 0, 24440, 26981, + 12806, 357, 20859, 22813, 12761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 39030, 2115, 31064, 0, 2575, 0, 0, 0, 0, 21074, 15203, 0, 0, 0, 6345, + 9336, 24455, 0, 25397, 35572, 6527, 16736, 0, 39997, 15713, 6816, 32079, 5802, 21880, 6923, 36547, + 31345, 15517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 39674, 0, 0, 0, 39566, 34052, 0, 0, 39333, 0, 0, 34775, 0, + 12002, 12305, 21112, 0, 0, 0, 0, 34256, 18723, 0, 0, 7865, 25870, 4002, 30693, 0, + 8116, 15520, 27744, 15299, 0, 35800, 11213, 0, 0, 0, 0, 0, 0, 0, 37167, 0, + 0, 0, 0, 17162, 0, 0, 17936, 6415, 6942, 0, 0, 0, 23969, 6355, 0, 0, + 13688, 4323, 32362, 0, 0, 0, 8581, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5391, 0, 0, 0, + 10586, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40915, 0, 0, 23515, 30108, + 10588, 22578, 8862, 0, 21544, 0, 0, 15554, 0, 0, 39587, 0, 0, 0, 0, 0, + 0, 32730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26547, 37051, 13237, 0, 0, 0, 0, 0, 23429, 3205, 25921, 0, 28359, 23774, 11789, + 0, 26320, 6982, 0, 0, 0, 0, 0, 0, 0, 0, 24542, 0, 15461, 0, 0, + 31002, 40766, 12359, 0, 0, 0, 0, 4977, 0, 4891, 0, 0, 0, 18555, 15272, 16137, + 5575, 24127, 0, 20658, 0, 0, 9831, 10595, 3006, 10515, 0, 0, 0, 0, 0, 0, + 0, 0, 2376, 38982, 0, 0, 9717, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 33526, 22375, 14949, 0, 0, 8439, 27673, 0, 28227, 25090, 0, 31225, 34413, 22412, 32738, 22052, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16207, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1069, 39168, 12399, 0, 0, 13920, 17466, 15497, 0, + 40043, 0, 0, 0, 0, 0, 0, 0, 38219, 0, 16663, 23204, 1820, 0, 0, 0, + 0, 0, 0, 0, 0, 36238, 22779, 0, 0, 0, 0, 27932, 18955, 0, 5594, 6386, + 17732, 40683, 0, 0, 0, 0, 0, 0, 0, 0, 2942, 0, 0, 0, 0, 0, + 0, 0, 3232, 28528, 0, 0, 0, 0, 0, 25103, 5414, 0, 0, 25224, 0, 23005, + 0, 0, 0, 0, 0, 0, 39920, 32816, 0, 0, 13259, 24844, 16776, 2168, 25037, 0, + 0, 0, 0, 0, 0, 32569, 16820, 0, 0, 0, 16459, 0, 0, 0, 0, 16180, + 0, 16181, 0, 0, 37466, 0, 0, 0, 0, 0, 13503, 24231, 12095, 0, 0, 8420, + 0, 0, 35657, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35684, 39375, 0, 0, 1591, 26739, 14316, 0, 0, 0, 0, 10314, 7952, 0, 14387, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 41267, 35414, 0, 0, 0, 0, 32330, 35415, 0, 27729, 0, 4217, 0, 0, 20605, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 38582, 0, 34048, 0, 0, 25549, 0, 11992, 0, 0, 0, 26421, 0, 0, 0, + 27187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36895, 37262, + 0, 0, 15066, 0, 0, 0, 0, 0, 0, 40737, 18734, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3541, 16051, 0, 0, 0, 0, + 40562, 0, 0, 0, 0, 0, 10762, 0, 0, 33570, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40910, 36513, + 0, 0, 40152, 0, 0, 18333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 21812, 0, 0, 0, 0, 0, 0, 1304, 0, 3631, 0, 41106, 7772, 18773, 23113, + 0, 0, 0, 0, 0, 40430, 0, 38976, 26870, 37183, 18774, 17588, 0, 0, 0, 14944, + 17747, 1028, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 35943, 9364, 0, 0, 0, 0, 0, 0, 0, 343, 0, 0, 9665, + 20455, 0, 34550, 16361, 0, 0, 1993, 0, 0, 38099, 36863, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36002, 21296, 0, 0, 0, 0, 0, 21299, 9840, 15109, 0, + 26892, 0, 32302, 0, 23727, 25104, 15970, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26507, 0, 12011, 0, 30407, 0, 0, 0, 0, 0, 7545, 7552, 0, 37218, 0, 0, + 0, 39369, 9298, 0, 13635, 19487, 10342, 0, 36820, 0, 0, 0, 0, 0, 0, 6433, + 27625, 0, 17098, 0, 0, 13642, 21701, 470, 36975, 0, 0, 0, 0, 0, 39385, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10352, 15348, 0, 0, 0, 0, 6437, 12708, + 0, 3120, 0, 4218, 10364, 38547, 0, 0, 0, 0, 19782, 0, 0, 10365, 40834, 40195, + 0, 0, 30087, 0, 0, 0, 0, 0, 41228, 0, 25553, 6775, 13296, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10546, 0, 1011, 20612, 0, 0, 0, 0, 41053, + 0, 0, 1621, 0, 15692, 12768, 0, 0, 0, 0, 40578, 0, 33387, 0, 0, 0, + 0, 0, 0, 10388, 0, 23993, 0, 0, 0, 0, 0, 0, 0, 7470, 26757, 0, + 0, 0, 40523, 15797, 38314, 32087, 0, 1259, 35835, 0, 2957, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19661, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30360, 0, 0, 0, 0, 0, 0, 31163, 15657, 31071, + 33221, 15371, 0, 14273, 6478, 11428, 0, 0, 39755, 2435, 25517, 12343, 0, 35213, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14053, 34865, 0, 0, 0, + 0, 40961, 0, 0, 0, 0, 0, 0, 0, 2283, 0, 0, 0, 0, 0, 0, + 0, 27662, 17201, 9187, 2961, 0, 7476, 18245, 0, 13711, 37808, 0, 0, 39773, 0, 0, + 3817, 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19113, 12924, 0, 4144, + 27503, 0, 18943, 15093, 13540, 0, 29200, 38400, 0, 0, 35924, 0, 4525, 21178, 12737, 0, + 0, 0, 0, 0, 12606, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13036, 0, 0, 997, 0, 7267, 28229, 41231, 0, + 8562, 8594, 16575, 0, 40667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11109, + 0, 0, 29922, 0, 0, 0, 1338, 14514, 0, 0, 0, 0, 0, 0, 11181, 0, + 0, 0, 3365, 0, 0, 0, 15777, 5258, 8742, 32906, 0, 13745, 0, 2235, 0, 0, + 0, 0, 0, 0, 0, 0, 41078, 0, 23092, 0, 0, 27326, 2084, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 21657, 34558, 40112, 0, 19906, 0, 1455, 0, 32562, + 0, 0, 0, 0, 18830, 16968, 0, 0, 0, 12645, 0, 20357, 16811, 0, 39852, 36710, + 1456, 0, 0, 0, 0, 0, 0, 0, 20830, 25197, 0, 0, 0, 0, 0, 0, + 0, 0, 21475, 0, 0, 0, 0, 0, 0, 0, 24989, 39011, 0, 0, 0, 0, + 16819, 0, 0, 0, 0, 0, 0, 5284, 14999, 0, 0, 0, 18146, 0, 18164, 34451, + 0, 0, 0, 35011, 39177, 23143, 69, 0, 21791, 19521, 0, 0, 0, 0, 0, 0, + 0, 15201, 0, 14254, 34476, 20266, 0, 36127, 30310, 35066, 30183, 22500, 28182, 0, 0, 0, + 0, 0, 0, 0, 0, 15565, 0, 0, 10646, 0, 20504, 18025, 35743, 26601, 0, 41289, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29736, 0, 36668, 0, 30227, + 9594, 10718, 0, 0, 0, 27063, 0, 33353, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 3319, 0, 15518, 35766, 34852, 29498, 6287, 2548, 18328, 0, 0, 0, 24629, 33831, 26615, + 15786, 29669, 0, 23815, 0, 3873, 0, 0, 0, 0, 30959, 0, 18484, 196, 0, 0, + 0, 0, 0, 0, 15212, 0, 35032, 0, 8002, 0, 0, 0, 1057, 16408, 23606, 5811, + 0, 0, 13523, 9530, 0, 33356, 0, 0, 15454, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32363, 31133, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8955, 0, 0, 0, 21955, 15372, 0, 0, 0, 15658, 0, 0, 0, 0, + 0, 29279, 9066, 19281, 0, 18335, 0, 0, 0, 30817, 30966, 0, 0, 0, 0, 0, + 0, 8976, 0, 29812, 21643, 0, 0, 20158, 0, 0, 0, 16496, 23825, 19391, 38983, 0, + 11235, 36571, 13992, 0, 19799, 0, 0, 8056, 0, 0, 0, 24801, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18340, 8241, 5219, 0, + 8960, 0, 4791, 0, 0, 33286, 0, 0, 0, 0, 0, 0, 29758, 27200, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24514, 0, 0, 0, 0, 0, + 0, 0, 0, 25456, 0, 0, 0, 0, 0, 0, 0, 17318, 0, 0, 0, 12233, + 30174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29653, 0, 0, 0, + 0, 0, 28710, 0, 18165, 0, 35658, 25641, 0, 22001, 0, 0, 0, 2164, 0, 0, + 0, 37708, 25048, 40303, 9905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7177, 9908, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2059, 22827, 17798, 0, 0, 0, 0, 0, 0, 0, 15978, 8015, 29315, 31102, 0, 14421, + 0, 0, 0, 0, 0, 0, 0, 0, 39107, 0, 8035, 0, 0, 0, 0, 0, + 0, 0, 18383, 0, 0, 0, 31847, 29280, 0, 0, 0, 12595, 0, 0, 0, 35094, + 0, 4659, 0, 0, 22168, 24180, 0, 0, 0, 0, 0, 18394, 12460, 0, 0, 0, + 0, 0, 29645, 35522, 0, 2882, 0, 0, 0, 0, 0, 8929, 0, 0, 6219, 0, + 0, 0, 0, 0, 0, 0, 32466, 0, 0, 29531, 0, 40376, 35556, 35712, 40828, 23408, + 0, 0, 2573, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6641, 0, 0, 3678, + 18709, 6645, 0, 7369, 27054, 29170, 12117, 24533, 27527, 3160, 0, 0, 11572, 27145, 0, 0, + 37838, 0, 0, 0, 0, 0, 18370, 0, 19419, 8993, 0, 0, 0, 32080, 20613, 0, + 26671, 0, 22916, 35074, 24701, 25184, 0, 0, 0, 14625, 0, 0, 36205, 520, 21518, 0, + 3766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25404, 4112, 21530, 17163, 13233, 15318, + 2424, 3753, 40363, 40842, 34780, 0, 0, 0, 0, 0, 0, 0, 30960, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12546, 12547, 0, 0, 0, + 18932, 24636, 6654, 742, 2663, 0, 1931, 0, 3423, 39037, 19548, 0, 12558, 20315, 37651, 0, + 31209, 39730, 22830, 0, 0, 3686, 0, 0, 0, 0, 0, 20016, 7454, 4832, 19858, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36161, 19533, 5778, + 5867, 0, 23770, 0, 0, 10188, 39491, 14495, 21428, 0, 0, 0, 20019, 9179, 0, 0, + 0, 0, 0, 40364, 21545, 40642, 0, 35214, 4590, 0, 33503, 0, 31836, 0, 0, 1858, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2284, 0, + 0, 0, 0, 34525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13913, 0, 0, 14567, 5315, 6459, 0, 35142, 14160, 15462, 19217, 30721, 29755, 36784, 22040, + 0, 22536, 6108, 0, 30722, 3099, 13150, 0, 27663, 40645, 27936, 0, 25658, 0, 37058, 0, + 0, 0, 0, 6983, 0, 0, 15679, 0, 40337, 0, 0, 0, 0, 0, 31988, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8057, 28959, 31592, 3776, 8438, + 18866, 2443, 26329, 18254, 0, 31856, 12191, 35593, 28681, 0, 10971, 0, 0, 4836, 8764, 0, + 27118, 25952, 10730, 32391, 0, 0, 31992, 0, 0, 0, 0, 20823, 28363, 0, 38566, 0, + 7887, 26033, 21795, 35926, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24277, 24430, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11821, 27505, 5157, 21930, 20666, 23698, 3648, 22019, 14795, 0, 0, + 3008, 17822, 1754, 15621, 5220, 3831, 29571, 5221, 19431, 11111, 17684, 32215, 0, 2380, 18805, 4129, + 31226, 19396, 0, 0, 0, 40850, 0, 6464, 0, 0, 27513, 8242, 14675, 40108, 0, 5921, + 30509, 4148, 23699, 29961, 0, 17458, 1559, 16938, 0, 0, 16939, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1353, 8251, 4796, 6336, 0, 38100, 18395, 34085, 24509, 12215, + 23830, 0, 13053, 26440, 6799, 27275, 2148, 33532, 6178, 0, 25161, 0, 34803, 25690, 17976, 13054, + 5716, 7632, 5832, 41198, 0, 21668, 0, 0, 0, 0, 28112, 29330, 237, 0, 0, 2446, + 6113, 26644, 6466, 29130, 13482, 41199, 38792, 13055, 5229, 5162, 27834, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38675, 29515, 39829, 0, 0, 36801, 22023, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17057, 0, 0, 23788, 0, 28243, 14574, 128, 8744, 14682, 30009, 1363, 23615, 2004, 11838, + 0, 13184, 0, 0, 9010, 28114, 0, 0, 0, 0, 4413, 23982, 0, 0, 0, 34426, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5834, + 0, 0, 20354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23003, 18187, 13754, 40351, + 9207, 0, 0, 6485, 38903, 0, 26463, 24312, 20050, 0, 22897, 4576, 3780, 0, 0, 25815, + 0, 0, 0, 0, 0, 0, 29331, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18286, 18870, 18686, 41019, 0, 0, 0, 18959, 11379, 0, 29402, + 29932, 23977, 17984, 865, 22203, 38626, 0, 17319, 0, 0, 0, 29145, 11008, 0, 0, 0, + 0, 0, 17846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11712, 24754, 33844, 0, 14179, 6025, 28164, 0, 30863, 0, 34442, + 34341, 647, 0, 13287, 21300, 17335, 11011, 23554, 39921, 0, 0, 0, 0, 0, 0, 0, + 0, 1382, 0, 0, 37120, 6026, 17989, 17350, 40691, 12664, 14451, 0, 7748, 0, 37444, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17855, 38000, 23796, 13603, 9377, 0, 40695, 0, + 0, 8273, 0, 0, 0, 0, 0, 0, 0, 26065, 0, 0, 4677, 0, 0, 0, + 0, 0, 0, 11713, 0, 0, 0, 0, 5331, 18446, 36034, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25776, 37793, 0, 5603, 0, 0, 0, 0, 0, + 0, 8452, 38062, 26362, 37464, 2031, 0, 6092, 7238, 0, 37228, 0, 26594, 0, 0, 0, + 0, 0, 8888, 0, 20328, 29989, 0, 0, 17787, 0, 0, 0, 0, 0, 0, 0, + 0, 38378, 22238, 0, 20005, 0, 20477, 7333, 0, 20891, 27740, 35445, 12712, 40307, 0, 0, + 0, 0, 0, 575, 37263, 0, 22956, 0, 0, 0, 11284, 2300, 13349, 0, 0, 0, + 28658, 0, 0, 0, 0, 0, 0, 0, 0, 39709, 0, 20090, 15319, 0, 0, 0, + 0, 34893, 6568, 25008, 2130, 4010, 24084, 18230, 1932, 0, 15255, 7663, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5392, 0, 0, 0, 6292, 8708, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 18077, 31690, 0, 21341, 40011, 40012, 0, + 0, 0, 0, 3772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21367, 12166, 0, 24722, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15135, 0, 0, 32382, 0, 10420, 0, 17897, 0, 40767, 0, 0, + 0, 21958, 4651, 0, 0, 0, 0, 2562, 0, 0, 0, 0, 0, 39964, 2066, 0, + 0, 0, 0, 0, 3777, 31857, 25801, 32203, 26034, 20272, 0, 7264, 39435, 0, 4786, 0, + 0, 0, 0, 0, 32035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21898, 16940, + 41071, 0, 4729, 38281, 0, 16941, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23355, 0, 40584, 4797, 23055, 0, 7275, 28691, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 40790, 41109, 40030, 25448, 17911, 28692, 0, + 0, 0, 0, 0, 0, 0, 27135, 0, 0, 0, 4746, 40796, 7899, 0, 0, 0, + 0, 32782, 0, 0, 0, 0, 0, 0, 7738, 0, 0, 0, 0, 0, 0, 32417, + 13190, 0, 7682, 0, 0, 0, 0, 17320, 20684, 0, 0, 0, 0, 0, 0, 36712, + 0, 0, 0, 0, 0, 12072, 0, 24755, 0, 0, 0, 0, 21441, 0, 0, 0, + 20063, 0, 0, 23557, 0, 0, 10455, 0, 17565, 0, 0, 0, 0, 0, 0, 41306, + 0, 0, 18169, 0, 0, 40188, 0, 21446, 0, 0, 12434, 25363, 13643, 8424, 0, 0, + 35713, 0, 0, 40039, 0, 31333, 0, 0, 0, 0, 8831, 4633, 0, 20329, 0, 0, + 0, 34049, 0, 39398, 32699, 0, 0, 7965, 10907, 0, 0, 0, 5519, 0, 14860, 5897, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 27170, 0, 0, 30469, 0, 0, 0, + 0, 0, 0, 20892, 5523, 27064, 4384, 27241, 0, 30230, 3084, 7244, 0, 9092, 37491, 0, + 0, 9354, 0, 0, 0, 0, 0, 0, 0, 0, 24158, 0, 38644, 5040, 26487, 0, + 0, 0, 0, 0, 0, 0, 40004, 32498, 20480, 40872, 11467, 20010, 0, 31814, 39710, 22036, + 6730, 0, 0, 0, 4452, 20714, 0, 3039, 0, 35803, 8996, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14045, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38336, 22831, 35202, 13690, 0, 22459, 0, 0, 26111, 40482, 14223, 0, 0, + 18231, 37176, 0, 14422, 0, 0, 0, 0, 21887, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19662, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3130, 0, 40426, 21429, 15573, 13591, 11224, 0, 0, 33137, 41253, 34635, + 14913, 0, 0, 0, 0, 10869, 40093, 26549, 0, 34526, 0, 33007, 5994, 0, 0, 3133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13027, 12582, 0, 0, 4327, 10682, 0, 0, 0, 0, 0, 0, 0, 0, + 4958, 0, 0, 0, 15136, 33228, 11790, 13032, 40100, 38470, 8220, 3632, 1047, 21893, 0, 0, + 0, 12596, 23776, 0, 30411, 21941, 1305, 27598, 0, 0, 0, 0, 0, 0, 0, 0, + 14056, 35223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7481, 0, 0, 16930, 0, 0, 17216, 22543, 0, 0, 0, 0, + 0, 0, 28221, 18255, 10425, 11914, 28733, 27599, 39798, 1966, 0, 0, 0, 31858, 0, 0, + 0, 22939, 25134, 0, 20824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36572, 0, 0, + 0, 0, 5067, 0, 0, 0, 0, 0, 0, 0, 23441, 5889, 21566, 27506, 0, 26438, + 16098, 28232, 0, 6245, 6009, 0, 0, 0, 0, 0, 0, 0, 8925, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40408, + 9798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33533, 24820, 0, 0, + 34086, 0, 0, 13389, 38997, 0, 5833, 25915, 1030, 0, 28371, 23831, 0, 0, 0, 33534, + 0, 34087, 0, 0, 20669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28244, 16212, 40261, 40114, 0, 17284, 0, 5127, 14524, 0, 37943, + 2814, 19120, 0, 0, 26049, 0, 17475, 0, 41127, 0, 0, 16312, 27510, 24191, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6247, 0, 0, 0, 0, 0, 31397, 19912, + 0, 12647, 0, 0, 3447, 0, 21294, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34999, 0, 0, 16224, 0, 0, 18960, 0, + 28255, 7903, 0, 0, 16770, 30764, 0, 0, 0, 0, 0, 0, 0, 0, 4540, 0, + 0, 0, 0, 0, 17336, 0, 22804, 0, 15048, 14578, 0, 16230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12665, 0, 0, 20365, 0, 35112, 1427, 0, 0, + 0, 4586, 27695, 0, 0, 27696, 0, 0, 10456, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21060, 0, 6035, 0, 0, 3073, 37905, 0, 33425, 27233, 0, 2776, 20390, + 17407, 36083, 33211, 30536, 9160, 29688, 28411, 7471, 4906, 21539, 4644, 41271, 13712, 33880, 1967, 13871, + 36233, 33528, 0, 36978, 33350, 0, 23478, 843, 33262, 8950, 0, 0, 41158, 0, 0, 0, + 13581, 0, 15128, 0, 0, 33272, 857, 27255, 37328, 0, 40055, 38658, 0, 0, 0, 0, + 0, 0, 39907, 0, 0, 0, 2563, 0, 4208, 18337, 0, 0, 0, 0, 28142, 0, + 40259, 0, 0, 0, 0, 0, 0, 0, 0, 1513, 0, 0, 0, 33194, 0, 34279, + 0, 0, 18133, 0, 0, 0, 0, 34281, 0, 0, 0, 0, 29464, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5549, 0, 0, 0, 0, 0, 0, + 0, 22501, 11067, 2453, 0, 0, 0, 0, 0, 0, 29231, 20737, 14731, 0, 20738, 0, + 14616, 18304, 0, 18182, 0, 0, 0, 18305, 11076, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7967, 10908, 0, 0, 6924, 8898, 9093, 0, 0, 0, + 0, 9306, 0, 0, 0, 0, 0, 0, 0, 19026, 0, 7245, 18929, 19852, 8005, 18223, + 0, 0, 0, 0, 0, 32865, 9103, 0, 32365, 1933, 0, 12561, 0, 0, 0, 0, + 0, 0, 0, 24913, 18745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27594, 0, + 0, 20740, 37330, 10101, 0, 0, 0, 0, 0, 37736, 5199, 0, 0, 0, 0, 37059, + 12911, 0, 0, 8520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2378, + 26724, 18318, 0, 0, 0, 0, 13375, 0, 0, 28048, 28049, 39967, 0, 0, 0, 0, + 0, 0, 17749, 0, 33838, 18807, 0, 12623, 0, 0, 34414, 0, 0, 0, 0, 18820, + 0, 20457, 29131, 0, 0, 0, 11438, 0, 0, 35958, 28737, 0, 31300, 0, 0, 0, + 12224, 0, 0, 0, 0, 0, 0, 6387, 16074, 0, 15047, 0, 0, 0, 0, 26893, + 21031, 23006, 0, 0, 27280, 25023, 0, 0, 0, 0, 0, 0, 25310, 0, 0, 7601, + 0, 0, 28445, 29988, 0, 34766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6678, 4350, 0, 9152, 7607, 0, 0, 25507, 0, 0, + 0, 8544, 32479, 0, 32480, 10794, 0, 28898, 26306, 34781, 40873, 0, 37557, 0, 0, 0, + 0, 0, 0, 0, 27962, 0, 0, 4124, 32484, 0, 581, 0, 19424, 0, 8119, 16178, + 17039, 0, 13691, 36692, 0, 0, 0, 0, 37331, 0, 3620, 0, 4125, 35863, 26240, 0, + 0, 0, 12361, 34324, 0, 0, 31372, 4270, 19514, 0, 0, 0, 0, 8047, 12734, 9067, + 9122, 12786, 0, 0, 0, 32204, 0, 14000, 40882, 18526, 0, 0, 9069, 0, 0, 0, + 25278, 0, 26250, 0, 0, 14957, 29646, 36862, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12941, 6382, 0, 11000, 0, 0, 0, 25959, 37425, 0, 0, 0, + 0, 0, 19367, 0, 39443, 34338, 8568, 0, 11280, 0, 0, 0, 0, 0, 24994, 0, + 0, 34847, 0, 41156, 0, 0, 0, 32583, 35715, 34477, 10639, 36979, 0, 0, 0, 3584, + 0, 3464, 0, 0, 10165, 25999, 21983, 28448, 7571, 3408, 0, 0, 10649, 33961, 0, 0, + 0, 0, 0, 0, 0, 0, 39567, 0, 0, 0, 0, 24776, 0, 0, 0, 0, + 31487, 7985, 0, 27248, 9909, 0, 22982, 0, 4429, 0, 0, 0, 0, 0, 0, 0, + 2637, 0, 0, 10583, 0, 0, 0, 0, 22205, 26620, 32623, 0, 0, 33750, 4431, 29506, + 22987, 0, 0, 0, 0, 0, 0, 28479, 2516, 0, 0, 41063, 12020, 33676, 34636, 2639, + 0, 30106, 0, 0, 0, 0, 0, 0, 32194, 33763, 10773, 11375, 8723, 3742, 1307, 10590, + 10591, 3493, 0, 2564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38471, + 0, 38543, 28497, 0, 0, 22993, 28498, 0, 36791, 8058, 4359, 4959, 28429, 0, 18256, 0, + 0, 4360, 0, 10602, 0, 10125, 16168, 0, 26882, 0, 0, 0, 0, 29647, 11832, 10435, + 22764, 37405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32120, 10038, 0, 22998, + 0, 0, 0, 0, 0, 0, 16225, 12073, 0, 0, 0, 0, 0, 0, 0, 0, + 28610, 0, 0, 0, 16591, 0, 27354, 0, 0, 0, 5381, 5768, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 33364, 0, 0, 30512, 0, 3068, 20951, 0, + 14826, 0, 0, 7081, 7085, 21814, 21828, 0, 0, 0, 0, 0, 0, 40407, 0, 0, + 0, 0, 21905, 0, 17761, 16730, 0, 405, 0, 0, 0, 0, 3252, 0, 0, 9525, + 24956, 8772, 0, 8951, 26480, 0, 0, 0, 0, 16272, 39284, 35864, 9709, 30547, 19087, 0, + 0, 0, 26947, 36340, 26787, 29813, 1308, 0, 38263, 39965, 0, 25491, 23335, 8235, 2444, 0, + 0, 0, 0, 16942, 19398, 0, 17459, 1560, 0, 0, 0, 4159, 35959, 0, 0, 0, + 22043, 0, 0, 0, 0, 35978, 15780, 0, 0, 1577, 0, 3663, 24848, 20695, 38923, 26142, + 26143, 0, 0, 0, 0, 0, 0, 34891, 8890, 20955, 0, 0, 32962, 0, 0, 29337, + 0, 0, 0, 0, 0, 0, 35132, 0, 0, 26097, 0, 0, 0, 0, 0, 25974, + 0, 0, 5731, 33633, 0, 0, 0, 0, 0, 24777, 0, 0, 0, 0, 0, 0, + 10584, 26803, 29558, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6807, 0, 0, 0, 0, 17653, 0, 10721, 17040, 0, 32503, 0, 0, 26715, 0, 0, + 7873, 0, 0, 0, 0, 0, 0, 0, 34528, 30489, 23179, 6739, 0, 11225, 23686, 0, + 33008, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4459, 26760, 0, + 0, 0, 7150, 0, 33229, 0, 29959, 34641, 0, 17812, 0, 0, 20023, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40982, 0, 40768, 0, 10973, 36431, 17451, 4917, + 29282, 29343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25432, 0, 104, 0, 0, + 114, 38991, 9763, 18808, 38845, 20033, 17685, 38992, 0, 0, 0, 24872, 4532, 0, 0, 29480, + 0, 28694, 38676, 10992, 0, 22765, 0, 4920, 25449, 0, 0, 0, 0, 0, 21136, 0, + 0, 0, 0, 21037, 5261, 13486, 0, 0, 0, 0, 0, 14683, 7126, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17338, 0, 9767, 30271, 0, 0, + 0, 0, 21495, 0, 13850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 22565, 3567, 0, 0, 0, 0, 0, + 0, 0, 22566, 35639, 6321, 30218, 33992, 0, 23454, 26294, 0, 0, 33461, 0, 0, 10312, + 22099, 0, 22234, 0, 33325, 0, 3519, 28616, 41171, 41124, 23462, 6322, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 27526, 0, 0, 20857, 31435, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3018, 35688, 0, 0, 39247, 0, 0, 14463, 5030, + 0, 25854, 0, 0, 40292, 30395, 0, 0, 25855, 633, 12830, 19350, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30158, 0, 23472, 0, 0, 0, 0, 40454, + 30081, 0, 0, 22854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22321, 15821, 35436, + 0, 32963, 37670, 10520, 0, 10745, 39250, 4282, 27055, 30222, 0, 32843, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8853, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15673, + 20886, 0, 0, 14394, 33863, 24703, 3086, 18891, 10378, 26800, 21027, 0, 10379, 2543, 34303, 8837, + 21519, 0, 9781, 34374, 9383, 0, 0, 39682, 16634, 0, 0, 0, 0, 0, 0, 6412, + 23489, 24704, 14871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7713, 0, 33634, 29950, 0, 9996, 15649, 0, 0, 26616, 39711, 0, 22166, 39270, 17164, + 30355, 0, 7304, 33181, 0, 0, 34267, 0, 0, 0, 0, 14412, 26707, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19528, 0, 30015, + 40627, 31508, 36268, 14043, 29994, 0, 0, 8857, 12549, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40404, + 0, 0, 29433, 0, 39409, 0, 12322, 0, 0, 0, 36417, 30805, 0, 11422, 29507, 2691, + 0, 0, 15943, 23607, 638, 2514, 30146, 21016, 13586, 0, 34315, 0, 29797, 0, 30963, 0, + 4496, 0, 0, 33662, 36272, 0, 0, 1058, 0, 0, 0, 0, 18860, 0, 0, 0, + 0, 38019, 4908, 0, 0, 0, 21540, 14561, 10763, 0, 0, 0, 8861, 0, 0, 0, + 0, 0, 0, 0, 0, 10764, 15193, 8907, 0, 11695, 33009, 0, 0, 31837, 10002, 20020, + 0, 31022, 11931, 25950, 33185, 38969, 12021, 0, 8912, 0, 0, 25842, 13861, 30198, 0, 0, + 0, 6546, 3429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31551, 0, 0, + 0, 0, 20021, 38128, 25922, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 29999, 39732, 30965, 0, 0, 36172, 30017, 0, 3693, 38264, 0, 32645, 20538, + 4652, 0, 0, 1447, 33400, 0, 0, 35494, 0, 0, 0, 0, 0, 0, 11568, 0, + 38396, 28315, 11903, 14655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4653, 0, 0, 12192, 34082, 28287, 2479, 0, 35928, 0, 0, 0, 0, 1553, 0, + 0, 0, 14945, 17217, 0, 0, 22221, 0, 0, 0, 0, 37966, 35233, 0, 1325, 39040, + 39041, 0, 14354, 38984, 0, 0, 27399, 0, 0, 0, 31595, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 33580, 20947, 32205, 9718, 30825, 0, 0, 12386, 25809, + 0, 0, 6177, 21860, 6461, 39294, 15666, 0, 0, 20494, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 748, 11816, 0, 0, 40931, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25902, 0, 29002, 35513, 0, 37387, 0, 0, + 0, 35097, 21669, 0, 3837, 11940, 0, 6587, 0, 23545, 36492, 1818, 21655, 11533, 0, 0, + 0, 0, 0, 0, 0, 0, 36493, 0, 0, 0, 749, 0, 0, 0, 9492, 16763, + 41224, 0, 0, 0, 0, 0, 0, 0, 0, 2815, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13061, 0, 0, 0, 19913, 0, 32788, 0, 0, 0, 0, 0, 33195, + 0, 16975, 0, 0, 0, 0, 0, 0, 0, 0, 24087, 0, 0, 0, 0, 30766, + 20923, 0, 22135, 0, 16712, 0, 0, 19137, 0, 0, 0, 18993, 0, 8821, 0, 18994, + 0, 0, 24849, 0, 0, 0, 19144, 0, 21044, 0, 0, 19145, 37791, 0, 0, 0, + 0, 0, 27533, 0, 0, 20127, 30452, 2426, 12883, 30480, 0, 0, 0, 0, 0, 12735, + 0, 0, 0, 0, 11360, 0, 0, 0, 17569, 40854, 517, 27166, 0, 0, 30329, 0, + 0, 0, 27234, 0, 0, 0, 0, 9511, 31462, 0, 25550, 35071, 0, 0, 8545, 0, + 0, 0, 0, 0, 0, 37737, 0, 0, 36564, 30238, 1955, 0, 0, 0, 0, 33191, + 0, 0, 22627, 1980, 0, 0, 9919, 38569, 31128, 0, 35266, 1372, 9923, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3585, 0, 0, 39683, 0, 21230, 0, 0, + 0, 31210, 55, 0, 0, 0, 0, 0, 53, 37193, 3640, 0, 0, 14166, 39816, 39830, + 39831, 14455, 0, 0, 0, 0, 9964, 0, 0, 0, 22822, 0, 0, 35027, 0, 0, + 0, 0, 0, 36751, 22826, 0, 20616, 0, 0, 0, 0, 0, 41295, 22983, 0, 33929, + 15842, 35806, 22984, 0, 0, 0, 0, 0, 0, 0, 0, 40526, 0, 0, 0, 0, + 0, 0, 0, 21245, 24664, 4604, 0, 0, 0, 0, 0, 0, 35046, 0, 0, 0, + 0, 7628, 0, 0, 0, 31994, 0, 13246, 2521, 0, 0, 32775, 2522, 0, 0, 0, + 0, 0, 3368, 4799, 0, 0, 0, 24510, 0, 37417, 0, 37100, 0, 0, 0, 30987, + 0, 2528, 37207, 0, 0, 0, 0, 0, 0, 41258, 5374, 0, 0, 14804, 5375, 36390, + 0, 7786, 0, 0, 0, 31037, 0, 0, 13947, 23479, 0, 24327, 0, 16119, 0, 28623, + 32074, 0, 29234, 0, 16123, 0, 29341, 0, 10930, 40149, 38587, 28460, 0, 29239, 28468, 28480, + 11172, 34529, 29451, 0, 29452, 28481, 0, 0, 0, 0, 0, 0, 11272, 0, 12787, 23536, + 0, 28503, 0, 0, 28641, 11239, 0, 0, 40443, 11153, 0, 0, 16390, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 41218, 35660, 7935, 31326, 0, 7936, 0, 6059, 28446, 0, + 0, 0, 0, 0, 0, 0, 3036, 0, 0, 25377, 25003, 0, 8642, 0, 0, 0, + 0, 7987, 5670, 5859, 36632, 0, 12831, 0, 0, 18375, 0, 0, 36633, 22512, 0, 11964, + 24472, 0, 7248, 31211, 29607, 10175, 0, 0, 28630, 0, 0, 0, 0, 0, 10536, 0, + 0, 0, 0, 0, 29361, 0, 0, 0, 40007, 0, 0, 554, 33010, 5347, 0, 13862, + 0, 0, 0, 0, 0, 10870, 859, 0, 6105, 0, 0, 0, 21858, 30819, 37062, 0, + 33230, 8048, 32384, 23522, 29756, 0, 0, 12362, 0, 36515, 0, 5490, 30552, 31575, 0, 22017, + 0, 26768, 36854, 0, 41, 13161, 0, 9008, 25752, 0, 0, 0, 8977, 0, 0, 26167, + 28829, 0, 0, 0, 0, 0, 0, 18809, 316, 0, 23543, 33406, 0, 5000, 0, 0, + 0, 7189, 30842, 0, 6664, 17693, 7219, 11534, 14958, 28512, 41232, 25240, 2237, 29024, 0, 0, + 11240, 33535, 0, 38615, 0, 0, 0, 8442, 0, 0, 22389, 2240, 32812, 4968, 0, 0, + 0, 12648, 0, 0, 0, 0, 17060, 0, 0, 22088, 0, 0, 0, 18429, 17339, 31713, + 29035, 0, 0, 18134, 0, 0, 0, 0, 17068, 25169, 18170, 0, 0, 0, 9701, 0, + 0, 0, 0, 0, 22917, 20617, 22008, 0, 0, 474, 0, 0, 0, 0, 0, 0, + 0, 23316, 0, 0, 34402, 0, 0, 0, 0, 0, 30239, 262, 0, 20517, 20453, 34137, + 19914, 0, 0, 9323, 0, 0, 13330, 0, 0, 0, 0, 8325, 0, 0, 0, 0, + 0, 2181, 31318, 38924, 25284, 15578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 38853, 39889, 24581, 9738, 8885, 23041, 11062, 20228, 0, 0, 29229, 0, + 0, 0, 0, 30464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40192, 4933, 33351, 20842, 0, 0, 14703, 0, + 0, 21389, 0, 0, 0, 0, 0, 0, 11068, 26090, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39388, 0, 0, 28402, + 0, 27628, 0, 0, 0, 35716, 0, 0, 0, 0, 0, 0, 0, 24456, 39652, 18889, + 25551, 0, 23254, 37152, 39989, 34771, 32258, 20710, 3789, 11604, 14258, 14326, 22729, 0, 0, 0, + 0, 13513, 0, 9315, 0, 20607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31463, 23065, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12522, + 0, 0, 0, 0, 0, 0, 30957, 907, 35573, 7989, 27634, 14712, 12539, 0, 21325, 0, + 987, 0, 0, 0, 0, 33635, 0, 0, 24297, 1916, 0, 0, 30451, 39035, 0, 31091, + 26450, 38208, 34828, 0, 0, 27845, 21520, 0, 0, 0, 0, 1219, 0, 0, 0, 0, + 0, 0, 0, 4626, 23897, 0, 0, 0, 0, 0, 32755, 39403, 26504, 0, 0, 39684, + 22328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5903, + 0, 0, 0, 0, 0, 0, 31100, 0, 39568, 1220, 0, 7608, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 24630, 21277, 1923, 6649, 0, 26984, + 33489, 2902, 33490, 35136, 20011, 0, 0, 0, 33131, 40628, 8187, 0, 0, 22576, 33967, 0, + 37288, 32176, 37289, 37018, 0, 14413, 28406, 15550, 0, 0, 39271, 19853, 8514, 0, 0, 0, + 0, 0, 20805, 31733, 1237, 0, 8188, 0, 0, 0, 0, 0, 32762, 0, 0, 0, + 14267, 0, 0, 9028, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3476, 14268, 14269, 0, 0, 26108, 0, 7428, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8006, 0, 0, 0, 30405, + 33491, 1851, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10276, 0, 32866, 22668, 37178, 0, 29271, 22528, 0, 26985, 15742, 12152, 0, 0, 38386, + 20966, 20739, 0, 8019, 6452, 0, 0, 26783, 2551, 0, 3484, 9604, 20403, 28769, 550, 23905, + 0, 40634, 30806, 34063, 0, 20299, 38020, 36773, 0, 36902, 0, 26231, 10401, 18897, 39484, 0, + 0, 0, 14152, 39096, 0, 0, 19859, 36774, 0, 31104, 451, 0, 0, 14780, 25561, 4601, + 39422, 0, 0, 0, 0, 0, 0, 0, 0, 10939, 34734, 0, 15080, 26510, 15609, 0, + 0, 23764, 0, 0, 19860, 0, 0, 0, 0, 0, 29382, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3485, + 0, 33337, 0, 11932, 0, 0, 5568, 16491, 0, 38157, 2437, 28354, 41110, 28136, 0, 31984, + 0, 33011, 0, 0, 13705, 36780, 0, 9061, 8843, 0, 0, 0, 15084, 11567, 12346, 23013, + 31164, 0, 35866, 0, 0, 20946, 0, 25484, 20996, 0, 22880, 26314, 5868, 12347, 11146, 6571, + 15568, 28483, 0, 10723, 0, 27260, 0, 0, 0, 10549, 7648, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 21377, 0, 0, 0, 3919, 0, 0, + 0, 0, 0, 0, 0, 0, 23981, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 31838, 10944, 27851, 31109, 0, 9915, 25564, 19864, 0, 25874, 0, 31215, 0, 36786, + 0, 28637, 26633, 0, 0, 0, 23433, 0, 9794, 23610, 32104, 0, 0, 0, 0, 28139, + 18776, 0, 0, 23187, 5870, 0, 0, 23328, 12782, 36787, 31695, 3005, 0, 0, 0, 0, + 0, 20159, 18572, 1145, 0, 0, 0, 0, 0, 0, 22262, 0, 0, 0, 39111, 26634, + 2797, 8221, 0, 0, 0, 0, 24732, 27665, 0, 0, 41149, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38891, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22537, 0, 0, + 4605, 0, 0, 0, 0, 0, 8561, 6363, 0, 7890, 9363, 25971, 27925, 13037, 23024, 0, + 2262, 1064, 20742, 38842, 32717, 0, 14510, 27267, 13038, 16935, 0, 4127, 16625, 0, 10485, 10974, + 9113, 38790, 13723, 32555, 0, 6332, 10009, 12788, 32556, 12375, 27318, 16535, 12193, 26247, 0, 0, + 28919, 40775, 27467, 0, 12376, 4028, 12608, 26638, 17972, 17680, 0, 25877, 0, 201, 25662, 0, + 29116, 5212, 0, 11342, 0, 25802, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25682, 31168, 14667, 11343, 16835, 18798, 0, 0, 28639, 38347, + 0, 0, 0, 23781, 0, 0, 0, 31596, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4433, 26515, 0, 0, 0, 0, 25803, 0, 0, 19678, 24813, 0, 1981, 8440, 0, + 24181, 14797, 5255, 2918, 34799, 10432, 0, 12206, 0, 1788, 0, 19736, 0, 0, 0, 6620, + 344, 14060, 18810, 20275, 5829, 10489, 0, 12930, 0, 0, 11183, 9009, 0, 0, 18811, 8069, + 11705, 0, 38323, 0, 14001, 27674, 25119, 0, 0, 0, 0, 0, 5222, 0, 30415, 1451, + 0, 0, 0, 0, 12791, 0, 0, 0, 0, 0, 0, 5159, 14277, 32206, 1982, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32000, + 0, 1561, 0, 0, 0, 22996, 0, 0, 25972, 947, 26176, 30743, 0, 2335, 18812, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5223, 0, 9204, 37967, 684, 8476, 0, + 0, 2986, 12631, 17755, 0, 24511, 13178, 18821, 6483, 28101, 34992, 36235, 0, 28513, 34993, 14064, + 3934, 8073, 37601, 26462, 0, 1819, 5327, 27132, 0, 0, 18610, 24185, 19118, 22999, 0, 19901, + 13747, 0, 0, 12217, 0, 0, 18822, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2965, 20352, 19902, 13057, 0, 0, 2208, 0, 28073, 0, 0, 0, + 0, 0, 0, 0, 10495, 25813, 0, 40791, 15535, 8849, 27677, 0, 0, 0, 0, 0, + 29138, 38727, 33074, 27520, 3558, 36707, 18684, 19981, 17840, 27771, 0, 0, 31628, 7277, 7900, 26692, + 29139, 2642, 37763, 0, 7901, 13185, 5720, 0, 0, 0, 32909, 5129, 0, 0, 0, 39512, + 0, 0, 0, 33707, 0, 0, 0, 0, 21580, 7354, 19908, 20458, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18537, 6388, + 0, 38731, 13192, 10135, 5233, 26073, 13193, 28703, 13494, 22945, 0, 22898, 0, 40444, 0, 17702, + 40883, 0, 40684, 0, 11119, 0, 0, 0, 0, 31888, 0, 19915, 14685, 20358, 32230, 0, + 16028, 19916, 12954, 0, 0, 0, 21765, 0, 5721, 25961, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4038, + 39518, 23793, 18914, 0, 40686, 0, 0, 0, 41304, 10020, 28172, 9073, 0, 3870, 12653, 36004, + 37112, 0, 0, 0, 0, 0, 0, 0, 21766, 21298, 25755, 0, 0, 0, 17924, 0, + 0, 21660, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24075, 35006, 8270, + 27483, 16031, 24841, 6181, 27333, 0, 0, 0, 0, 0, 16992, 14537, 25694, 0, 0, 0, + 38454, 0, 0, 0, 32682, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19825, 26956, 5758, 17351, 5506, 38114, 0, 19138, + 2275, 0, 0, 286, 0, 0, 13083, 0, 5928, 0, 0, 36460, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 36025, 5283, 21769, 0, 37779, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17067, 17009, + 11131, 0, 36914, 0, 0, 0, 0, 0, 0, 0, 21058, 0, 0, 0, 0, 0, + 0, 0, 3237, 0, 0, 0, 0, 0, 0, 7753, 1641, 0, 0, 0, 0, 19436, + 8485, 12080, 0, 4622, 0, 36864, 0, 0, 36915, 0, 0, 0, 33470, 0, 0, 0, + 0, 33624, 11020, 18600, 0, 31964, 35770, 0, 0, 0, 0, 0, 0, 0, 11023, 11080, + 40837, 0, 0, 0, 0, 0, 0, 8902, 29897, 31157, 18064, 9104, 39903, 0, 0, 0, + 0, 0, 0, 0, 18604, 0, 0, 0, 41111, 0, 0, 0, 29621, 31928, 10414, 0, + 0, 0, 0, 37745, 0, 0, 0, 0, 0, 20998, 1956, 10877, 23537, 27293, 23918, 40023, + 35091, 9114, 0, 0, 0, 591, 15222, 0, 0, 0, 0, 0, 0, 0, 10427, 12610, + 10975, 34415, 0, 0, 0, 0, 4240, 6083, 24551, 10779, 0, 0, 10298, 0, 0, 41113, + 0, 32220, 0, 0, 32041, 31884, 0, 0, 26050, 0, 0, 0, 8749, 31889, 0, 0, + 0, 8751, 0, 0, 18915, 0, 8752, 15477, 0, 27205, 40360, 0, 29039, 34236, 21310, 0, + 0, 0, 0, 0, 0, 0, 19185, 28119, 0, 0, 2767, 0, 0, 31334, 0, 36929, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 38178, 0, 35746, 31465, 10651, 24935, 30470, + 3532, 31802, 29296, 37874, 0, 35313, 12291, 11605, 7819, 0, 8106, 0, 0, 12292, 33797, 0, + 0, 28598, 0, 6439, 0, 0, 0, 37547, 0, 0, 0, 5657, 0, 0, 40243, 28547, + 0, 25478, 33925, 37264, 7335, 869, 0, 24866, 0, 2123, 12714, 38422, 0, 21805, 26506, 0, + 0, 0, 17153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9595, 9327, 0, 5042, 0, 0, 0, 0, 0, 0, 0, 8317, + 0, 0, 4454, 0, 34505, 27793, 27076, 0, 15694, 39575, 29608, 24779, 6945, 0, 33269, 25560, + 37020, 0, 0, 35808, 35809, 33650, 7830, 8700, 0, 0, 0, 0, 10389, 36084, 0, 10719, + 0, 6732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33270, 7249, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 23168, 26113, 0, 6453, 5689, 16893, 35843, + 31686, 8842, 29612, 15328, 10722, 16092, 21542, 3486, 29095, 0, 29613, 0, 0, 0, 0, 0, + 16894, 20910, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 38593, 870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29385, 0, 37962, 6970, 27195, 15556, 22364, 8208, 18764, 33012, 33013, 33396, 18765, 29317, 28484, + 4461, 24725, 0, 8209, 39427, 0, 33014, 41025, 7519, 20410, 33222, 0, 0, 29622, 23297, 0, + 22702, 0, 28203, 7120, 0, 0, 0, 11030, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27799, 0, 1624, 6067, 617, + 26865, 33015, 32714, 7475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4115, 27448, 34905, 14929, 26788, 0, 36697, 7350, 0, 0, 15949, 5708, 0, 19585, + 13714, 0, 34404, 0, 0, 30554, 0, 0, 25913, 13715, 37065, 30820, 6985, 24969, 14231, 7773, + 18387, 6001, 22674, 0, 17546, 10956, 18941, 0, 0, 0, 0, 0, 0, 0, 0, 5821, + 0, 0, 0, 4783, 20722, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30453, 14719, 15383, 34405, 13466, 0, 0, 0, 0, 0, 0, + 0, 8920, 0, 25435, 28273, 26331, 0, 0, 3498, 0, 23337, 28364, 0, 35234, 38186, 25035, + 38668, 429, 41067, 28365, 38985, 31860, 0, 3958, 13476, 41193, 8661, 31378, 0, 0, 19040, 12378, + 0, 0, 32886, 32887, 0, 0, 6267, 0, 0, 0, 0, 24547, 0, 0, 0, 0, + 0, 22888, 0, 18258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13724, 0, 11808, 0, 0, 0, 26173, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 39507, 115, 33701, 1340, 0, 35124, 21356, 40215, + 0, 28065, 0, 32897, 37388, 24740, 0, 0, 41072, 39436, 38770, 19042, 30744, 3700, 20171, 0, + 12207, 0, 28066, 35163, 31702, 29874, 17462, 33815, 0, 31382, 0, 0, 0, 0, 0, 19590, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10695, 0, 0, 19043, + 6375, 4573, 2711, 18814, 28067, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19044, 0, 0, 0, 0, 0, 39913, 16954, 7537, 0, 14108, 16022, 35962, 11187, 4800, 0, + 37406, 1051, 29976, 27328, 5073, 31173, 4469, 21679, 5328, 41079, 10017, 0, 22551, 4131, 0, 0, + 6467, 22000, 0, 0, 40171, 0, 32907, 38998, 24186, 33774, 0, 25988, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1355, 0, 8254, 0, 0, 0, 0, 0, 17260, 0, 0, 0, 0, 0, 6859, 0, + 35127, 27330, 0, 26051, 0, 23205, 9849, 26052, 0, 8259, 19591, 0, 16699, 38618, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2643, 0, 0, 0, 0, 30846, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16700, 0, 38326, + 36359, 129, 32814, 0, 1365, 0, 0, 0, 0, 0, 0, 2733, 0, 0, 22555, 4577, + 17843, 23374, 0, 12650, 14073, 6164, 7459, 35529, 29881, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19963, 2271, 34206, 0, 0, 0, 0, 0, + 0, 0, 34846, 0, 29521, 0, 0, 0, 39519, 0, 33086, 18961, 0, 17322, 0, 19595, + 0, 0, 32012, 0, 0, 27938, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27958, 33983, 0, 0, 0, 0, 0, 17341, 37612, 0, + 0, 38688, 0, 28537, 33821, 30864, 35275, 22157, 19596, 29147, 22805, 0, 6471, 24660, 35606, 0, + 0, 0, 0, 30128, 2645, 0, 0, 14011, 0, 0, 0, 0, 6869, 0, 0, 0, + 0, 0, 0, 2746, 36386, 18135, 0, 32303, 0, 23213, 0, 37777, 19047, 36461, 24845, 0, + 0, 0, 7484, 40805, 0, 0, 0, 0, 0, 24369, 0, 0, 0, 21664, 30873, 27489, + 0, 8274, 0, 0, 20693, 20694, 30132, 2647, 38153, 0, 0, 0, 0, 0, 17005, 17010, + 0, 32016, 14746, 0, 21005, 20186, 0, 0, 11551, 0, 27515, 0, 33586, 0, 0, 7485, + 0, 33098, 0, 0, 0, 0, 28541, 36661, 0, 38690, 0, 0, 0, 0, 0, 0, + 0, 23962, 21045, 0, 17994, 0, 0, 0, 19009, 32311, 8086, 0, 18172, 0, 0, 0, + 25966, 0, 11859, 0, 0, 0, 0, 0, 29488, 0, 24376, 0, 11461, 0, 217, 0, + 0, 0, 0, 0, 0, 19425, 0, 21337, 0, 0, 0, 9792, 21956, 0, 0, 32547, + 0, 13867, 0, 0, 0, 0, 39291, 0, 20838, 0, 0, 25903, 11112, 0, 41080, 11707, + 0, 0, 12218, 0, 0, 0, 35269, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 33263, 0, 0, 16182, 37265, 14892, 0, 0, 0, 0, + 0, 27373, 39275, 0, 36647, 0, 8654, 0, 13143, 33188, 0, 0, 11638, 0, 0, 27452, + 0, 0, 3704, 10181, 0, 0, 0, 0, 17714, 0, 0, 0, 0, 13221, 0, 8886, + 0, 40600, 0, 0, 0, 0, 0, 23407, 0, 0, 0, 0, 23644, 0, 6257, 22913, + 0, 0, 11069, 0, 0, 21702, 0, 23474, 5850, 5851, 0, 17113, 0, 0, 33329, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20845, 0, 39251, + 16183, 39654, 0, 6873, 1843, 22915, 33474, 36669, 4382, 17137, 0, 0, 22188, 0, 0, 33437, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23124, 0, 3058, 23490, 0, + 0, 35771, 0, 29070, 6724, 18376, 0, 13120, 0, 0, 0, 0, 0, 38704, 37641, 0, + 0, 0, 0, 0, 0, 0, 36996, 0, 8805, 0, 10806, 0, 0, 0, 23420, 0, + 20806, 11413, 18485, 31818, 6838, 16511, 7511, 30356, 0, 4811, 0, 22354, 0, 0, 0, 4886, + 30994, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8579, 0, 0, 0, 4772, 0, 0, 23507, 16895, 24164, 23856, 15553, 1041, 0, 27190, + 0, 0, 0, 0, 0, 0, 0, 30545, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40759, + 0, 0, 29190, 23687, 6358, 0, 0, 29806, 0, 0, 30549, 0, 0, 0, 10946, 33223, + 0, 26241, 39589, 0, 0, 0, 0, 3548, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40101, 31003, 3494, 28362, 33025, 0, 15465, 0, + 0, 26193, 26873, 27196, 0, 13822, 0, 0, 0, 8590, 18905, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33026, 0, 0, 0, 0, 0, 39590, 0, 0, 0, 19393, 0, + 27450, 15469, 0, 5887, 35341, 0, 28050, 4146, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4788, 30169, 0, 0, 33040, 0, 0, 0, 0, 0, 0, 0, 33811, 0, 0, + 0, 0, 10490, 14951, 0, 0, 29208, 7533, 0, 39595, 27124, 29923, 0, 0, 3701, 0, + 29209, 38724, 10556, 0, 24815, 30625, 0, 6621, 825, 0, 0, 0, 17686, 0, 0, 0, + 0, 0, 0, 0, 27675, 0, 0, 0, 0, 0, 1602, 33050, 1662, 0, 4588, 0, + 0, 0, 14678, 10436, 0, 0, 0, 16024, 36580, 0, 0, 0, 0, 0, 0, 0, + 27409, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21581, 0, 37101, + 40677, 19910, 11001, 0, 0, 17841, 0, 0, 0, 0, 0, 0, 0, 13600, 33345, 0, + 0, 0, 0, 34560, 0, 0, 0, 0, 0, 13757, 16220, 27415, 13758, 16705, 0, 0, + 41086, 0, 27138, 0, 0, 0, 0, 0, 30646, 6339, 28082, 0, 0, 0, 0, 0, + 0, 0, 0, 32919, 25211, 0, 0, 0, 0, 0, 0, 0, 19239, 0, 0, 0, + 0, 23730, 0, 0, 0, 0, 0, 0, 21059, 18166, 0, 0, 12675, 0, 0, 0, + 20511, 0, 0, 9137, 0, 0, 0, 0, 33798, 0, 0, 0, 33479, 0, 0, 0, + 0, 1947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30558, 0, 0, 0, + 0, 0, 15671, 0, 0, 0, 30328, 0, 2590, 0, 19636, 15437, 0, 0, 4450, 0, + 0, 0, 32350, 20619, 0, 0, 0, 0, 0, 0, 11874, 2838, 26851, 39150, 6946, 20013, + 0, 26852, 24714, 27250, 0, 4354, 34506, 0, 0, 10862, 23169, 39734, 11470, 0, 0, 0, + 0, 0, 0, 0, 39580, 0, 36845, 0, 0, 0, 0, 0, 8618, 35042, 23014, 0, + 0, 0, 0, 0, 0, 0, 0, 35483, 3394, 12584, 0, 58, 0, 6211, 0, 28209, + 0, 14350, 0, 0, 0, 0, 0, 0, 23524, 17442, 33835, 0, 17723, 0, 0, 0, + 0, 37932, 33837, 4595, 22656, 0, 15950, 0, 29117, 11376, 5120, 9660, 3141, 0, 26398, 12611, + 0, 0, 0, 0, 17550, 15195, 26812, 0, 6246, 36800, 23345, 0, 32739, 0, 0, 0, + 0, 0, 35963, 18530, 0, 0, 4149, 0, 0, 0, 0, 16627, 8566, 0, 0, 0, + 38353, 0, 30642, 0, 0, 0, 12955, 0, 0, 0, 0, 36377, 7290, 17342, 23719, 0, + 0, 0, 35114, 0, 0, 0, 15917, 30653, 0, 25107, 0, 0, 32741, 25108, 0, 0, + 10892, 0, 0, 0, 0, 6672, 3983, 0, 0, 26603, 0, 0, 40619, 6831, 12540, 0, + 0, 28655, 0, 21986, 0, 0, 0, 0, 0, 0, 0, 13809, 24097, 0, 0, 0, + 0, 23755, 14630, 0, 0, 24631, 30097, 0, 0, 0, 21885, 27747, 0, 0, 0, 35455, + 0, 9169, 11929, 21997, 40749, 0, 13353, 0, 0, 31746, 26460, 0, 35484, 39759, 0, 0, + 0, 0, 0, 0, 0, 19090, 0, 40016, 14930, 28675, 21894, 14656, 10958, 0, 39777, 0, + 0, 0, 0, 1092, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3641, 33768, 12379, + 9296, 14511, 31115, 30117, 0, 24652, 30559, 6481, 0, 27198, 0, 39167, 21162, 0, 0, 31867, + 38994, 39819, 0, 20853, 0, 0, 0, 0, 12931, 0, 0, 0, 0, 0, 34983, 9804, + 0, 0, 5636, 0, 12046, 14065, 0, 0, 0, 0, 0, 0, 14966, 37764, 0, 0, + 0, 0, 0, 0, 12407, 0, 28078, 0, 12960, 0, 16076, 31129, 15887, 1584, 14985, 0, + 0, 1387, 0, 2749, 0, 40806, 17377, 0, 0, 0, 7815, 23800, 34464, 0, 28742, 20588, + 0, 0, 0, 15602, 31466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11081, 11082, + 0, 7992, 0, 0, 34854, 9845, 0, 25272, 36262, 7714, 15067, 0, 37843, 0, 0, 34116, + 0, 31806, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31921, 0, + 0, 10171, 0, 0, 0, 0, 0, 0, 0, 0, 11083, 0, 0, 10856, 23125, 7208, + 0, 0, 0, 0, 12722, 0, 0, 35458, 0, 0, 0, 0, 0, 30052, 20849, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36149, 36269, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12565, 30507, 27090, 6534, 6782, 0, 30104, 30195, 17183, 0, 0, 0, 25257, + 0, 0, 4456, 33665, 40008, 40877, 0, 0, 0, 0, 0, 0, 30485, 34220, 0, 12566, + 3023, 0, 0, 0, 0, 0, 0, 0, 0, 12336, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26282, 29807, 0, 1659, 31839, 22463, 38506, 0, 0, 11779, 0, + 28312, 0, 10477, 0, 37673, 0, 31166, 0, 18080, 0, 38507, 11173, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2697, 0, 0, 0, 0, 0, 0, 0, 6971, + 0, 3184, 0, 0, 0, 0, 0, 28211, 0, 29322, 0, 0, 0, 0, 0, 0, + 39778, 29195, 279, 40648, 40880, 15384, 0, 26023, 29281, 18779, 0, 0, 0, 0, 26259, 38472, + 0, 0, 0, 3695, 0, 34643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 20778, 10878, 0, 0, 0, 0, 0, 0, 3434, 0, 0, 28037, 0, 0, + 0, 0, 0, 21130, 0, 0, 12380, 6704, 10815, 0, 4591, 38401, 36174, 0, 32735, 0, + 1502, 1065, 16205, 0, 3436, 0, 23612, 0, 169, 26879, 0, 0, 3642, 0, 0, 0, + 0, 0, 0, 0, 0, 21813, 0, 12612, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21961, 0, 31933, 0, 0, 2640, 0, 43, 0, 0, 26814, 10433, 0, + 12389, 3439, 31869, 39295, 0, 0, 28416, 0, 19313, 0, 0, 22477, 0, 0, 33529, 23829, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32039, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37389, 0, 0, 0, 0, 0, + 0, 13731, 32042, 18679, 0, 24187, 0, 2601, 0, 0, 0, 34872, 12632, 26139, 18576, 0, + 12219, 39832, 30510, 0, 1356, 172, 35349, 173, 0, 0, 0, 0, 16955, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32118, 0, 0, 0, 0, 14363, 28738, + 0, 10301, 10499, 0, 0, 38403, 38679, 35981, 31885, 0, 31886, 7202, 34427, 0, 0, 20779, + 0, 0, 0, 0, 0, 9120, 0, 0, 0, 0, 0, 0, 0, 0, 37864, 0, + 0, 0, 0, 0, 39972, 0, 2817, 4163, 11845, 37995, 9732, 13070, 34207, 0, 0, 0, + 32564, 10500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5236, 0, 0, 0, 20216, 21661, 0, 19923, 0, 17847, 40117, 23057, 28549, + 0, 0, 0, 36456, 29030, 9809, 0, 0, 0, 0, 23960, 0, 18962, 25820, 17848, 3510, + 32936, 0, 0, 9812, 831, 19233, 14802, 0, 0, 0, 7028, 0, 0, 0, 0, 0, + 0, 0, 0, 10452, 0, 19805, 0, 0, 33092, 22806, 0, 9954, 3234, 26358, 11856, 0, + 0, 0, 0, 0, 0, 0, 36388, 0, 13087, 0, 0, 0, 0, 179, 0, 0, + 0, 28538, 35361, 29934, 0, 0, 0, 18297, 0, 41261, 0, 17014, 0, 22810, 33986, 0, + 21201, 6316, 0, 0, 16438, 0, 0, 0, 0, 0, 38575, 14835, 39075, 12294, 23655, 0, + 9937, 7609, 0, 9938, 10667, 10403, 10765, 0, 0, 0, 38716, 3818, 28607, 23868, 0, 26554, + 36343, 0, 0, 24224, 0, 0, 12039, 0, 31870, 10492, 31876, 31935, 10203, 16628, 0, 17286, + 0, 0, 3281, 0, 0, 0, 15107, 31664, 10043, 0, 0, 0, 0, 0, 6283, 0, + 6231, 30281, 0, 0, 6232, 38044, 14781, 0, 18547, 4017, 0, 39285, 0, 0, 0, 23330, + 15239, 12026, 16274, 0, 0, 0, 0, 0, 0, 0, 8323, 0, 27201, 0, 6157, 0, + 0, 0, 0, 18532, 29855, 0, 0, 37093, 31383, 0, 29287, 0, 0, 0, 0, 0, + 0, 0, 9807, 0, 0, 0, 0, 0, 28706, 23383, 0, 0, 0, 0, 0, 0, + 17856, 17370, 0, 34024, 0, 0, 0, 0, 8852, 29468, 10065, 3989, 0, 29990, 0, 33341, + 36760, 20620, 3538, 0, 11024, 6328, 0, 20770, 0, 20898, 0, 18054, 0, 0, 0, 87, + 32088, 0, 0, 0, 15216, 27750, 25858, 0, 0, 0, 35847, 0, 0, 0, 0, 35870, + 32768, 0, 39428, 6296, 0, 0, 0, 0, 19359, 0, 0, 0, 19077, 14932, 0, 0, + 0, 23915, 18085, 0, 0, 0, 0, 0, 0, 22678, 4606, 6796, 37194, 0, 0, 0, + 40581, 0, 31871, 11275, 20496, 28834, 0, 0, 0, 23052, 0, 20178, 19400, 0, 9322, 0, + 23707, 0, 17917, 20459, 30759, 2484, 0, 11121, 28162, 0, 0, 14686, 26178, 19924, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30651, 31661, 18197, 0, 0, 1388, 30876, 0, 0, + 0, 17114, 38946, 0, 36601, 10919, 30317, 422, 12873, 0, 0, 0, 0, 41269, 38649, 1853, + 24537, 34733, 0, 0, 6147, 24780, 0, 0, 0, 0, 22524, 38550, 0, 0, 26234, 9054, + 1608, 35473, 8021, 0, 33184, 27091, 29566, 0, 0, 6065, 0, 0, 29751, 32635, 31216, 22258, + 11631, 0, 0, 0, 0, 16273, 0, 0, 0, 27761, 4737, 26169, 40056, 38892, 30617, 16275, + 1309, 0, 0, 6175, 0, 0, 21131, 32810, 25248, 29895, 30828, 36792, 19732, 37593, 39969, 0, + 0, 0, 0, 0, 0, 0, 27893, 0, 9124, 26483, 0, 38857, 22548, 0, 0, 29572, + 0, 3441, 22382, 2718, 36581, 27509, 0, 31298, 0, 22552, 11440, 0, 8079, 0, 1611, 0, + 0, 0, 0, 21096, 0, 1612, 30858, 36587, 0, 21139, 9343, 0, 0, 0, 0, 0, + 17353, 0, 33199, 34449, 22970, 22245, 0, 0, 0, 0, 28334, 0, 25329, 26269, 0, 0, + 0, 0, 28335, 0, 0, 0, 0, 0, 5099, 0, 19832, 0, 0, 0, 0, 0, + 0, 0, 0, 27172, 0, 0, 0, 0, 9043, 0, 9939, 27080, 34832, 0, 9163, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15359, 0, 0, 14414, 0, + 22039, 2428, 729, 33336, 2186, 0, 0, 17938, 88, 0, 0, 0, 20145, 16287, 0, 0, + 0, 32624, 0, 26511, 0, 0, 0, 0, 0, 0, 0, 11966, 21338, 0, 0, 0, + 0, 0, 0, 0, 39339, 0, 17966, 38434, 0, 0, 37855, 0, 0, 33678, 0, 0, + 0, 0, 0, 0, 3349, 31072, 31555, 0, 0, 932, 0, 0, 26382, 0, 0, 0, + 37352, 20160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6488, 0, 0, 2597, 0, 38276, 3396, 0, 29513, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 35512, 0, 0, 0, 0, 0, 34909, 0, 0, 15667, 0, + 7630, 32898, 3397, 0, 0, 0, 0, 0, 0, 0, 0, 16018, 0, 0, 0, 1713, + 0, 18534, 0, 0, 0, 35965, 20179, 33059, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9550, 0, 19119, 0, 0, 26343, 0, 0, 0, 0, 0, 0, 0, 14525, 6338, + 0, 0, 32121, 0, 0, 39600, 0, 0, 1736, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 39601, 40445, 33941, 17560, 28249, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16454, 14694, 20217, 34138, 38736, 9734, 0, 0, 0, 0, + 0, 0, 39860, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30870, 25013, 2646, + 0, 0, 0, 0, 0, 0, 0, 0, 25368, 0, 37780, 0, 40807, 0, 0, 0, + 19242, 9627, 0, 3322, 0, 14415, 29311, 30412, 0, 0, 0, 39404, 0, 0, 21014, 0, + 0, 0, 0, 9946, 0, 0, 0, 0, 31576, 17898, 0, 0, 34327, 33697, 0, 0, + 0, 0, 11113, 8475, 33702, 0, 31877, 0, 0, 0, 4802, 0, 0, 31893, 11009, 0, + 0, 0, 0, 0, 0, 34342, 0, 0, 0, 0, 0, 0, 0, 0, 35719, 3469, + 14862, 0, 41049, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13514, 35777, 0, 28719, + 3594, 445, 29716, 40893, 24618, 0, 0, 3595, 31728, 0, 0, 0, 0, 0, 0, 0, + 21326, 0, 4618, 0, 31268, 0, 4004, 27943, 36604, 14558, 447, 0, 4430, 5682, 22092, 3603, + 0, 24662, 0, 34386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38551, 0, 0, + 0, 0, 32369, 1059, 15827, 23508, 40009, 14492, 24165, 20634, 37574, 0, 9644, 41145, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24166, 0, 0, 0, 0, 0, 0, 0, 0, + 10949, 24644, 9873, 8214, 16533, 26166, 31556, 2062, 27101, 36649, 9464, 0, 21546, 0, 0, 10796, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20153, 0, 0, 0, 6986, 32197, + 37888, 33689, 24306, 6153, 16833, 23525, 16344, 8050, 23434, 3743, 0, 0, 4654, 0, 0, 20659, + 860, 0, 0, 0, 5399, 0, 0, 0, 13725, 3758, 3643, 37372, 4727, 28051, 29202, 27400, + 38438, 8060, 0, 3107, 7814, 10777, 38439, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13726, 38440, 38606, 0, 0, 34543, 9880, 31297, 11185, 5743, 34986, 27894, + 23702, 12390, 33365, 23544, 15042, 0, 9881, 0, 0, 0, 0, 0, 0, 0, 34551, 13748, + 4730, 0, 29877, 38771, 22710, 18823, 39440, 4036, 20180, 23926, 0, 17554, 0, 0, 0, 0, + 0, 0, 17262, 0, 0, 0, 6861, 28076, 14968, 0, 0, 14526, 28701, 17700, 25861, 6217, + 0, 37994, 39513, 0, 0, 0, 33893, 18115, 0, 0, 5471, 0, 0, 38623, 33784, 24313, + 13549, 22637, 0, 0, 10039, 0, 0, 0, 0, 0, 37113, 9810, 0, 34090, 0, 0, + 34091, 2742, 13760, 14538, 34572, 6395, 0, 10736, 32421, 34092, 0, 0, 0, 0, 18136, 13763, + 36031, 24853, 8416, 7750, 0, 15004, 24759, 0, 0, 0, 0, 14320, 0, 12509, 12438, 0, + 0, 0, 0, 0, 0, 31674, 22121, 0, 15864, 15687, 0, 15688, 38495, 0, 0, 473, + 0, 0, 3201, 11084, 21809, 6833, 33333, 6631, 26752, 30318, 7575, 0, 0, 31490, 40727, 0, + 11085, 0, 0, 0, 0, 1653, 0, 30163, 614, 8690, 0, 15355, 0, 0, 0, 0, + 0, 0, 40518, 8009, 20624, 12771, 30099, 37293, 0, 20771, 14895, 14484, 9265, 22957, 0, 0, + 21278, 0, 0, 0, 30223, 34507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3862, 15828, 9912, 0, 32488, 31534, 0, 4820, 29567, 25746, 0, 6700, + 3093, 0, 0, 0, 16796, 40754, 0, 39314, 41270, 0, 0, 15256, 38045, 0, 37504, 24483, + 0, 0, 0, 7180, 34065, 0, 12567, 0, 2515, 0, 0, 0, 0, 0, 0, 0, + 27263, 33876, 32873, 29052, 10105, 32096, 26242, 30022, 10178, 16094, 2459, 6238, 21859, 34637, 3350, 23045, + 23517, 37738, 7878, 0, 0, 0, 0, 29550, 0, 0, 0, 0, 0, 0, 0, 31073, + 26761, 30150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28725, 0, 34224, 39781, 18783, 34536, 14433, 0, 0, 5440, 0, 4024, + 41107, 6987, 39499, 22368, 0, 1631, 0, 5633, 0, 0, 0, 0, 0, 0, 0, 0, + 16276, 0, 35224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10227, 22074, 28759, 15269, + 33525, 41031, 12614, 31379, 0, 0, 4128, 0, 0, 22994, 34539, 30170, 0, 6364, 0, 22680, + 3644, 11938, 22836, 0, 4526, 38475, 0, 0, 0, 0, 30287, 0, 0, 0, 0, 30259, + 0, 0, 0, 6999, 30829, 514, 0, 13248, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2565, 0, 4033, 15737, 29022, 41013, 17238, 28505, 25810, 0, 0, 22077, 22078, + 0, 0, 0, 25984, 24029, 0, 0, 0, 0, 0, 0, 0, 0, 41073, 0, 39820, + 34544, 0, 13732, 21205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18978, 24745, 0, 5497, 17595, 2809, 24188, 18577, 6015, 4731, 0, 0, + 12462, 0, 0, 3010, 27469, 41081, 0, 15277, 0, 0, 23928, 16956, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27439, 37407, + 38772, 16761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 22943, 0, 0, 0, 0, 39003, 32783, 0, 28739, 4803, 16366, + 0, 33537, 27412, 38478, 2269, 0, 0, 1151, 22414, 0, 0, 0, 0, 3371, 0, 0, + 0, 0, 0, 24070, 12227, 0, 0, 0, 0, 0, 38530, 0, 16367, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29332, 25816, 13879, 40352, 6801, 0, 2603, 14800, 28849, 1074, 0, 7284, 17844, 38327, 28250, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26054, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39854, 29930, 0, 24367, 0, 4339, 0, 0, 0, + 28531, 1822, 30971, 0, 0, 22961, 0, 0, 0, 0, 0, 0, 0, 20557, 2162, 0, + 0, 15888, 0, 4865, 25250, 832, 16320, 0, 0, 0, 0, 0, 0, 21417, 16993, 0, + 0, 0, 0, 0, 0, 13497, 18639, 17355, 18436, 9685, 0, 0, 0, 2830, 0, 0, + 0, 0, 0, 0, 32140, 0, 2859, 0, 33096, 38740, 0, 0, 0, 0, 0, 27491, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20105, 19002, 19243, 0, 0, + 5761, 0, 0, 0, 0, 0, 0, 0, 6036, 0, 30297, 37795, 19011, 0, 19013, 0, + 0, 0, 0, 16825, 0, 30256, 6047, 21195, 26457, 32975, 22516, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19566, 0, 36207, 0, 1925, 0, 40321, 0, 0, 3684, 0, + 0, 0, 0, 0, 0, 0, 20772, 30100, 0, 29663, 35140, 0, 0, 0, 0, 0, + 0, 11577, 0, 25344, 0, 35203, 0, 0, 0, 0, 0, 30109, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 41117, 37353, 0, 0, 6, 0, 40018, 30286, 0, 0, + 0, 6743, 39970, 9854, 11522, 20273, 0, 0, 0, 4237, 24178, 8921, 29514, 19733, 0, 0, + 0, 28882, 0, 0, 25442, 0, 0, 25443, 23346, 9805, 0, 0, 0, 32561, 29285, 0, + 0, 0, 0, 0, 0, 32672, 0, 0, 38619, 4804, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16382, 0, 0, 0, 26647, 0, 16775, 17356, 0, 2675, 21608, 19003, + 0, 29469, 11731, 0, 0, 0, 0, 8896, 0, 0, 0, 0, 0, 0, 0, 0, + 23481, 36989, 0, 33129, 0, 0, 0, 0, 37719, 423, 5045, 12125, 33865, 0, 0, 14878, + 21706, 0, 0, 0, 0, 0, 0, 0, 6441, 12307, 0, 0, 0, 0, 0, 0, + 21988, 8952, 989, 0, 15521, 34856, 18308, 21239, 38501, 36270, 21396, 22216, 0, 8903, 2127, 10391, + 25481, 9640, 0, 0, 0, 1243, 31512, 14485, 11898, 1266, 0, 29362, 39316, 0, 0, 35848, + 4457, 0, 1811, 0, 0, 0, 0, 8910, 0, 0, 7181, 0, 0, 34791, 33572, 0, + 0, 10587, 0, 0, 38149, 2626, 10683, 0, 29276, 0, 0, 0, 39429, 33225, 33553, 0, + 0, 39212, 0, 0, 30368, 0, 0, 0, 15086, 0, 0, 0, 0, 31110, 0, 0, + 18785, 0, 39289, 25485, 3358, 8051, 0, 6988, 28915, 28823, 0, 14720, 3040, 28491, 5634, 0, + 40928, 0, 0, 15526, 29900, 0, 15527, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 25486, 37810, 10429, 40964, 4527, 24550, 0, 0, 0, 20826, 6706, + 33581, 15531, 32393, 0, 0, 0, 0, 0, 0, 0, 0, 6365, 15223, 0, 36344, 0, + 0, 0, 40779, 0, 0, 0, 0, 11523, 0, 22376, 0, 17239, 0, 1985, 8738, 14515, + 15386, 0, 10983, 34988, 28836, 0, 24504, 25492, 18319, 11823, 12209, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39821, 0, 28841, 39598, 15279, 0, 0, + 0, 0, 0, 0, 34873, 0, 28866, 10604, 0, 0, 0, 17596, 0, 2384, 0, 0, + 0, 20949, 40967, 0, 5498, 0, 13393, 22390, 0, 9469, 7098, 13187, 13545, 21861, 38193, 0, + 0, 0, 0, 22395, 5264, 0, 24827, 17483, 20831, 16425, 0, 0, 0, 0, 7637, 0, + 0, 0, 11911, 0, 0, 0, 15834, 0, 36245, 27470, 13199, 0, 0, 0, 0, 0, + 0, 0, 19234, 0, 18846, 0, 0, 0, 0, 0, 8757, 25225, 0, 0, 22807, 0, + 18437, 0, 0, 0, 39174, 32422, 0, 0, 17991, 17493, 26258, 2026, 17364, 0, 0, 0, + 0, 0, 0, 32925, 8759, 20464, 17495, 0, 0, 15006, 40036, 0, 0, 0, 0, 15396, + 0, 6037, 0, 39015, 0, 27222, 12104, 18366, 9461, 38187, 32418, 23639, 0, 26604, 0, 0, + 36208, 13810, 0, 0, 26623, 26624, 25769, 0, 0, 0, 0, 31840, 0, 0, 0, 0, + 0, 15702, 0, 24803, 0, 8735, 644, 0, 1342, 23703, 0, 0, 0, 0, 0, 0, + 1714, 645, 0, 41303, 22632, 0, 12059, 0, 0, 0, 0, 0, 0, 0, 648, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21740, 0, 3198, 0, 22311, 0, + 0, 8087, 29761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22567, 22962, 0, 0, + 3514, 0, 0, 33951, 23456, 31321, 0, 0, 39615, 5646, 4479, 36730, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4480, 0, 0, 5647, 40595, 0, 41024, + 4550, 0, 0, 22100, 34470, 23463, 25469, 12754, 0, 39625, 24583, 37701, 0, 27026, 0, 0, + 0, 10208, 0, 0, 0, 0, 0, 0, 0, 30041, 0, 0, 1647, 0, 15232, 0, + 0, 0, 4309, 0, 4424, 0, 36200, 27046, 20956, 25644, 0, 34767, 3404, 0, 4348, 0, + 0, 8891, 20001, 0, 12439, 0, 0, 0, 0, 0, 0, 0, 8793, 38198, 0, 0, + 0, 1034, 0, 0, 0, 0, 0, 33158, 16120, 0, 5959, 0, 0, 29493, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27534, 0, 0, 0, 5035, 0, + 0, 0, 0, 0, 0, 0, 17032, 0, 36628, 13345, 0, 0, 28418, 24867, 36144, 37492, + 13662, 0, 23661, 34896, 34259, 0, 0, 24357, 0, 0, 0, 0, 0, 0, 0, 22250, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12716, 0, 29718, 0, 29046, 0, 0, 0, 0, + 0, 6651, 2781, 12724, 3604, 12885, 27376, 0, 0, 0, 0, 0, 0, 0, 0, 28461, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 39413, 0, 37559, 0, 0, 10858, 0, 17801, 0, 0, 0, + 38250, 0, 4015, 0, 0, 0, 24669, 1021, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11331, 15717, 26758, 0, 13695, 0, 30486, + 0, 0, 0, 10863, 0, 0, 0, 0, 0, 0, 38259, 38072, 34866, 0, 3549, 14345, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17663, 36939, 0, 0, 0, 0, + 1445, 0, 15844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3877, 34203, 40643, 0, + 24173, 32376, 0, 37507, 31287, 13467, 32552, 26170, 0, 39782, 0, 0, 3757, 0, 1411, 30556, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37356, 29916, 0, + 0, 3041, 0, 0, 0, 11810, 23827, 0, 30733, 0, 0, 0, 0, 0, 0, 0, + 36794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5712, 0, 4987, 0, + 0, 36795, 14355, 29918, 38075, 0, 0, 11824, 0, 26177, 0, 0, 12040, 0, 0, 0, + 0, 0, 0, 0, 34989, 0, 0, 0, 0, 32399, 0, 0, 0, 0, 32400, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5717, 0, 14361, 0, + 0, 0, 11834, 0, 15334, 36802, 0, 0, 17287, 0, 0, 0, 4106, 0, 3508, 0, + 12060, 0, 36808, 0, 37767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28524, 38106, + 0, 0, 0, 21590, 40357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32305, 0, 0, 0, 0, 0, 0, 0, 26901, 0, 15589, 23395, 29834, 7231, 4807, + 0, 0, 29980, 2490, 2176, 32522, 22270, 14081, 23221, 26455, 21690, 20866, 0, 24232, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1158, 0, 0, + 0, 0, 0, 1170, 721, 1467, 40705, 20869, 30776, 10207, 0, 0, 0, 0, 0, 0, + 0, 13889, 0, 39326, 0, 0, 0, 24129, 0, 0, 0, 0, 0, 0, 10251, 29583, + 38176, 26794, 4818, 11455, 25543, 38039, 21372, 0, 0, 0, 0, 0, 0, 0, 32067, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24926, 12493, 36123, 17027, 19491, 26469, 10055, 4871, + 15054, 12510, 2108, 18474, 7825, 36743, 15758, 0, 0, 0, 0, 0, 32529, 0, 0, 0, + 0, 37834, 0, 24239, 11670, 23063, 0, 0, 0, 0, 0, 16857, 22246, 27235, 14395, 35440, + 39252, 3719, 0, 31675, 0, 11021, 25506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11398, 24094, 39400, 36406, + 31729, 23995, 12541, 39262, 11482, 0, 36997, 41005, 19706, 0, 0, 0, 26777, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 24947, 0, 0, 0, 0, 0, 0, + 13232, 10384, 0, 29609, 10392, 30889, 35814, 22143, 0, 0, 30995, 23756, 17168, 35461, 4182, 33652, + 30696, 0, 0, 0, 0, 0, 8650, 0, 37169, 0, 0, 38562, 8401, 23675, 15257, 16897, + 26625, 9417, 0, 22718, 0, 0, 16898, 0, 11027, 0, 0, 29799, 27563, 0, 11093, 16899, + 0, 0, 18565, 0, 0, 0, 5304, 0, 41298, 26235, 0, 26551, 0, 7771, 14647, 29623, + 13453, 24051, 8554, 40760, 11507, 26243, 0, 0, 28667, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30053, 0, 18193, 0, + 3351, 31032, 41256, 37357, 0, 40209, 0, 25130, 31749, 24795, 0, 8724, 0, 0, 0, 0, + 0, 0, 23189, 33520, 0, 0, 0, 0, 8361, 25084, 3822, 19879, 0, 0, 0, 0, + 0, 0, 26640, 24804, 0, 0, 24026, 2266, 0, 0, 17240, 0, 30417, 16691, 33236, 16501, + 0, 0, 27126, 39296, 7271, 0, 0, 0, 0, 0, 39822, 0, 0, 0, 0, 36178, + 0, 17263, 0, 0, 0, 0, 20548, 30752, 0, 36360, 25202, 0, 0, 0, 0, 0, + 24916, 0, 0, 0, 0, 19175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5036, 0, 36263, 1133, 8644, 0, 30981, 34491, 20239, 0, 8528, 24619, 39405, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9102, 29610, 0, 18058, 29083, + 4390, 35462, 7341, 22921, 1244, 0, 807, 0, 0, 0, 0, 0, 0, 0, 0, 22331, + 0, 28098, 0, 0, 27796, 30605, 32713, 0, 0, 0, 0, 0, 10278, 34518, 0, 0, + 0, 0, 0, 0, 0, 0, 35475, 38159, 36480, 21017, 0, 0, 0, 0, 0, 37963, + 0, 29318, 31557, 13530, 34398, 0, 0, 0, 0, 0, 0, 0, 21167, 28728, 34645, 29325, + 39783, 3773, 28957, 0, 0, 0, 0, 38510, 0, 0, 0, 0, 0, 0, 20253, 0, + 0, 31288, 36225, 34646, 16605, 0, 0, 0, 0, 22927, 0, 11939, 9891, 20749, 4528, 0, + 0, 15703, 3778, 0, 36856, 0, 0, 0, 40656, 0, 0, 27890, 0, 0, 0, 0, + 0, 0, 36287, 0, 0, 41197, 25914, 18341, 10128, 30838, 19888, 10984, 17241, 0, 20174, 0, + 672, 13048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25091, 0, 0, 0, + 19889, 0, 20750, 10710, 11116, 20039, 26196, 0, 0, 26387, 3043, 0, 40673, 0, 39441, 21432, + 0, 0, 0, 0, 0, 12633, 0, 0, 15392, 39299, 0, 0, 0, 0, 0, 5130, + 17729, 38680, 8963, 16582, 11151, 4073, 0, 13062, 16025, 0, 0, 0, 0, 26497, 0, 0, + 0, 0, 0, 0, 3214, 28740, 0, 11004, 19919, 22226, 38684, 2923, 0, 8444, 0, 0, + 35997, 0, 28251, 0, 0, 0, 33714, 12655, 16455, 0, 0, 0, 35531, 0, 0, 20183, + 0, 20362, 0, 0, 0, 4691, 0, 0, 16429, 0, 0, 34343, 0, 0, 20070, 0, + 0, 0, 36660, 2346, 13090, 0, 0, 27909, 0, 0, 0, 0, 0, 0, 34453, 0, + 0, 14768, 0, 0, 0, 6990, 0, 0, 7673, 0, 7675, 0, 0, 0, 0, 0, + 0, 9493, 19326, 0, 17756, 0, 0, 0, 0, 3685, 0, 16900, 0, 0, 0, 0, + 0, 39502, 0, 0, 33060, 0, 0, 3838, 0, 12414, 0, 0, 0, 22446, 0, 0, + 0, 0, 13663, 0, 0, 0, 0, 40050, 0, 0, 0, 0, 0, 33334, 0, 0, + 0, 15870, 0, 0, 0, 0, 0, 0, 0, 14097, 0, 11088, 0, 0, 23758, 0, + 0, 0, 0, 2457, 0, 0, 23298, 30361, 19574, 0, 6264, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15593, 0, 5054, 0, 21082, 0, 10677, 0, 0, 0, 0, 0, + 0, 0, 16288, 6741, 23688, 0, 36164, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 18569, 11632, 0, 0, 0, 8215, 19578, 0, 40013, 0, + 0, 36605, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16568, 12366, 35893, + 18246, 4521, 0, 21022, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29971, 32553, 0, 0, 0, 1501, 4156, 31376, 0, 14435, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32809, 22473, 40657, 25714, 0, 25981, 40881, 0, 39345, 0, 0, + 41069, 24737, 0, 3645, 0, 39800, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25021, 23696, 34174, 3042, 10430, 25602, 0, 0, 0, + 14438, 31380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3646, 15874, 0, 4608, + 25673, 16143, 3503, 41074, 13379, 0, 37090, 29823, 19890, 4918, 27600, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7734, 9032, 6158, 2577, 19679, 2804, 1416, 37391, 0, 0, 30325, + 41075, 0, 40786, 0, 4086, 30379, 30202, 0, 24915, 0, 0, 30380, 0, 32040, 0, 0, + 0, 0, 0, 0, 36523, 13172, 0, 0, 30753, 29133, 25957, 0, 23357, 26128, 37409, 12401, + 6306, 2811, 29878, 0, 0, 18274, 0, 40541, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25674, 0, 0, 34669, 9205, 0, 17265, 2525, 0, 0, 0, 5718, 0, + 38677, 22929, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18579, 0, 39846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17477, 0, 0, 0, 19173, 0, 0, 0, 0, 0, 0, 0, 6802, 0, 0, + 14980, 17306, 16377, 0, 25675, 9121, 2734, 33539, 0, 0, 39602, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 33982, 1870, 3285, 0, 40353, 10517, 0, 0, 598, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6020, 0, 0, 38685, 9811, 0, 0, 1578, 16227, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13883, 0, 0, 0, 0, 0, + 0, 0, 8334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 19983, 0, 37439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31765, 0, 22716, 27688, 0, 0, + 0, 0, 0, 0, 5504, 0, 0, 0, 4303, 5599, 12244, 2747, 0, 0, 0, 40693, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13323, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29697, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17012, 0, 0, + 0, 0, 23880, 0, 0, 0, 4304, 0, 0, 0, 0, 0, 0, 0, 0, 28540, + 0, 5929, 0, 13092, 0, 0, 0, 0, 0, 0, 0, 39604, 15001, 0, 20562, 0, + 19147, 0, 0, 0, 0, 0, 786, 0, 0, 0, 0, 0, 0, 41135, 0, 0, + 0, 0, 0, 0, 0, 38916, 0, 0, 37126, 0, 0, 789, 0, 0, 19274, 31784, + 11070, 35721, 6824, 9089, 29775, 39077, 0, 24633, 27997, 17635, 24717, 18067, 9418, 16498, 29678, 4915, + 18575, 11529, 27199, 13380, 41211, 8333, 30633, 0, 0, 16039, 6494, 27792, 23280, 34829, 0, 0, + 0, 27068, 0, 8330, 0, 0, 5389, 35033, 0, 0, 0, 23759, 0, 26425, 2903, 20520, + 0, 20525, 0, 0, 0, 21123, 0, 0, 4497, 0, 21543, 38837, 2458, 0, 0, 27797, + 21548, 4462, 0, 0, 15087, 0, 26431, 0, 40210, 6744, 231, 1094, 0, 0, 29196, 0, + 22581, 31991, 24650, 26791, 0, 0, 0, 28780, 0, 0, 0, 19394, 22658, 0, 29210, 25446, + 0, 0, 0, 0, 0, 0, 0, 4537, 0, 0, 12221, 7776, 31390, 13547, 16583, 38355, + 22391, 2290, 0, 21743, 0, 2822, 0, 0, 0, 0, 0, 0, 0, 0, 19410, 9684, + 21484, 3713, 2860, 0, 0, 0, 21061, 0, 0, 31918, 14259, 12440, 39194, 0, 0, 0, + 0, 29541, 0, 0, 19815, 37721, 0, 39902, 29995, 25705, 32989, 31514, 0, 29545, 21708, 0, + 30484, 12887, 0, 7578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1491, 0, 0, 0, 0, 35476, 0, 0, 5986, 12156, 8431, 0, 0, 12898, + 14193, 0, 0, 0, 0, 0, 15132, 0, 0, 0, 25067, 0, 20994, 20719, 33681, 27829, + 26720, 15830, 25075, 30612, 0, 0, 0, 5997, 20997, 0, 25749, 8913, 6297, 0, 21400, 0, + 0, 2984, 10415, 34639, 0, 0, 0, 0, 0, 29816, 2082, 0, 10959, 36652, 0, 26987, + 4025, 0, 0, 0, 0, 0, 0, 0, 0, 32647, 19819, 17045, 29113, 0, 12915, 0, + 0, 0, 39591, 9273, 9393, 0, 23526, 0, 7436, 37196, 38987, 30734, 6877, 2669, 31600, 0, + 9194, 0, 0, 0, 0, 0, 0, 25085, 11811, 0, 32891, 36346, 0, 28501, 30252, 8063, + 13828, 22622, 0, 0, 0, 26792, 37091, 15719, 0, 22629, 32899, 21846, 32402, 13173, 33703, 0, + 1343, 0, 0, 0, 21001, 0, 17592, 0, 22682, 0, 0, 0, 14172, 0, 0, 0, + 28430, 34670, 124, 0, 0, 32664, 23930, 31299, 28843, 0, 15098, 0, 0, 0, 0, 0, + 16148, 0, 0, 0, 0, 0, 0, 16537, 0, 21208, 0, 0, 6309, 27299, 0, 13489, + 21582, 0, 37102, 0, 0, 0, 0, 0, 2448, 0, 13490, 0, 11243, 30944, 35128, 6864, + 9471, 11152, 13395, 0, 0, 0, 0, 0, 0, 0, 16812, 0, 26388, 36672, 0, 5473, + 9372, 21689, 0, 28256, 32566, 0, 25818, 2886, 0, 0, 0, 0, 0, 0, 25734, 0, + 37816, 0, 7590, 13202, 33717, 0, 0, 0, 31896, 27301, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32921, 17366, 0, 0, 29698, 0, 0, 20104, 2832, 11957, 0, + 0, 40412, 37786, 0, 0, 0, 0, 0, 0, 0, 0, 16397, 0, 34454, 5332, 32524, + 37689, 29528, 1001, 25891, 32331, 5949, 22606, 22665, 0, 28422, 0, 13369, 35123, 0, 37768, 0, + 25354, 24076, 23217, 5843, 23218, 0, 0, 10047, 37529, 36721, 12264, 8340, 9859, 27010, 0, 24676, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30973, 0, 0, 39179, 22905, 34351, 9076, + 14594, 29335, 0, 0, 0, 0, 0, 6892, 0, 0, 34151, 17955, 1171, 0, 0, 0, + 40821, 10628, 0, 6714, 0, 6558, 33849, 0, 26264, 0, 26265, 34921, 25176, 0, 0, 0, + 0, 0, 0, 0, 30076, 0, 0, 1750, 33615, 29965, 3305, 0, 6271, 35722, 0, 0, + 0, 3076, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14733, 12119, 0, 38871, 1007, 0, 29297, 0, 0, 0, 0, + 22322, 0, 0, 0, 0, 8173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 30139, 0, 32159, 21322, 18371, 0, 0, 40609, 0, 39264, + 27556, 40894, 7715, 6495, 22602, 34492, 27915, 24620, 6929, 23751, 0, 23811, 0, 2154, 34117, 0, + 0, 0, 0, 0, 0, 40513, 0, 0, 19613, 13431, 0, 0, 0, 0, 0, 38645, + 22525, 31515, 34622, 7514, 21531, 0, 39715, 0, 28341, 0, 35816, 0, 16739, 33653, 0, 35817, + 0, 0, 30539, 0, 0, 12143, 3127, 5981, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37560, 0, 31680, 0, 18225, 28342, 0, 0, 0, 0, 0, 0, 0, + 0, 1022, 32032, 34630, 0, 4712, 0, 15258, 0, 0, 24359, 18509, 1087, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38709, 4695, 31217, 33504, 3135, 10220, 14916, 0, + 3223, 2557, 2791, 39492, 34069, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8717, 3185, 35216, 0, 0, 0, 0, 3956, 24796, 33027, 0, 38718, 15492, + 0, 14935, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24797, 0, 19880, + 35239, 41011, 23083, 0, 27122, 0, 0, 0, 0, 27321, 2709, 0, 0, 6370, 0, 9765, + 18815, 34332, 0, 0, 0, 0, 21469, 1715, 0, 0, 0, 0, 0, 0, 0, 29926, + 0, 0, 0, 0, 0, 0, 21358, 11297, 23791, 0, 0, 0, 0, 0, 0, 32048, + 0, 0, 18147, 0, 0, 0, 0, 17428, 0, 35895, 0, 17203, 27768, 0, 0, 5069, + 0, 0, 30859, 0, 0, 4448, 0, 0, 0, 14303, 10658, 0, 36999, 0, 15927, 0, + 0, 0, 10176, 8651, 7411, 0, 0, 15936, 0, 0, 9526, 3544, 0, 0, 14305, 0, + 0, 28135, 0, 0, 5987, 0, 0, 0, 0, 0, 0, 0, 28166, 0, 0, 0, + 24259, 0, 0, 0, 9536, 0, 0, 0, 0, 0, 0, 40499, 0, 0, 29423, 0, + 0, 37740, 0, 0, 0, 0, 0, 41161, 0, 0, 0, 0, 0, 0, 0, 31220, + 4740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39785, 0, 0, 0, 0, + 27543, 0, 6154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30622, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3745, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25722, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12394, 0, 0, 0, 0, 0, 5876, 0, 2336, 0, + 15622, 0, 0, 30634, 0, 0, 0, 2270, 0, 0, 19264, 21972, 0, 0, 0, 0, + 0, 0, 25884, 0, 0, 0, 30643, 0, 0, 0, 0, 0, 25887, 0, 0, 13880, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30647, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2218, 17000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37789, + 0, 0, 0, 0, 37817, 0, 0, 3250, 0, 0, 26226, 0, 0, 0, 0, 0, + 0, 0, 10859, 26191, 29996, 0, 7832, 0, 24332, 33494, 0, 0, 0, 4083, 8194, 0, + 0, 0, 35849, 6150, 8026, 8027, 38251, 23127, 0, 18070, 0, 0, 0, 26192, 22218, 0, + 0, 0, 36165, 19215, 11227, 36279, 1061, 36940, 26552, 0, 33017, 3955, 0, 0, 0, 0, + 0, 0, 0, 0, 26553, 5817, 0, 0, 0, 35896, 0, 3101, 8846, 18388, 22885, 37889, + 34647, 20653, 0, 28140, 0, 0, 0, 0, 0, 0, 0, 14162, 0, 27854, 22150, 0, + 34204, 26024, 6748, 0, 0, 4157, 33042, 0, 29869, 8922, 33883, 0, 16167, 0, 18095, 0, + 5064, 38441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36101, 27806, 0, 37197, + 30118, 30119, 0, 0, 482, 25195, 1986, 5070, 0, 38445, 10781, 0, 0, 0, 11708, 0, + 0, 0, 0, 0, 0, 18608, 0, 0, 0, 0, 18196, 25579, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5225, 19891, 32044, 31025, 10019, 40792, 39226, 26046, 4861, 17266, 0, + 5745, 17471, 9072, 0, 0, 0, 22384, 0, 0, 0, 36357, 0, 10818, 0, 6582, 31391, + 0, 0, 0, 0, 0, 0, 0, 22751, 10496, 0, 18396, 20674, 7483, 18911, 38288, 2007, + 5835, 19541, 0, 40487, 18833, 22132, 6590, 2151, 0, 0, 0, 0, 3144, 19465, 0, 0, + 0, 0, 0, 0, 0, 0, 31634, 0, 0, 0, 0, 0, 0, 205, 39918, 0, + 21029, 30173, 10446, 0, 0, 6593, 30288, 39919, 2463, 17307, 27477, 0, 0, 0, 2464, 0, + 27685, 0, 6594, 0, 11886, 0, 0, 0, 0, 0, 0, 0, 12961, 21745, 5237, 8268, + 12071, 11851, 4418, 0, 36659, 25819, 29522, 0, 0, 0, 0, 0, 0, 0, 18349, 0, + 0, 28102, 18129, 19411, 5838, 0, 0, 0, 22176, 0, 18130, 0, 0, 17347, 0, 21768, + 0, 0, 0, 17852, 26289, 0, 7551, 0, 0, 0, 0, 26290, 0, 0, 18140, 38741, + 0, 1724, 17006, 0, 0, 27698, 25214, 12972, 40696, 0, 0, 18143, 18144, 19986, 0, 27492, + 0, 0, 0, 0, 18148, 0, 0, 11944, 0, 0, 0, 0, 0, 0, 18167, 12975, + 24861, 0, 0, 0, 21749, 14142, 3128, 0, 0, 0, 0, 0, 39108, 24431, 0, 24433, + 7012, 0, 0, 26058, 0, 0, 0, 0, 0, 909, 0, 7424, 0, 0, 7515, 7452, + 0, 0, 0, 0, 7372, 15678, 0, 0, 0, 0, 37987, 11793, 0, 7458, 0, 0, + 0, 6595, 0, 0, 0, 0, 21989, 21710, 22167, 5196, 5108, 89, 0, 29319, 3026, 342, + 19792, 21018, 0, 0, 2042, 37338, 32098, 19357, 0, 0, 22834, 0, 6536, 0, 5400, 0, + 0, 33309, 21351, 9949, 4029, 27429, 19430, 0, 0, 0, 0, 0, 30418, 35950, 5924, 34333, + 0, 31122, 28113, 0, 202, 16362, 21023, 0, 24667, 20276, 21874, 2272, 2291, 0, 0, 0, + 16451, 29333, 35273, 0, 21415, 0, 27431, 0, 0, 0, 0, 4419, 0, 13085, 0, 0, + 8480, 0, 0, 0, 13209, 9813, 0, 38635, 0, 19182, 0, 0, 12126, 9641, 0, 0, + 0, 12777, 12453, 0, 0, 33872, 0, 7725, 0, 0, 0, 1269, 23301, 0, 0, 37575, + 269, 5532, 0, 0, 6964, 7615, 0, 0, 14648, 21281, 30110, 0, 26630, 8037, 31986, 24790, + 22989, 30369, 18081, 19305, 40096, 814, 0, 37339, 0, 0, 0, 0, 1045, 19358, 0, 12733, + 0, 34839, 0, 15727, 13536, 0, 1785, 0, 0, 0, 19218, 9612, 6794, 39786, 0, 0, + 0, 39216, 6991, 40165, 456, 0, 0, 0, 39217, 7732, 6300, 21406, 2142, 6576, 26126, 26036, + 1329, 0, 0, 0, 39802, 38988, 2143, 0, 0, 0, 14946, 34132, 0, 0, 0, 31872, + 0, 40668, 557, 34990, 3866, 28507, 23704, 0, 21148, 37392, 7006, 12932, 35951, 32661, 0, 21568, + 0, 0, 1755, 0, 0, 0, 0, 9834, 32900, 5925, 0, 0, 14443, 28370, 6010, 8074, + 20258, 27133, 33890, 29134, 37410, 0, 0, 32908, 8075, 39834, 21293, 33891, 34804, 0, 7784, 40990, + 40111, 33775, 0, 0, 0, 40172, 0, 16238, 0, 36524, 8622, 16150, 0, 6852, 30635, 19739, + 0, 0, 0, 11263, 3868, 0, 28377, 28516, 28378, 28517, 33981, 0, 8964, 12825, 0, 2008, + 28518, 37627, 0, 0, 0, 0, 0, 0, 28519, 0, 0, 0, 0, 4214, 0, 0, + 33340, 10444, 28324, 0, 0, 0, 0, 20677, 3734, 28146, 38289, 18841, 38773, 19230, 33708, 12957, + 26257, 0, 33709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13286, 0, + 0, 0, 830, 19334, 0, 29648, 31894, 0, 0, 25459, 0, 26773, 40118, 0, 12962, 8269, + 5501, 0, 0, 36593, 14450, 0, 36015, 676, 0, 26059, 28259, 0, 6711, 33090, 0, 0, + 0, 11364, 0, 0, 0, 25606, 21302, 40120, 9686, 0, 19236, 0, 0, 0, 0, 0, + 0, 0, 39447, 33718, 0, 39448, 0, 14997, 14452, 0, 0, 37613, 18642, 0, 0, 2029, + 0, 0, 25461, 33099, 0, 0, 0, 0, 0, 31769, 19149, 0, 0, 0, 8760, 0, + 0, 41123, 10085, 0, 13355, 25770, 24261, 25118, 22194, 37741, 3094, 8039, 22240, 0, 0, 19794, + 0, 0, 28911, 0, 15480, 31850, 0, 0, 0, 0, 0, 6795, 0, 35897, 0, 0, + 28223, 0, 31996, 14722, 0, 30623, 0, 35933, 0, 37393, 0, 558, 30124, 28508, 22199, 0, + 0, 0, 1790, 0, 0, 37940, 37941, 6513, 25667, 30636, 0, 0, 0, 0, 0, 30760, + 9676, 0, 4970, 32010, 0, 0, 11941, 14745, 28147, 0, 28254, 0, 0, 18539, 562, 37431, + 39354, 9683, 0, 15916, 8569, 5131, 0, 0, 0, 32301, 38546, 26060, 0, 15395, 2088, 2023, + 0, 0, 28260, 0, 37450, 2089, 14281, 14282, 0, 14805, 15009, 0, 20875, 38542, 28893, 30710, + 31982, 32998, 0, 0, 0, 25811, 12211, 0, 0, 33077, 0, 0, 6598, 40851, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 37623, 24335, 8040, 22365, 22195, 0, 36283, 0, + 10593, 41066, 0, 8916, 6212, 10324, 31112, 0, 22129, 0, 0, 28052, 15224, 21569, 10237, 7805, + 7007, 35259, 0, 0, 29516, 6218, 39005, 25916, 0, 0, 0, 20678, 28080, 0, 16665, 0, + 23123, 6867, 40689, 35276, 0, 0, 0, 32465, 9494, 25295, 18175, 0, 0, 358, 0, 0, + 2612, 0, 6699, 24475, 15651, 33496, 11326, 34901, 39203, 29549, 1042, 0, 0, 257, 0, 15194, + 0, 15654, 22255, 36905, 341, 19816, 20635, 0, 0, 0, 0, 0, 8121, 24360, 16193, 6265, + 28726, 0, 0, 23822, 35086, 30811, 10950, 20643, 10323, 33878, 0, 1289, 22925, 0, 5534, 0, + 39160, 0, 26866, 15218, 2438, 0, 0, 33506, 39161, 0, 40252, 0, 0, 0, 0, 11794, + 3552, 0, 0, 10709, 21762, 21557, 34648, 0, 3744, 8131, 9466, 23190, 0, 8785, 29552, 0, + 0, 0, 28729, 23824, 0, 0, 14352, 33521, 23435, 0, 39218, 0, 0, 0, 24654, 0, + 6878, 0, 0, 11814, 10732, 24410, 0, 3056, 0, 0, 8238, 0, 10599, 31601, 31223, 19516, + 0, 0, 29054, 0, 0, 10600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1973, 0, 24308, 8786, 0, 0, 8064, 15983, 0, 0, 0, 0, 0, 1663, 14173, 15225, + 9544, 0, 8596, 33530, 234, 37754, 31386, 35517, 14061, 0, 18817, 24974, 29924, 0, 12626, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14234, 14954, 22763, 16069, 0, 0, + 30266, 11835, 6665, 37626, 13749, 0, 9672, 8599, 23001, 19823, 40440, 10190, 0, 0, 0, 0, + 0, 0, 0, 0, 36610, 24658, 0, 16807, 259, 22592, 31009, 0, 0, 24341, 0, 24311, + 20355, 6248, 20042, 38620, 0, 24416, 35526, 0, 0, 0, 0, 0, 0, 0, 597, 0, + 0, 14725, 0, 38290, 33710, 16378, 19265, 19266, 21937, 864, 0, 23028, 33711, 0, 0, 0, + 383, 0, 0, 0, 0, 0, 10711, 0, 0, 10712, 38686, 0, 26075, 8600, 0, 22946, + 17751, 0, 0, 0, 0, 30269, 33786, 0, 0, 0, 0, 0, 15964, 0, 0, 7029, + 10143, 26061, 0, 0, 5239, 0, 0, 0, 0, 0, 33787, 0, 7034, 8365, 0, 5348, + 0, 19965, 35359, 21671, 0, 22808, 0, 0, 0, 2339, 0, 0, 0, 0, 37662, 0, + 7038, 21605, 0, 0, 36247, 0, 0, 24037, 0, 10609, 18149, 0, 2676, 36504, 0, 0, + 0, 0, 9380, 0, 21477, 33507, 28668, 14007, 0, 0, 0, 22355, 0, 17652, 0, 0, + 918, 0, 0, 33152, 30000, 2983, 8402, 0, 10864, 30487, 0, 0, 8029, 22289, 0, 21083, + 34060, 33974, 0, 0, 18313, 18082, 33976, 24727, 10221, 35486, 10106, 0, 8041, 453, 35487, 0, + 1948, 0, 0, 0, 10594, 17205, 0, 0, 0, 25796, 31577, 0, 0, 0, 27111, 22703, + 11233, 35497, 1961, 1974, 21179, 24655, 0, 0, 30735, 3109, 36796, 0, 30830, 11700, 25805, 0, + 0, 0, 10733, 27892, 10121, 22197, 0, 7384, 0, 18263, 40109, 22549, 0, 17243, 0, 0, + 4212, 31614, 39297, 0, 1067, 39322, 28235, 34546, 0, 0, 0, 0, 24365, 31387, 17619, 0, + 38898, 17593, 0, 0, 0, 13598, 0, 10605, 36704, 0, 16209, 10819, 0, 37659, 10699, 35260, + 0, 36494, 33840, 36803, 0, 0, 0, 0, 24976, 0, 0, 0, 28847, 28379, 0, 17288, + 27902, 17289, 0, 0, 37418, 0, 0, 35984, 0, 0, 0, 0, 0, 33417, 323, 29882, + 28081, 27453, 0, 37432, 0, 7741, 0, 0, 0, 28083, 29933, 37433, 39304, 39305, 0, 28970, + 0, 0, 0, 0, 18288, 0, 3374, 28163, 25964, 0, 0, 0, 0, 0, 0, 9210, + 7749, 17858, 22717, 0, 0, 0, 17371, 0, 18444, 3896, 32689, 10610, 33100, 26570, 0, 0, + 18451, 10741, 33823, 7755, 0, 442, 1894, 28947, 27998, 38876, 1537, 27874, 29909, 28356, 32637, 10553, + 25955, 0, 7432, 0, 0, 0, 0, 21717, 19542, 0, 0, 0, 0, 11365, 39450, 0, + 0, 0, 35723, 0, 37247, 0, 0, 35448, 37671, 3473, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36213, 21715, 25482, 0, 0, 0, 20901, 0, 0, 0, 0, + 0, 0, 0, 29267, 0, 424, 0, 0, 0, 0, 7118, 39278, 6965, 23022, 12157, 21243, + 0, 14224, 12778, 0, 0, 8403, 0, 0, 0, 18071, 0, 41182, 0, 0, 924, 0, + 0, 0, 0, 0, 0, 27257, 35582, 22010, 0, 0, 0, 21127, 27104, 0, 19427, 27105, + 0, 29103, 0, 0, 0, 0, 0, 0, 8914, 0, 0, 0, 0, 16802, 776, 37512, + 41236, 16499, 33401, 0, 0, 38049, 3395, 12916, 19674, 12785, 37359, 0, 0, 37360, 35498, 0, + 0, 0, 19472, 38050, 0, 40532, 29115, 0, 0, 31851, 14512, 38095, 18802, 28962, 0, 0, + 40536, 18096, 0, 14670, 0, 0, 12198, 14744, 0, 0, 40781, 0, 37677, 6155, 0, 0, + 0, 0, 21048, 0, 0, 0, 3730, 0, 0, 0, 0, 0, 0, 0, 0, 272, + 0, 0, 0, 8816, 0, 1866, 6110, 30737, 0, 0, 0, 0, 24973, 15389, 0, 0, + 22630, 15226, 8071, 36657, 0, 29875, 29711, 36909, 34912, 0, 35126, 0, 0, 34665, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32217, 0, 29127, 0, 28236, 0, 0, 0, + 4410, 0, 0, 0, 33585, 31388, 2234, 37394, 0, 0, 2812, 32008, 0, 15335, 2337, 2526, + 24666, 0, 0, 4921, 0, 28075, 0, 0, 11150, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31175, 37517, 0, 0, 0, 0, 13321, 32516, 38531, + 25885, 20553, 0, 26399, 2386, 28145, 4162, 20043, 40218, 3732, 12641, 3733, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17480, 0, 0, 0, 0, 9920, 0, + 0, 0, 0, 0, 6625, 32518, 3287, 26400, 17308, 11542, 0, 0, 5500, 0, 0, 17597, + 0, 0, 0, 0, 0, 0, 37970, 0, 0, 0, 12066, 17922, 0, 0, 6391, 10139, + 36590, 37661, 9850, 18126, 0, 17519, 0, 385, 5265, 36007, 21746, 26355, 0, 33198, 0, 0, + 4973, 37434, 2241, 31130, 2570, 2021, 0, 13080, 0, 0, 0, 0, 0, 0, 19932, 30767, + 20559, 0, 0, 0, 0, 27548, 13761, 27609, 12074, 0, 0, 4343, 0, 18442, 11282, 0, + 30061, 0, 0, 37123, 0, 0, 2861, 36599, 12079, 0, 16436, 0, 0, 0, 0, 20870, + 401, 8384, 35558, 12758, 0, 4937, 6098, 34113, 25291, 14736, 29862, 33568, 27849, 0, 2370, 3271, + 0, 6072, 0, 0, 0, 0, 0, 0, 0, 0, 9875, 0, 0, 0, 0, 31289, + 0, 0, 0, 0, 0, 0, 23440, 0, 12212, 0, 0, 0, 0, 0, 15958, 30639, + 0, 0, 0, 0, 0, 0, 27175, 8084, 0, 29885, 0, 1656, 0, 28664, 10153, 22759, + 0, 0, 0, 37055, 28669, 0, 0, 0, 0, 0, 0, 0, 32456, 0, 33414, 0, + 0, 0, 0, 31028, 9921, 22393, 0, 0, 0, 0, 0, 0, 0, 28707, 0, 1669, + 32463, 0, 0, 35607, 0, 0, 22728, 11318, 20768, 425, 0, 7344, 0, 0, 0, 6064, + 0, 0, 0, 0, 0, 0, 0, 7582, 0, 0, 13819, 0, 0, 0, 28325, 0, + 0, 0, 0, 0, 30409, 8657, 0, 0, 7583, 0, 30114, 0, 30931, 9275, 6683, 0, + 38980, 4432, 35047, 0, 642, 2140, 20654, 0, 22959, 0, 0, 8728, 0, 0, 18249, 0, + 0, 25192, 0, 0, 0, 0, 0, 0, 8408, 0, 10961, 20723, 0, 0, 33403, 11473, + 8065, 11681, 0, 24805, 13727, 30057, 37078, 20660, 40025, 14356, 0, 27294, 15831, 24499, 17814, 8239, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33698, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17975, 0, 21570, 0, 22478, 0, 8247, 2147, 35952, 0, + 0, 1987, 0, 6850, 0, 0, 0, 0, 0, 38995, 0, 17244, 0, 0, 29843, 4966, + 0, 18827, 34336, 6159, 24190, 30382, 20510, 41152, 8258, 24747, 967, 346, 23931, 0, 0, 0, + 0, 25120, 0, 0, 0, 0, 0, 0, 25096, 11189, 32405, 16108, 0, 0, 0, 4801, + 0, 0, 35524, 0, 0, 0, 3442, 40992, 21138, 3372, 6484, 36611, 39024, 0, 28760, 34808, + 32911, 33782, 0, 6514, 27430, 32223, 32224, 0, 0, 6863, 0, 0, 0, 0, 0, 0, + 0, 0, 16170, 0, 0, 0, 0, 0, 30849, 36708, 37104, 0, 0, 29058, 0, 13881, + 0, 28850, 23375, 0, 5750, 28927, 18956, 38733, 30904, 12651, 284, 21973, 23618, 0, 0, 0, + 26889, 28434, 0, 0, 20679, 0, 0, 0, 36809, 0, 0, 0, 0, 0, 0, 0, + 38453, 0, 0, 35001, 0, 0, 0, 0, 0, 0, 0, 3709, 16985, 37114, 2826, 35355, + 0, 0, 3658, 0, 16986, 0, 0, 0, 0, 0, 0, 0, 0, 29829, 0, 41087, + 0, 0, 32235, 0, 0, 0, 0, 31899, 0, 1670, 10021, 23384, 25917, 0, 7446, 0, + 26357, 0, 0, 0, 0, 0, 0, 0, 11300, 0, 0, 0, 0, 0, 0, 0, + 717, 37121, 37122, 0, 12418, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15747, 40946, 0, 0, 0, 0, 0, 0, 32426, 19936, 0, 0, 0, 0, 0, + 0, 0, 0, 17372, 39868, 7294, 17860, 2219, 6405, 9472, 33368, 17013, 23558, 0, 0, 15002, + 30063, 0, 14697, 32690, 0, 0, 0, 0, 24858, 0, 0, 0, 40413, 0, 0, 0, + 0, 15010, 0, 0, 0, 0, 13790, 0, 40067, 32324, 18360, 34818, 25177, 35691, 17776, 1835, + 11889, 12511, 6197, 39986, 24905, 13646, 0, 0, 0, 0, 14468, 0, 963, 0, 0, 1083, + 8703, 4286, 0, 23761, 27876, 30800, 3338, 18504, 37023, 16163, 23762, 5737, 28423, 38710, 0, 7259, + 17835, 29474, 12127, 23663, 10932, 0, 0, 37025, 23502, 37026, 30192, 0, 478, 23304, 25771, 24003, + 34273, 32271, 0, 0, 0, 0, 0, 0, 4356, 7345, 0, 16093, 9712, 25033, 6973, 24487, + 0, 0, 19306, 15660, 35043, 0, 0, 25034, 3890, 12822, 0, 40253, 0, 6537, 30213, 0, + 21129, 0, 0, 0, 34407, 29632, 0, 0, 0, 0, 0, 33279, 9719, 22837, 0, 0, + 0, 37198, 10486, 0, 40658, 0, 0, 26496, 37201, 0, 0, 12627, 0, 23925, 27545, 4335, + 41076, 16839, 21255, 0, 30204, 38446, 0, 5226, 0, 0, 0, 0, 0, 0, 6468, 1512, + 13599, 23614, 10440, 3759, 34419, 0, 34672, 0, 0, 0, 27815, 29026, 35056, 0, 15307, 0, + 40503, 9677, 45, 9922, 0, 0, 0, 0, 28380, 33712, 1576, 0, 7806, 24751, 19543, 0, + 9808, 0, 0, 0, 0, 0, 1378, 14984, 4165, 0, 0, 23098, 0, 0, 0, 36008, + 0, 0, 23720, 36017, 7030, 18131, 0, 1383, 0, 0, 0, 0, 0, 12075, 20571, 0, + 0, 34023, 0, 0, 34703, 0, 0, 0, 17373, 0, 28711, 0, 0, 0, 19007, 0, + 15176, 19669, 32638, 0, 0, 0, 0, 57, 0, 0, 28426, 0, 0, 19798, 0, 9761, + 0, 0, 0, 8593, 21089, 10238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25036, 0, 0, 0, 0, 2387, 25989, 0, 0, 0, 0, 22558, 0, 0, 0, 0, + 0, 0, 32817, 32691, 14486, 0, 0, 0, 0, 3346, 21124, 0, 0, 0, 0, 0, + 21191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20777, 0, 26432, + 0, 5741, 0, 0, 18089, 0, 39164, 35048, 0, 8229, 23779, 24492, 14507, 1814, 19587, 38512, + 28548, 0, 0, 0, 3696, 0, 0, 0, 0, 0, 0, 38553, 0, 26874, 36670, 0, + 24500, 5404, 29203, 40508, 0, 36288, 0, 21132, 1867, 15833, 39593, 6749, 4529, 779, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16948, 0, 0, 14518, 30942, 17823, 0, 0, 31075, + 26991, 21467, 19518, 14278, 0, 0, 0, 0, 33408, 0, 0, 0, 0, 31058, 0, 5408, + 0, 31623, 240, 4967, 40968, 10133, 4213, 1100, 0, 6216, 0, 38793, 0, 0, 0, 34177, + 0, 0, 5590, 11954, 0, 0, 0, 20416, 0, 0, 8260, 0, 783, 15474, 19592, 25260, + 40941, 23616, 31936, 27905, 33415, 20919, 0, 0, 0, 19403, 0, 0, 0, 0, 38404, 2725, + 26562, 31077, 0, 0, 0, 0, 46, 716, 10204, 0, 25962, 28381, 29216, 34278, 0, 1821, + 25458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26134, 31029, 0, 0, 325, + 0, 40468, 0, 22752, 28148, 35356, 27906, 6249, 27907, 19127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7550, 41233, 0, 21150, 5474, 39521, 4840, 17708, 12466, 1872, 4584, 3376, 2087, + 0, 25864, 38111, 0, 0, 0, 0, 0, 13554, 0, 0, 35113, 18691, 0, 2314, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21304, 0, 0, 0, 0, 0, 0, 0, + 13764, 23102, 40488, 38116, 0, 0, 0, 0, 0, 0, 17378, 0, 0, 16232, 0, 0, + 3715, 0, 0, 38743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1498, 31001, 0, + 0, 0, 0, 10735, 0, 0, 0, 22782, 0, 26063, 0, 0, 0, 0, 21305, 7591, + 33579, 0, 26989, 0, 14689, 0, 0, 0, 14994, 0, 37457, 0, 9749, 9754, 0, 10962, + 0, 0, 17224, 32893, 7094, 37594, 9879, 0, 0, 14174, 0, 15471, 0, 40934, 7539, 0, + 22340, 8817, 0, 12948, 21257, 0, 32225, 17310, 3028, 0, 7099, 8820, 37435, 11010, 7548, 326, + 0, 0, 0, 7129, 0, 0, 0, 0, 15478, 15707, 2024, 0, 0, 35280, 13556, 0, + 0, 0, 0, 0, 0, 0, 3031, 8822, 25623, 0, 37790, 0, 17931, 0, 0, 0, + 0, 37459, 37796, 38537, 32692, 0, 0, 20370, 0, 0, 0, 9596, 14263, 0, 30165, 0, + 0, 31681, 30699, 40629, 30801, 15938, 0, 0, 19788, 0, 10280, 10152, 7373, 21687, 36906, 11218, + 0, 0, 16530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40204, 9611, 1291, 12823, 29390, 0, 18936, 15569, 41162, 18083, 23321, 0, 40207, 0, 0, 0, + 0, 9181, 41112, 0, 34739, 27947, 0, 15947, 0, 2877, 0, 34975, 0, 0, 37361, 0, + 0, 0, 0, 0, 0, 27266, 16298, 35899, 6242, 0, 0, 0, 31224, 36489, 8066, 40436, + 8133, 0, 28053, 17050, 35092, 29960, 0, 0, 0, 0, 0, 0, 0, 9661, 0, 0, + 0, 18944, 34666, 23347, 16536, 40216, 0, 9615, 10888, 0, 0, 0, 0, 0, 0, 14062, + 0, 0, 3555, 0, 0, 14521, 38448, 0, 20288, 0, 0, 0, 0, 0, 0, 0, + 40173, 8413, 33339, 12403, 0, 0, 0, 26197, 19803, 37946, 0, 0, 0, 27204, 0, 0, + 18957, 36912, 13322, 21862, 0, 0, 0, 0, 14690, 36913, 0, 0, 36009, 29031, 30649, 3067, + 17987, 9240, 0, 17325, 17752, 0, 0, 13398, 34811, 1583, 23377, 0, 0, 0, 36018, 0, + 0, 1723, 19934, 2605, 0, 8415, 0, 0, 0, 24846, 5600, 16720, 0, 0, 0, 0, + 18150, 0, 0, 0, 11305, 24857, 0, 19150, 0, 15972, 0, 0, 0, 24640, 37179, 11219, + 0, 0, 0, 16797, 0, 25347, 32731, 27757, 0, 0, 6457, 1626, 0, 0, 0, 0, + 21688, 0, 10480, 22242, 0, 7526, 20821, 0, 0, 7883, 0, 0, 10964, 30454, 26122, 0, + 13370, 31290, 0, 0, 0, 0, 0, 0, 0, 8230, 0, 0, 0, 0, 0, 0, + 0, 1787, 40344, 0, 40213, 3437, 0, 26686, 10884, 2063, 0, 0, 0, 0, 25194, 0, + 0, 0, 0, 0, 0, 0, 20827, 0, 17225, 0, 0, 12740, 0, 0, 19312, 0, + 0, 19892, 20728, 40028, 32284, 11706, 9342, 14358, 0, 20828, 0, 25621, 0, 31230, 0, 25580, + 0, 38515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 21873, 32901, 0, 13313, 0, 0, 0, 0, 0, 0, 17053, 27272, 35968, 5591, 24393, + 14522, 0, 0, 39835, 0, 16504, 2149, 15845, 35969, 0, 1997, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3654, 0, 0, 0, 0, 0, 13318, 0, 31125, + 34134, 0, 0, 0, 0, 29977, 19519, 0, 7385, 40679, 0, 23617, 0, 28433, 23365, 0, + 22415, 1635, 7679, 29844, 11241, 0, 0, 7017, 0, 0, 0, 7018, 0, 0, 6114, 0, + 25585, 0, 0, 0, 0, 0, 7019, 0, 0, 0, 0, 0, 0, 0, 34680, 27772, + 0, 0, 0, 0, 0, 36448, 21259, 21260, 35527, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 20044, 0, 0, 0, 0, 35148, 22931, + 4610, 0, 30860, 0, 9924, 36372, 0, 29520, 39855, 7445, 36810, 0, 0, 15960, 241, 489, + 0, 10138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21003, 20973, + 0, 0, 14074, 0, 0, 30567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4039, 0, 28383, 28928, 23379, 28851, 30765, 8446, 0, 8754, 0, 10140, 0, 20922, 8755, + 0, 0, 0, 0, 39306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 28436, 0, 0, 0, 27686, 0, 21359, 25932, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32917, 0, 0, 0, 41089, + 37118, 21360, 23210, 0, 0, 26649, 0, 0, 0, 0, 0, 0, 2064, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16077, 16994, 0, 9281, 0, + 0, 0, 0, 0, 0, 0, 34574, 2153, 13205, 0, 31239, 2466, 17927, 40450, 0, 11655, + 0, 29651, 38481, 0, 10518, 0, 0, 9841, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14113, 0, 0, 0, 6027, 0, 36462, 0, 0, 0, 0, 39866, 0, 0, 0, + 0, 0, 30771, 0, 12669, 25499, 0, 0, 387, 5266, 19141, 35281, 30569, 0, 0, 0, + 0, 0, 23961, 0, 0, 0, 0, 0, 0, 8758, 12670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 41035, 0, 35539, 0, 0, 38482, 0, 17862, 0, 0, + 0, 0, 0, 0, 35284, 0, 0, 0, 0, 0, 0, 0, 38634, 0, 0, 0, + 3851, 1587, 0, 0, 0, 0, 33720, 36717, 0, 0, 0, 0, 0, 33101, 30654, 17381, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2030, 13094, 2753, 16079, 0, + 0, 24397, 0, 0, 0, 0, 0, 27495, 31666, 24859, 0, 0, 0, 0, 0, 0, + 19152, 0, 0, 5286, 21384, 17069, 0, 498, 0, 6953, 7869, 8195, 11913, 38508, 162, 0, + 0, 24651, 3819, 20254, 34131, 29842, 21254, 11137, 27269, 0, 33531, 39971, 15281, 0, 0, 0, + 0, 0, 32625, 32626, 4458, 3614, 0, 5865, 35850, 0, 6066, 0, 0, 10107, 30322, 0, + 35585, 816, 35873, 0, 0, 0, 0, 34127, 0, 0, 0, 0, 32490, 0, 0, 0, + 0, 0, 0, 1106, 0, 0, 13720, 8659, 38315, 0, 39221, 10965, 31578, 33140, 32649, 8231, + 39966, 0, 19675, 33141, 23916, 0, 0, 0, 7625, 588, 11289, 0, 0, 0, 0, 0, + 0, 13371, 0, 819, 34172, 34976, 0, 0, 0, 0, 0, 31852, 0, 14671, 0, 24894, + 37752, 28577, 29708, 20662, 38442, 24807, 0, 7891, 0, 24808, 3647, 0, 36798, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 29123, 0, 0, 30200, 0, 0, 30123, 0, 3929, + 0, 8664, 0, 0, 0, 0, 0, 0, 37515, 8665, 24809, 0, 0, 0, 0, 14672, + 0, 0, 6012, 35519, 26884, 35954, 0, 9616, 13314, 0, 27810, 24505, 0, 7009, 11474, 11683, + 34083, 0, 0, 14520, 0, 38545, 3649, 16608, 0, 23348, 33410, 0, 11643, 29644, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8249, 0, 0, 34084, 13735, 20099, + 37396, 0, 0, 0, 0, 0, 0, 0, 40485, 13383, 39836, 3369, 0, 13750, 32665, 3193, + 16961, 37759, 0, 39837, 16580, 31126, 24821, 0, 30439, 0, 35351, 35970, 16505, 0, 29693, 174, + 14962, 34674, 0, 0, 0, 14680, 0, 39227, 0, 39838, 19540, 0, 0, 0, 33450, 0, + 0, 4160, 3894, 0, 0, 0, 0, 0, 23934, 7443, 2922, 0, 20214, 28077, 348, 0, + 8139, 0, 0, 0, 30851, 39442, 20417, 2884, 34429, 37420, 0, 8261, 28520, 12464, 0, 7543, + 0, 0, 11003, 14449, 0, 37206, 0, 0, 0, 0, 0, 23369, 19740, 0, 0, 1638, + 9836, 0, 0, 0, 20518, 0, 30383, 30384, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14070, 37421, 32231, 0, 0, 4245, 12412, 0, 32459, 22306, 8265, 0, + 0, 0, 18284, 0, 25837, 33912, 41033, 0, 13759, 0, 0, 38625, 0, 37108, 37109, 19744, + 20308, 19680, 6709, 8266, 0, 0, 0, 0, 0, 0, 0, 13196, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20290, 0, 285, 0, 0, 0, 0, 15475, 0, 0, + 0, 0, 0, 0, 0, 0, 10786, 0, 0, 0, 9074, 0, 31654, 0, 25460, 8671, + 22089, 37610, 32047, 0, 0, 26135, 22483, 0, 24395, 36591, 24833, 0, 8980, 0, 8756, 32132, + 0, 28084, 0, 0, 0, 599, 23380, 10820, 0, 0, 0, 31655, 0, 31177, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23211, 11126, 9559, + 0, 5598, 26390, 19369, 20463, 12661, 31716, 32136, 12417, 2924, 15625, 3710, 0, 0, 0, 0, + 0, 0, 38776, 22741, 28086, 19046, 16995, 19984, 3711, 29246, 0, 18132, 0, 3661, 0, 0, + 0, 0, 0, 0, 0, 0, 3712, 0, 0, 3662, 0, 0, 0, 21476, 0, 36613, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20184, 0, + 27279, 0, 31900, 0, 7035, 40804, 0, 0, 13762, 12245, 10740, 26817, 17358, 0, 23214, 0, + 40035, 27692, 24847, 0, 0, 0, 0, 0, 0, 0, 0, 32922, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27693, 0, 0, 0, 33545, 0, 0, 0, 0, + 8271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21747, + 34280, 18296, 12826, 9560, 15968, 3665, 2315, 3944, 0, 9768, 0, 5165, 0, 0, 0, 13207, + 0, 5267, 10822, 0, 15626, 0, 4041, 23729, 134, 0, 22642, 0, 0, 0, 0, 0, + 0, 34142, 14078, 19987, 0, 1725, 16395, 9213, 3850, 0, 0, 36598, 9282, 37125, 40122, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2220, 0, 18298, + 2090, 19244, 13766, 39124, 20369, 9483, 0, 12796, 0, 16233, 0, 0, 0, 0, 0, 0, + 27206, 0, 0, 9769, 0, 0, 19988, 23797, 16322, 0, 10457, 29886, 0, 0, 0, 0, + 0, 11656, 0, 0, 0, 0, 0, 0, 10611, 0, 0, 0, 18916, 0, 0, 12797, + 0, 0, 0, 0, 0, 9561, 0, 0, 35362, 11306, 0, 0, 0, 0, 0, 0, + 19153, 0, 0, 0, 15011, 0, 0, 0, 9447, 0, 0, 24996, 21478, 0, 0, 19417, + 0, 0, 37906, 30917, 3590, 3596, 39406, 0, 4386, 40479, 11166, 13664, 24783, 29747, 20405, 19728, + 37056, 311, 589, 0, 22470, 39122, 18664, 3626, 29691, 0, 13594, 0, 38610, 0, 0, 0, + 0, 0, 13876, 18680, 0, 0, 13189, 28762, 2885, 0, 4471, 0, 0, 30254, 4611, 15245, + 0, 1516, 0, 0, 0, 0, 0, 0, 30907, 0, 0, 23723, 0, 0, 0, 8481, + 0, 0, 11857, 0, 8451, 0, 12672, 8483, 0, 11268, 0, 0, 0, 27758, 0, 0, + 7885, 0, 0, 0, 0, 22539, 0, 2155, 0, 0, 0, 0, 995, 0, 0, 0, + 0, 0, 26990, 0, 0, 11352, 0, 9546, 0, 0, 21963, 0, 0, 0, 0, 0, + 0, 0, 0, 22200, 0, 36496, 29555, 32780, 0, 40347, 0, 37097, 0, 0, 0, 0, + 0, 13181, 0, 0, 24874, 30385, 16073, 40505, 0, 37422, 9837, 22895, 41170, 41085, 0, 40180, + 21838, 40181, 0, 0, 0, 0, 22715, 20054, 0, 0, 0, 0, 1385, 28087, 0, 0, + 0, 23101, 20066, 0, 0, 0, 0, 0, 0, 0, 0, 35283, 37210, 0, 37451, 0, + 40266, 0, 0, 18145, 0, 0, 0, 0, 0, 0, 21787, 0, 0, 0, 18072, 0, + 17720, 0, 30055, 0, 1144, 20917, 24798, 0, 22540, 6266, 21559, 30004, 0, 12179, 0, 18090, + 0, 0, 0, 15701, 28054, 0, 0, 0, 29709, 0, 0, 0, 0, 0, 20931, 38278, + 0, 0, 29666, 8741, 6540, 0, 0, 13736, 0, 29284, 29425, 3504, 24743, 0, 26132, 0, + 1999, 16962, 0, 19229, 0, 17698, 27411, 5481, 0, 3443, 20353, 0, 28967, 11910, 0, 21489, + 0, 15103, 11118, 0, 18839, 35268, 0, 20675, 3044, 0, 0, 0, 28394, 0, 15393, 8267, + 0, 3029, 0, 0, 28382, 0, 0, 24561, 0, 0, 0, 28085, 0, 37947, 0, 28385, + 15672, 2018, 0, 18559, 20689, 0, 17521, 33897, 28386, 19413, 1386, 0, 0, 0, 0, 0, + 0, 0, 29220, 0, 17491, 28709, 26361, 0, 24852, 6404, 11370, 25991, 0, 0, 0, 15891, + 0, 0, 0, 21614, 0, 21615, 19154, 41262, 35751, 32352, 3020, 29449, 0, 0, 0, 0, + 0, 0, 27595, 0, 20096, 0, 0, 20025, 0, 0, 0, 30377, 0, 996, 23920, 0, + 20568, 0, 0, 18277, 31127, 0, 19768, 0, 29695, 0, 0, 20781, 0, 19746, 0, 0, + 0, 0, 41307, 0, 30002, 15302, 30005, 0, 0, 0, 3110, 39349, 0, 3702, 29244, 0, + 39824, 2714, 2719, 0, 0, 24366, 29978, 11709, 25098, 38621, 12950, 2726, 0, 11539, 0, 11651, + 3509, 0, 11540, 10561, 37892, 0, 29856, 1422, 0, 11547, 37893, 0, 0, 0, 0, 20690, + 8930, 0, 8931, 0, 9688, 0, 2748, 0, 25105, 25719, 15892, 22753, 0, 0, 25601, 0, + 0, 0, 21713, 11108, 13916, 21353, 826, 0, 21291, 0, 1346, 10988, 16949, 0, 0, 40174, + 20862, 0, 25011, 7785, 1152, 16976, 1668, 21383, 6180, 0, 0, 17488, 21362, 17492, 19268, 39013, + 0, 0, 0, 12746, 35540, 0, 18470, 0, 35852, 0, 0, 0, 0, 5063, 6460, 0, + 0, 0, 0, 35590, 0, 28609, 10154, 27403, 0, 0, 0, 0, 30324, 0, 28055, 35052, + 7152, 0, 39223, 0, 0, 0, 0, 0, 0, 0, 6303, 12937, 0, 0, 0, 22131, + 11647, 0, 2602, 26254, 18611, 0, 37414, 0, 34682, 30386, 24119, 19098, 37423, 0, 0, 29827, + 30852, 0, 30023, 0, 0, 11916, 968, 24195, 0, 13882, 16283, 0, 39603, 37110, 0, 4472, + 0, 0, 0, 0, 0, 0, 35274, 6022, 2604, 5837, 19409, 0, 5502, 30568, 21416, 16815, + 1756, 31178, 0, 39172, 0, 0, 25530, 30270, 20182, 13832, 0, 10787, 0, 38571, 25605, 40803, + 22090, 0, 20691, 0, 20185, 0, 23212, 20692, 0, 0, 39446, 600, 0, 20364, 0, 18847, + 0, 23215, 3714, 0, 17001, 36023, 0, 0, 5507, 4841, 0, 6600, 19316, 34582, 0, 38365, + 34583, 6601, 23059, 0, 0, 37784, 0, 0, 0, 12078, 19370, 13091, 21748, 24288, 0, 24289, + 0, 0, 35285, 0, 28586, 0, 0, 0, 0, 12974, 0, 0, 2571, 0, 5241, 29041, + 17383, 0, 0, 21438, 2754, 38139, 0, 0, 0, 0, 37468, 0, 41201, 1424, 0, 0, + 3964, 0, 0, 0, 0, 0, 0, 0, 25158, 0, 25164, 34744, 2036, 0, 0, 0, + 0, 4668, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20055, 0, 15418, 0, + 4674, 0, 0, 0, 0, 0, 0, 31719, 0, 19269, 0, 26896, 5762, 0, 0, 26897, + 0, 0, 6075, 14194, 0, 37588, 8409, 0, 0, 0, 11858, 12199, 0, 22378, 0, 5465, + 0, 1071, 0, 0, 22133, 28522, 0, 37521, 8567, 37522, 0, 0, 0, 0, 0, 12745, + 0, 0, 0, 15560, 0, 0, 6220, 0, 0, 32236, 23555, 0, 25918, 0, 0, 0, + 36300, 0, 0, 18445, 0, 0, 29005, 18450, 0, 0, 25348, 0, 0, 36296, 22892, 23054, + 37599, 25493, 0, 7375, 0, 0, 0, 10156, 20036, 10997, 40795, 0, 18111, 14197, 25495, 0, + 0, 0, 22896, 9470, 7127, 0, 0, 0, 0, 0, 0, 0, 0, 4671, 15104, 0, + 0, 0, 0, 0, 0, 0, 33429, 0, 7101, 29218, 0, 34812, 0, 133, 11012, 31717, + 0, 11013, 0, 27689, 17063, 0, 36024, 9211, 0, 28853, 0, 0, 0, 0, 0, 0, + 25106, 40947, 17007, 0, 13558, 0, 0, 7295, 23103, 27699, 0, 13768, 18649, 17384, 2755, 0, + 35089, 0, 0, 0, 0, 11648, 0, 0, 0, 10738, 5749, 24671, 14972, 0, 22634, 0, + 0, 0, 15913, 0, 0, 31764, 29062, 0, 0, 33716, 0, 0, 0, 0, 0, 1457, + 0, 0, 10328, 17494, 0, 0, 28091, 17753, 0, 0, 0, 0, 13884, 0, 0, 0, + 0, 17385, 2756, 0, 0, 23341, 23350, 0, 0, 40800, 0, 40802, 0, 23385, 0, 23388, + 40808, 0, 38536, 38538, 22006, 0, 14444, 0, 0, 34554, 0, 0, 10182, 20920, 0, 0, + 0, 0, 0, 0, 34561, 0, 38734, 26992, 39517, 0, 0, 0, 0, 38405, 0, 0, + 0, 0, 0, 0, 25498, 38406, 0, 36012, 20500, 34208, 0, 39859, 0, 16152, 32014, 0, + 22684, 28534, 0, 35605, 0, 0, 33419, 38534, 0, 6754, 7026, 0, 0, 0, 36186, 0, + 7031, 28103, 178, 4866, 0, 30130, 0, 30131, 32015, 0, 0, 4341, 0, 28104, 0, 0, + 0, 0, 0, 0, 0, 12666, 23835, 41090, 38535, 37895, 38739, 0, 35534, 0, 0, 0, + 0, 0, 34209, 37680, 0, 0, 0, 0, 0, 10454, 23620, 0, 0, 0, 2529, 0, + 0, 0, 0, 21944, 0, 0, 0, 0, 11014, 0, 34704, 0, 24199, 2028, 23935, 13834, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21364, 0, 0, 2834, 24315, + 0, 38169, 0, 0, 36249, 33102, 0, 23389, 13210, 0, 0, 33546, 0, 38366, 0, 7042, + 0, 0, 0, 41040, 35609, 0, 0, 0, 0, 39524, 17386, 0, 0, 17387, 36189, 0, + 0, 17497, 0, 2757, 0, 15012, 0, 38003, 0, 0, 0, 0, 0, 0, 38539, 22673, + 0, 18409, 0, 18410, 0, 0, 0, 0, 18417, 0, 0, 0, 0, 18432, 0, 0, + 18438, 0, 19545, 0, 0, 39016, 0, 0, 0, 0, 0, 0, 8477, 9013, 25165, 4672, + 13397, 0, 0, 0, 0, 0, 0, 2038, 0, 40358, 24564, 34745, 0, 0, 0, 0, + 32792, 0, 11684, 24758, 0, 0, 0, 0, 18177, 0, 36185, 0, 0, 0, 22644, 0, + 0, 0, 17496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6686, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 518, 0, 0, 0, 0, 0, 0, 38601, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18974, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27813, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14806, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36551, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 21806, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7518, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 28061, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15598, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3407, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34009, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23605, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8959, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 19101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35624, 0, 0, 0, 0, 0, 35380, + 0, 0, 21068, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31727, 0, 32725, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14808, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37697, 0, 15752, 0, 0, 18017, 0, 0, 0, 0, 0, 0, + 21240, 0, 0, 2117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10013, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7852, 0, 4485, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14953, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38745, 0, 0, 0, 0, 0, 2120, 27981, 0, 0, 0, 0, 0, 0, 11494, 0, + 0, 0, 0, 0, 38609, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14837, 0, 0, + 0, 0, 0, 10066, 29, 0, 0, 0, 29084, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 33637, 10659, 0, 0, 0, 0, 0, 0, + 0, 0, 7971, 0, 11680, 26867, 0, 0, 0, 23049, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39390, 0, 0, 14854, 0, + 0, 0, 21632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3625, 0, 29104 +}; + +static GS_UNICASE_CHARACTER plane00[] = { + {0x0000, 0x0000, 0x0000}, {0x0001, 0x0001, 0x0001}, {0x0002, 0x0002, 0x0002}, {0x0003, 0x0003, 0x0003}, + {0x0004, 0x0004, 0x0004}, {0x0005, 0x0005, 0x0005}, {0x0006, 0x0006, 0x0006}, {0x0007, 0x0007, 0x0007}, + {0x0008, 0x0008, 0x0008}, {0x0009, 0x0009, 0x0009}, {0x000A, 0x000A, 0x000A}, {0x000B, 0x000B, 0x000B}, + {0x000C, 0x000C, 0x000C}, {0x000D, 0x000D, 0x000D}, {0x000E, 0x000E, 0x000E}, {0x000F, 0x000F, 0x000F}, + {0x0010, 0x0010, 0x0010}, {0x0011, 0x0011, 0x0011}, {0x0012, 0x0012, 0x0012}, {0x0013, 0x0013, 0x0013}, + {0x0014, 0x0014, 0x0014}, {0x0015, 0x0015, 0x0015}, {0x0016, 0x0016, 0x0016}, {0x0017, 0x0017, 0x0017}, + {0x0018, 0x0018, 0x0018}, {0x0019, 0x0019, 0x0019}, {0x001A, 0x001A, 0x001A}, {0x001B, 0x001B, 0x001B}, + {0x001C, 0x001C, 0x001C}, {0x001D, 0x001D, 0x001D}, {0x001E, 0x001E, 0x001E}, {0x001F, 0x001F, 0x001F}, + {0x0020, 0x0020, 0x0020}, {0x0021, 0x0021, 0x0021}, {0x0022, 0x0022, 0x0022}, {0x0023, 0x0023, 0x0023}, + {0x0024, 0x0024, 0x0024}, {0x0025, 0x0025, 0x0025}, {0x0026, 0x0026, 0x0026}, {0x0027, 0x0027, 0x0027}, + {0x0028, 0x0028, 0x0028}, {0x0029, 0x0029, 0x0029}, {0x002A, 0x002A, 0x002A}, {0x002B, 0x002B, 0x002B}, + {0x002C, 0x002C, 0x002C}, {0x002D, 0x002D, 0x002D}, {0x002E, 0x002E, 0x002E}, {0x002F, 0x002F, 0x002F}, + {0x0030, 0x0030, 0x0030}, {0x0031, 0x0031, 0x0031}, {0x0032, 0x0032, 0x0032}, {0x0033, 0x0033, 0x0033}, + {0x0034, 0x0034, 0x0034}, {0x0035, 0x0035, 0x0035}, {0x0036, 0x0036, 0x0036}, {0x0037, 0x0037, 0x0037}, + {0x0038, 0x0038, 0x0038}, {0x0039, 0x0039, 0x0039}, {0x003A, 0x003A, 0x003A}, {0x003B, 0x003B, 0x003B}, + {0x003C, 0x003C, 0x003C}, {0x003D, 0x003D, 0x003D}, {0x003E, 0x003E, 0x003E}, {0x003F, 0x003F, 0x003F}, + {0x0040, 0x0040, 0x0040}, {0x0041, 0x0061, 0x0041}, {0x0042, 0x0062, 0x0042}, {0x0043, 0x0063, 0x0043}, + {0x0044, 0x0064, 0x0044}, {0x0045, 0x0065, 0x0045}, {0x0046, 0x0066, 0x0046}, {0x0047, 0x0067, 0x0047}, + {0x0048, 0x0068, 0x0048}, {0x0049, 0x0069, 0x0049}, {0x004A, 0x006A, 0x004A}, {0x004B, 0x006B, 0x004B}, + {0x004C, 0x006C, 0x004C}, {0x004D, 0x006D, 0x004D}, {0x004E, 0x006E, 0x004E}, {0x004F, 0x006F, 0x004F}, + {0x0050, 0x0070, 0x0050}, {0x0051, 0x0071, 0x0051}, {0x0052, 0x0072, 0x0052}, {0x0053, 0x0073, 0x0053}, + {0x0054, 0x0074, 0x0054}, {0x0055, 0x0075, 0x0055}, {0x0056, 0x0076, 0x0056}, {0x0057, 0x0077, 0x0057}, + {0x0058, 0x0078, 0x0058}, {0x0059, 0x0079, 0x0059}, {0x005A, 0x007A, 0x005A}, {0x005B, 0x005B, 0x005B}, + {0x005C, 0x005C, 0x005C}, {0x005D, 0x005D, 0x005D}, {0x005E, 0x005E, 0x005E}, {0x005F, 0x005F, 0x005F}, + {0x0060, 0x0060, 0x0060}, {0x0041, 0x0061, 0x0041}, {0x0042, 0x0062, 0x0042}, {0x0043, 0x0063, 0x0043}, + {0x0044, 0x0064, 0x0044}, {0x0045, 0x0065, 0x0045}, {0x0046, 0x0066, 0x0046}, {0x0047, 0x0067, 0x0047}, + {0x0048, 0x0068, 0x0048}, {0x0049, 0x0069, 0x0049}, {0x004A, 0x006A, 0x004A}, {0x004B, 0x006B, 0x004B}, + {0x004C, 0x006C, 0x004C}, {0x004D, 0x006D, 0x004D}, {0x004E, 0x006E, 0x004E}, {0x004F, 0x006F, 0x004F}, + {0x0050, 0x0070, 0x0050}, {0x0051, 0x0071, 0x0051}, {0x0052, 0x0072, 0x0052}, {0x0053, 0x0073, 0x0053}, + {0x0054, 0x0074, 0x0054}, {0x0055, 0x0075, 0x0055}, {0x0056, 0x0076, 0x0056}, {0x0057, 0x0077, 0x0057}, + {0x0058, 0x0078, 0x0058}, {0x0059, 0x0079, 0x0059}, {0x005A, 0x007A, 0x005A}, {0x007B, 0x007B, 0x007B}, + {0x007C, 0x007C, 0x007C}, {0x007D, 0x007D, 0x007D}, {0x007E, 0x007E, 0x007E}, {0x007F, 0x007F, 0x007F}, + {0x0080, 0x0080, 0x0080}, {0x0081, 0x0081, 0x0081}, {0x0082, 0x0082, 0x0082}, {0x0083, 0x0083, 0x0083}, + {0x0084, 0x0084, 0x0084}, {0x0085, 0x0085, 0x0085}, {0x0086, 0x0086, 0x0086}, {0x0087, 0x0087, 0x0087}, + {0x0088, 0x0088, 0x0088}, {0x0089, 0x0089, 0x0089}, {0x008A, 0x008A, 0x008A}, {0x008B, 0x008B, 0x008B}, + {0x008C, 0x008C, 0x008C}, {0x008D, 0x008D, 0x008D}, {0x008E, 0x008E, 0x008E}, {0x008F, 0x008F, 0x008F}, + {0x0090, 0x0090, 0x0090}, {0x0091, 0x0091, 0x0091}, {0x0092, 0x0092, 0x0092}, {0x0093, 0x0093, 0x0093}, + {0x0094, 0x0094, 0x0094}, {0x0095, 0x0095, 0x0095}, {0x0096, 0x0096, 0x0096}, {0x0097, 0x0097, 0x0097}, + {0x0098, 0x0098, 0x0098}, {0x0099, 0x0099, 0x0099}, {0x009A, 0x009A, 0x009A}, {0x009B, 0x009B, 0x009B}, + {0x009C, 0x009C, 0x009C}, {0x009D, 0x009D, 0x009D}, {0x009E, 0x009E, 0x009E}, {0x009F, 0x009F, 0x009F}, + {0x00A0, 0x00A0, 0x00A0}, {0x00A1, 0x00A1, 0x00A1}, {0x00A2, 0x00A2, 0x00A2}, {0x00A3, 0x00A3, 0x00A3}, + {0x00A4, 0x00A4, 0x00A4}, {0x00A5, 0x00A5, 0x00A5}, {0x00A6, 0x00A6, 0x00A6}, {0x00A7, 0x00A7, 0x00A7}, + {0x00A8, 0x00A8, 0x00A8}, {0x00A9, 0x00A9, 0x00A9}, {0x00AA, 0x00AA, 0x00AA}, {0x00AB, 0x00AB, 0x00AB}, + {0x00AC, 0x00AC, 0x00AC}, {0x00AD, 0x00AD, 0x00AD}, {0x00AE, 0x00AE, 0x00AE}, {0x00AF, 0x00AF, 0x00AF}, + {0x00B0, 0xA6CC, 0x00B5}, {0x00B1, 0x00B1, 0x00B1}, {0x00B2, 0x00B2, 0x00B2}, {0x00B3, 0x00B3, 0x00B3}, + {0x00B4, 0x00B4, 0x00B4}, {0x00B5, 0x00B5, 0x00B5}, {0x00B6, 0x00B6, 0x00B6}, {0x00B7, 0x00B7, 0x00B7}, + {0x00B8, 0x00B8, 0x00B8}, {0x00B9, 0x00B9, 0x00B9}, {0x00BA, 0xA8A4, 0x00C0}, {0x00BB, 0xA8A2, 0x00C1}, + {0x00BC, 0x00D9, 0x00C2}, {0x00BD, 0x00DA, 0x00C3}, {0x00BE, 0x00DB, 0x00C4}, {0x00BF, 0x00DC, 0x00C5}, + {0x00C0, 0x00DD, 0x00C6}, {0x00C1, 0x00DE, 0x00C7}, {0x00C2, 0xA8A8, 0x00C8}, {0x00C3, 0xA8A6, 0x00C9}, + {0x00C4, 0xA8BA, 0x00CA}, {0x00C5, 0x00DF, 0x00CB}, {0x00C6, 0xA8AC, 0x00CC}, {0x00C7, 0xA8AA, 0x00CD}, + {0x00C8, 0x00E0, 0x00CE}, {0x00C9, 0x00E1, 0x00CF}, {0x00CA, 0x00E2, 0x00D0}, {0x00CB, 0x00E3, 0x00D1}, + {0x00CC, 0xA8B0, 0x00D2}, {0x00CD, 0xA8AE, 0x00D3}, {0x00CE, 0x00E4, 0x00D4}, {0x00CF, 0x00E5, 0x00D5}, + {0x00D0, 0x00E6, 0x00D6}, {0x00D1, 0x00E7, 0x00D8}, {0x00D2, 0xA8B4, 0x00D9}, {0x00D3, 0xA8B2, 0x00DA}, + {0x00D4, 0x00E8, 0x00DB}, {0x00D5, 0xA8B9, 0x00DC}, {0x00D6, 0x00E9, 0x00DD}, {0x00D7, 0x00EA, 0x00DE}, + {0x00D8, 0x00D8, 0x00DF}, {0x00BC, 0x00D9, 0x00C2}, {0x00BD, 0x00DA, 0x00C3}, {0x00BE, 0x00DB, 0x00C4}, + {0x00BF, 0x00DC, 0x00C5}, {0x00C0, 0x00DD, 0x00C6}, {0x00C1, 0x00DE, 0x00C7}, {0x00C5, 0x00DF, 0x00CB}, + {0x00C8, 0x00E0, 0x00CE}, {0x00C9, 0x00E1, 0x00CF}, {0x00CA, 0x00E2, 0x00D0}, {0x00CB, 0x00E3, 0x00D1}, + {0x00CE, 0x00E4, 0x00D4}, {0x00CF, 0x00E5, 0x00D5}, {0x00D0, 0x00E6, 0x00D6}, {0x00D1, 0x00E7, 0x00D8}, + {0x00D4, 0x00E8, 0x00DB}, {0x00D6, 0x00E9, 0x00DD}, {0x00D7, 0x00EA, 0x00DE}, {0x015C, 0x00EB, 0x0178}, + {0x00EC, 0xA8A1, 0x0100}, {0x00ED, 0x00EE, 0x0102}, {0x00ED, 0x00EE, 0x0102}, {0x00EF, 0x00F0, 0x0104}, + {0x00EF, 0x00F0, 0x0104}, {0x00F1, 0x00F2, 0x0106}, {0x00F1, 0x00F2, 0x0106}, {0x00F3, 0x00F4, 0x0108}, + {0x00F3, 0x00F4, 0x0108}, {0x00F5, 0x00F6, 0x010A}, {0x00F5, 0x00F6, 0x010A}, {0x00F7, 0x00F8, 0x010C}, + {0x00F7, 0x00F8, 0x010C}, {0x00F9, 0x00FA, 0x010E}, {0x00F9, 0x00FA, 0x010E}, {0x00FB, 0x00FC, 0x0110}, + {0x00FB, 0x00FC, 0x0110}, {0x00FD, 0xA8A5, 0x0112}, {0x00FE, 0x00FF, 0x0114}, {0x00FE, 0x00FF, 0x0114} +}; + +static GS_UNICASE_CHARACTER plane01[] = { + {0x0100, 0x0101, 0x0116}, {0x0100, 0x0101, 0x0116}, {0x0102, 0x0103, 0x0118}, {0x0102, 0x0103, 0x0118}, + {0x0104, 0xA8A7, 0x011A}, {0x0105, 0x0106, 0x011C}, {0x0105, 0x0106, 0x011C}, {0x0107, 0x0108, 0x011E}, + {0x0107, 0x0108, 0x011E}, {0x0109, 0x010A, 0x0120}, {0x0109, 0x010A, 0x0120}, {0x010B, 0x010C, 0x0122}, + {0x010B, 0x010C, 0x0122}, {0x010D, 0x010E, 0x0124}, {0x010D, 0x010E, 0x0124}, {0x010F, 0x0110, 0x0126}, + {0x010F, 0x0110, 0x0126}, {0x0111, 0x0112, 0x0128}, {0x0111, 0x0112, 0x0128}, {0x0113, 0xA8A9, 0x012A}, + {0x0114, 0x0115, 0x012C}, {0x0114, 0x0115, 0x012C}, {0x0116, 0x0117, 0x012E}, {0x0116, 0x0117, 0x012E}, + {0x0118, 0x0069, 0x0130}, {0x0049, 0x0119, 0x0049}, {0x011A, 0x011B, 0x0132}, {0x011A, 0x011B, 0x0132}, + {0x011C, 0x011D, 0x0134}, {0x011C, 0x011D, 0x0134}, {0x011E, 0x011F, 0x0136}, {0x011E, 0x011F, 0x0136}, + {0x0120, 0x0120, 0x0138}, {0x0121, 0x0122, 0x0139}, {0x0121, 0x0122, 0x0139}, {0x0123, 0x0124, 0x013B}, + {0x0123, 0x0124, 0x013B}, {0x0125, 0x0126, 0x013D}, {0x0125, 0x0126, 0x013D}, {0x0127, 0x0128, 0x013F}, + {0x0127, 0x0128, 0x013F}, {0x0129, 0x012A, 0x0141}, {0x0129, 0x012A, 0x0141}, {0x012B, 0xA8BD, 0x0143}, + {0x012C, 0x012D, 0x0145}, {0x012C, 0x012D, 0x0145}, {0x012E, 0xA8BE, 0x0147}, {0x012F, 0x012F, 0x0149}, + {0x0130, 0x0131, 0x014A}, {0x0130, 0x0131, 0x014A}, {0x0132, 0xA8AD, 0x014C}, {0x0133, 0x0134, 0x014E}, + {0x0133, 0x0134, 0x014E}, {0x0135, 0x0136, 0x0150}, {0x0135, 0x0136, 0x0150}, {0x0137, 0x0138, 0x0152}, + {0x0137, 0x0138, 0x0152}, {0x0139, 0x013A, 0x0154}, {0x0139, 0x013A, 0x0154}, {0x013B, 0x013C, 0x0156}, + {0x013B, 0x013C, 0x0156}, {0x013D, 0x013E, 0x0158}, {0x013D, 0x013E, 0x0158}, {0x013F, 0x0140, 0x015A}, + {0x013F, 0x0140, 0x015A}, {0x0141, 0x0142, 0x015C}, {0x0141, 0x0142, 0x015C}, {0x0143, 0x0144, 0x015E}, + {0x0143, 0x0144, 0x015E}, {0x0145, 0x0146, 0x0160}, {0x0145, 0x0146, 0x0160}, {0x0147, 0x0148, 0x0162}, + {0x0147, 0x0148, 0x0162}, {0x0149, 0x014A, 0x0164}, {0x0149, 0x014A, 0x0164}, {0x014B, 0x014C, 0x0166}, + {0x014B, 0x014C, 0x0166}, {0x014D, 0x014E, 0x0168}, {0x014D, 0x014E, 0x0168}, {0x014F, 0xA8B1, 0x016A}, + {0x0150, 0x0151, 0x016C}, {0x0150, 0x0151, 0x016C}, {0x0152, 0x0153, 0x016E}, {0x0152, 0x0153, 0x016E}, + {0x0154, 0x0155, 0x0170}, {0x0154, 0x0155, 0x0170}, {0x0156, 0x0157, 0x0172}, {0x0156, 0x0157, 0x0172}, + {0x0158, 0x0159, 0x0174}, {0x0158, 0x0159, 0x0174}, {0x015A, 0x015B, 0x0176}, {0x015A, 0x015B, 0x0176}, + {0x015C, 0x00EB, 0x0178}, {0x015D, 0x015E, 0x0179}, {0x015D, 0x015E, 0x0179}, {0x015F, 0x0160, 0x017B}, + {0x015F, 0x0160, 0x017B}, {0x0161, 0x0162, 0x017D}, {0x0161, 0x0162, 0x017D}, {0x0053, 0x0163, 0x017F}, + {0x021E, 0x0164, 0x0243}, {0x0165, 0x022D, 0x0181}, {0x0166, 0x0167, 0x0182}, {0x0166, 0x0167, 0x0182}, + {0x0168, 0x0169, 0x0184}, {0x0168, 0x0169, 0x0184}, {0x016A, 0x022E, 0x0186}, {0x016B, 0x016C, 0x0187}, + {0x016B, 0x016C, 0x0187}, {0x016D, 0x0230, 0x0189}, {0x016E, 0x0231, 0x018A}, {0x016F, 0x0170, 0x018B}, + {0x016F, 0x0170, 0x018B}, {0x0171, 0x0171, 0x018D}, {0x0172, 0x01B9, 0x018E}, {0x0173, 0x0233, 0x018F}, + {0x0174, 0x0235, 0x0190}, {0x0175, 0x0176, 0x0191}, {0x0175, 0x0176, 0x0191}, {0x0177, 0x023A, 0x0193}, + {0x0178, 0x023C, 0x0194}, {0x01D2, 0x0179, 0x01F6}, {0x017A, 0x0242, 0x0196}, {0x017B, 0x0241, 0x0197}, + {0x017C, 0x017D, 0x0198}, {0x017C, 0x017D, 0x0198}, {0x0218, 0x017E, 0x023D}, {0x017F, 0x017F, 0x019B}, + {0x0180, 0x0248, 0x019C}, {0x0181, 0x024B, 0x019D}, {0x01FB, 0x0182, 0x0220}, {0x0183, 0x024E, 0x019F}, + {0x0184, 0x0185, 0x01A0}, {0x0184, 0x0185, 0x01A0}, {0x0186, 0x0187, 0x01A2}, {0x0186, 0x0187, 0x01A2}, + {0x0188, 0x0189, 0x01A4}, {0x0188, 0x0189, 0x01A4}, {0x018A, 0x0259, 0x01A6}, {0x018B, 0x018C, 0x01A7}, + {0x018B, 0x018C, 0x01A7}, {0x018D, 0x025C, 0x01A9}, {0x018E, 0x018E, 0x01AA}, {0x018F, 0x018F, 0x01AB}, + {0x0190, 0x0191, 0x01AC}, {0x0190, 0x0191, 0x01AC}, {0x0192, 0x0261, 0x01AE}, {0x0193, 0x0194, 0x01AF}, + {0x0193, 0x0194, 0x01AF}, {0x0195, 0x0263, 0x01B1}, {0x0196, 0x0264, 0x01B2}, {0x0197, 0x0198, 0x01B3}, + {0x0197, 0x0198, 0x01B3}, {0x0199, 0x019A, 0x01B5}, {0x0199, 0x019A, 0x01B5}, {0x019B, 0x026B, 0x01B7}, + {0x019C, 0x019D, 0x01B8}, {0x019C, 0x019D, 0x01B8}, {0x019E, 0x019E, 0x01BA}, {0x019F, 0x019F, 0x01BB}, + {0x01A0, 0x01A1, 0x01BC}, {0x01A0, 0x01A1, 0x01BC}, {0x01A2, 0x01A2, 0x01BE}, {0x01D3, 0x01A3, 0x01F7}, + {0x01A4, 0x01A4, 0x01C0}, {0x01A5, 0x01A5, 0x01C1}, {0x01A6, 0x01A6, 0x01C2}, {0x01A7, 0x01A7, 0x01C3}, + {0x01A8, 0x01AA, 0x01C4}, {0x01A9, 0x01AA, 0x01C5}, {0x01A8, 0x01AA, 0x01C4}, {0x01AB, 0x01AD, 0x01C7}, + {0x01AC, 0x01AD, 0x01C8}, {0x01AB, 0x01AD, 0x01C7}, {0x01AE, 0x01B0, 0x01CA}, {0x01AF, 0x01B0, 0x01CB}, + {0x01AE, 0x01B0, 0x01CA}, {0x01B1, 0xA8A3, 0x01CD}, {0x01B2, 0xA8AB, 0x01CF}, {0x01B3, 0xA8AF, 0x01D1}, + {0x01B4, 0xA8B3, 0x01D3}, {0x01B5, 0xA8B5, 0x01D5}, {0x01B6, 0xA8B6, 0x01D7}, {0x01B7, 0xA8B7, 0x01D9}, + {0x01B8, 0xA8B8, 0x01DB}, {0x0172, 0x01B9, 0x018E}, {0x01BA, 0x01BB, 0x01DE}, {0x01BA, 0x01BB, 0x01DE}, + {0x01BC, 0x01BD, 0x01E0}, {0x01BC, 0x01BD, 0x01E0}, {0x01BE, 0x01BF, 0x01E2}, {0x01BE, 0x01BF, 0x01E2}, + {0x01C0, 0x01C1, 0x01E4}, {0x01C0, 0x01C1, 0x01E4}, {0x01C2, 0x01C3, 0x01E6}, {0x01C2, 0x01C3, 0x01E6}, + {0x01C4, 0x01C5, 0x01E8}, {0x01C4, 0x01C5, 0x01E8}, {0x01C6, 0x01C7, 0x01EA}, {0x01C6, 0x01C7, 0x01EA}, + {0x01C8, 0x01C9, 0x01EC}, {0x01C8, 0x01C9, 0x01EC}, {0x01CA, 0x01CB, 0x01EE}, {0x01CA, 0x01CB, 0x01EE}, + {0x01CC, 0x01CC, 0x01F0}, {0x01CD, 0x01CF, 0x01F1}, {0x01CE, 0x01CF, 0x01F2}, {0x01CD, 0x01CF, 0x01F1}, + {0x01D0, 0x01D1, 0x01F4}, {0x01D0, 0x01D1, 0x01F4}, {0x01D2, 0x0179, 0x01F6}, {0x01D3, 0x01A3, 0x01F7}, + {0x01D4, 0xA8BF, 0x01F8}, {0x01D5, 0x01D6, 0x01FA}, {0x01D5, 0x01D6, 0x01FA}, {0x01D7, 0x01D8, 0x01FC}, + {0x01D7, 0x01D8, 0x01FC}, {0x01D9, 0x01DA, 0x01FE}, {0x01D9, 0x01DA, 0x01FE}, {0x01DB, 0x01DC, 0x0200}, + {0x01DB, 0x01DC, 0x0200}, {0x01DD, 0x01DE, 0x0202}, {0x01DD, 0x01DE, 0x0202}, {0x01DF, 0x01E0, 0x0204}, + {0x01DF, 0x01E0, 0x0204}, {0x01E1, 0x01E2, 0x0206}, {0x01E1, 0x01E2, 0x0206}, {0x01E3, 0x01E4, 0x0208}, + {0x01E3, 0x01E4, 0x0208}, {0x01E5, 0x01E6, 0x020A}, {0x01E5, 0x01E6, 0x020A}, {0x01E7, 0x01E8, 0x020C}, + {0x01E7, 0x01E8, 0x020C}, {0x01E9, 0x01EA, 0x020E}, {0x01E9, 0x01EA, 0x020E}, {0x01EB, 0x01EC, 0x0210}, + {0x01EB, 0x01EC, 0x0210}, {0x01ED, 0x01EE, 0x0212}, {0x01ED, 0x01EE, 0x0212}, {0x01EF, 0x01F0, 0x0214}, + {0x01EF, 0x01F0, 0x0214}, {0x01F1, 0x01F2, 0x0216}, {0x01F1, 0x01F2, 0x0216}, {0x01F3, 0x01F4, 0x0218}, + {0x01F3, 0x01F4, 0x0218}, {0x01F5, 0x01F6, 0x021A}, {0x01F5, 0x01F6, 0x021A}, {0x01F7, 0x01F8, 0x021C}, + {0x01F7, 0x01F8, 0x021C}, {0x01F9, 0x01FA, 0x021E}, {0x01F9, 0x01FA, 0x021E}, {0x01FB, 0x0182, 0x0220}, + {0x01FC, 0x01FC, 0x0221}, {0x01FD, 0x01FE, 0x0222}, {0x01FD, 0x01FE, 0x0222}, {0x01FF, 0x0200, 0x0224} +}; + +static GS_UNICASE_CHARACTER plane02[] = { + {0x01FF, 0x0200, 0x0224}, {0x0201, 0x0202, 0x0226}, {0x0201, 0x0202, 0x0226}, {0x0203, 0x0204, 0x0228}, + {0x0203, 0x0204, 0x0228}, {0x0205, 0x0206, 0x022A}, {0x0205, 0x0206, 0x022A}, {0x0207, 0x0208, 0x022C}, + {0x0207, 0x0208, 0x022C}, {0x0209, 0x020A, 0x022E}, {0x0209, 0x020A, 0x022E}, {0x020B, 0x020C, 0x0230}, + {0x020B, 0x020C, 0x0230}, {0x020D, 0x020E, 0x0232}, {0x020D, 0x020E, 0x0232}, {0x020F, 0x020F, 0x0234}, + {0x0210, 0x0210, 0x0235}, {0x0211, 0x0211, 0x0236}, {0x0212, 0x0212, 0x0237}, {0x0213, 0x0213, 0x0238}, + {0x0214, 0x0214, 0x0239}, {0x0215, 0x2AA5, 0x023A}, {0x0216, 0x0217, 0x023B}, {0x0216, 0x0217, 0x023B}, + {0x0218, 0x017E, 0x023D}, {0x0219, 0x2AA6, 0x023E}, {0x2ABE, 0x021A, 0x2C7E}, {0x2ABF, 0x021B, 0x2C7F}, + {0x021C, 0x021D, 0x0241}, {0x021C, 0x021D, 0x0241}, {0x021E, 0x0164, 0x0243}, {0x021F, 0x0262, 0x0244}, + {0x0220, 0x0265, 0x0245}, {0x0221, 0x0222, 0x0246}, {0x0221, 0x0222, 0x0246}, {0x0223, 0x0224, 0x0248}, + {0x0223, 0x0224, 0x0248}, {0x0225, 0x0226, 0x024A}, {0x0225, 0x0226, 0x024A}, {0x0227, 0x0228, 0x024C}, + {0x0227, 0x0228, 0x024C}, {0x0229, 0x022A, 0x024E}, {0x0229, 0x022A, 0x024E}, {0x2AAF, 0x022B, 0x2C6F}, + {0x2AB0, 0x022C, 0x2C70}, {0x0165, 0x022D, 0x0181}, {0x016A, 0x022E, 0x0186}, {0x022F, 0x022F, 0x0255}, + {0x016D, 0x0230, 0x0189}, {0x016E, 0x0231, 0x018A}, {0x0232, 0x0232, 0x0258}, {0x0173, 0x0233, 0x018F}, + {0x0234, 0x0234, 0x025A}, {0x0174, 0x0235, 0x0190}, {0x0236, 0x0236, 0x025C}, {0x0237, 0x0237, 0x025D}, + {0x0238, 0x0238, 0x025E}, {0x0239, 0x0239, 0x025F}, {0x0177, 0x023A, 0x0193}, {0x023B, 0x023B, 0x0262}, + {0x0178, 0x023C, 0x0194}, {0x023D, 0x023D, 0x0264}, {0x023E, 0x023E, 0x0265}, {0x023F, 0x023F, 0x0266}, + {0x0240, 0x0240, 0x0267}, {0x017B, 0x0241, 0x0197}, {0x017A, 0x0242, 0x0196}, {0x0243, 0x0243, 0x026A}, + {0x2AA2, 0x0244, 0x2C62}, {0x0245, 0x0245, 0x026C}, {0x0246, 0x0246, 0x026D}, {0x0247, 0x0247, 0x026E}, + {0x0180, 0x0248, 0x019C}, {0x0249, 0x0249, 0x0270}, {0x2AAE, 0x024A, 0x2C6E}, {0x0181, 0x024B, 0x019D}, + {0x024C, 0x024C, 0x0273}, {0x024D, 0x024D, 0x0274}, {0x0183, 0x024E, 0x019F}, {0x024F, 0x024F, 0x0276}, + {0x0250, 0x0250, 0x0277}, {0x0251, 0x0251, 0x0278}, {0x0252, 0x0252, 0x0279}, {0x0253, 0x0253, 0x027A}, + {0x0254, 0x0254, 0x027B}, {0x0255, 0x0255, 0x027C}, {0x2AA4, 0x0256, 0x2C64}, {0x0257, 0x0257, 0x027E}, + {0x0258, 0x0258, 0x027F}, {0x018A, 0x0259, 0x01A6}, {0x025A, 0x025A, 0x0281}, {0x025B, 0x025B, 0x0282}, + {0x018D, 0x025C, 0x01A9}, {0x025D, 0x025D, 0x0284}, {0x025E, 0x025E, 0x0285}, {0x025F, 0x025F, 0x0286}, + {0x0260, 0x0260, 0x0287}, {0x0192, 0x0261, 0x01AE}, {0x021F, 0x0262, 0x0244}, {0x0195, 0x0263, 0x01B1}, + {0x0196, 0x0264, 0x01B2}, {0x0220, 0x0265, 0x0245}, {0x0266, 0x0266, 0x028D}, {0x0267, 0x0267, 0x028E}, + {0x0268, 0x0268, 0x028F}, {0x0269, 0x0269, 0x0290}, {0x026A, 0x026A, 0x0291}, {0x019B, 0x026B, 0x01B7}, + {0x026C, 0x026C, 0x0293}, {0x026D, 0x026D, 0x0294}, {0x026E, 0x026E, 0x0295}, {0x026F, 0x026F, 0x0296}, + {0x0270, 0x0270, 0x0297}, {0x0271, 0x0271, 0x0298}, {0x0272, 0x0272, 0x0299}, {0x0273, 0x0273, 0x029A}, + {0x0274, 0x0274, 0x029B}, {0x0275, 0x0275, 0x029C}, {0x0276, 0x0276, 0x029D}, {0x0277, 0x0277, 0x029E}, + {0x0278, 0x0278, 0x029F}, {0x0279, 0x0279, 0x02A0}, {0x027A, 0x027A, 0x02A1}, {0x027B, 0x027B, 0x02A2}, + {0x027C, 0x027C, 0x02A3}, {0x027D, 0x027D, 0x02A4}, {0x027E, 0x027E, 0x02A5}, {0x027F, 0x027F, 0x02A6}, + {0x0280, 0x0280, 0x02A7}, {0x0281, 0x0281, 0x02A8}, {0x0282, 0x0282, 0x02A9}, {0x0283, 0x0283, 0x02AA}, + {0x0284, 0x0284, 0x02AB}, {0x0285, 0x0285, 0x02AC}, {0x0286, 0x0286, 0x02AD}, {0x0287, 0x0287, 0x02AE}, + {0x0288, 0x0288, 0x02AF}, {0x0289, 0x0289, 0x02B0}, {0x028A, 0x028A, 0x02B1}, {0x028B, 0x028B, 0x02B2}, + {0x028C, 0x028C, 0x02B3}, {0x028D, 0x028D, 0x02B4}, {0x028E, 0x028E, 0x02B5}, {0x028F, 0x028F, 0x02B6}, + {0x0290, 0x0290, 0x02B7}, {0x0291, 0x0291, 0x02B8}, {0x0292, 0x0292, 0x02B9}, {0x0293, 0x0293, 0x02BA}, + {0x0294, 0x0294, 0x02BB}, {0x0295, 0x0295, 0x02BC}, {0x0296, 0x0296, 0x02BD}, {0x0297, 0x0297, 0x02BE}, + {0x0298, 0x0298, 0x02BF}, {0x0299, 0x0299, 0x02C0}, {0x029A, 0x029A, 0x02C1}, {0x029B, 0x029B, 0x02C2}, + {0x029C, 0x029C, 0x02C3}, {0x029D, 0x029D, 0x02C4}, {0x029E, 0x029E, 0x02C5}, {0x029F, 0x029F, 0x02C6}, + {0x02A0, 0x02A0, 0x02C8}, {0x02A1, 0x02A1, 0x02CC}, {0x02A2, 0x02A2, 0x02CD}, {0x02A3, 0x02A3, 0x02CE}, + {0x02A4, 0x02A4, 0x02CF}, {0x02A5, 0x02A5, 0x02D0}, {0x02A6, 0x02A6, 0x02D1}, {0x02A7, 0x02A7, 0x02D2}, + {0x02A8, 0x02A8, 0x02D3}, {0x02A9, 0x02A9, 0x02D4}, {0x02AA, 0x02AA, 0x02D5}, {0x02AB, 0x02AB, 0x02D6}, + {0x02AC, 0x02AC, 0x02D7}, {0x02AD, 0x02AD, 0x02D8}, {0x02AE, 0x02AE, 0x02DA}, {0x02AF, 0x02AF, 0x02DB}, + {0x02B0, 0x02B0, 0x02DC}, {0x02B1, 0x02B1, 0x02DD}, {0x02B2, 0x02B2, 0x02DE}, {0x02B3, 0x02B3, 0x02DF}, + {0x02B4, 0x02B4, 0x02E0}, {0x02B5, 0x02B5, 0x02E1}, {0x02B6, 0x02B6, 0x02E2}, {0x02B7, 0x02B7, 0x02E3}, + {0x02B8, 0x02B8, 0x02E4}, {0x02B9, 0x02B9, 0x02E5}, {0x02BA, 0x02BA, 0x02E6}, {0x02BB, 0x02BB, 0x02E7}, + {0x02BC, 0x02BC, 0x02E8}, {0x02BD, 0x02BD, 0x02E9}, {0x02BE, 0x02BE, 0x02EA}, {0x02BF, 0x02BF, 0x02EB}, + {0x02C0, 0x02C0, 0x02EC}, {0x02C1, 0x02C1, 0x02ED}, {0x02C2, 0x02C2, 0x02EE}, {0x02C3, 0x02C3, 0x02EF}, + {0x02C4, 0x02C4, 0x02F0}, {0x02C5, 0x02C5, 0x02F1}, {0x02C6, 0x02C6, 0x02F2}, {0x02C7, 0x02C7, 0x02F3}, + {0x02C8, 0x02C8, 0x02F4}, {0x02C9, 0x02C9, 0x02F5}, {0x02CA, 0x02CA, 0x02F6}, {0x02CB, 0x02CB, 0x02F7}, + {0x02CC, 0x02CC, 0x02F8}, {0x02CD, 0x02CD, 0x02F9}, {0x02CE, 0x02CE, 0x02FA}, {0x02CF, 0x02CF, 0x02FB}, + {0x02D0, 0x02D0, 0x02FC}, {0x02D1, 0x02D1, 0x02FD}, {0x02D2, 0x02D2, 0x02FE}, {0x02D3, 0x02D3, 0x02FF}, + {0x02D4, 0x02D4, 0x0300}, {0x02D5, 0x02D5, 0x0301}, {0x02D6, 0x02D6, 0x0302}, {0x02D7, 0x02D7, 0x0303}, + {0x02D8, 0x02D8, 0x0304}, {0x02D9, 0x02D9, 0x0305}, {0x02DA, 0x02DA, 0x0306}, {0x02DB, 0x02DB, 0x0307}, + {0x02DC, 0x02DC, 0x0308}, {0x02DD, 0x02DD, 0x0309}, {0x02DE, 0x02DE, 0x030A}, {0x02DF, 0x02DF, 0x030B}, + {0x02E0, 0x02E0, 0x030C}, {0x02E1, 0x02E1, 0x030D}, {0x02E2, 0x02E2, 0x030E}, {0x02E3, 0x02E3, 0x030F}, + {0x02E4, 0x02E4, 0x0310}, {0x02E5, 0x02E5, 0x0311}, {0x02E6, 0x02E6, 0x0312}, {0x02E7, 0x02E7, 0x0313}, + {0x02E8, 0x02E8, 0x0314}, {0x02E9, 0x02E9, 0x0315}, {0x02EA, 0x02EA, 0x0316}, {0x02EB, 0x02EB, 0x0317}, + {0x02EC, 0x02EC, 0x0318}, {0x02ED, 0x02ED, 0x0319}, {0x02EE, 0x02EE, 0x031A}, {0x02EF, 0x02EF, 0x031B}, + {0x02F0, 0x02F0, 0x031C}, {0x02F1, 0x02F1, 0x031D}, {0x02F2, 0x02F2, 0x031E}, {0x02F3, 0x02F3, 0x031F}, + {0x02F4, 0x02F4, 0x0320}, {0x02F5, 0x02F5, 0x0321}, {0x02F6, 0x02F6, 0x0322}, {0x02F7, 0x02F7, 0x0323}, + {0x02F8, 0x02F8, 0x0324}, {0x02F9, 0x02F9, 0x0325}, {0x02FA, 0x02FA, 0x0326}, {0x02FB, 0x02FB, 0x0327}, + {0x02FC, 0x02FC, 0x0328}, {0x02FD, 0x02FD, 0x0329}, {0x02FE, 0x02FE, 0x032A}, {0x02FF, 0x02FF, 0x032B} +}; + +static GS_UNICASE_CHARACTER plane03[] = { + {0x0300, 0x0300, 0x032C}, {0x0301, 0x0301, 0x032D}, {0x0302, 0x0302, 0x032E}, {0x0303, 0x0303, 0x032F}, + {0x0304, 0x0304, 0x0330}, {0x0305, 0x0305, 0x0331}, {0x0306, 0x0306, 0x0332}, {0x0307, 0x0307, 0x0333}, + {0x0308, 0x0308, 0x0334}, {0x0309, 0x0309, 0x0335}, {0x030A, 0x030A, 0x0336}, {0x030B, 0x030B, 0x0337}, + {0x030C, 0x030C, 0x0338}, {0x030D, 0x030D, 0x0339}, {0x030E, 0x030E, 0x033A}, {0x030F, 0x030F, 0x033B}, + {0x0310, 0x0310, 0x033C}, {0x0311, 0x0311, 0x033D}, {0x0312, 0x0312, 0x033E}, {0x0313, 0x0313, 0x033F}, + {0x0314, 0x0314, 0x0340}, {0x0315, 0x0315, 0x0341}, {0x0316, 0x0316, 0x0342}, {0x0317, 0x0317, 0x0343}, + {0x0318, 0x0318, 0x0344}, {0xA6A9, 0x0319, 0x0345}, {0x031A, 0x031A, 0x0346}, {0x031B, 0x031B, 0x0347}, + {0x031C, 0x031C, 0x0348}, {0x031D, 0x031D, 0x0349}, {0x031E, 0x031E, 0x034A}, {0x031F, 0x031F, 0x034B}, + {0x0320, 0x0320, 0x034C}, {0x0321, 0x0321, 0x034D}, {0x0322, 0x0322, 0x034E}, {0x0323, 0x0323, 0x034F}, + {0x0324, 0x0324, 0x0350}, {0x0325, 0x0325, 0x0351}, {0x0326, 0x0326, 0x0352}, {0x0327, 0x0327, 0x0353}, + {0x0328, 0x0328, 0x0354}, {0x0329, 0x0329, 0x0355}, {0x032A, 0x032A, 0x0356}, {0x032B, 0x032B, 0x0357}, + {0x032C, 0x032C, 0x0358}, {0x032D, 0x032D, 0x0359}, {0x032E, 0x032E, 0x035A}, {0x032F, 0x032F, 0x035B}, + {0x0330, 0x0330, 0x035C}, {0x0331, 0x0331, 0x035D}, {0x0332, 0x0332, 0x035E}, {0x0333, 0x0333, 0x035F}, + {0x0334, 0x0334, 0x0360}, {0x0335, 0x0335, 0x0361}, {0x0336, 0x0336, 0x0362}, {0x0337, 0x0337, 0x0363}, + {0x0338, 0x0338, 0x0364}, {0x0339, 0x0339, 0x0365}, {0x033A, 0x033A, 0x0366}, {0x033B, 0x033B, 0x0367}, + {0x033C, 0x033C, 0x0368}, {0x033D, 0x033D, 0x0369}, {0x033E, 0x033E, 0x036A}, {0x033F, 0x033F, 0x036B}, + {0x0340, 0x0340, 0x036C}, {0x0341, 0x0341, 0x036D}, {0x0342, 0x0342, 0x036E}, {0x0343, 0x0343, 0x036F}, + {0x0344, 0x0345, 0x0370}, {0x0344, 0x0345, 0x0370}, {0x0346, 0x0347, 0x0372}, {0x0346, 0x0347, 0x0372}, + {0x0348, 0x0348, 0x0374}, {0x0349, 0x0349, 0x0375}, {0x034A, 0x034B, 0x0376}, {0x034A, 0x034B, 0x0376}, + {0x034C, 0x034C, 0x0378}, {0x034D, 0x034D, 0x0379}, {0x034E, 0x034E, 0x037A}, {0x03A1, 0x034F, 0x03FD}, + {0x03A2, 0x0350, 0x03FE}, {0x03A3, 0x0351, 0x03FF}, {0x0352, 0x0352, 0x037E}, {0x0353, 0x0353, 0x037F}, + {0x0354, 0x0354, 0x0380}, {0x0355, 0x0355, 0x0381}, {0x0356, 0x0356, 0x0382}, {0x0357, 0x0357, 0x0383}, + {0x0358, 0x0358, 0x0384}, {0x0359, 0x0359, 0x0385}, {0x035A, 0x0368, 0x0386}, {0x035B, 0x035B, 0x0387}, + {0x035C, 0x0369, 0x0388}, {0x035D, 0x036A, 0x0389}, {0x035E, 0x036B, 0x038A}, {0x035F, 0x035F, 0x038B}, + {0x0360, 0x0370, 0x038C}, {0x0361, 0x0361, 0x038D}, {0x0362, 0x0371, 0x038E}, {0x0363, 0x0372, 0x038F}, + {0x0364, 0x0364, 0x0390}, {0x0365, 0x0365, 0x03A2}, {0x0366, 0x036E, 0x03AA}, {0x0367, 0x036F, 0x03AB}, + {0x035A, 0x0368, 0x0386}, {0x035C, 0x0369, 0x0388}, {0x035D, 0x036A, 0x0389}, {0x035E, 0x036B, 0x038A}, + {0x036C, 0x036C, 0x03B0}, {0x036D, 0xA6D2, 0x03C2}, {0x0366, 0x036E, 0x03AA}, {0x0367, 0x036F, 0x03AB}, + {0x0360, 0x0370, 0x038C}, {0x0362, 0x0371, 0x038E}, {0x0363, 0x0372, 0x038F}, {0x0373, 0x037B, 0x03CF}, + {0x0374, 0xA6C2, 0x03D0}, {0x0375, 0xA6C8, 0x03D1}, {0x0376, 0x0376, 0x03D2}, {0x0377, 0x0377, 0x03D3}, + {0x0378, 0x0378, 0x03D4}, {0x0379, 0xA6D5, 0x03D5}, {0x037A, 0xA6D0, 0x03D6}, {0x0373, 0x037B, 0x03CF}, + {0x037C, 0x037D, 0x03D8}, {0x037C, 0x037D, 0x03D8}, {0x037E, 0x037F, 0x03DA}, {0x037E, 0x037F, 0x03DA}, + {0x0380, 0x0381, 0x03DC}, {0x0380, 0x0381, 0x03DC}, {0x0382, 0x0383, 0x03DE}, {0x0382, 0x0383, 0x03DE}, + {0x0384, 0x0385, 0x03E0}, {0x0384, 0x0385, 0x03E0}, {0x0386, 0x0387, 0x03E2}, {0x0386, 0x0387, 0x03E2}, + {0x0388, 0x0389, 0x03E4}, {0x0388, 0x0389, 0x03E4}, {0x038A, 0x038B, 0x03E6}, {0x038A, 0x038B, 0x03E6}, + {0x038C, 0x038D, 0x03E8}, {0x038C, 0x038D, 0x03E8}, {0x038E, 0x038F, 0x03EA}, {0x038E, 0x038F, 0x03EA}, + {0x0390, 0x0391, 0x03EC}, {0x0390, 0x0391, 0x03EC}, {0x0392, 0x0393, 0x03EE}, {0x0392, 0x0393, 0x03EE}, + {0x0394, 0xA6CA, 0x03F0}, {0x0395, 0xA6D1, 0x03F1}, {0x039D, 0x0396, 0x03F9}, {0x0397, 0x0397, 0x03F3}, + {0x0398, 0xA6C8, 0x03F4}, {0x0399, 0xA6C5, 0x03F5}, {0x039A, 0x039A, 0x03F6}, {0x039B, 0x039C, 0x03F7}, + {0x039B, 0x039C, 0x03F7}, {0x039D, 0x0396, 0x03F9}, {0x039E, 0x039F, 0x03FA}, {0x039E, 0x039F, 0x03FA}, + {0x03A0, 0x03A0, 0x03FC}, {0x03A1, 0x034F, 0x03FD}, {0x03A2, 0x0350, 0x03FE}, {0x03A3, 0x0351, 0x03FF}, + {0x03A4, 0x03B3, 0x0400}, {0x03A5, 0x03B4, 0x0402}, {0x03A6, 0x03B5, 0x0403}, {0x03A7, 0x03B6, 0x0404}, + {0x03A8, 0x03B7, 0x0405}, {0x03A9, 0x03B8, 0x0406}, {0x03AA, 0x03B9, 0x0407}, {0x03AB, 0x03BA, 0x0408}, + {0x03AC, 0x03BB, 0x0409}, {0x03AD, 0x03BC, 0x040A}, {0x03AE, 0x03BD, 0x040B}, {0x03AF, 0x03BE, 0x040C}, + {0x03B0, 0x03BF, 0x040D}, {0x03B1, 0x03C0, 0x040E}, {0x03B2, 0x03C1, 0x040F}, {0x03A4, 0x03B3, 0x0400}, + {0x03A5, 0x03B4, 0x0402}, {0x03A6, 0x03B5, 0x0403}, {0x03A7, 0x03B6, 0x0404}, {0x03A8, 0x03B7, 0x0405}, + {0x03A9, 0x03B8, 0x0406}, {0x03AA, 0x03B9, 0x0407}, {0x03AB, 0x03BA, 0x0408}, {0x03AC, 0x03BB, 0x0409}, + {0x03AD, 0x03BC, 0x040A}, {0x03AE, 0x03BD, 0x040B}, {0x03AF, 0x03BE, 0x040C}, {0x03B0, 0x03BF, 0x040D}, + {0x03B1, 0x03C0, 0x040E}, {0x03B2, 0x03C1, 0x040F}, {0x03C2, 0x03C3, 0x0460}, {0x03C2, 0x03C3, 0x0460}, + {0x03C4, 0x03C5, 0x0462}, {0x03C4, 0x03C5, 0x0462}, {0x03C6, 0x03C7, 0x0464}, {0x03C6, 0x03C7, 0x0464}, + {0x03C8, 0x03C9, 0x0466}, {0x03C8, 0x03C9, 0x0466}, {0x03CA, 0x03CB, 0x0468}, {0x03CA, 0x03CB, 0x0468}, + {0x03CC, 0x03CD, 0x046A}, {0x03CC, 0x03CD, 0x046A}, {0x03CE, 0x03CF, 0x046C}, {0x03CE, 0x03CF, 0x046C}, + {0x03D0, 0x03D1, 0x046E}, {0x03D0, 0x03D1, 0x046E}, {0x03D2, 0x03D3, 0x0470}, {0x03D2, 0x03D3, 0x0470}, + {0x03D4, 0x03D5, 0x0472}, {0x03D4, 0x03D5, 0x0472}, {0x03D6, 0x03D7, 0x0474}, {0x03D6, 0x03D7, 0x0474}, + {0x03D8, 0x03D9, 0x0476}, {0x03D8, 0x03D9, 0x0476}, {0x03DA, 0x03DB, 0x0478}, {0x03DA, 0x03DB, 0x0478}, + {0x03DC, 0x03DD, 0x047A}, {0x03DC, 0x03DD, 0x047A}, {0x03DE, 0x03DF, 0x047C}, {0x03DE, 0x03DF, 0x047C}, + {0x03E0, 0x03E1, 0x047E}, {0x03E0, 0x03E1, 0x047E}, {0x03E2, 0x03E3, 0x0480}, {0x03E2, 0x03E3, 0x0480}, + {0x03E4, 0x03E4, 0x0482}, {0x03E5, 0x03E5, 0x0483}, {0x03E6, 0x03E6, 0x0484}, {0x03E7, 0x03E7, 0x0485}, + {0x03E8, 0x03E8, 0x0486}, {0x03E9, 0x03E9, 0x0487}, {0x03EA, 0x03EA, 0x0488}, {0x03EB, 0x03EB, 0x0489}, + {0x03EC, 0x03ED, 0x048A}, {0x03EC, 0x03ED, 0x048A}, {0x03EE, 0x03EF, 0x048C}, {0x03EE, 0x03EF, 0x048C}, + {0x03F0, 0x03F1, 0x048E}, {0x03F0, 0x03F1, 0x048E}, {0x03F2, 0x03F3, 0x0490}, {0x03F2, 0x03F3, 0x0490}, + {0x03F4, 0x03F5, 0x0492}, {0x03F4, 0x03F5, 0x0492}, {0x03F6, 0x03F7, 0x0494}, {0x03F6, 0x03F7, 0x0494}, + {0x03F8, 0x03F9, 0x0496}, {0x03F8, 0x03F9, 0x0496}, {0x03FA, 0x03FB, 0x0498}, {0x03FA, 0x03FB, 0x0498}, + {0x03FC, 0x03FD, 0x049A}, {0x03FC, 0x03FD, 0x049A}, {0x03FE, 0x03FF, 0x049C}, {0x03FE, 0x03FF, 0x049C} +}; + +static GS_UNICASE_CHARACTER plane04[] = { + {0x0400, 0x0401, 0x049E}, {0x0400, 0x0401, 0x049E}, {0x0402, 0x0403, 0x04A0}, {0x0402, 0x0403, 0x04A0}, + {0x0404, 0x0405, 0x04A2}, {0x0404, 0x0405, 0x04A2}, {0x0406, 0x0407, 0x04A4}, {0x0406, 0x0407, 0x04A4}, + {0x0408, 0x0409, 0x04A6}, {0x0408, 0x0409, 0x04A6}, {0x040A, 0x040B, 0x04A8}, {0x040A, 0x040B, 0x04A8}, + {0x040C, 0x040D, 0x04AA}, {0x040C, 0x040D, 0x04AA}, {0x040E, 0x040F, 0x04AC}, {0x040E, 0x040F, 0x04AC}, + {0x0410, 0x0411, 0x04AE}, {0x0410, 0x0411, 0x04AE}, {0x0412, 0x0413, 0x04B0}, {0x0412, 0x0413, 0x04B0}, + {0x0414, 0x0415, 0x04B2}, {0x0414, 0x0415, 0x04B2}, {0x0416, 0x0417, 0x04B4}, {0x0416, 0x0417, 0x04B4}, + {0x0418, 0x0419, 0x04B6}, {0x0418, 0x0419, 0x04B6}, {0x041A, 0x041B, 0x04B8}, {0x041A, 0x041B, 0x04B8}, + {0x041C, 0x041D, 0x04BA}, {0x041C, 0x041D, 0x04BA}, {0x041E, 0x041F, 0x04BC}, {0x041E, 0x041F, 0x04BC}, + {0x0420, 0x0421, 0x04BE}, {0x0420, 0x0421, 0x04BE}, {0x0422, 0x0431, 0x04C0}, {0x0423, 0x0424, 0x04C1}, + {0x0423, 0x0424, 0x04C1}, {0x0425, 0x0426, 0x04C3}, {0x0425, 0x0426, 0x04C3}, {0x0427, 0x0428, 0x04C5}, + {0x0427, 0x0428, 0x04C5}, {0x0429, 0x042A, 0x04C7}, {0x0429, 0x042A, 0x04C7}, {0x042B, 0x042C, 0x04C9}, + {0x042B, 0x042C, 0x04C9}, {0x042D, 0x042E, 0x04CB}, {0x042D, 0x042E, 0x04CB}, {0x042F, 0x0430, 0x04CD}, + {0x042F, 0x0430, 0x04CD}, {0x0422, 0x0431, 0x04C0}, {0x0432, 0x0433, 0x04D0}, {0x0432, 0x0433, 0x04D0}, + {0x0434, 0x0435, 0x04D2}, {0x0434, 0x0435, 0x04D2}, {0x0436, 0x0437, 0x04D4}, {0x0436, 0x0437, 0x04D4}, + {0x0438, 0x0439, 0x04D6}, {0x0438, 0x0439, 0x04D6}, {0x043A, 0x043B, 0x04D8}, {0x043A, 0x043B, 0x04D8}, + {0x043C, 0x043D, 0x04DA}, {0x043C, 0x043D, 0x04DA}, {0x043E, 0x043F, 0x04DC}, {0x043E, 0x043F, 0x04DC}, + {0x0440, 0x0441, 0x04DE}, {0x0440, 0x0441, 0x04DE}, {0x0442, 0x0443, 0x04E0}, {0x0442, 0x0443, 0x04E0}, + {0x0444, 0x0445, 0x04E2}, {0x0444, 0x0445, 0x04E2}, {0x0446, 0x0447, 0x04E4}, {0x0446, 0x0447, 0x04E4}, + {0x0448, 0x0449, 0x04E6}, {0x0448, 0x0449, 0x04E6}, {0x044A, 0x044B, 0x04E8}, {0x044A, 0x044B, 0x04E8}, + {0x044C, 0x044D, 0x04EA}, {0x044C, 0x044D, 0x04EA}, {0x044E, 0x044F, 0x04EC}, {0x044E, 0x044F, 0x04EC}, + {0x0450, 0x0451, 0x04EE}, {0x0450, 0x0451, 0x04EE}, {0x0452, 0x0453, 0x04F0}, {0x0452, 0x0453, 0x04F0}, + {0x0454, 0x0455, 0x04F2}, {0x0454, 0x0455, 0x04F2}, {0x0456, 0x0457, 0x04F4}, {0x0456, 0x0457, 0x04F4}, + {0x0458, 0x0459, 0x04F6}, {0x0458, 0x0459, 0x04F6}, {0x045A, 0x045B, 0x04F8}, {0x045A, 0x045B, 0x04F8}, + {0x045C, 0x045D, 0x04FA}, {0x045C, 0x045D, 0x04FA}, {0x045E, 0x045F, 0x04FC}, {0x045E, 0x045F, 0x04FC}, + {0x0460, 0x0461, 0x04FE}, {0x0460, 0x0461, 0x04FE}, {0x0462, 0x0463, 0x0500}, {0x0462, 0x0463, 0x0500}, + {0x0464, 0x0465, 0x0502}, {0x0464, 0x0465, 0x0502}, {0x0466, 0x0467, 0x0504}, {0x0466, 0x0467, 0x0504}, + {0x0468, 0x0469, 0x0506}, {0x0468, 0x0469, 0x0506}, {0x046A, 0x046B, 0x0508}, {0x046A, 0x046B, 0x0508}, + {0x046C, 0x046D, 0x050A}, {0x046C, 0x046D, 0x050A}, {0x046E, 0x046F, 0x050C}, {0x046E, 0x046F, 0x050C}, + {0x0470, 0x0471, 0x050E}, {0x0470, 0x0471, 0x050E}, {0x0472, 0x0473, 0x0510}, {0x0472, 0x0473, 0x0510}, + {0x0474, 0x0475, 0x0512}, {0x0474, 0x0475, 0x0512}, {0x0476, 0x0477, 0x0514}, {0x0476, 0x0477, 0x0514}, + {0x0478, 0x0479, 0x0516}, {0x0478, 0x0479, 0x0516}, {0x047A, 0x047B, 0x0518}, {0x047A, 0x047B, 0x0518}, + {0x047C, 0x047D, 0x051A}, {0x047C, 0x047D, 0x051A}, {0x047E, 0x047F, 0x051C}, {0x047E, 0x047F, 0x051C}, + {0x0480, 0x0481, 0x051E}, {0x0480, 0x0481, 0x051E}, {0x0482, 0x0483, 0x0520}, {0x0482, 0x0483, 0x0520}, + {0x0484, 0x0485, 0x0522}, {0x0484, 0x0485, 0x0522}, {0x0486, 0x0487, 0x0524}, {0x0486, 0x0487, 0x0524}, + {0x0488, 0x0488, 0x0526}, {0x0489, 0x0489, 0x0527}, {0x048A, 0x048A, 0x0528}, {0x048B, 0x048B, 0x0529}, + {0x048C, 0x048C, 0x052A}, {0x048D, 0x048D, 0x052B}, {0x048E, 0x048E, 0x052C}, {0x048F, 0x048F, 0x052D}, + {0x0490, 0x0490, 0x052E}, {0x0491, 0x0491, 0x052F}, {0x0492, 0x0492, 0x0530}, {0x0493, 0x04C3, 0x0531}, + {0x0494, 0x04C4, 0x0532}, {0x0495, 0x04C5, 0x0533}, {0x0496, 0x04C6, 0x0534}, {0x0497, 0x04C7, 0x0535}, + {0x0498, 0x04C8, 0x0536}, {0x0499, 0x04C9, 0x0537}, {0x049A, 0x04CA, 0x0538}, {0x049B, 0x04CB, 0x0539}, + {0x049C, 0x04CC, 0x053A}, {0x049D, 0x04CD, 0x053B}, {0x049E, 0x04CE, 0x053C}, {0x049F, 0x04CF, 0x053D}, + {0x04A0, 0x04D0, 0x053E}, {0x04A1, 0x04D1, 0x053F}, {0x04A2, 0x04D2, 0x0540}, {0x04A3, 0x04D3, 0x0541}, + {0x04A4, 0x04D4, 0x0542}, {0x04A5, 0x04D5, 0x0543}, {0x04A6, 0x04D6, 0x0544}, {0x04A7, 0x04D7, 0x0545}, + {0x04A8, 0x04D8, 0x0546}, {0x04A9, 0x04D9, 0x0547}, {0x04AA, 0x04DA, 0x0548}, {0x04AB, 0x04DB, 0x0549}, + {0x04AC, 0x04DC, 0x054A}, {0x04AD, 0x04DD, 0x054B}, {0x04AE, 0x04DE, 0x054C}, {0x04AF, 0x04DF, 0x054D}, + {0x04B0, 0x04E0, 0x054E}, {0x04B1, 0x04E1, 0x054F}, {0x04B2, 0x04E2, 0x0550}, {0x04B3, 0x04E3, 0x0551}, + {0x04B4, 0x04E4, 0x0552}, {0x04B5, 0x04E5, 0x0553}, {0x04B6, 0x04E6, 0x0554}, {0x04B7, 0x04E7, 0x0555}, + {0x04B8, 0x04E8, 0x0556}, {0x04B9, 0x04B9, 0x0557}, {0x04BA, 0x04BA, 0x0558}, {0x04BB, 0x04BB, 0x0559}, + {0x04BC, 0x04BC, 0x055A}, {0x04BD, 0x04BD, 0x055B}, {0x04BE, 0x04BE, 0x055C}, {0x04BF, 0x04BF, 0x055D}, + {0x04C0, 0x04C0, 0x055E}, {0x04C1, 0x04C1, 0x055F}, {0x04C2, 0x04C2, 0x0560}, {0x0493, 0x04C3, 0x0531}, + {0x0494, 0x04C4, 0x0532}, {0x0495, 0x04C5, 0x0533}, {0x0496, 0x04C6, 0x0534}, {0x0497, 0x04C7, 0x0535}, + {0x0498, 0x04C8, 0x0536}, {0x0499, 0x04C9, 0x0537}, {0x049A, 0x04CA, 0x0538}, {0x049B, 0x04CB, 0x0539}, + {0x049C, 0x04CC, 0x053A}, {0x049D, 0x04CD, 0x053B}, {0x049E, 0x04CE, 0x053C}, {0x049F, 0x04CF, 0x053D}, + {0x04A0, 0x04D0, 0x053E}, {0x04A1, 0x04D1, 0x053F}, {0x04A2, 0x04D2, 0x0540}, {0x04A3, 0x04D3, 0x0541}, + {0x04A4, 0x04D4, 0x0542}, {0x04A5, 0x04D5, 0x0543}, {0x04A6, 0x04D6, 0x0544}, {0x04A7, 0x04D7, 0x0545}, + {0x04A8, 0x04D8, 0x0546}, {0x04A9, 0x04D9, 0x0547}, {0x04AA, 0x04DA, 0x0548}, {0x04AB, 0x04DB, 0x0549}, + {0x04AC, 0x04DC, 0x054A}, {0x04AD, 0x04DD, 0x054B}, {0x04AE, 0x04DE, 0x054C}, {0x04AF, 0x04DF, 0x054D}, + {0x04B0, 0x04E0, 0x054E}, {0x04B1, 0x04E1, 0x054F}, {0x04B2, 0x04E2, 0x0550}, {0x04B3, 0x04E3, 0x0551}, + {0x04B4, 0x04E4, 0x0552}, {0x04B5, 0x04E5, 0x0553}, {0x04B6, 0x04E6, 0x0554}, {0x04B7, 0x04E7, 0x0555}, + {0x04B8, 0x04E8, 0x0556}, {0x04E9, 0x04E9, 0x0587}, {0x04EA, 0x04EA, 0x0588}, {0x04EB, 0x04EB, 0x0589}, + {0x04EC, 0x04EC, 0x058A}, {0x04ED, 0x04ED, 0x058B}, {0x04EE, 0x04EE, 0x058C}, {0x04EF, 0x04EF, 0x058D}, + {0x04F0, 0x04F0, 0x058E}, {0x04F1, 0x04F1, 0x058F}, {0x04F2, 0x04F2, 0x0590}, {0x04F3, 0x04F3, 0x0591}, + {0x04F4, 0x04F4, 0x0592}, {0x04F5, 0x04F5, 0x0593}, {0x04F6, 0x04F6, 0x0594}, {0x04F7, 0x04F7, 0x0595}, + {0x04F8, 0x04F8, 0x0596}, {0x04F9, 0x04F9, 0x0597}, {0x04FA, 0x04FA, 0x0598}, {0x04FB, 0x04FB, 0x0599}, + {0x04FC, 0x04FC, 0x059A}, {0x04FD, 0x04FD, 0x059B}, {0x04FE, 0x04FE, 0x059C}, {0x04FF, 0x04FF, 0x059D} +}; + +static GS_UNICASE_CHARACTER plane10[] = { + {0x1000, 0x1000, 0x109E}, {0x1001, 0x1001, 0x109F}, {0x1002, 0x2B40, 0x10A0}, {0x1003, 0x2B41, 0x10A1}, + {0x1004, 0x2B42, 0x10A2}, {0x1005, 0x2B43, 0x10A3}, {0x1006, 0x2B44, 0x10A4}, {0x1007, 0x2B45, 0x10A5}, + {0x1008, 0x2B46, 0x10A6}, {0x1009, 0x2B47, 0x10A7}, {0x100A, 0x2B48, 0x10A8}, {0x100B, 0x2B49, 0x10A9}, + {0x100C, 0x2B4A, 0x10AA}, {0x100D, 0x2B4B, 0x10AB}, {0x100E, 0x2B4C, 0x10AC}, {0x100F, 0x2B4D, 0x10AD}, + {0x1010, 0x2B4E, 0x10AE}, {0x1011, 0x2B4F, 0x10AF}, {0x1012, 0x2B50, 0x10B0}, {0x1013, 0x2B51, 0x10B1}, + {0x1014, 0x2B52, 0x10B2}, {0x1015, 0x2B53, 0x10B3}, {0x1016, 0x2B54, 0x10B4}, {0x1017, 0x2B55, 0x10B5}, + {0x1018, 0x2B56, 0x10B6}, {0x1019, 0x2B57, 0x10B7}, {0x101A, 0x2B58, 0x10B8}, {0x101B, 0x2B59, 0x10B9}, + {0x101C, 0x2B5A, 0x10BA}, {0x101D, 0x2B5B, 0x10BB}, {0x101E, 0x2B5C, 0x10BC}, {0x101F, 0x2B5D, 0x10BD}, + {0x1020, 0x2B5E, 0x10BE}, {0x1021, 0x2B5F, 0x10BF}, {0x1022, 0x2B60, 0x10C0}, {0x1023, 0x2B61, 0x10C1}, + {0x1024, 0x2B62, 0x10C2}, {0x1025, 0x2B63, 0x10C3}, {0x1026, 0x2B64, 0x10C4}, {0x1027, 0x2B65, 0x10C5}, + {0x1028, 0x1028, 0x10C6}, {0x1029, 0x1029, 0x10C7}, {0x102A, 0x102A, 0x10C8}, {0x102B, 0x102B, 0x10C9}, + {0x102C, 0x102C, 0x10CA}, {0x102D, 0x102D, 0x10CB}, {0x102E, 0x102E, 0x10CC}, {0x102F, 0x102F, 0x10CD}, + {0x1030, 0x1030, 0x10CE}, {0x1031, 0x1031, 0x10CF}, {0x1032, 0x1032, 0x10D0}, {0x1033, 0x1033, 0x10D1}, + {0x1034, 0x1034, 0x10D2}, {0x1035, 0x1035, 0x10D3}, {0x1036, 0x1036, 0x10D4}, {0x1037, 0x1037, 0x10D5}, + {0x1038, 0x1038, 0x10D6}, {0x1039, 0x1039, 0x10D7}, {0x103A, 0x103A, 0x10D8}, {0x103B, 0x103B, 0x10D9}, + {0x103C, 0x103C, 0x10DA}, {0x103D, 0x103D, 0x10DB}, {0x103E, 0x103E, 0x10DC}, {0x103F, 0x103F, 0x10DD}, + {0x1040, 0x1040, 0x10DE}, {0x1041, 0x1041, 0x10DF}, {0x1042, 0x1042, 0x10E0}, {0x1043, 0x1043, 0x10E1}, + {0x1044, 0x1044, 0x10E2}, {0x1045, 0x1045, 0x10E3}, {0x1046, 0x1046, 0x10E4}, {0x1047, 0x1047, 0x10E5}, + {0x1048, 0x1048, 0x10E6}, {0x1049, 0x1049, 0x10E7}, {0x104A, 0x104A, 0x10E8}, {0x104B, 0x104B, 0x10E9}, + {0x104C, 0x104C, 0x10EA}, {0x104D, 0x104D, 0x10EB}, {0x104E, 0x104E, 0x10EC}, {0x104F, 0x104F, 0x10ED}, + {0x1050, 0x1050, 0x10EE}, {0x1051, 0x1051, 0x10EF}, {0x1052, 0x1052, 0x10F0}, {0x1053, 0x1053, 0x10F1}, + {0x1054, 0x1054, 0x10F2}, {0x1055, 0x1055, 0x10F3}, {0x1056, 0x1056, 0x10F4}, {0x1057, 0x1057, 0x10F5}, + {0x1058, 0x1058, 0x10F6}, {0x1059, 0x1059, 0x10F7}, {0x105A, 0x105A, 0x10F8}, {0x105B, 0x105B, 0x10F9}, + {0x105C, 0x105C, 0x10FA}, {0x105D, 0x105D, 0x10FB}, {0x105E, 0x105E, 0x10FC}, {0x105F, 0x105F, 0x10FD}, + {0x1060, 0x1060, 0x10FE}, {0x1061, 0x1061, 0x10FF}, {0x1062, 0x1062, 0x1100}, {0x1063, 0x1063, 0x1101}, + {0x1064, 0x1064, 0x1102}, {0x1065, 0x1065, 0x1103}, {0x1066, 0x1066, 0x1104}, {0x1067, 0x1067, 0x1105}, + {0x1068, 0x1068, 0x1106}, {0x1069, 0x1069, 0x1107}, {0x106A, 0x106A, 0x1108}, {0x106B, 0x106B, 0x1109}, + {0x106C, 0x106C, 0x110A}, {0x106D, 0x106D, 0x110B}, {0x106E, 0x106E, 0x110C}, {0x106F, 0x106F, 0x110D}, + {0x1070, 0x1070, 0x110E}, {0x1071, 0x1071, 0x110F}, {0x1072, 0x1072, 0x1110}, {0x1073, 0x1073, 0x1111}, + {0x1074, 0x1074, 0x1112}, {0x1075, 0x1075, 0x1113}, {0x1076, 0x1076, 0x1114}, {0x1077, 0x1077, 0x1115}, + {0x1078, 0x1078, 0x1116}, {0x1079, 0x1079, 0x1117}, {0x107A, 0x107A, 0x1118}, {0x107B, 0x107B, 0x1119}, + {0x107C, 0x107C, 0x111A}, {0x107D, 0x107D, 0x111B}, {0x107E, 0x107E, 0x111C}, {0x107F, 0x107F, 0x111D}, + {0x1080, 0x1080, 0x111E}, {0x1081, 0x1081, 0x111F}, {0x1082, 0x1082, 0x1120}, {0x1083, 0x1083, 0x1121}, + {0x1084, 0x1084, 0x1122}, {0x1085, 0x1085, 0x1123}, {0x1086, 0x1086, 0x1124}, {0x1087, 0x1087, 0x1125}, + {0x1088, 0x1088, 0x1126}, {0x1089, 0x1089, 0x1127}, {0x108A, 0x108A, 0x1128}, {0x108B, 0x108B, 0x1129}, + {0x108C, 0x108C, 0x112A}, {0x108D, 0x108D, 0x112B}, {0x108E, 0x108E, 0x112C}, {0x108F, 0x108F, 0x112D}, + {0x1090, 0x1090, 0x112E}, {0x1091, 0x1091, 0x112F}, {0x1092, 0x1092, 0x1130}, {0x1093, 0x1093, 0x1131}, + {0x1094, 0x1094, 0x1132}, {0x1095, 0x1095, 0x1133}, {0x1096, 0x1096, 0x1134}, {0x1097, 0x1097, 0x1135}, + {0x1098, 0x1098, 0x1136}, {0x1099, 0x1099, 0x1137}, {0x109A, 0x109A, 0x1138}, {0x109B, 0x109B, 0x1139}, + {0x109C, 0x109C, 0x113A}, {0x109D, 0x109D, 0x113B}, {0x109E, 0x109E, 0x113C}, {0x109F, 0x109F, 0x113D}, + {0x10A0, 0x10A0, 0x113E}, {0x10A1, 0x10A1, 0x113F}, {0x10A2, 0x10A2, 0x1140}, {0x10A3, 0x10A3, 0x1141}, + {0x10A4, 0x10A4, 0x1142}, {0x10A5, 0x10A5, 0x1143}, {0x10A6, 0x10A6, 0x1144}, {0x10A7, 0x10A7, 0x1145}, + {0x10A8, 0x10A8, 0x1146}, {0x10A9, 0x10A9, 0x1147}, {0x10AA, 0x10AA, 0x1148}, {0x10AB, 0x10AB, 0x1149}, + {0x10AC, 0x10AC, 0x114A}, {0x10AD, 0x10AD, 0x114B}, {0x10AE, 0x10AE, 0x114C}, {0x10AF, 0x10AF, 0x114D}, + {0x10B0, 0x10B0, 0x114E}, {0x10B1, 0x10B1, 0x114F}, {0x10B2, 0x10B2, 0x1150}, {0x10B3, 0x10B3, 0x1151}, + {0x10B4, 0x10B4, 0x1152}, {0x10B5, 0x10B5, 0x1153}, {0x10B6, 0x10B6, 0x1154}, {0x10B7, 0x10B7, 0x1155}, + {0x10B8, 0x10B8, 0x1156}, {0x10B9, 0x10B9, 0x1157}, {0x10BA, 0x10BA, 0x1158}, {0x10BB, 0x10BB, 0x1159}, + {0x10BC, 0x10BC, 0x115A}, {0x10BD, 0x10BD, 0x115B}, {0x10BE, 0x10BE, 0x115C}, {0x10BF, 0x10BF, 0x115D}, + {0x10C0, 0x10C0, 0x115E}, {0x10C1, 0x10C1, 0x115F}, {0x10C2, 0x10C2, 0x1160}, {0x10C3, 0x10C3, 0x1161}, + {0x10C4, 0x10C4, 0x1162}, {0x10C5, 0x10C5, 0x1163}, {0x10C6, 0x10C6, 0x1164}, {0x10C7, 0x10C7, 0x1165}, + {0x10C8, 0x10C8, 0x1166}, {0x10C9, 0x10C9, 0x1167}, {0x10CA, 0x10CA, 0x1168}, {0x10CB, 0x10CB, 0x1169}, + {0x10CC, 0x10CC, 0x116A}, {0x10CD, 0x10CD, 0x116B}, {0x10CE, 0x10CE, 0x116C}, {0x10CF, 0x10CF, 0x116D}, + {0x10D0, 0x10D0, 0x116E}, {0x10D1, 0x10D1, 0x116F}, {0x10D2, 0x10D2, 0x1170}, {0x10D3, 0x10D3, 0x1171}, + {0x10D4, 0x10D4, 0x1172}, {0x10D5, 0x10D5, 0x1173}, {0x10D6, 0x10D6, 0x1174}, {0x10D7, 0x10D7, 0x1175}, + {0x10D8, 0x10D8, 0x1176}, {0x10D9, 0x10D9, 0x1177}, {0x10DA, 0x10DA, 0x1178}, {0x10DB, 0x10DB, 0x1179}, + {0x10DC, 0x10DC, 0x117A}, {0x10DD, 0x10DD, 0x117B}, {0x10DE, 0x10DE, 0x117C}, {0x10DF, 0x10DF, 0x117D}, + {0x10E0, 0x10E0, 0x117E}, {0x10E1, 0x10E1, 0x117F}, {0x10E2, 0x10E2, 0x1180}, {0x10E3, 0x10E3, 0x1181}, + {0x10E4, 0x10E4, 0x1182}, {0x10E5, 0x10E5, 0x1183}, {0x10E6, 0x10E6, 0x1184}, {0x10E7, 0x10E7, 0x1185}, + {0x10E8, 0x10E8, 0x1186}, {0x10E9, 0x10E9, 0x1187}, {0x10EA, 0x10EA, 0x1188}, {0x10EB, 0x10EB, 0x1189}, + {0x10EC, 0x10EC, 0x118A}, {0x10ED, 0x10ED, 0x118B}, {0x10EE, 0x10EE, 0x118C}, {0x10EF, 0x10EF, 0x118D}, + {0x10F0, 0x10F0, 0x118E}, {0x10F1, 0x10F1, 0x118F}, {0x10F2, 0x10F2, 0x1190}, {0x10F3, 0x10F3, 0x1191}, + {0x10F4, 0x10F4, 0x1192}, {0x10F5, 0x10F5, 0x1193}, {0x10F6, 0x10F6, 0x1194}, {0x10F7, 0x10F7, 0x1195}, + {0x10F8, 0x10F8, 0x1196}, {0x10F9, 0x10F9, 0x1197}, {0x10FA, 0x10FA, 0x1198}, {0x10FB, 0x10FB, 0x1199}, + {0x10FC, 0x10FC, 0x119A}, {0x10FD, 0x10FD, 0x119B}, {0x10FE, 0x10FE, 0x119C}, {0x10FF, 0x10FF, 0x119D} +}; + +static GS_UNICASE_CHARACTER plane1D[] = { + {0x1D00, 0x1D00, 0x1D9E}, {0x1D01, 0x1D01, 0x1D9F}, {0x1D02, 0x1D02, 0x1DA0}, {0x1D03, 0x1D03, 0x1DA1}, + {0x1D04, 0x1D04, 0x1DA2}, {0x1D05, 0x1D05, 0x1DA3}, {0x1D06, 0x1D06, 0x1DA4}, {0x1D07, 0x1D07, 0x1DA5}, + {0x1D08, 0x1D08, 0x1DA6}, {0x1D09, 0x1D09, 0x1DA7}, {0x1D0A, 0x1D0A, 0x1DA8}, {0x1D0B, 0x1D0B, 0x1DA9}, + {0x1D0C, 0x1D0C, 0x1DAA}, {0x1D0D, 0x1D0D, 0x1DAB}, {0x1D0E, 0x1D0E, 0x1DAC}, {0x1D0F, 0x1D0F, 0x1DAD}, + {0x1D10, 0x1D10, 0x1DAE}, {0x1D11, 0x1D11, 0x1DAF}, {0x1D12, 0x1D12, 0x1DB0}, {0x1D13, 0x1D13, 0x1DB1}, + {0x1D14, 0x1D14, 0x1DB2}, {0x1D15, 0x1D15, 0x1DB3}, {0x1D16, 0x1D16, 0x1DB4}, {0x1D17, 0x1D17, 0x1DB5}, + {0x1D18, 0x1D18, 0x1DB6}, {0x1D19, 0x1D19, 0x1DB7}, {0x1D1A, 0x1D1A, 0x1DB8}, {0x1D1B, 0x1D1B, 0x1DB9}, + {0x1D1C, 0x1D1C, 0x1DBA}, {0x1D1D, 0x1D1D, 0x1DBB}, {0x1D1E, 0x1D1E, 0x1DBC}, {0x1D1F, 0x1D1F, 0x1DBD}, + {0x1D20, 0x1D20, 0x1DBE}, {0x1D21, 0x1D21, 0x1DBF}, {0x1D22, 0x1D22, 0x1DC0}, {0x1D23, 0x1D23, 0x1DC1}, + {0x1D24, 0x1D24, 0x1DC2}, {0x1D25, 0x1D25, 0x1DC3}, {0x1D26, 0x1D26, 0x1DC4}, {0x1D27, 0x1D27, 0x1DC5}, + {0x1D28, 0x1D28, 0x1DC6}, {0x1D29, 0x1D29, 0x1DC7}, {0x1D2A, 0x1D2A, 0x1DC8}, {0x1D2B, 0x1D2B, 0x1DC9}, + {0x1D2C, 0x1D2C, 0x1DCA}, {0x1D2D, 0x1D2D, 0x1DCB}, {0x1D2E, 0x1D2E, 0x1DCC}, {0x1D2F, 0x1D2F, 0x1DCD}, + {0x1D30, 0x1D30, 0x1DCE}, {0x1D31, 0x1D31, 0x1DCF}, {0x1D32, 0x1D32, 0x1DD0}, {0x1D33, 0x1D33, 0x1DD1}, + {0x1D34, 0x1D34, 0x1DD2}, {0x1D35, 0x1D35, 0x1DD3}, {0x1D36, 0x1D36, 0x1DD4}, {0x1D37, 0x1D37, 0x1DD5}, + {0x1D38, 0x1D38, 0x1DD6}, {0x1D39, 0x1D39, 0x1DD7}, {0x1D3A, 0x1D3A, 0x1DD8}, {0x1D3B, 0x1D3B, 0x1DD9}, + {0x1D3C, 0x1D3C, 0x1DDA}, {0x1D3D, 0x1D3D, 0x1DDB}, {0x1D3E, 0x1D3E, 0x1DDC}, {0x1D3F, 0x1D3F, 0x1DDD}, + {0x1D40, 0x1D40, 0x1DDE}, {0x1D41, 0x1D41, 0x1DDF}, {0x1D42, 0x1D42, 0x1DE0}, {0x1D43, 0x1D43, 0x1DE1}, + {0x1D44, 0x1D44, 0x1DE2}, {0x1D45, 0x1D45, 0x1DE3}, {0x1D46, 0x1D46, 0x1DE4}, {0x1D47, 0x1D47, 0x1DE5}, + {0x1D48, 0x1D48, 0x1DE6}, {0x1D49, 0x1D49, 0x1DE7}, {0x1D4A, 0x1D4A, 0x1DE8}, {0x1D4B, 0x1D4B, 0x1DE9}, + {0x1D4C, 0x1D4C, 0x1DEA}, {0x1D4D, 0x1D4D, 0x1DEB}, {0x1D4E, 0x1D4E, 0x1DEC}, {0x1D4F, 0x1D4F, 0x1DED}, + {0x1D50, 0x1D50, 0x1DEE}, {0x1D51, 0x1D51, 0x1DEF}, {0x1D52, 0x1D52, 0x1DF0}, {0x1D53, 0x1D53, 0x1DF1}, + {0x1D54, 0x1D54, 0x1DF2}, {0x1D55, 0x1D55, 0x1DF3}, {0x1D56, 0x1D56, 0x1DF4}, {0x1D57, 0x1D57, 0x1DF5}, + {0x1D58, 0x1D58, 0x1DF6}, {0x1D59, 0x1D59, 0x1DF7}, {0x1D5A, 0x1D5A, 0x1DF8}, {0x1D5B, 0x1D5B, 0x1DF9}, + {0x1D5C, 0x1D5C, 0x1DFA}, {0x1D5D, 0x1D5D, 0x1DFB}, {0x1D5E, 0x1D5E, 0x1DFC}, {0x1D5F, 0x1D5F, 0x1DFD}, + {0x1D60, 0x1D60, 0x1DFE}, {0x1D61, 0x1D61, 0x1DFF}, {0x1D62, 0x1D63, 0x1E00}, {0x1D62, 0x1D63, 0x1E00}, + {0x1D64, 0x1D65, 0x1E02}, {0x1D64, 0x1D65, 0x1E02}, {0x1D66, 0x1D67, 0x1E04}, {0x1D66, 0x1D67, 0x1E04}, + {0x1D68, 0x1D69, 0x1E06}, {0x1D68, 0x1D69, 0x1E06}, {0x1D6A, 0x1D6B, 0x1E08}, {0x1D6A, 0x1D6B, 0x1E08}, + {0x1D6C, 0x1D6D, 0x1E0A}, {0x1D6C, 0x1D6D, 0x1E0A}, {0x1D6E, 0x1D6F, 0x1E0C}, {0x1D6E, 0x1D6F, 0x1E0C}, + {0x1D70, 0x1D71, 0x1E0E}, {0x1D70, 0x1D71, 0x1E0E}, {0x1D72, 0x1D73, 0x1E10}, {0x1D72, 0x1D73, 0x1E10}, + {0x1D74, 0x1D75, 0x1E12}, {0x1D74, 0x1D75, 0x1E12}, {0x1D76, 0x1D77, 0x1E14}, {0x1D76, 0x1D77, 0x1E14}, + {0x1D78, 0x1D79, 0x1E16}, {0x1D78, 0x1D79, 0x1E16}, {0x1D7A, 0x1D7B, 0x1E18}, {0x1D7A, 0x1D7B, 0x1E18}, + {0x1D7C, 0x1D7D, 0x1E1A}, {0x1D7C, 0x1D7D, 0x1E1A}, {0x1D7E, 0x1D7F, 0x1E1C}, {0x1D7E, 0x1D7F, 0x1E1C}, + {0x1D80, 0x1D81, 0x1E1E}, {0x1D80, 0x1D81, 0x1E1E}, {0x1D82, 0x1D83, 0x1E20}, {0x1D82, 0x1D83, 0x1E20}, + {0x1D84, 0x1D85, 0x1E22}, {0x1D84, 0x1D85, 0x1E22}, {0x1D86, 0x1D87, 0x1E24}, {0x1D86, 0x1D87, 0x1E24}, + {0x1D88, 0x1D89, 0x1E26}, {0x1D88, 0x1D89, 0x1E26}, {0x1D8A, 0x1D8B, 0x1E28}, {0x1D8A, 0x1D8B, 0x1E28}, + {0x1D8C, 0x1D8D, 0x1E2A}, {0x1D8C, 0x1D8D, 0x1E2A}, {0x1D8E, 0x1D8F, 0x1E2C}, {0x1D8E, 0x1D8F, 0x1E2C}, + {0x1D90, 0x1D91, 0x1E2E}, {0x1D90, 0x1D91, 0x1E2E}, {0x1D92, 0x1D93, 0x1E30}, {0x1D92, 0x1D93, 0x1E30}, + {0x1D94, 0x1D95, 0x1E32}, {0x1D94, 0x1D95, 0x1E32}, {0x1D96, 0x1D97, 0x1E34}, {0x1D96, 0x1D97, 0x1E34}, + {0x1D98, 0x1D99, 0x1E36}, {0x1D98, 0x1D99, 0x1E36}, {0x1D9A, 0x1D9B, 0x1E38}, {0x1D9A, 0x1D9B, 0x1E38}, + {0x1D9C, 0x1D9D, 0x1E3A}, {0x1D9C, 0x1D9D, 0x1E3A}, {0x1D9E, 0x1D9F, 0x1E3C}, {0x1D9E, 0x1D9F, 0x1E3C}, + {0x1DA0, 0xA8BC, 0x1E3E}, {0x1DA1, 0x1DA1, 0xE7C7}, {0x1DA2, 0x1DA3, 0x1E40}, {0x1DA2, 0x1DA3, 0x1E40}, + {0x1DA4, 0x1DA5, 0x1E42}, {0x1DA4, 0x1DA5, 0x1E42}, {0x1DA6, 0x1DA7, 0x1E44}, {0x1DA6, 0x1DA7, 0x1E44}, + {0x1DA8, 0x1DA9, 0x1E46}, {0x1DA8, 0x1DA9, 0x1E46}, {0x1DAA, 0x1DAB, 0x1E48}, {0x1DAA, 0x1DAB, 0x1E48}, + {0x1DAC, 0x1DAD, 0x1E4A}, {0x1DAC, 0x1DAD, 0x1E4A}, {0x1DAE, 0x1DAF, 0x1E4C}, {0x1DAE, 0x1DAF, 0x1E4C}, + {0x1DB0, 0x1DB1, 0x1E4E}, {0x1DB0, 0x1DB1, 0x1E4E}, {0x1DB2, 0x1DB3, 0x1E50}, {0x1DB2, 0x1DB3, 0x1E50}, + {0x1DB4, 0x1DB5, 0x1E52}, {0x1DB4, 0x1DB5, 0x1E52}, {0x1DB6, 0x1DB7, 0x1E54}, {0x1DB6, 0x1DB7, 0x1E54}, + {0x1DB8, 0x1DB9, 0x1E56}, {0x1DB8, 0x1DB9, 0x1E56}, {0x1DBA, 0x1DBB, 0x1E58}, {0x1DBA, 0x1DBB, 0x1E58}, + {0x1DBC, 0x1DBD, 0x1E5A}, {0x1DBC, 0x1DBD, 0x1E5A}, {0x1DBE, 0x1DBF, 0x1E5C}, {0x1DBE, 0x1DBF, 0x1E5C}, + {0x1DC0, 0x1DC1, 0x1E5E}, {0x1DC0, 0x1DC1, 0x1E5E}, {0x1DC2, 0x1DC3, 0x1E60}, {0x1DC2, 0x1DC3, 0x1E60}, + {0x1DC4, 0x1DC5, 0x1E62}, {0x1DC4, 0x1DC5, 0x1E62}, {0x1DC6, 0x1DC7, 0x1E64}, {0x1DC6, 0x1DC7, 0x1E64}, + {0x1DC8, 0x1DC9, 0x1E66}, {0x1DC8, 0x1DC9, 0x1E66}, {0x1DCA, 0x1DCB, 0x1E68}, {0x1DCA, 0x1DCB, 0x1E68}, + {0x1DCC, 0x1DCD, 0x1E6A}, {0x1DCC, 0x1DCD, 0x1E6A}, {0x1DCE, 0x1DCF, 0x1E6C}, {0x1DCE, 0x1DCF, 0x1E6C}, + {0x1DD0, 0x1DD1, 0x1E6E}, {0x1DD0, 0x1DD1, 0x1E6E}, {0x1DD2, 0x1DD3, 0x1E70}, {0x1DD2, 0x1DD3, 0x1E70}, + {0x1DD4, 0x1DD5, 0x1E72}, {0x1DD4, 0x1DD5, 0x1E72}, {0x1DD6, 0x1DD7, 0x1E74}, {0x1DD6, 0x1DD7, 0x1E74}, + {0x1DD8, 0x1DD9, 0x1E76}, {0x1DD8, 0x1DD9, 0x1E76}, {0x1DDA, 0x1DDB, 0x1E78}, {0x1DDA, 0x1DDB, 0x1E78}, + {0x1DDC, 0x1DDD, 0x1E7A}, {0x1DDC, 0x1DDD, 0x1E7A}, {0x1DDE, 0x1DDF, 0x1E7C}, {0x1DDE, 0x1DDF, 0x1E7C}, + {0x1DE0, 0x1DE1, 0x1E7E}, {0x1DE0, 0x1DE1, 0x1E7E}, {0x1DE2, 0x1DE3, 0x1E80}, {0x1DE2, 0x1DE3, 0x1E80}, + {0x1DE4, 0x1DE5, 0x1E82}, {0x1DE4, 0x1DE5, 0x1E82}, {0x1DE6, 0x1DE7, 0x1E84}, {0x1DE6, 0x1DE7, 0x1E84}, + {0x1DE8, 0x1DE9, 0x1E86}, {0x1DE8, 0x1DE9, 0x1E86}, {0x1DEA, 0x1DEB, 0x1E88}, {0x1DEA, 0x1DEB, 0x1E88}, + {0x1DEC, 0x1DED, 0x1E8A}, {0x1DEC, 0x1DED, 0x1E8A}, {0x1DEE, 0x1DEF, 0x1E8C}, {0x1DEE, 0x1DEF, 0x1E8C}, + {0x1DF0, 0x1DF1, 0x1E8E}, {0x1DF0, 0x1DF1, 0x1E8E}, {0x1DF2, 0x1DF3, 0x1E90}, {0x1DF2, 0x1DF3, 0x1E90}, + {0x1DF4, 0x1DF5, 0x1E92}, {0x1DF4, 0x1DF5, 0x1E92}, {0x1DF6, 0x1DF7, 0x1E94}, {0x1DF6, 0x1DF7, 0x1E94}, + {0x1DF8, 0x1DF8, 0x1E96}, {0x1DF9, 0x1DF9, 0x1E97}, {0x1DFA, 0x1DFA, 0x1E98}, {0x1DFB, 0x1DFB, 0x1E99}, + {0x1DFC, 0x1DFC, 0x1E9A}, {0x1DFD, 0x1DC3, 0x1E9B}, {0x1DFE, 0x1DFE, 0x1E9C}, {0x1DFF, 0x1DFF, 0x1E9D} +}; + +static GS_UNICASE_CHARACTER plane1E[] = { + {0x1E00, 0x00D8, 0x1E9E}, {0x1E01, 0x1E01, 0x1E9F}, {0x1E02, 0x1E03, 0x1EA0}, {0x1E02, 0x1E03, 0x1EA0}, + {0x1E04, 0x1E05, 0x1EA2}, {0x1E04, 0x1E05, 0x1EA2}, {0x1E06, 0x1E07, 0x1EA4}, {0x1E06, 0x1E07, 0x1EA4}, + {0x1E08, 0x1E09, 0x1EA6}, {0x1E08, 0x1E09, 0x1EA6}, {0x1E0A, 0x1E0B, 0x1EA8}, {0x1E0A, 0x1E0B, 0x1EA8}, + {0x1E0C, 0x1E0D, 0x1EAA}, {0x1E0C, 0x1E0D, 0x1EAA}, {0x1E0E, 0x1E0F, 0x1EAC}, {0x1E0E, 0x1E0F, 0x1EAC}, + {0x1E10, 0x1E11, 0x1EAE}, {0x1E10, 0x1E11, 0x1EAE}, {0x1E12, 0x1E13, 0x1EB0}, {0x1E12, 0x1E13, 0x1EB0}, + {0x1E14, 0x1E15, 0x1EB2}, {0x1E14, 0x1E15, 0x1EB2}, {0x1E16, 0x1E17, 0x1EB4}, {0x1E16, 0x1E17, 0x1EB4}, + {0x1E18, 0x1E19, 0x1EB6}, {0x1E18, 0x1E19, 0x1EB6}, {0x1E1A, 0x1E1B, 0x1EB8}, {0x1E1A, 0x1E1B, 0x1EB8}, + {0x1E1C, 0x1E1D, 0x1EBA}, {0x1E1C, 0x1E1D, 0x1EBA}, {0x1E1E, 0x1E1F, 0x1EBC}, {0x1E1E, 0x1E1F, 0x1EBC}, + {0x1E20, 0x1E21, 0x1EBE}, {0x1E20, 0x1E21, 0x1EBE}, {0x1E22, 0x1E23, 0x1EC0}, {0x1E22, 0x1E23, 0x1EC0}, + {0x1E24, 0x1E25, 0x1EC2}, {0x1E24, 0x1E25, 0x1EC2}, {0x1E26, 0x1E27, 0x1EC4}, {0x1E26, 0x1E27, 0x1EC4}, + {0x1E28, 0x1E29, 0x1EC6}, {0x1E28, 0x1E29, 0x1EC6}, {0x1E2A, 0x1E2B, 0x1EC8}, {0x1E2A, 0x1E2B, 0x1EC8}, + {0x1E2C, 0x1E2D, 0x1ECA}, {0x1E2C, 0x1E2D, 0x1ECA}, {0x1E2E, 0x1E2F, 0x1ECC}, {0x1E2E, 0x1E2F, 0x1ECC}, + {0x1E30, 0x1E31, 0x1ECE}, {0x1E30, 0x1E31, 0x1ECE}, {0x1E32, 0x1E33, 0x1ED0}, {0x1E32, 0x1E33, 0x1ED0}, + {0x1E34, 0x1E35, 0x1ED2}, {0x1E34, 0x1E35, 0x1ED2}, {0x1E36, 0x1E37, 0x1ED4}, {0x1E36, 0x1E37, 0x1ED4}, + {0x1E38, 0x1E39, 0x1ED6}, {0x1E38, 0x1E39, 0x1ED6}, {0x1E3A, 0x1E3B, 0x1ED8}, {0x1E3A, 0x1E3B, 0x1ED8}, + {0x1E3C, 0x1E3D, 0x1EDA}, {0x1E3C, 0x1E3D, 0x1EDA}, {0x1E3E, 0x1E3F, 0x1EDC}, {0x1E3E, 0x1E3F, 0x1EDC}, + {0x1E40, 0x1E41, 0x1EDE}, {0x1E40, 0x1E41, 0x1EDE}, {0x1E42, 0x1E43, 0x1EE0}, {0x1E42, 0x1E43, 0x1EE0}, + {0x1E44, 0x1E45, 0x1EE2}, {0x1E44, 0x1E45, 0x1EE2}, {0x1E46, 0x1E47, 0x1EE4}, {0x1E46, 0x1E47, 0x1EE4}, + {0x1E48, 0x1E49, 0x1EE6}, {0x1E48, 0x1E49, 0x1EE6}, {0x1E4A, 0x1E4B, 0x1EE8}, {0x1E4A, 0x1E4B, 0x1EE8}, + {0x1E4C, 0x1E4D, 0x1EEA}, {0x1E4C, 0x1E4D, 0x1EEA}, {0x1E4E, 0x1E4F, 0x1EEC}, {0x1E4E, 0x1E4F, 0x1EEC}, + {0x1E50, 0x1E51, 0x1EEE}, {0x1E50, 0x1E51, 0x1EEE}, {0x1E52, 0x1E53, 0x1EF0}, {0x1E52, 0x1E53, 0x1EF0}, + {0x1E54, 0x1E55, 0x1EF2}, {0x1E54, 0x1E55, 0x1EF2}, {0x1E56, 0x1E57, 0x1EF4}, {0x1E56, 0x1E57, 0x1EF4}, + {0x1E58, 0x1E59, 0x1EF6}, {0x1E58, 0x1E59, 0x1EF6}, {0x1E5A, 0x1E5B, 0x1EF8}, {0x1E5A, 0x1E5B, 0x1EF8}, + {0x1E5C, 0x1E5D, 0x1EFA}, {0x1E5C, 0x1E5D, 0x1EFA}, {0x1E5E, 0x1E5F, 0x1EFC}, {0x1E5E, 0x1E5F, 0x1EFC}, + {0x1E60, 0x1E61, 0x1EFE}, {0x1E60, 0x1E61, 0x1EFE}, {0x1E6A, 0x1E62, 0x1F08}, {0x1E6B, 0x1E63, 0x1F09}, + {0x1E6C, 0x1E64, 0x1F0A}, {0x1E6D, 0x1E65, 0x1F0B}, {0x1E6E, 0x1E66, 0x1F0C}, {0x1E6F, 0x1E67, 0x1F0D}, + {0x1E70, 0x1E68, 0x1F0E}, {0x1E71, 0x1E69, 0x1F0F}, {0x1E6A, 0x1E62, 0x1F08}, {0x1E6B, 0x1E63, 0x1F09}, + {0x1E6C, 0x1E64, 0x1F0A}, {0x1E6D, 0x1E65, 0x1F0B}, {0x1E6E, 0x1E66, 0x1F0C}, {0x1E6F, 0x1E67, 0x1F0D}, + {0x1E70, 0x1E68, 0x1F0E}, {0x1E71, 0x1E69, 0x1F0F}, {0x1E7A, 0x1E72, 0x1F18}, {0x1E7B, 0x1E73, 0x1F19}, + {0x1E7C, 0x1E74, 0x1F1A}, {0x1E7D, 0x1E75, 0x1F1B}, {0x1E7E, 0x1E76, 0x1F1C}, {0x1E7F, 0x1E77, 0x1F1D}, + {0x1E78, 0x1E78, 0x1F16}, {0x1E79, 0x1E79, 0x1F17}, {0x1E7A, 0x1E72, 0x1F18}, {0x1E7B, 0x1E73, 0x1F19}, + {0x1E7C, 0x1E74, 0x1F1A}, {0x1E7D, 0x1E75, 0x1F1B}, {0x1E7E, 0x1E76, 0x1F1C}, {0x1E7F, 0x1E77, 0x1F1D}, + {0x1E80, 0x1E80, 0x1F1E}, {0x1E81, 0x1E81, 0x1F1F}, {0x1E8A, 0x1E82, 0x1F28}, {0x1E8B, 0x1E83, 0x1F29}, + {0x1E8C, 0x1E84, 0x1F2A}, {0x1E8D, 0x1E85, 0x1F2B}, {0x1E8E, 0x1E86, 0x1F2C}, {0x1E8F, 0x1E87, 0x1F2D}, + {0x1E90, 0x1E88, 0x1F2E}, {0x1E91, 0x1E89, 0x1F2F}, {0x1E8A, 0x1E82, 0x1F28}, {0x1E8B, 0x1E83, 0x1F29}, + {0x1E8C, 0x1E84, 0x1F2A}, {0x1E8D, 0x1E85, 0x1F2B}, {0x1E8E, 0x1E86, 0x1F2C}, {0x1E8F, 0x1E87, 0x1F2D}, + {0x1E90, 0x1E88, 0x1F2E}, {0x1E91, 0x1E89, 0x1F2F}, {0x1E9A, 0x1E92, 0x1F38}, {0x1E9B, 0x1E93, 0x1F39}, + {0x1E9C, 0x1E94, 0x1F3A}, {0x1E9D, 0x1E95, 0x1F3B}, {0x1E9E, 0x1E96, 0x1F3C}, {0x1E9F, 0x1E97, 0x1F3D}, + {0x1EA0, 0x1E98, 0x1F3E}, {0x1EA1, 0x1E99, 0x1F3F}, {0x1E9A, 0x1E92, 0x1F38}, {0x1E9B, 0x1E93, 0x1F39}, + {0x1E9C, 0x1E94, 0x1F3A}, {0x1E9D, 0x1E95, 0x1F3B}, {0x1E9E, 0x1E96, 0x1F3C}, {0x1E9F, 0x1E97, 0x1F3D}, + {0x1EA0, 0x1E98, 0x1F3E}, {0x1EA1, 0x1E99, 0x1F3F}, {0x1EAA, 0x1EA2, 0x1F48}, {0x1EAB, 0x1EA3, 0x1F49}, + {0x1EAC, 0x1EA4, 0x1F4A}, {0x1EAD, 0x1EA5, 0x1F4B}, {0x1EAE, 0x1EA6, 0x1F4C}, {0x1EAF, 0x1EA7, 0x1F4D}, + {0x1EA8, 0x1EA8, 0x1F46}, {0x1EA9, 0x1EA9, 0x1F47}, {0x1EAA, 0x1EA2, 0x1F48}, {0x1EAB, 0x1EA3, 0x1F49}, + {0x1EAC, 0x1EA4, 0x1F4A}, {0x1EAD, 0x1EA5, 0x1F4B}, {0x1EAE, 0x1EA6, 0x1F4C}, {0x1EAF, 0x1EA7, 0x1F4D}, + {0x1EB0, 0x1EB0, 0x1F4E}, {0x1EB1, 0x1EB1, 0x1F4F}, {0x1EB2, 0x1EB2, 0x1F50}, {0x1EBB, 0x1EB3, 0x1F59}, + {0x1EB4, 0x1EB4, 0x1F52}, {0x1EBD, 0x1EB5, 0x1F5B}, {0x1EB6, 0x1EB6, 0x1F54}, {0x1EBF, 0x1EB7, 0x1F5D}, + {0x1EB8, 0x1EB8, 0x1F56}, {0x1EC1, 0x1EB9, 0x1F5F}, {0x1EBA, 0x1EBA, 0x1F58}, {0x1EBB, 0x1EB3, 0x1F59}, + {0x1EBC, 0x1EBC, 0x1F5A}, {0x1EBD, 0x1EB5, 0x1F5B}, {0x1EBE, 0x1EBE, 0x1F5C}, {0x1EBF, 0x1EB7, 0x1F5D}, + {0x1EC0, 0x1EC0, 0x1F5E}, {0x1EC1, 0x1EB9, 0x1F5F}, {0x1ECA, 0x1EC2, 0x1F68}, {0x1ECB, 0x1EC3, 0x1F69}, + {0x1ECC, 0x1EC4, 0x1F6A}, {0x1ECD, 0x1EC5, 0x1F6B}, {0x1ECE, 0x1EC6, 0x1F6C}, {0x1ECF, 0x1EC7, 0x1F6D}, + {0x1ED0, 0x1EC8, 0x1F6E}, {0x1ED1, 0x1EC9, 0x1F6F}, {0x1ECA, 0x1EC2, 0x1F68}, {0x1ECB, 0x1EC3, 0x1F69}, + {0x1ECC, 0x1EC4, 0x1F6A}, {0x1ECD, 0x1EC5, 0x1F6B}, {0x1ECE, 0x1EC6, 0x1F6C}, {0x1ECF, 0x1EC7, 0x1F6D}, + {0x1ED0, 0x1EC8, 0x1F6E}, {0x1ED1, 0x1EC9, 0x1F6F}, {0x1F1C, 0x1ED2, 0x1FBA}, {0x1F1D, 0x1ED3, 0x1FBB}, + {0x1F2A, 0x1ED4, 0x1FC8}, {0x1F2B, 0x1ED5, 0x1FC9}, {0x1F2C, 0x1ED6, 0x1FCA}, {0x1F2D, 0x1ED7, 0x1FCB}, + {0x1F3C, 0x1ED8, 0x1FDA}, {0x1F3D, 0x1ED9, 0x1FDB}, {0x1F5A, 0x1EDA, 0x1FF8}, {0x1F5B, 0x1EDB, 0x1FF9}, + {0x1F4C, 0x1EDC, 0x1FEA}, {0x1F4D, 0x1EDD, 0x1FEB}, {0x1F5C, 0x1EDE, 0x1FFA}, {0x1F5D, 0x1EDF, 0x1FFB}, + {0x1EE0, 0x1EE0, 0x1F7E}, {0x1EE1, 0x1EE1, 0x1F7F}, {0x1EEA, 0x1EE2, 0x1F88}, {0x1EEB, 0x1EE3, 0x1F89}, + {0x1EEC, 0x1EE4, 0x1F8A}, {0x1EED, 0x1EE5, 0x1F8B}, {0x1EEE, 0x1EE6, 0x1F8C}, {0x1EEF, 0x1EE7, 0x1F8D}, + {0x1EF0, 0x1EE8, 0x1F8E}, {0x1EF1, 0x1EE9, 0x1F8F}, {0x1EEA, 0x1EE2, 0x1F88}, {0x1EEB, 0x1EE3, 0x1F89}, + {0x1EEC, 0x1EE4, 0x1F8A}, {0x1EED, 0x1EE5, 0x1F8B}, {0x1EEE, 0x1EE6, 0x1F8C}, {0x1EEF, 0x1EE7, 0x1F8D}, + {0x1EF0, 0x1EE8, 0x1F8E}, {0x1EF1, 0x1EE9, 0x1F8F}, {0x1EFA, 0x1EF2, 0x1F98}, {0x1EFB, 0x1EF3, 0x1F99}, + {0x1EFC, 0x1EF4, 0x1F9A}, {0x1EFD, 0x1EF5, 0x1F9B}, {0x1EFE, 0x1EF6, 0x1F9C}, {0x1EFF, 0x1EF7, 0x1F9D}, + {0x1F00, 0x1EF8, 0x1F9E}, {0x1F01, 0x1EF9, 0x1F9F}, {0x1EFA, 0x1EF2, 0x1F98}, {0x1EFB, 0x1EF3, 0x1F99}, + {0x1EFC, 0x1EF4, 0x1F9A}, {0x1EFD, 0x1EF5, 0x1F9B}, {0x1EFE, 0x1EF6, 0x1F9C}, {0x1EFF, 0x1EF7, 0x1F9D} +}; + +static GS_UNICASE_CHARACTER plane1F[] = { + {0x1F00, 0x1EF8, 0x1F9E}, {0x1F01, 0x1EF9, 0x1F9F}, {0x1F0A, 0x1F02, 0x1FA8}, {0x1F0B, 0x1F03, 0x1FA9}, + {0x1F0C, 0x1F04, 0x1FAA}, {0x1F0D, 0x1F05, 0x1FAB}, {0x1F0E, 0x1F06, 0x1FAC}, {0x1F0F, 0x1F07, 0x1FAD}, + {0x1F10, 0x1F08, 0x1FAE}, {0x1F11, 0x1F09, 0x1FAF}, {0x1F0A, 0x1F02, 0x1FA8}, {0x1F0B, 0x1F03, 0x1FA9}, + {0x1F0C, 0x1F04, 0x1FAA}, {0x1F0D, 0x1F05, 0x1FAB}, {0x1F0E, 0x1F06, 0x1FAC}, {0x1F0F, 0x1F07, 0x1FAD}, + {0x1F10, 0x1F08, 0x1FAE}, {0x1F11, 0x1F09, 0x1FAF}, {0x1F1A, 0x1F12, 0x1FB8}, {0x1F1B, 0x1F13, 0x1FB9}, + {0x1F14, 0x1F14, 0x1FB2}, {0x1F1E, 0x1F15, 0x1FBC}, {0x1F16, 0x1F16, 0x1FB4}, {0x1F17, 0x1F17, 0x1FB5}, + {0x1F18, 0x1F18, 0x1FB6}, {0x1F19, 0x1F19, 0x1FB7}, {0x1F1A, 0x1F12, 0x1FB8}, {0x1F1B, 0x1F13, 0x1FB9}, + {0x1F1C, 0x1ED2, 0x1FBA}, {0x1F1D, 0x1ED3, 0x1FBB}, {0x1F1E, 0x1F15, 0x1FBC}, {0x1F1F, 0x1F1F, 0x1FBD}, + {0x1F20, 0xA6C9, 0x1FBE}, {0x1F21, 0x1F21, 0x1FBF}, {0x1F22, 0x1F22, 0x1FC0}, {0x1F23, 0x1F23, 0x1FC1}, + {0x1F24, 0x1F24, 0x1FC2}, {0x1F2E, 0x1F25, 0x1FCC}, {0x1F26, 0x1F26, 0x1FC4}, {0x1F27, 0x1F27, 0x1FC5}, + {0x1F28, 0x1F28, 0x1FC6}, {0x1F29, 0x1F29, 0x1FC7}, {0x1F2A, 0x1ED4, 0x1FC8}, {0x1F2B, 0x1ED5, 0x1FC9}, + {0x1F2C, 0x1ED6, 0x1FCA}, {0x1F2D, 0x1ED7, 0x1FCB}, {0x1F2E, 0x1F25, 0x1FCC}, {0x1F2F, 0x1F2F, 0x1FCD}, + {0x1F30, 0x1F30, 0x1FCE}, {0x1F31, 0x1F31, 0x1FCF}, {0x1F3A, 0x1F32, 0x1FD8}, {0x1F3B, 0x1F33, 0x1FD9}, + {0x1F34, 0x1F34, 0x1FD2}, {0x1F35, 0x1F35, 0x1FD3}, {0x1F36, 0x1F36, 0x1FD4}, {0x1F37, 0x1F37, 0x1FD5}, + {0x1F38, 0x1F38, 0x1FD6}, {0x1F39, 0x1F39, 0x1FD7}, {0x1F3A, 0x1F32, 0x1FD8}, {0x1F3B, 0x1F33, 0x1FD9}, + {0x1F3C, 0x1ED8, 0x1FDA}, {0x1F3D, 0x1ED9, 0x1FDB}, {0x1F3E, 0x1F3E, 0x1FDC}, {0x1F3F, 0x1F3F, 0x1FDD}, + {0x1F40, 0x1F40, 0x1FDE}, {0x1F41, 0x1F41, 0x1FDF}, {0x1F4A, 0x1F42, 0x1FE8}, {0x1F4B, 0x1F43, 0x1FE9}, + {0x1F44, 0x1F44, 0x1FE2}, {0x1F45, 0x1F45, 0x1FE3}, {0x1F46, 0x1F46, 0x1FE4}, {0x1F4E, 0x1F47, 0x1FEC}, + {0x1F48, 0x1F48, 0x1FE6}, {0x1F49, 0x1F49, 0x1FE7}, {0x1F4A, 0x1F42, 0x1FE8}, {0x1F4B, 0x1F43, 0x1FE9}, + {0x1F4C, 0x1EDC, 0x1FEA}, {0x1F4D, 0x1EDD, 0x1FEB}, {0x1F4E, 0x1F47, 0x1FEC}, {0x1F4F, 0x1F4F, 0x1FED}, + {0x1F50, 0x1F50, 0x1FEE}, {0x1F51, 0x1F51, 0x1FEF}, {0x1F52, 0x1F52, 0x1FF0}, {0x1F53, 0x1F53, 0x1FF1}, + {0x1F54, 0x1F54, 0x1FF2}, {0x1F5E, 0x1F55, 0x1FFC}, {0x1F56, 0x1F56, 0x1FF4}, {0x1F57, 0x1F57, 0x1FF5}, + {0x1F58, 0x1F58, 0x1FF6}, {0x1F59, 0x1F59, 0x1FF7}, {0x1F5A, 0x1EDA, 0x1FF8}, {0x1F5B, 0x1EDB, 0x1FF9}, + {0x1F5C, 0x1EDE, 0x1FFA}, {0x1F5D, 0x1EDF, 0x1FFB}, {0x1F5E, 0x1F55, 0x1FFC}, {0x1F5F, 0x1F5F, 0x1FFD}, + {0x1F60, 0x1F60, 0x1FFE}, {0x1F61, 0x1F61, 0x1FFF}, {0x1F62, 0x1F62, 0x2000}, {0x1F63, 0x1F63, 0x2001}, + {0x1F64, 0x1F64, 0x2002}, {0x1F65, 0x1F65, 0x2003}, {0x1F66, 0x1F66, 0x2004}, {0x1F67, 0x1F67, 0x2005}, + {0x1F68, 0x1F68, 0x2006}, {0x1F69, 0x1F69, 0x2007}, {0x1F6A, 0x1F6A, 0x2008}, {0x1F6B, 0x1F6B, 0x2009}, + {0x1F6C, 0x1F6C, 0x200A}, {0x1F6D, 0x1F6D, 0x200B}, {0x1F6E, 0x1F6E, 0x200C}, {0x1F6F, 0x1F6F, 0x200D}, + {0x1F70, 0x1F70, 0x200E}, {0x1F71, 0x1F71, 0x200F}, {0x1F72, 0x1F72, 0x2011}, {0x1F73, 0x1F73, 0x2012}, + {0x1F74, 0x1F74, 0x2017}, {0x1F75, 0x1F75, 0x201A}, {0x1F76, 0x1F76, 0x201B}, {0x1F77, 0x1F77, 0x201E}, + {0x1F78, 0x1F78, 0x201F}, {0x1F79, 0x1F79, 0x2020}, {0x1F7A, 0x1F7A, 0x2021}, {0x1F7B, 0x1F7B, 0x2022}, + {0x1F7C, 0x1F7C, 0x2023}, {0x1F7D, 0x1F7D, 0x2024}, {0x1F7E, 0x1F7E, 0x2027}, {0x1F7F, 0x1F7F, 0x2028}, + {0x1F80, 0x1F80, 0x2029}, {0x1F81, 0x1F81, 0x202A}, {0x1F82, 0x1F82, 0x202B}, {0x1F83, 0x1F83, 0x202C}, + {0x1F84, 0x1F84, 0x202D}, {0x1F85, 0x1F85, 0x202E}, {0x1F86, 0x1F86, 0x202F}, {0x1F87, 0x1F87, 0x2031}, + {0x1F88, 0x1F88, 0x2034}, {0x1F89, 0x1F89, 0x2036}, {0x1F8A, 0x1F8A, 0x2037}, {0x1F8B, 0x1F8B, 0x2038}, + {0x1F8C, 0x1F8C, 0x2039}, {0x1F8D, 0x1F8D, 0x203A}, {0x1F8E, 0x1F8E, 0x203C}, {0x1F8F, 0x1F8F, 0x203D}, + {0x1F90, 0x1F90, 0x203E}, {0x1F91, 0x1F91, 0x203F}, {0x1F92, 0x1F92, 0x2040}, {0x1F93, 0x1F93, 0x2041}, + {0x1F94, 0x1F94, 0x2042}, {0x1F95, 0x1F95, 0x2043}, {0x1F96, 0x1F96, 0x2044}, {0x1F97, 0x1F97, 0x2045}, + {0x1F98, 0x1F98, 0x2046}, {0x1F99, 0x1F99, 0x2047}, {0x1F9A, 0x1F9A, 0x2048}, {0x1F9B, 0x1F9B, 0x2049}, + {0x1F9C, 0x1F9C, 0x204A}, {0x1F9D, 0x1F9D, 0x204B}, {0x1F9E, 0x1F9E, 0x204C}, {0x1F9F, 0x1F9F, 0x204D}, + {0x1FA0, 0x1FA0, 0x204E}, {0x1FA1, 0x1FA1, 0x204F}, {0x1FA2, 0x1FA2, 0x2050}, {0x1FA3, 0x1FA3, 0x2051}, + {0x1FA4, 0x1FA4, 0x2052}, {0x1FA5, 0x1FA5, 0x2053}, {0x1FA6, 0x1FA6, 0x2054}, {0x1FA7, 0x1FA7, 0x2055}, + {0x1FA8, 0x1FA8, 0x2056}, {0x1FA9, 0x1FA9, 0x2057}, {0x1FAA, 0x1FAA, 0x2058}, {0x1FAB, 0x1FAB, 0x2059}, + {0x1FAC, 0x1FAC, 0x205A}, {0x1FAD, 0x1FAD, 0x205B}, {0x1FAE, 0x1FAE, 0x205C}, {0x1FAF, 0x1FAF, 0x205D}, + {0x1FB0, 0x1FB0, 0x205E}, {0x1FB1, 0x1FB1, 0x205F}, {0x1FB2, 0x1FB2, 0x2060}, {0x1FB3, 0x1FB3, 0x2061}, + {0x1FB4, 0x1FB4, 0x2062}, {0x1FB5, 0x1FB5, 0x2063}, {0x1FB6, 0x1FB6, 0x2064}, {0x1FB7, 0x1FB7, 0x2065}, + {0x1FB8, 0x1FB8, 0x2066}, {0x1FB9, 0x1FB9, 0x2067}, {0x1FBA, 0x1FBA, 0x2068}, {0x1FBB, 0x1FBB, 0x2069}, + {0x1FBC, 0x1FBC, 0x206A}, {0x1FBD, 0x1FBD, 0x206B}, {0x1FBE, 0x1FBE, 0x206C}, {0x1FBF, 0x1FBF, 0x206D}, + {0x1FC0, 0x1FC0, 0x206E}, {0x1FC1, 0x1FC1, 0x206F}, {0x1FC2, 0x1FC2, 0x2070}, {0x1FC3, 0x1FC3, 0x2071}, + {0x1FC4, 0x1FC4, 0x2072}, {0x1FC5, 0x1FC5, 0x2073}, {0x1FC6, 0x1FC6, 0x2074}, {0x1FC7, 0x1FC7, 0x2075}, + {0x1FC8, 0x1FC8, 0x2076}, {0x1FC9, 0x1FC9, 0x2077}, {0x1FCA, 0x1FCA, 0x2078}, {0x1FCB, 0x1FCB, 0x2079}, + {0x1FCC, 0x1FCC, 0x207A}, {0x1FCD, 0x1FCD, 0x207B}, {0x1FCE, 0x1FCE, 0x207C}, {0x1FCF, 0x1FCF, 0x207D}, + {0x1FD0, 0x1FD0, 0x207E}, {0x1FD1, 0x1FD1, 0x207F}, {0x1FD2, 0x1FD2, 0x2080}, {0x1FD3, 0x1FD3, 0x2081}, + {0x1FD4, 0x1FD4, 0x2082}, {0x1FD5, 0x1FD5, 0x2083}, {0x1FD6, 0x1FD6, 0x2084}, {0x1FD7, 0x1FD7, 0x2085}, + {0x1FD8, 0x1FD8, 0x2086}, {0x1FD9, 0x1FD9, 0x2087}, {0x1FDA, 0x1FDA, 0x2088}, {0x1FDB, 0x1FDB, 0x2089}, + {0x1FDC, 0x1FDC, 0x208A}, {0x1FDD, 0x1FDD, 0x208B}, {0x1FDE, 0x1FDE, 0x208C}, {0x1FDF, 0x1FDF, 0x208D}, + {0x1FE0, 0x1FE0, 0x208E}, {0x1FE1, 0x1FE1, 0x208F}, {0x1FE2, 0x1FE2, 0x2090}, {0x1FE3, 0x1FE3, 0x2091}, + {0x1FE4, 0x1FE4, 0x2092}, {0x1FE5, 0x1FE5, 0x2093}, {0x1FE6, 0x1FE6, 0x2094}, {0x1FE7, 0x1FE7, 0x2095}, + {0x1FE8, 0x1FE8, 0x2096}, {0x1FE9, 0x1FE9, 0x2097}, {0x1FEA, 0x1FEA, 0x2098}, {0x1FEB, 0x1FEB, 0x2099}, + {0x1FEC, 0x1FEC, 0x209A}, {0x1FED, 0x1FED, 0x209B}, {0x1FEE, 0x1FEE, 0x209C}, {0x1FEF, 0x1FEF, 0x209D}, + {0x1FF0, 0x1FF0, 0x209E}, {0x1FF1, 0x1FF1, 0x209F}, {0x1FF2, 0x1FF2, 0x20A0}, {0x1FF3, 0x1FF3, 0x20A1}, + {0x1FF4, 0x1FF4, 0x20A2}, {0x1FF5, 0x1FF5, 0x20A3}, {0x1FF6, 0x1FF6, 0x20A4}, {0x1FF7, 0x1FF7, 0x20A5}, + {0x1FF8, 0x1FF8, 0x20A6}, {0x1FF9, 0x1FF9, 0x20A7}, {0x1FFA, 0x1FFA, 0x20A8}, {0x1FFB, 0x1FFB, 0x20A9}, + {0x1FFC, 0x1FFC, 0x20AA}, {0x1FFD, 0x1FFD, 0x20AB}, {0x1FFE, 0x1FFE, 0x20AD}, {0x1FFF, 0x1FFF, 0x20AE} +}; + +static GS_UNICASE_CHARACTER plane20[] = { + {0x2000, 0x2000, 0x20AF}, {0x2001, 0x2001, 0x20B0}, {0x2002, 0x2002, 0x20B1}, {0x2003, 0x2003, 0x20B2}, + {0x2004, 0x2004, 0x20B3}, {0x2005, 0x2005, 0x20B4}, {0x2006, 0x2006, 0x20B5}, {0x2007, 0x2007, 0x20B6}, + {0x2008, 0x2008, 0x20B7}, {0x2009, 0x2009, 0x20B8}, {0x200A, 0x200A, 0x20B9}, {0x200B, 0x200B, 0x20BA}, + {0x200C, 0x200C, 0x20BB}, {0x200D, 0x200D, 0x20BC}, {0x200E, 0x200E, 0x20BD}, {0x200F, 0x200F, 0x20BE}, + {0x2010, 0x2010, 0x20BF}, {0x2011, 0x2011, 0x20C0}, {0x2012, 0x2012, 0x20C1}, {0x2013, 0x2013, 0x20C2}, + {0x2014, 0x2014, 0x20C3}, {0x2015, 0x2015, 0x20C4}, {0x2016, 0x2016, 0x20C5}, {0x2017, 0x2017, 0x20C6}, + {0x2018, 0x2018, 0x20C7}, {0x2019, 0x2019, 0x20C8}, {0x201A, 0x201A, 0x20C9}, {0x201B, 0x201B, 0x20CA}, + {0x201C, 0x201C, 0x20CB}, {0x201D, 0x201D, 0x20CC}, {0x201E, 0x201E, 0x20CD}, {0x201F, 0x201F, 0x20CE}, + {0x2020, 0x2020, 0x20CF}, {0x2021, 0x2021, 0x20D0}, {0x2022, 0x2022, 0x20D1}, {0x2023, 0x2023, 0x20D2}, + {0x2024, 0x2024, 0x20D3}, {0x2025, 0x2025, 0x20D4}, {0x2026, 0x2026, 0x20D5}, {0x2027, 0x2027, 0x20D6}, + {0x2028, 0x2028, 0x20D7}, {0x2029, 0x2029, 0x20D8}, {0x202A, 0x202A, 0x20D9}, {0x202B, 0x202B, 0x20DA}, + {0x202C, 0x202C, 0x20DB}, {0x202D, 0x202D, 0x20DC}, {0x202E, 0x202E, 0x20DD}, {0x202F, 0x202F, 0x20DE}, + {0x2030, 0x2030, 0x20DF}, {0x2031, 0x2031, 0x20E0}, {0x2032, 0x2032, 0x20E1}, {0x2033, 0x2033, 0x20E2}, + {0x2034, 0x2034, 0x20E3}, {0x2035, 0x2035, 0x20E4}, {0x2036, 0x2036, 0x20E5}, {0x2037, 0x2037, 0x20E6}, + {0x2038, 0x2038, 0x20E7}, {0x2039, 0x2039, 0x20E8}, {0x203A, 0x203A, 0x20E9}, {0x203B, 0x203B, 0x20EA}, + {0x203C, 0x203C, 0x20EB}, {0x203D, 0x203D, 0x20EC}, {0x203E, 0x203E, 0x20ED}, {0x203F, 0x203F, 0x20EE}, + {0x2040, 0x2040, 0x20EF}, {0x2041, 0x2041, 0x20F0}, {0x2042, 0x2042, 0x20F1}, {0x2043, 0x2043, 0x20F2}, + {0x2044, 0x2044, 0x20F3}, {0x2045, 0x2045, 0x20F4}, {0x2046, 0x2046, 0x20F5}, {0x2047, 0x2047, 0x20F6}, + {0x2048, 0x2048, 0x20F7}, {0x2049, 0x2049, 0x20F8}, {0x204A, 0x204A, 0x20F9}, {0x204B, 0x204B, 0x20FA}, + {0x204C, 0x204C, 0x20FB}, {0x204D, 0x204D, 0x20FC}, {0x204E, 0x204E, 0x20FD}, {0x204F, 0x204F, 0x20FE}, + {0x2050, 0x2050, 0x20FF}, {0x2051, 0x2051, 0x2100}, {0x2052, 0x2052, 0x2101}, {0x2053, 0x2053, 0x2102}, + {0x2054, 0x2054, 0x2104}, {0x2055, 0x2055, 0x2106}, {0x2056, 0x2056, 0x2107}, {0x2057, 0x2057, 0x2108}, + {0x2058, 0x2058, 0x210A}, {0x2059, 0x2059, 0x210B}, {0x205A, 0x205A, 0x210C}, {0x205B, 0x205B, 0x210D}, + {0x205C, 0x205C, 0x210E}, {0x205D, 0x205D, 0x210F}, {0x205E, 0x205E, 0x2110}, {0x205F, 0x205F, 0x2111}, + {0x2060, 0x2060, 0x2112}, {0x2061, 0x2061, 0x2113}, {0x2062, 0x2062, 0x2114}, {0x2063, 0x2063, 0x2115}, + {0x2064, 0x2064, 0x2117}, {0x2065, 0x2065, 0x2118}, {0x2066, 0x2066, 0x2119}, {0x2067, 0x2067, 0x211A}, + {0x2068, 0x2068, 0x211B}, {0x2069, 0x2069, 0x211C}, {0x206A, 0x206A, 0x211D}, {0x206B, 0x206B, 0x211E}, + {0x206C, 0x206C, 0x211F}, {0x206D, 0x206D, 0x2120}, {0x206E, 0x206E, 0x2122}, {0x206F, 0x206F, 0x2123}, + {0x2070, 0x2070, 0x2124}, {0x2071, 0x2071, 0x2125}, {0x2072, 0xA6D8, 0x2126}, {0x2073, 0x2073, 0x2127}, + {0x2074, 0x2074, 0x2128}, {0x2075, 0x2075, 0x2129}, {0x2076, 0x006B, 0x212A}, {0x2077, 0x00DC, 0x212B}, + {0x2078, 0x2078, 0x212C}, {0x2079, 0x2079, 0x212D}, {0x207A, 0x207A, 0x212E}, {0x207B, 0x207B, 0x212F}, + {0x207C, 0x207C, 0x2130}, {0x207D, 0x207D, 0x2131}, {0x207E, 0x209A, 0x2132}, {0x207F, 0x207F, 0x2133}, + {0x2080, 0x2080, 0x2134}, {0x2081, 0x2081, 0x2135}, {0x2082, 0x2082, 0x2136}, {0x2083, 0x2083, 0x2137}, + {0x2084, 0x2084, 0x2138}, {0x2085, 0x2085, 0x2139}, {0x2086, 0x2086, 0x213A}, {0x2087, 0x2087, 0x213B}, + {0x2088, 0x2088, 0x213C}, {0x2089, 0x2089, 0x213D}, {0x208A, 0x208A, 0x213E}, {0x208B, 0x208B, 0x213F}, + {0x208C, 0x208C, 0x2140}, {0x208D, 0x208D, 0x2141}, {0x208E, 0x208E, 0x2142}, {0x208F, 0x208F, 0x2143}, + {0x2090, 0x2090, 0x2144}, {0x2091, 0x2091, 0x2145}, {0x2092, 0x2092, 0x2146}, {0x2093, 0x2093, 0x2147}, + {0x2094, 0x2094, 0x2148}, {0x2095, 0x2095, 0x2149}, {0x2096, 0x2096, 0x214A}, {0x2097, 0x2097, 0x214B}, + {0x2098, 0x2098, 0x214C}, {0x2099, 0x2099, 0x214D}, {0x207E, 0x209A, 0x2132}, {0x209B, 0x209B, 0x214F}, + {0x209C, 0x209C, 0x2150}, {0x209D, 0x209D, 0x2151}, {0x209E, 0x209E, 0x2152}, {0x209F, 0x209F, 0x2153}, + {0x20A0, 0x20A0, 0x2154}, {0x20A1, 0x20A1, 0x2155}, {0x20A2, 0x20A2, 0x2156}, {0x20A3, 0x20A3, 0x2157}, + {0x20A4, 0x20A4, 0x2158}, {0x20A5, 0x20A5, 0x2159}, {0x20A6, 0x20A6, 0x215A}, {0x20A7, 0x20A7, 0x215B}, + {0x20A8, 0x20A8, 0x215C}, {0x20A9, 0x20A9, 0x215D}, {0x20AA, 0x20AA, 0x215E}, {0x20AB, 0x20AB, 0x215F}, + {0x20AC, 0x20B2, 0x216C}, {0x20AD, 0x20B3, 0x216D}, {0x20AE, 0x20B4, 0x216E}, {0x20AF, 0x20B5, 0x216F}, + {0xA2FB, 0x20B0, 0x216A}, {0xA2FC, 0x20B1, 0x216B}, {0x20AC, 0x20B2, 0x216C}, {0x20AD, 0x20B3, 0x216D}, + {0x20AE, 0x20B4, 0x216E}, {0x20AF, 0x20B5, 0x216F}, {0x20B6, 0x20B6, 0x2180}, {0x20B7, 0x20B7, 0x2181}, + {0x20B8, 0x20B8, 0x2182}, {0x20B9, 0x20BA, 0x2183}, {0x20B9, 0x20BA, 0x2183}, {0x20BB, 0x20BB, 0x2185}, + {0x20BC, 0x20BC, 0x2186}, {0x20BD, 0x20BD, 0x2187}, {0x20BE, 0x20BE, 0x2188}, {0x20BF, 0x20BF, 0x2189}, + {0x20C0, 0x20C0, 0x218A}, {0x20C1, 0x20C1, 0x218B}, {0x20C2, 0x20C2, 0x218C}, {0x20C3, 0x20C3, 0x218D}, + {0x20C4, 0x20C4, 0x218E}, {0x20C5, 0x20C5, 0x218F}, {0x20C6, 0x20C6, 0x2194}, {0x20C7, 0x20C7, 0x2195}, + {0x20C8, 0x20C8, 0x219A}, {0x20C9, 0x20C9, 0x219B}, {0x20CA, 0x20CA, 0x219C}, {0x20CB, 0x20CB, 0x219D}, + {0x20CC, 0x20CC, 0x219E}, {0x20CD, 0x20CD, 0x219F}, {0x20CE, 0x20CE, 0x21A0}, {0x20CF, 0x20CF, 0x21A1}, + {0x20D0, 0x20D0, 0x21A2}, {0x20D1, 0x20D1, 0x21A3}, {0x20D2, 0x20D2, 0x21A4}, {0x20D3, 0x20D3, 0x21A5}, + {0x20D4, 0x20D4, 0x21A6}, {0x20D5, 0x20D5, 0x21A7}, {0x20D6, 0x20D6, 0x21A8}, {0x20D7, 0x20D7, 0x21A9}, + {0x20D8, 0x20D8, 0x21AA}, {0x20D9, 0x20D9, 0x21AB}, {0x20DA, 0x20DA, 0x21AC}, {0x20DB, 0x20DB, 0x21AD}, + {0x20DC, 0x20DC, 0x21AE}, {0x20DD, 0x20DD, 0x21AF}, {0x20DE, 0x20DE, 0x21B0}, {0x20DF, 0x20DF, 0x21B1}, + {0x20E0, 0x20E0, 0x21B2}, {0x20E1, 0x20E1, 0x21B3}, {0x20E2, 0x20E2, 0x21B4}, {0x20E3, 0x20E3, 0x21B5}, + {0x20E4, 0x20E4, 0x21B6}, {0x20E5, 0x20E5, 0x21B7}, {0x20E6, 0x20E6, 0x21B8}, {0x20E7, 0x20E7, 0x21B9}, + {0x20E8, 0x20E8, 0x21BA}, {0x20E9, 0x20E9, 0x21BB}, {0x20EA, 0x20EA, 0x21BC}, {0x20EB, 0x20EB, 0x21BD}, + {0x20EC, 0x20EC, 0x21BE}, {0x20ED, 0x20ED, 0x21BF}, {0x20EE, 0x20EE, 0x21C0}, {0x20EF, 0x20EF, 0x21C1}, + {0x20F0, 0x20F0, 0x21C2}, {0x20F1, 0x20F1, 0x21C3}, {0x20F2, 0x20F2, 0x21C4}, {0x20F3, 0x20F3, 0x21C5}, + {0x20F4, 0x20F4, 0x21C6}, {0x20F5, 0x20F5, 0x21C7}, {0x20F6, 0x20F6, 0x21C8}, {0x20F7, 0x20F7, 0x21C9}, + {0x20F8, 0x20F8, 0x21CA}, {0x20F9, 0x20F9, 0x21CB}, {0x20FA, 0x20FA, 0x21CC}, {0x20FB, 0x20FB, 0x21CD}, + {0x20FC, 0x20FC, 0x21CE}, {0x20FD, 0x20FD, 0x21CF}, {0x20FE, 0x20FE, 0x21D0}, {0x20FF, 0x20FF, 0x21D1} +}; + +static GS_UNICASE_CHARACTER plane23[] = { + {0x2300, 0x2300, 0x23F8}, {0x2301, 0x2301, 0x23F9}, {0x2302, 0x2302, 0x23FA}, {0x2303, 0x2303, 0x23FB}, + {0x2304, 0x2304, 0x23FC}, {0x2305, 0x2305, 0x23FD}, {0x2306, 0x2306, 0x23FE}, {0x2307, 0x2307, 0x23FF}, + {0x2308, 0x2308, 0x2400}, {0x2309, 0x2309, 0x2401}, {0x230A, 0x230A, 0x2402}, {0x230B, 0x230B, 0x2403}, + {0x230C, 0x230C, 0x2404}, {0x230D, 0x230D, 0x2405}, {0x230E, 0x230E, 0x2406}, {0x230F, 0x230F, 0x2407}, + {0x2310, 0x2310, 0x2408}, {0x2311, 0x2311, 0x2409}, {0x2312, 0x2312, 0x240A}, {0x2313, 0x2313, 0x240B}, + {0x2314, 0x2314, 0x240C}, {0x2315, 0x2315, 0x240D}, {0x2316, 0x2316, 0x240E}, {0x2317, 0x2317, 0x240F}, + {0x2318, 0x2318, 0x2410}, {0x2319, 0x2319, 0x2411}, {0x231A, 0x231A, 0x2412}, {0x231B, 0x231B, 0x2413}, + {0x231C, 0x231C, 0x2414}, {0x231D, 0x231D, 0x2415}, {0x231E, 0x231E, 0x2416}, {0x231F, 0x231F, 0x2417}, + {0x2320, 0x2320, 0x2418}, {0x2321, 0x2321, 0x2419}, {0x2322, 0x2322, 0x241A}, {0x2323, 0x2323, 0x241B}, + {0x2324, 0x2324, 0x241C}, {0x2325, 0x2325, 0x241D}, {0x2326, 0x2326, 0x241E}, {0x2327, 0x2327, 0x241F}, + {0x2328, 0x2328, 0x2420}, {0x2329, 0x2329, 0x2421}, {0x232A, 0x232A, 0x2422}, {0x232B, 0x232B, 0x2423}, + {0x232C, 0x232C, 0x2424}, {0x232D, 0x232D, 0x2425}, {0x232E, 0x232E, 0x2426}, {0x232F, 0x232F, 0x2427}, + {0x2330, 0x2330, 0x2428}, {0x2331, 0x2331, 0x2429}, {0x2332, 0x2332, 0x242A}, {0x2333, 0x2333, 0x242B}, + {0x2334, 0x2334, 0x242C}, {0x2335, 0x2335, 0x242D}, {0x2336, 0x2336, 0x242E}, {0x2337, 0x2337, 0x242F}, + {0x2338, 0x2338, 0x2430}, {0x2339, 0x2339, 0x2431}, {0x233A, 0x233A, 0x2432}, {0x233B, 0x233B, 0x2433}, + {0x233C, 0x233C, 0x2434}, {0x233D, 0x233D, 0x2435}, {0x233E, 0x233E, 0x2436}, {0x233F, 0x233F, 0x2437}, + {0x2340, 0x2340, 0x2438}, {0x2341, 0x2341, 0x2439}, {0x2342, 0x2342, 0x243A}, {0x2343, 0x2343, 0x243B}, + {0x2344, 0x2344, 0x243C}, {0x2345, 0x2345, 0x243D}, {0x2346, 0x2346, 0x243E}, {0x2347, 0x2347, 0x243F}, + {0x2348, 0x2348, 0x2440}, {0x2349, 0x2349, 0x2441}, {0x234A, 0x234A, 0x2442}, {0x234B, 0x234B, 0x2443}, + {0x234C, 0x234C, 0x2444}, {0x234D, 0x234D, 0x2445}, {0x234E, 0x234E, 0x2446}, {0x234F, 0x234F, 0x2447}, + {0x2350, 0x2350, 0x2448}, {0x2351, 0x2351, 0x2449}, {0x2352, 0x2352, 0x244A}, {0x2353, 0x2353, 0x244B}, + {0x2354, 0x2354, 0x244C}, {0x2355, 0x2355, 0x244D}, {0x2356, 0x2356, 0x244E}, {0x2357, 0x2357, 0x244F}, + {0x2358, 0x2358, 0x2450}, {0x2359, 0x2359, 0x2451}, {0x235A, 0x235A, 0x2452}, {0x235B, 0x235B, 0x2453}, + {0x235C, 0x235C, 0x2454}, {0x235D, 0x235D, 0x2455}, {0x235E, 0x235E, 0x2456}, {0x235F, 0x235F, 0x2457}, + {0x2360, 0x2360, 0x2458}, {0x2361, 0x2361, 0x2459}, {0x2362, 0x2362, 0x245A}, {0x2363, 0x2363, 0x245B}, + {0x2364, 0x2364, 0x245C}, {0x2365, 0x2365, 0x245D}, {0x2366, 0x2366, 0x245E}, {0x2367, 0x2367, 0x245F}, + {0x2368, 0x2368, 0x246A}, {0x2369, 0x2369, 0x246B}, {0x236A, 0x236A, 0x246C}, {0x236B, 0x236B, 0x246D}, + {0x236C, 0x236C, 0x246E}, {0x236D, 0x236D, 0x246F}, {0x236E, 0x236E, 0x2470}, {0x236F, 0x236F, 0x2471}, + {0x2370, 0x2370, 0x2472}, {0x2371, 0x2371, 0x2473}, {0x2372, 0x2372, 0x249C}, {0x2373, 0x2373, 0x249D}, + {0x2374, 0x2374, 0x249E}, {0x2375, 0x2375, 0x249F}, {0x2376, 0x2376, 0x24A0}, {0x2377, 0x2377, 0x24A1}, + {0x2378, 0x2378, 0x24A2}, {0x2379, 0x2379, 0x24A3}, {0x237A, 0x237A, 0x24A4}, {0x237B, 0x237B, 0x24A5}, + {0x237C, 0x237C, 0x24A6}, {0x237D, 0x237D, 0x24A7}, {0x237E, 0x237E, 0x24A8}, {0x237F, 0x237F, 0x24A9}, + {0x2380, 0x2380, 0x24AA}, {0x2381, 0x2381, 0x24AB}, {0x2382, 0x2382, 0x24AC}, {0x2383, 0x2383, 0x24AD}, + {0x2384, 0x2384, 0x24AE}, {0x2385, 0x2385, 0x24AF}, {0x2386, 0x2386, 0x24B0}, {0x2387, 0x2387, 0x24B1}, + {0x2388, 0x2388, 0x24B2}, {0x2389, 0x2389, 0x24B3}, {0x238A, 0x238A, 0x24B4}, {0x238B, 0x238B, 0x24B5}, + {0x238C, 0x23A6, 0x24B6}, {0x238D, 0x23A7, 0x24B7}, {0x238E, 0x23A8, 0x24B8}, {0x238F, 0x23A9, 0x24B9}, + {0x2390, 0x23AA, 0x24BA}, {0x2391, 0x23AB, 0x24BB}, {0x2392, 0x23AC, 0x24BC}, {0x2393, 0x23AD, 0x24BD}, + {0x2394, 0x23AE, 0x24BE}, {0x2395, 0x23AF, 0x24BF}, {0x2396, 0x23B0, 0x24C0}, {0x2397, 0x23B1, 0x24C1}, + {0x2398, 0x23B2, 0x24C2}, {0x2399, 0x23B3, 0x24C3}, {0x239A, 0x23B4, 0x24C4}, {0x239B, 0x23B5, 0x24C5}, + {0x239C, 0x23B6, 0x24C6}, {0x239D, 0x23B7, 0x24C7}, {0x239E, 0x23B8, 0x24C8}, {0x239F, 0x23B9, 0x24C9}, + {0x23A0, 0x23BA, 0x24CA}, {0x23A1, 0x23BB, 0x24CB}, {0x23A2, 0x23BC, 0x24CC}, {0x23A3, 0x23BD, 0x24CD}, + {0x23A4, 0x23BE, 0x24CE}, {0x23A5, 0x23BF, 0x24CF}, {0x238C, 0x23A6, 0x24B6}, {0x238D, 0x23A7, 0x24B7}, + {0x238E, 0x23A8, 0x24B8}, {0x238F, 0x23A9, 0x24B9}, {0x2390, 0x23AA, 0x24BA}, {0x2391, 0x23AB, 0x24BB}, + {0x2392, 0x23AC, 0x24BC}, {0x2393, 0x23AD, 0x24BD}, {0x2394, 0x23AE, 0x24BE}, {0x2395, 0x23AF, 0x24BF}, + {0x2396, 0x23B0, 0x24C0}, {0x2397, 0x23B1, 0x24C1}, {0x2398, 0x23B2, 0x24C2}, {0x2399, 0x23B3, 0x24C3}, + {0x239A, 0x23B4, 0x24C4}, {0x239B, 0x23B5, 0x24C5}, {0x239C, 0x23B6, 0x24C6}, {0x239D, 0x23B7, 0x24C7}, + {0x239E, 0x23B8, 0x24C8}, {0x239F, 0x23B9, 0x24C9}, {0x23A0, 0x23BA, 0x24CA}, {0x23A1, 0x23BB, 0x24CB}, + {0x23A2, 0x23BC, 0x24CC}, {0x23A3, 0x23BD, 0x24CD}, {0x23A4, 0x23BE, 0x24CE}, {0x23A5, 0x23BF, 0x24CF}, + {0x23C0, 0x23C0, 0x24EA}, {0x23C1, 0x23C1, 0x24EB}, {0x23C2, 0x23C2, 0x24EC}, {0x23C3, 0x23C3, 0x24ED}, + {0x23C4, 0x23C4, 0x24EE}, {0x23C5, 0x23C5, 0x24EF}, {0x23C6, 0x23C6, 0x24F0}, {0x23C7, 0x23C7, 0x24F1}, + {0x23C8, 0x23C8, 0x24F2}, {0x23C9, 0x23C9, 0x24F3}, {0x23CA, 0x23CA, 0x24F4}, {0x23CB, 0x23CB, 0x24F5}, + {0x23CC, 0x23CC, 0x24F6}, {0x23CD, 0x23CD, 0x24F7}, {0x23CE, 0x23CE, 0x24F8}, {0x23CF, 0x23CF, 0x24F9}, + {0x23D0, 0x23D0, 0x24FA}, {0x23D1, 0x23D1, 0x24FB}, {0x23D2, 0x23D2, 0x24FC}, {0x23D3, 0x23D3, 0x24FD}, + {0x23D4, 0x23D4, 0x24FE}, {0x23D5, 0x23D5, 0x24FF}, {0x23D6, 0x23D6, 0x254C}, {0x23D7, 0x23D7, 0x254D}, + {0x23D8, 0x23D8, 0x254E}, {0x23D9, 0x23D9, 0x254F}, {0x23DA, 0x23DA, 0x2574}, {0x23DB, 0x23DB, 0x2575}, + {0x23DC, 0x23DC, 0x2576}, {0x23DD, 0x23DD, 0x2577}, {0x23DE, 0x23DE, 0x2578}, {0x23DF, 0x23DF, 0x2579}, + {0x23E0, 0x23E0, 0x257A}, {0x23E1, 0x23E1, 0x257B}, {0x23E2, 0x23E2, 0x257C}, {0x23E3, 0x23E3, 0x257D}, + {0x23E4, 0x23E4, 0x257E}, {0x23E5, 0x23E5, 0x257F}, {0x23E6, 0x23E6, 0x2580}, {0x23E7, 0x23E7, 0x2590}, + {0x23E8, 0x23E8, 0x2591}, {0x23E9, 0x23E9, 0x2592}, {0x23EA, 0x23EA, 0x2596}, {0x23EB, 0x23EB, 0x2597}, + {0x23EC, 0x23EC, 0x2598}, {0x23ED, 0x23ED, 0x2599}, {0x23EE, 0x23EE, 0x259A}, {0x23EF, 0x23EF, 0x259B}, + {0x23F0, 0x23F0, 0x259C}, {0x23F1, 0x23F1, 0x259D}, {0x23F2, 0x23F2, 0x259E}, {0x23F3, 0x23F3, 0x259F}, + {0x23F4, 0x23F4, 0x25A2}, {0x23F5, 0x23F5, 0x25A3}, {0x23F6, 0x23F6, 0x25A4}, {0x23F7, 0x23F7, 0x25A5}, + {0x23F8, 0x23F8, 0x25A6}, {0x23F9, 0x23F9, 0x25A7}, {0x23FA, 0x23FA, 0x25A8}, {0x23FB, 0x23FB, 0x25A9}, + {0x23FC, 0x23FC, 0x25AA}, {0x23FD, 0x23FD, 0x25AB}, {0x23FE, 0x23FE, 0x25AC}, {0x23FF, 0x23FF, 0x25AD} +}; + +static GS_UNICASE_CHARACTER plane2A[] = { + {0x2A00, 0x2A00, 0x2BC0}, {0x2A01, 0x2A01, 0x2BC1}, {0x2A02, 0x2A02, 0x2BC2}, {0x2A03, 0x2A03, 0x2BC3}, + {0x2A04, 0x2A04, 0x2BC4}, {0x2A05, 0x2A05, 0x2BC5}, {0x2A06, 0x2A06, 0x2BC6}, {0x2A07, 0x2A07, 0x2BC7}, + {0x2A08, 0x2A08, 0x2BC8}, {0x2A09, 0x2A09, 0x2BC9}, {0x2A0A, 0x2A0A, 0x2BCA}, {0x2A0B, 0x2A0B, 0x2BCB}, + {0x2A0C, 0x2A0C, 0x2BCC}, {0x2A0D, 0x2A0D, 0x2BCD}, {0x2A0E, 0x2A0E, 0x2BCE}, {0x2A0F, 0x2A0F, 0x2BCF}, + {0x2A10, 0x2A10, 0x2BD0}, {0x2A11, 0x2A11, 0x2BD1}, {0x2A12, 0x2A12, 0x2BD2}, {0x2A13, 0x2A13, 0x2BD3}, + {0x2A14, 0x2A14, 0x2BD4}, {0x2A15, 0x2A15, 0x2BD5}, {0x2A16, 0x2A16, 0x2BD6}, {0x2A17, 0x2A17, 0x2BD7}, + {0x2A18, 0x2A18, 0x2BD8}, {0x2A19, 0x2A19, 0x2BD9}, {0x2A1A, 0x2A1A, 0x2BDA}, {0x2A1B, 0x2A1B, 0x2BDB}, + {0x2A1C, 0x2A1C, 0x2BDC}, {0x2A1D, 0x2A1D, 0x2BDD}, {0x2A1E, 0x2A1E, 0x2BDE}, {0x2A1F, 0x2A1F, 0x2BDF}, + {0x2A20, 0x2A20, 0x2BE0}, {0x2A21, 0x2A21, 0x2BE1}, {0x2A22, 0x2A22, 0x2BE2}, {0x2A23, 0x2A23, 0x2BE3}, + {0x2A24, 0x2A24, 0x2BE4}, {0x2A25, 0x2A25, 0x2BE5}, {0x2A26, 0x2A26, 0x2BE6}, {0x2A27, 0x2A27, 0x2BE7}, + {0x2A28, 0x2A28, 0x2BE8}, {0x2A29, 0x2A29, 0x2BE9}, {0x2A2A, 0x2A2A, 0x2BEA}, {0x2A2B, 0x2A2B, 0x2BEB}, + {0x2A2C, 0x2A2C, 0x2BEC}, {0x2A2D, 0x2A2D, 0x2BED}, {0x2A2E, 0x2A2E, 0x2BEE}, {0x2A2F, 0x2A2F, 0x2BEF}, + {0x2A30, 0x2A30, 0x2BF0}, {0x2A31, 0x2A31, 0x2BF1}, {0x2A32, 0x2A32, 0x2BF2}, {0x2A33, 0x2A33, 0x2BF3}, + {0x2A34, 0x2A34, 0x2BF4}, {0x2A35, 0x2A35, 0x2BF5}, {0x2A36, 0x2A36, 0x2BF6}, {0x2A37, 0x2A37, 0x2BF7}, + {0x2A38, 0x2A38, 0x2BF8}, {0x2A39, 0x2A39, 0x2BF9}, {0x2A3A, 0x2A3A, 0x2BFA}, {0x2A3B, 0x2A3B, 0x2BFB}, + {0x2A3C, 0x2A3C, 0x2BFC}, {0x2A3D, 0x2A3D, 0x2BFD}, {0x2A3E, 0x2A3E, 0x2BFE}, {0x2A3F, 0x2A3F, 0x2BFF}, + {0x2A40, 0x2A70, 0x2C00}, {0x2A41, 0x2A71, 0x2C01}, {0x2A42, 0x2A72, 0x2C02}, {0x2A43, 0x2A73, 0x2C03}, + {0x2A44, 0x2A74, 0x2C04}, {0x2A45, 0x2A75, 0x2C05}, {0x2A46, 0x2A76, 0x2C06}, {0x2A47, 0x2A77, 0x2C07}, + {0x2A48, 0x2A78, 0x2C08}, {0x2A49, 0x2A79, 0x2C09}, {0x2A4A, 0x2A7A, 0x2C0A}, {0x2A4B, 0x2A7B, 0x2C0B}, + {0x2A4C, 0x2A7C, 0x2C0C}, {0x2A4D, 0x2A7D, 0x2C0D}, {0x2A4E, 0x2A7E, 0x2C0E}, {0x2A4F, 0x2A7F, 0x2C0F}, + {0x2A50, 0x2A80, 0x2C10}, {0x2A51, 0x2A81, 0x2C11}, {0x2A52, 0x2A82, 0x2C12}, {0x2A53, 0x2A83, 0x2C13}, + {0x2A54, 0x2A84, 0x2C14}, {0x2A55, 0x2A85, 0x2C15}, {0x2A56, 0x2A86, 0x2C16}, {0x2A57, 0x2A87, 0x2C17}, + {0x2A58, 0x2A88, 0x2C18}, {0x2A59, 0x2A89, 0x2C19}, {0x2A5A, 0x2A8A, 0x2C1A}, {0x2A5B, 0x2A8B, 0x2C1B}, + {0x2A5C, 0x2A8C, 0x2C1C}, {0x2A5D, 0x2A8D, 0x2C1D}, {0x2A5E, 0x2A8E, 0x2C1E}, {0x2A5F, 0x2A8F, 0x2C1F}, + {0x2A60, 0x2A90, 0x2C20}, {0x2A61, 0x2A91, 0x2C21}, {0x2A62, 0x2A92, 0x2C22}, {0x2A63, 0x2A93, 0x2C23}, + {0x2A64, 0x2A94, 0x2C24}, {0x2A65, 0x2A95, 0x2C25}, {0x2A66, 0x2A96, 0x2C26}, {0x2A67, 0x2A97, 0x2C27}, + {0x2A68, 0x2A98, 0x2C28}, {0x2A69, 0x2A99, 0x2C29}, {0x2A6A, 0x2A9A, 0x2C2A}, {0x2A6B, 0x2A9B, 0x2C2B}, + {0x2A6C, 0x2A9C, 0x2C2C}, {0x2A6D, 0x2A9D, 0x2C2D}, {0x2A6E, 0x2A9E, 0x2C2E}, {0x2A6F, 0x2A6F, 0x2C2F}, + {0x2A40, 0x2A70, 0x2C00}, {0x2A41, 0x2A71, 0x2C01}, {0x2A42, 0x2A72, 0x2C02}, {0x2A43, 0x2A73, 0x2C03}, + {0x2A44, 0x2A74, 0x2C04}, {0x2A45, 0x2A75, 0x2C05}, {0x2A46, 0x2A76, 0x2C06}, {0x2A47, 0x2A77, 0x2C07}, + {0x2A48, 0x2A78, 0x2C08}, {0x2A49, 0x2A79, 0x2C09}, {0x2A4A, 0x2A7A, 0x2C0A}, {0x2A4B, 0x2A7B, 0x2C0B}, + {0x2A4C, 0x2A7C, 0x2C0C}, {0x2A4D, 0x2A7D, 0x2C0D}, {0x2A4E, 0x2A7E, 0x2C0E}, {0x2A4F, 0x2A7F, 0x2C0F}, + {0x2A50, 0x2A80, 0x2C10}, {0x2A51, 0x2A81, 0x2C11}, {0x2A52, 0x2A82, 0x2C12}, {0x2A53, 0x2A83, 0x2C13}, + {0x2A54, 0x2A84, 0x2C14}, {0x2A55, 0x2A85, 0x2C15}, {0x2A56, 0x2A86, 0x2C16}, {0x2A57, 0x2A87, 0x2C17}, + {0x2A58, 0x2A88, 0x2C18}, {0x2A59, 0x2A89, 0x2C19}, {0x2A5A, 0x2A8A, 0x2C1A}, {0x2A5B, 0x2A8B, 0x2C1B}, + {0x2A5C, 0x2A8C, 0x2C1C}, {0x2A5D, 0x2A8D, 0x2C1D}, {0x2A5E, 0x2A8E, 0x2C1E}, {0x2A5F, 0x2A8F, 0x2C1F}, + {0x2A60, 0x2A90, 0x2C20}, {0x2A61, 0x2A91, 0x2C21}, {0x2A62, 0x2A92, 0x2C22}, {0x2A63, 0x2A93, 0x2C23}, + {0x2A64, 0x2A94, 0x2C24}, {0x2A65, 0x2A95, 0x2C25}, {0x2A66, 0x2A96, 0x2C26}, {0x2A67, 0x2A97, 0x2C27}, + {0x2A68, 0x2A98, 0x2C28}, {0x2A69, 0x2A99, 0x2C29}, {0x2A6A, 0x2A9A, 0x2C2A}, {0x2A6B, 0x2A9B, 0x2C2B}, + {0x2A6C, 0x2A9C, 0x2C2C}, {0x2A6D, 0x2A9D, 0x2C2D}, {0x2A6E, 0x2A9E, 0x2C2E}, {0x2A9F, 0x2A9F, 0x2C5F}, + {0x2AA0, 0x2AA1, 0x2C60}, {0x2AA0, 0x2AA1, 0x2C60}, {0x2AA2, 0x0244, 0x2C62}, {0x2AA3, 0x1CDF, 0x2C63}, + {0x2AA4, 0x0256, 0x2C64}, {0x0215, 0x2AA5, 0x023A}, {0x0219, 0x2AA6, 0x023E}, {0x2AA7, 0x2AA8, 0x2C67}, + {0x2AA7, 0x2AA8, 0x2C67}, {0x2AA9, 0x2AAA, 0x2C69}, {0x2AA9, 0x2AAA, 0x2C69}, {0x2AAB, 0x2AAC, 0x2C6B}, + {0x2AAB, 0x2AAC, 0x2C6B}, {0x2AAD, 0xA8BB, 0x2C6D}, {0x2AAE, 0x024A, 0x2C6E}, {0x2AAF, 0x022B, 0x2C6F}, + {0x2AB0, 0x022C, 0x2C70}, {0x2AB1, 0x2AB1, 0x2C71}, {0x2AB2, 0x2AB3, 0x2C72}, {0x2AB2, 0x2AB3, 0x2C72}, + {0x2AB4, 0x2AB4, 0x2C74}, {0x2AB5, 0x2AB6, 0x2C75}, {0x2AB5, 0x2AB6, 0x2C75}, {0x2AB7, 0x2AB7, 0x2C77}, + {0x2AB8, 0x2AB8, 0x2C78}, {0x2AB9, 0x2AB9, 0x2C79}, {0x2ABA, 0x2ABA, 0x2C7A}, {0x2ABB, 0x2ABB, 0x2C7B}, + {0x2ABC, 0x2ABC, 0x2C7C}, {0x2ABD, 0x2ABD, 0x2C7D}, {0x2ABE, 0x021A, 0x2C7E}, {0x2ABF, 0x021B, 0x2C7F}, + {0x2AC0, 0x2AC1, 0x2C80}, {0x2AC0, 0x2AC1, 0x2C80}, {0x2AC2, 0x2AC3, 0x2C82}, {0x2AC2, 0x2AC3, 0x2C82}, + {0x2AC4, 0x2AC5, 0x2C84}, {0x2AC4, 0x2AC5, 0x2C84}, {0x2AC6, 0x2AC7, 0x2C86}, {0x2AC6, 0x2AC7, 0x2C86}, + {0x2AC8, 0x2AC9, 0x2C88}, {0x2AC8, 0x2AC9, 0x2C88}, {0x2ACA, 0x2ACB, 0x2C8A}, {0x2ACA, 0x2ACB, 0x2C8A}, + {0x2ACC, 0x2ACD, 0x2C8C}, {0x2ACC, 0x2ACD, 0x2C8C}, {0x2ACE, 0x2ACF, 0x2C8E}, {0x2ACE, 0x2ACF, 0x2C8E}, + {0x2AD0, 0x2AD1, 0x2C90}, {0x2AD0, 0x2AD1, 0x2C90}, {0x2AD2, 0x2AD3, 0x2C92}, {0x2AD2, 0x2AD3, 0x2C92}, + {0x2AD4, 0x2AD5, 0x2C94}, {0x2AD4, 0x2AD5, 0x2C94}, {0x2AD6, 0x2AD7, 0x2C96}, {0x2AD6, 0x2AD7, 0x2C96}, + {0x2AD8, 0x2AD9, 0x2C98}, {0x2AD8, 0x2AD9, 0x2C98}, {0x2ADA, 0x2ADB, 0x2C9A}, {0x2ADA, 0x2ADB, 0x2C9A}, + {0x2ADC, 0x2ADD, 0x2C9C}, {0x2ADC, 0x2ADD, 0x2C9C}, {0x2ADE, 0x2ADF, 0x2C9E}, {0x2ADE, 0x2ADF, 0x2C9E}, + {0x2AE0, 0x2AE1, 0x2CA0}, {0x2AE0, 0x2AE1, 0x2CA0}, {0x2AE2, 0x2AE3, 0x2CA2}, {0x2AE2, 0x2AE3, 0x2CA2}, + {0x2AE4, 0x2AE5, 0x2CA4}, {0x2AE4, 0x2AE5, 0x2CA4}, {0x2AE6, 0x2AE7, 0x2CA6}, {0x2AE6, 0x2AE7, 0x2CA6}, + {0x2AE8, 0x2AE9, 0x2CA8}, {0x2AE8, 0x2AE9, 0x2CA8}, {0x2AEA, 0x2AEB, 0x2CAA}, {0x2AEA, 0x2AEB, 0x2CAA}, + {0x2AEC, 0x2AED, 0x2CAC}, {0x2AEC, 0x2AED, 0x2CAC}, {0x2AEE, 0x2AEF, 0x2CAE}, {0x2AEE, 0x2AEF, 0x2CAE}, + {0x2AF0, 0x2AF1, 0x2CB0}, {0x2AF0, 0x2AF1, 0x2CB0}, {0x2AF2, 0x2AF3, 0x2CB2}, {0x2AF2, 0x2AF3, 0x2CB2}, + {0x2AF4, 0x2AF5, 0x2CB4}, {0x2AF4, 0x2AF5, 0x2CB4}, {0x2AF6, 0x2AF7, 0x2CB6}, {0x2AF6, 0x2AF7, 0x2CB6}, + {0x2AF8, 0x2AF9, 0x2CB8}, {0x2AF8, 0x2AF9, 0x2CB8}, {0x2AFA, 0x2AFB, 0x2CBA}, {0x2AFA, 0x2AFB, 0x2CBA}, + {0x2AFC, 0x2AFD, 0x2CBC}, {0x2AFC, 0x2AFD, 0x2CBC}, {0x2AFE, 0x2AFF, 0x2CBE}, {0x2AFE, 0x2AFF, 0x2CBE} +}; + +static GS_UNICASE_CHARACTER plane2B[] = { + {0x2B00, 0x2B01, 0x2CC0}, {0x2B00, 0x2B01, 0x2CC0}, {0x2B02, 0x2B03, 0x2CC2}, {0x2B02, 0x2B03, 0x2CC2}, + {0x2B04, 0x2B05, 0x2CC4}, {0x2B04, 0x2B05, 0x2CC4}, {0x2B06, 0x2B07, 0x2CC6}, {0x2B06, 0x2B07, 0x2CC6}, + {0x2B08, 0x2B09, 0x2CC8}, {0x2B08, 0x2B09, 0x2CC8}, {0x2B0A, 0x2B0B, 0x2CCA}, {0x2B0A, 0x2B0B, 0x2CCA}, + {0x2B0C, 0x2B0D, 0x2CCC}, {0x2B0C, 0x2B0D, 0x2CCC}, {0x2B0E, 0x2B0F, 0x2CCE}, {0x2B0E, 0x2B0F, 0x2CCE}, + {0x2B10, 0x2B11, 0x2CD0}, {0x2B10, 0x2B11, 0x2CD0}, {0x2B12, 0x2B13, 0x2CD2}, {0x2B12, 0x2B13, 0x2CD2}, + {0x2B14, 0x2B15, 0x2CD4}, {0x2B14, 0x2B15, 0x2CD4}, {0x2B16, 0x2B17, 0x2CD6}, {0x2B16, 0x2B17, 0x2CD6}, + {0x2B18, 0x2B19, 0x2CD8}, {0x2B18, 0x2B19, 0x2CD8}, {0x2B1A, 0x2B1B, 0x2CDA}, {0x2B1A, 0x2B1B, 0x2CDA}, + {0x2B1C, 0x2B1D, 0x2CDC}, {0x2B1C, 0x2B1D, 0x2CDC}, {0x2B1E, 0x2B1F, 0x2CDE}, {0x2B1E, 0x2B1F, 0x2CDE}, + {0x2B20, 0x2B21, 0x2CE0}, {0x2B20, 0x2B21, 0x2CE0}, {0x2B22, 0x2B23, 0x2CE2}, {0x2B22, 0x2B23, 0x2CE2}, + {0x2B24, 0x2B24, 0x2CE4}, {0x2B25, 0x2B25, 0x2CE5}, {0x2B26, 0x2B26, 0x2CE6}, {0x2B27, 0x2B27, 0x2CE7}, + {0x2B28, 0x2B28, 0x2CE8}, {0x2B29, 0x2B29, 0x2CE9}, {0x2B2A, 0x2B2A, 0x2CEA}, {0x2B2B, 0x2B2C, 0x2CEB}, + {0x2B2B, 0x2B2C, 0x2CEB}, {0x2B2D, 0x2B2E, 0x2CED}, {0x2B2D, 0x2B2E, 0x2CED}, {0x2B2F, 0x2B2F, 0x2CEF}, + {0x2B30, 0x2B30, 0x2CF0}, {0x2B31, 0x2B31, 0x2CF1}, {0x2B32, 0x2B32, 0x2CF2}, {0x2B33, 0x2B33, 0x2CF3}, + {0x2B34, 0x2B34, 0x2CF4}, {0x2B35, 0x2B35, 0x2CF5}, {0x2B36, 0x2B36, 0x2CF6}, {0x2B37, 0x2B37, 0x2CF7}, + {0x2B38, 0x2B38, 0x2CF8}, {0x2B39, 0x2B39, 0x2CF9}, {0x2B3A, 0x2B3A, 0x2CFA}, {0x2B3B, 0x2B3B, 0x2CFB}, + {0x2B3C, 0x2B3C, 0x2CFC}, {0x2B3D, 0x2B3D, 0x2CFD}, {0x2B3E, 0x2B3E, 0x2CFE}, {0x2B3F, 0x2B3F, 0x2CFF}, + {0x1002, 0x2B40, 0x10A0}, {0x1003, 0x2B41, 0x10A1}, {0x1004, 0x2B42, 0x10A2}, {0x1005, 0x2B43, 0x10A3}, + {0x1006, 0x2B44, 0x10A4}, {0x1007, 0x2B45, 0x10A5}, {0x1008, 0x2B46, 0x10A6}, {0x1009, 0x2B47, 0x10A7}, + {0x100A, 0x2B48, 0x10A8}, {0x100B, 0x2B49, 0x10A9}, {0x100C, 0x2B4A, 0x10AA}, {0x100D, 0x2B4B, 0x10AB}, + {0x100E, 0x2B4C, 0x10AC}, {0x100F, 0x2B4D, 0x10AD}, {0x1010, 0x2B4E, 0x10AE}, {0x1011, 0x2B4F, 0x10AF}, + {0x1012, 0x2B50, 0x10B0}, {0x1013, 0x2B51, 0x10B1}, {0x1014, 0x2B52, 0x10B2}, {0x1015, 0x2B53, 0x10B3}, + {0x1016, 0x2B54, 0x10B4}, {0x1017, 0x2B55, 0x10B5}, {0x1018, 0x2B56, 0x10B6}, {0x1019, 0x2B57, 0x10B7}, + {0x101A, 0x2B58, 0x10B8}, {0x101B, 0x2B59, 0x10B9}, {0x101C, 0x2B5A, 0x10BA}, {0x101D, 0x2B5B, 0x10BB}, + {0x101E, 0x2B5C, 0x10BC}, {0x101F, 0x2B5D, 0x10BD}, {0x1020, 0x2B5E, 0x10BE}, {0x1021, 0x2B5F, 0x10BF}, + {0x1022, 0x2B60, 0x10C0}, {0x1023, 0x2B61, 0x10C1}, {0x1024, 0x2B62, 0x10C2}, {0x1025, 0x2B63, 0x10C3}, + {0x1026, 0x2B64, 0x10C4}, {0x1027, 0x2B65, 0x10C5}, {0x2B66, 0x2B66, 0x2D26}, {0x2B67, 0x2B67, 0x2D27}, + {0x2B68, 0x2B68, 0x2D28}, {0x2B69, 0x2B69, 0x2D29}, {0x2B6A, 0x2B6A, 0x2D2A}, {0x2B6B, 0x2B6B, 0x2D2B}, + {0x2B6C, 0x2B6C, 0x2D2C}, {0x2B6D, 0x2B6D, 0x2D2D}, {0x2B6E, 0x2B6E, 0x2D2E}, {0x2B6F, 0x2B6F, 0x2D2F}, + {0x2B70, 0x2B70, 0x2D30}, {0x2B71, 0x2B71, 0x2D31}, {0x2B72, 0x2B72, 0x2D32}, {0x2B73, 0x2B73, 0x2D33}, + {0x2B74, 0x2B74, 0x2D34}, {0x2B75, 0x2B75, 0x2D35}, {0x2B76, 0x2B76, 0x2D36}, {0x2B77, 0x2B77, 0x2D37}, + {0x2B78, 0x2B78, 0x2D38}, {0x2B79, 0x2B79, 0x2D39}, {0x2B7A, 0x2B7A, 0x2D3A}, {0x2B7B, 0x2B7B, 0x2D3B}, + {0x2B7C, 0x2B7C, 0x2D3C}, {0x2B7D, 0x2B7D, 0x2D3D}, {0x2B7E, 0x2B7E, 0x2D3E}, {0x2B7F, 0x2B7F, 0x2D3F}, + {0x2B80, 0x2B80, 0x2D40}, {0x2B81, 0x2B81, 0x2D41}, {0x2B82, 0x2B82, 0x2D42}, {0x2B83, 0x2B83, 0x2D43}, + {0x2B84, 0x2B84, 0x2D44}, {0x2B85, 0x2B85, 0x2D45}, {0x2B86, 0x2B86, 0x2D46}, {0x2B87, 0x2B87, 0x2D47}, + {0x2B88, 0x2B88, 0x2D48}, {0x2B89, 0x2B89, 0x2D49}, {0x2B8A, 0x2B8A, 0x2D4A}, {0x2B8B, 0x2B8B, 0x2D4B}, + {0x2B8C, 0x2B8C, 0x2D4C}, {0x2B8D, 0x2B8D, 0x2D4D}, {0x2B8E, 0x2B8E, 0x2D4E}, {0x2B8F, 0x2B8F, 0x2D4F}, + {0x2B90, 0x2B90, 0x2D50}, {0x2B91, 0x2B91, 0x2D51}, {0x2B92, 0x2B92, 0x2D52}, {0x2B93, 0x2B93, 0x2D53}, + {0x2B94, 0x2B94, 0x2D54}, {0x2B95, 0x2B95, 0x2D55}, {0x2B96, 0x2B96, 0x2D56}, {0x2B97, 0x2B97, 0x2D57}, + {0x2B98, 0x2B98, 0x2D58}, {0x2B99, 0x2B99, 0x2D59}, {0x2B9A, 0x2B9A, 0x2D5A}, {0x2B9B, 0x2B9B, 0x2D5B}, + {0x2B9C, 0x2B9C, 0x2D5C}, {0x2B9D, 0x2B9D, 0x2D5D}, {0x2B9E, 0x2B9E, 0x2D5E}, {0x2B9F, 0x2B9F, 0x2D5F}, + {0x2BA0, 0x2BA0, 0x2D60}, {0x2BA1, 0x2BA1, 0x2D61}, {0x2BA2, 0x2BA2, 0x2D62}, {0x2BA3, 0x2BA3, 0x2D63}, + {0x2BA4, 0x2BA4, 0x2D64}, {0x2BA5, 0x2BA5, 0x2D65}, {0x2BA6, 0x2BA6, 0x2D66}, {0x2BA7, 0x2BA7, 0x2D67}, + {0x2BA8, 0x2BA8, 0x2D68}, {0x2BA9, 0x2BA9, 0x2D69}, {0x2BAA, 0x2BAA, 0x2D6A}, {0x2BAB, 0x2BAB, 0x2D6B}, + {0x2BAC, 0x2BAC, 0x2D6C}, {0x2BAD, 0x2BAD, 0x2D6D}, {0x2BAE, 0x2BAE, 0x2D6E}, {0x2BAF, 0x2BAF, 0x2D6F}, + {0x2BB0, 0x2BB0, 0x2D70}, {0x2BB1, 0x2BB1, 0x2D71}, {0x2BB2, 0x2BB2, 0x2D72}, {0x2BB3, 0x2BB3, 0x2D73}, + {0x2BB4, 0x2BB4, 0x2D74}, {0x2BB5, 0x2BB5, 0x2D75}, {0x2BB6, 0x2BB6, 0x2D76}, {0x2BB7, 0x2BB7, 0x2D77}, + {0x2BB8, 0x2BB8, 0x2D78}, {0x2BB9, 0x2BB9, 0x2D79}, {0x2BBA, 0x2BBA, 0x2D7A}, {0x2BBB, 0x2BBB, 0x2D7B}, + {0x2BBC, 0x2BBC, 0x2D7C}, {0x2BBD, 0x2BBD, 0x2D7D}, {0x2BBE, 0x2BBE, 0x2D7E}, {0x2BBF, 0x2BBF, 0x2D7F}, + {0x2BC0, 0x2BC0, 0x2D80}, {0x2BC1, 0x2BC1, 0x2D81}, {0x2BC2, 0x2BC2, 0x2D82}, {0x2BC3, 0x2BC3, 0x2D83}, + {0x2BC4, 0x2BC4, 0x2D84}, {0x2BC5, 0x2BC5, 0x2D85}, {0x2BC6, 0x2BC6, 0x2D86}, {0x2BC7, 0x2BC7, 0x2D87}, + {0x2BC8, 0x2BC8, 0x2D88}, {0x2BC9, 0x2BC9, 0x2D89}, {0x2BCA, 0x2BCA, 0x2D8A}, {0x2BCB, 0x2BCB, 0x2D8B}, + {0x2BCC, 0x2BCC, 0x2D8C}, {0x2BCD, 0x2BCD, 0x2D8D}, {0x2BCE, 0x2BCE, 0x2D8E}, {0x2BCF, 0x2BCF, 0x2D8F}, + {0x2BD0, 0x2BD0, 0x2D90}, {0x2BD1, 0x2BD1, 0x2D91}, {0x2BD2, 0x2BD2, 0x2D92}, {0x2BD3, 0x2BD3, 0x2D93}, + {0x2BD4, 0x2BD4, 0x2D94}, {0x2BD5, 0x2BD5, 0x2D95}, {0x2BD6, 0x2BD6, 0x2D96}, {0x2BD7, 0x2BD7, 0x2D97}, + {0x2BD8, 0x2BD8, 0x2D98}, {0x2BD9, 0x2BD9, 0x2D99}, {0x2BDA, 0x2BDA, 0x2D9A}, {0x2BDB, 0x2BDB, 0x2D9B}, + {0x2BDC, 0x2BDC, 0x2D9C}, {0x2BDD, 0x2BDD, 0x2D9D}, {0x2BDE, 0x2BDE, 0x2D9E}, {0x2BDF, 0x2BDF, 0x2D9F}, + {0x2BE0, 0x2BE0, 0x2DA0}, {0x2BE1, 0x2BE1, 0x2DA1}, {0x2BE2, 0x2BE2, 0x2DA2}, {0x2BE3, 0x2BE3, 0x2DA3}, + {0x2BE4, 0x2BE4, 0x2DA4}, {0x2BE5, 0x2BE5, 0x2DA5}, {0x2BE6, 0x2BE6, 0x2DA6}, {0x2BE7, 0x2BE7, 0x2DA7}, + {0x2BE8, 0x2BE8, 0x2DA8}, {0x2BE9, 0x2BE9, 0x2DA9}, {0x2BEA, 0x2BEA, 0x2DAA}, {0x2BEB, 0x2BEB, 0x2DAB}, + {0x2BEC, 0x2BEC, 0x2DAC}, {0x2BED, 0x2BED, 0x2DAD}, {0x2BEE, 0x2BEE, 0x2DAE}, {0x2BEF, 0x2BEF, 0x2DAF}, + {0x2BF0, 0x2BF0, 0x2DB0}, {0x2BF1, 0x2BF1, 0x2DB1}, {0x2BF2, 0x2BF2, 0x2DB2}, {0x2BF3, 0x2BF3, 0x2DB3}, + {0x2BF4, 0x2BF4, 0x2DB4}, {0x2BF5, 0x2BF5, 0x2DB5}, {0x2BF6, 0x2BF6, 0x2DB6}, {0x2BF7, 0x2BF7, 0x2DB7}, + {0x2BF8, 0x2BF8, 0x2DB8}, {0x2BF9, 0x2BF9, 0x2DB9}, {0x2BFA, 0x2BFA, 0x2DBA}, {0x2BFB, 0x2BFB, 0x2DBB}, + {0x2BFC, 0x2BFC, 0x2DBC}, {0x2BFD, 0x2BFD, 0x2DBD}, {0x2BFE, 0x2BFE, 0x2DBE}, {0x2BFF, 0x2BFF, 0x2DBF} +}; + +static GS_UNICASE_CHARACTER plane51[] = { + {0x5100, 0x5100, 0xA5C3}, {0x5101, 0x5101, 0xA5C4}, {0x5102, 0x5102, 0xA5C5}, {0x5103, 0x5103, 0xA5C6}, + {0x5104, 0x5104, 0xA5C7}, {0x5105, 0x5105, 0xA5C8}, {0x5106, 0x5106, 0xA5C9}, {0x5107, 0x5107, 0xA5CA}, + {0x5108, 0x5108, 0xA5CB}, {0x5109, 0x5109, 0xA5CC}, {0x510A, 0x510A, 0xA5CD}, {0x510B, 0x510B, 0xA5CE}, + {0x510C, 0x510C, 0xA5CF}, {0x510D, 0x510D, 0xA5D0}, {0x510E, 0x510E, 0xA5D1}, {0x510F, 0x510F, 0xA5D2}, + {0x5110, 0x5110, 0xA5D3}, {0x5111, 0x5111, 0xA5D4}, {0x5112, 0x5112, 0xA5D5}, {0x5113, 0x5113, 0xA5D6}, + {0x5114, 0x5114, 0xA5D7}, {0x5115, 0x5115, 0xA5D8}, {0x5116, 0x5116, 0xA5D9}, {0x5117, 0x5117, 0xA5DA}, + {0x5118, 0x5118, 0xA5DB}, {0x5119, 0x5119, 0xA5DC}, {0x511A, 0x511A, 0xA5DD}, {0x511B, 0x511B, 0xA5DE}, + {0x511C, 0x511C, 0xA5DF}, {0x511D, 0x511D, 0xA5E0}, {0x511E, 0x511E, 0xA5E1}, {0x511F, 0x511F, 0xA5E2}, + {0x5120, 0x5120, 0xA5E3}, {0x5121, 0x5121, 0xA5E4}, {0x5122, 0x5122, 0xA5E5}, {0x5123, 0x5123, 0xA5E6}, + {0x5124, 0x5124, 0xA5E7}, {0x5125, 0x5125, 0xA5E8}, {0x5126, 0x5126, 0xA5E9}, {0x5127, 0x5127, 0xA5EA}, + {0x5128, 0x5128, 0xA5EB}, {0x5129, 0x5129, 0xA5EC}, {0x512A, 0x512A, 0xA5ED}, {0x512B, 0x512B, 0xA5EE}, + {0x512C, 0x512C, 0xA5EF}, {0x512D, 0x512D, 0xA5F0}, {0x512E, 0x512E, 0xA5F1}, {0x512F, 0x512F, 0xA5F2}, + {0x5130, 0x5130, 0xA5F3}, {0x5131, 0x5131, 0xA5F4}, {0x5132, 0x5132, 0xA5F5}, {0x5133, 0x5133, 0xA5F6}, + {0x5134, 0x5134, 0xA5F7}, {0x5135, 0x5135, 0xA5F8}, {0x5136, 0x5136, 0xA5F9}, {0x5137, 0x5137, 0xA5FA}, + {0x5138, 0x5138, 0xA5FB}, {0x5139, 0x5139, 0xA5FC}, {0x513A, 0x513A, 0xA5FD}, {0x513B, 0x513B, 0xA5FE}, + {0x513C, 0x513C, 0xA5FF}, {0x513D, 0x513D, 0xA600}, {0x513E, 0x513E, 0xA601}, {0x513F, 0x513F, 0xA602}, + {0x5140, 0x5140, 0xA603}, {0x5141, 0x5141, 0xA604}, {0x5142, 0x5142, 0xA605}, {0x5143, 0x5143, 0xA606}, + {0x5144, 0x5144, 0xA607}, {0x5145, 0x5145, 0xA608}, {0x5146, 0x5146, 0xA609}, {0x5147, 0x5147, 0xA60A}, + {0x5148, 0x5148, 0xA60B}, {0x5149, 0x5149, 0xA60C}, {0x514A, 0x514A, 0xA60D}, {0x514B, 0x514B, 0xA60E}, + {0x514C, 0x514C, 0xA60F}, {0x514D, 0x514D, 0xA610}, {0x514E, 0x514E, 0xA611}, {0x514F, 0x514F, 0xA612}, + {0x5150, 0x5150, 0xA613}, {0x5151, 0x5151, 0xA614}, {0x5152, 0x5152, 0xA615}, {0x5153, 0x5153, 0xA616}, + {0x5154, 0x5154, 0xA617}, {0x5155, 0x5155, 0xA618}, {0x5156, 0x5156, 0xA619}, {0x5157, 0x5157, 0xA61A}, + {0x5158, 0x5158, 0xA61B}, {0x5159, 0x5159, 0xA61C}, {0x515A, 0x515A, 0xA61D}, {0x515B, 0x515B, 0xA61E}, + {0x515C, 0x515C, 0xA61F}, {0x515D, 0x515D, 0xA620}, {0x515E, 0x515E, 0xA621}, {0x515F, 0x515F, 0xA622}, + {0x5160, 0x5160, 0xA623}, {0x5161, 0x5161, 0xA624}, {0x5162, 0x5162, 0xA625}, {0x5163, 0x5163, 0xA626}, + {0x5164, 0x5164, 0xA627}, {0x5165, 0x5165, 0xA628}, {0x5166, 0x5166, 0xA629}, {0x5167, 0x5167, 0xA62A}, + {0x5168, 0x5168, 0xA62B}, {0x5169, 0x5169, 0xA62C}, {0x516A, 0x516A, 0xA62D}, {0x516B, 0x516B, 0xA62E}, + {0x516C, 0x516C, 0xA62F}, {0x516D, 0x516D, 0xA630}, {0x516E, 0x516E, 0xA631}, {0x516F, 0x516F, 0xA632}, + {0x5170, 0x5170, 0xA633}, {0x5171, 0x5171, 0xA634}, {0x5172, 0x5172, 0xA635}, {0x5173, 0x5173, 0xA636}, + {0x5174, 0x5174, 0xA637}, {0x5175, 0x5175, 0xA638}, {0x5176, 0x5176, 0xA639}, {0x5177, 0x5177, 0xA63A}, + {0x5178, 0x5178, 0xA63B}, {0x5179, 0x5179, 0xA63C}, {0x517A, 0x517A, 0xA63D}, {0x517B, 0x517B, 0xA63E}, + {0x517C, 0x517C, 0xA63F}, {0x517D, 0x517E, 0xA640}, {0x517D, 0x517E, 0xA640}, {0x517F, 0x5180, 0xA642}, + {0x517F, 0x5180, 0xA642}, {0x5181, 0x5182, 0xA644}, {0x5181, 0x5182, 0xA644}, {0x5183, 0x5184, 0xA646}, + {0x5183, 0x5184, 0xA646}, {0x5185, 0x5186, 0xA648}, {0x5185, 0x5186, 0xA648}, {0x5187, 0x5188, 0xA64A}, + {0x5187, 0x5188, 0xA64A}, {0x5189, 0x518A, 0xA64C}, {0x5189, 0x518A, 0xA64C}, {0x518B, 0x518C, 0xA64E}, + {0x518B, 0x518C, 0xA64E}, {0x518D, 0x518E, 0xA650}, {0x518D, 0x518E, 0xA650}, {0x518F, 0x5190, 0xA652}, + {0x518F, 0x5190, 0xA652}, {0x5191, 0x5192, 0xA654}, {0x5191, 0x5192, 0xA654}, {0x5193, 0x5194, 0xA656}, + {0x5193, 0x5194, 0xA656}, {0x5195, 0x5196, 0xA658}, {0x5195, 0x5196, 0xA658}, {0x5197, 0x5198, 0xA65A}, + {0x5197, 0x5198, 0xA65A}, {0x5199, 0x519A, 0xA65C}, {0x5199, 0x519A, 0xA65C}, {0x519B, 0x519C, 0xA65E}, + {0x519B, 0x519C, 0xA65E}, {0x519D, 0x519D, 0xA660}, {0x519E, 0x519E, 0xA661}, {0x519F, 0x51A0, 0xA662}, + {0x519F, 0x51A0, 0xA662}, {0x51A1, 0x51A2, 0xA664}, {0x51A1, 0x51A2, 0xA664}, {0x51A3, 0x51A4, 0xA666}, + {0x51A3, 0x51A4, 0xA666}, {0x51A5, 0x51A6, 0xA668}, {0x51A5, 0x51A6, 0xA668}, {0x51A7, 0x51A8, 0xA66A}, + {0x51A7, 0x51A8, 0xA66A}, {0x51A9, 0x51AA, 0xA66C}, {0x51A9, 0x51AA, 0xA66C}, {0x51AB, 0x51AB, 0xA66E}, + {0x51AC, 0x51AC, 0xA66F}, {0x51AD, 0x51AD, 0xA670}, {0x51AE, 0x51AE, 0xA671}, {0x51AF, 0x51AF, 0xA672}, + {0x51B0, 0x51B0, 0xA673}, {0x51B1, 0x51B1, 0xA674}, {0x51B2, 0x51B2, 0xA675}, {0x51B3, 0x51B3, 0xA676}, + {0x51B4, 0x51B4, 0xA677}, {0x51B5, 0x51B5, 0xA678}, {0x51B6, 0x51B6, 0xA679}, {0x51B7, 0x51B7, 0xA67A}, + {0x51B8, 0x51B8, 0xA67B}, {0x51B9, 0x51B9, 0xA67C}, {0x51BA, 0x51BA, 0xA67D}, {0x51BB, 0x51BB, 0xA67E}, + {0x51BC, 0x51BC, 0xA67F}, {0x51BD, 0x51BE, 0xA680}, {0x51BD, 0x51BE, 0xA680}, {0x51BF, 0x51C0, 0xA682}, + {0x51BF, 0x51C0, 0xA682}, {0x51C1, 0x51C2, 0xA684}, {0x51C1, 0x51C2, 0xA684}, {0x51C3, 0x51C4, 0xA686}, + {0x51C3, 0x51C4, 0xA686}, {0x51C5, 0x51C6, 0xA688}, {0x51C5, 0x51C6, 0xA688}, {0x51C7, 0x51C8, 0xA68A}, + {0x51C7, 0x51C8, 0xA68A}, {0x51C9, 0x51CA, 0xA68C}, {0x51C9, 0x51CA, 0xA68C}, {0x51CB, 0x51CC, 0xA68E}, + {0x51CB, 0x51CC, 0xA68E}, {0x51CD, 0x51CE, 0xA690}, {0x51CD, 0x51CE, 0xA690}, {0x51CF, 0x51D0, 0xA692}, + {0x51CF, 0x51D0, 0xA692}, {0x51D1, 0x51D2, 0xA694}, {0x51D1, 0x51D2, 0xA694}, {0x51D3, 0x51D4, 0xA696}, + {0x51D3, 0x51D4, 0xA696}, {0x51D5, 0x51D5, 0xA698}, {0x51D6, 0x51D6, 0xA699}, {0x51D7, 0x51D7, 0xA69A}, + {0x51D8, 0x51D8, 0xA69B}, {0x51D9, 0x51D9, 0xA69C}, {0x51DA, 0x51DA, 0xA69D}, {0x51DB, 0x51DB, 0xA69E}, + {0x51DC, 0x51DC, 0xA69F}, {0x51DD, 0x51DD, 0xA6A0}, {0x51DE, 0x51DE, 0xA6A1}, {0x51DF, 0x51DF, 0xA6A2}, + {0x51E0, 0x51E0, 0xA6A3}, {0x51E1, 0x51E1, 0xA6A4}, {0x51E2, 0x51E2, 0xA6A5}, {0x51E3, 0x51E3, 0xA6A6}, + {0x51E4, 0x51E4, 0xA6A7}, {0x51E5, 0x51E5, 0xA6A8}, {0x51E6, 0x51E6, 0xA6A9}, {0x51E7, 0x51E7, 0xA6AA}, + {0x51E8, 0x51E8, 0xA6AB}, {0x51E9, 0x51E9, 0xA6AC}, {0x51EA, 0x51EA, 0xA6AD}, {0x51EB, 0x51EB, 0xA6AE}, + {0x51EC, 0x51EC, 0xA6AF}, {0x51ED, 0x51ED, 0xA6B0}, {0x51EE, 0x51EE, 0xA6B1}, {0x51EF, 0x51EF, 0xA6B2}, + {0x51F0, 0x51F0, 0xA6B3}, {0x51F1, 0x51F1, 0xA6B4}, {0x51F2, 0x51F2, 0xA6B5}, {0x51F3, 0x51F3, 0xA6B6}, + {0x51F4, 0x51F4, 0xA6B7}, {0x51F5, 0x51F5, 0xA6B8}, {0x51F6, 0x51F6, 0xA6B9}, {0x51F7, 0x51F7, 0xA6BA}, + {0x51F8, 0x51F8, 0xA6BB}, {0x51F9, 0x51F9, 0xA6BC}, {0x51FA, 0x51FA, 0xA6BD}, {0x51FB, 0x51FB, 0xA6BE}, + {0x51FC, 0x51FC, 0xA6BF}, {0x51FD, 0x51FD, 0xA6C0}, {0x51FE, 0x51FE, 0xA6C1}, {0x51FF, 0x51FF, 0xA6C2} +}; + +static GS_UNICASE_CHARACTER plane52[] = { + {0x5200, 0x5200, 0xA6C3}, {0x5201, 0x5201, 0xA6C4}, {0x5202, 0x5202, 0xA6C5}, {0x5203, 0x5203, 0xA6C6}, + {0x5204, 0x5204, 0xA6C7}, {0x5205, 0x5205, 0xA6C8}, {0x5206, 0x5206, 0xA6C9}, {0x5207, 0x5207, 0xA6CA}, + {0x5208, 0x5208, 0xA6CB}, {0x5209, 0x5209, 0xA6CC}, {0x520A, 0x520A, 0xA6CD}, {0x520B, 0x520B, 0xA6CE}, + {0x520C, 0x520C, 0xA6CF}, {0x520D, 0x520D, 0xA6D0}, {0x520E, 0x520E, 0xA6D1}, {0x520F, 0x520F, 0xA6D2}, + {0x5210, 0x5210, 0xA6D3}, {0x5211, 0x5211, 0xA6D4}, {0x5212, 0x5212, 0xA6D5}, {0x5213, 0x5213, 0xA6D6}, + {0x5214, 0x5214, 0xA6D7}, {0x5215, 0x5215, 0xA6D8}, {0x5216, 0x5216, 0xA6D9}, {0x5217, 0x5217, 0xA6DA}, + {0x5218, 0x5218, 0xA6DB}, {0x5219, 0x5219, 0xA6DC}, {0x521A, 0x521A, 0xA6DD}, {0x521B, 0x521B, 0xA6DE}, + {0x521C, 0x521C, 0xA6DF}, {0x521D, 0x521D, 0xA6E0}, {0x521E, 0x521E, 0xA6E1}, {0x521F, 0x521F, 0xA6E2}, + {0x5220, 0x5220, 0xA6E3}, {0x5221, 0x5221, 0xA6E4}, {0x5222, 0x5222, 0xA6E5}, {0x5223, 0x5223, 0xA6E6}, + {0x5224, 0x5224, 0xA6E7}, {0x5225, 0x5225, 0xA6E8}, {0x5226, 0x5226, 0xA6E9}, {0x5227, 0x5227, 0xA6EA}, + {0x5228, 0x5228, 0xA6EB}, {0x5229, 0x5229, 0xA6EC}, {0x522A, 0x522A, 0xA6ED}, {0x522B, 0x522B, 0xA6EE}, + {0x522C, 0x522C, 0xA6EF}, {0x522D, 0x522D, 0xA6F0}, {0x522E, 0x522E, 0xA6F1}, {0x522F, 0x522F, 0xA6F2}, + {0x5230, 0x5230, 0xA6F3}, {0x5231, 0x5231, 0xA6F4}, {0x5232, 0x5232, 0xA6F5}, {0x5233, 0x5233, 0xA6F6}, + {0x5234, 0x5234, 0xA6F7}, {0x5235, 0x5235, 0xA6F8}, {0x5236, 0x5236, 0xA6F9}, {0x5237, 0x5237, 0xA6FA}, + {0x5238, 0x5238, 0xA6FB}, {0x5239, 0x5239, 0xA6FC}, {0x523A, 0x523A, 0xA6FD}, {0x523B, 0x523B, 0xA6FE}, + {0x523C, 0x523C, 0xA6FF}, {0x523D, 0x523D, 0xA700}, {0x523E, 0x523E, 0xA701}, {0x523F, 0x523F, 0xA702}, + {0x5240, 0x5240, 0xA703}, {0x5241, 0x5241, 0xA704}, {0x5242, 0x5242, 0xA705}, {0x5243, 0x5243, 0xA706}, + {0x5244, 0x5244, 0xA707}, {0x5245, 0x5245, 0xA708}, {0x5246, 0x5246, 0xA709}, {0x5247, 0x5247, 0xA70A}, + {0x5248, 0x5248, 0xA70B}, {0x5249, 0x5249, 0xA70C}, {0x524A, 0x524A, 0xA70D}, {0x524B, 0x524B, 0xA70E}, + {0x524C, 0x524C, 0xA70F}, {0x524D, 0x524D, 0xA710}, {0x524E, 0x524E, 0xA711}, {0x524F, 0x524F, 0xA712}, + {0x5250, 0x5250, 0xA713}, {0x5251, 0x5251, 0xA714}, {0x5252, 0x5252, 0xA715}, {0x5253, 0x5253, 0xA716}, + {0x5254, 0x5254, 0xA717}, {0x5255, 0x5255, 0xA718}, {0x5256, 0x5256, 0xA719}, {0x5257, 0x5257, 0xA71A}, + {0x5258, 0x5258, 0xA71B}, {0x5259, 0x5259, 0xA71C}, {0x525A, 0x525A, 0xA71D}, {0x525B, 0x525B, 0xA71E}, + {0x525C, 0x525C, 0xA71F}, {0x525D, 0x525D, 0xA720}, {0x525E, 0x525E, 0xA721}, {0x525F, 0x5260, 0xA722}, + {0x525F, 0x5260, 0xA722}, {0x5261, 0x5262, 0xA724}, {0x5261, 0x5262, 0xA724}, {0x5263, 0x5264, 0xA726}, + {0x5263, 0x5264, 0xA726}, {0x5265, 0x5266, 0xA728}, {0x5265, 0x5266, 0xA728}, {0x5267, 0x5268, 0xA72A}, + {0x5267, 0x5268, 0xA72A}, {0x5269, 0x526A, 0xA72C}, {0x5269, 0x526A, 0xA72C}, {0x526B, 0x526C, 0xA72E}, + {0x526B, 0x526C, 0xA72E}, {0x526D, 0x526D, 0xA730}, {0x526E, 0x526E, 0xA731}, {0x526F, 0x5270, 0xA732}, + {0x526F, 0x5270, 0xA732}, {0x5271, 0x5272, 0xA734}, {0x5271, 0x5272, 0xA734}, {0x5273, 0x5274, 0xA736}, + {0x5273, 0x5274, 0xA736}, {0x5275, 0x5276, 0xA738}, {0x5275, 0x5276, 0xA738}, {0x5277, 0x5278, 0xA73A}, + {0x5277, 0x5278, 0xA73A}, {0x5279, 0x527A, 0xA73C}, {0x5279, 0x527A, 0xA73C}, {0x527B, 0x527C, 0xA73E}, + {0x527B, 0x527C, 0xA73E}, {0x527D, 0x527E, 0xA740}, {0x527D, 0x527E, 0xA740}, {0x527F, 0x5280, 0xA742}, + {0x527F, 0x5280, 0xA742}, {0x5281, 0x5282, 0xA744}, {0x5281, 0x5282, 0xA744}, {0x5283, 0x5284, 0xA746}, + {0x5283, 0x5284, 0xA746}, {0x5285, 0x5286, 0xA748}, {0x5285, 0x5286, 0xA748}, {0x5287, 0x5288, 0xA74A}, + {0x5287, 0x5288, 0xA74A}, {0x5289, 0x528A, 0xA74C}, {0x5289, 0x528A, 0xA74C}, {0x528B, 0x528C, 0xA74E}, + {0x528B, 0x528C, 0xA74E}, {0x528D, 0x528E, 0xA750}, {0x528D, 0x528E, 0xA750}, {0x528F, 0x5290, 0xA752}, + {0x528F, 0x5290, 0xA752}, {0x5291, 0x5292, 0xA754}, {0x5291, 0x5292, 0xA754}, {0x5293, 0x5294, 0xA756}, + {0x5293, 0x5294, 0xA756}, {0x5295, 0x5296, 0xA758}, {0x5295, 0x5296, 0xA758}, {0x5297, 0x5298, 0xA75A}, + {0x5297, 0x5298, 0xA75A}, {0x5299, 0x529A, 0xA75C}, {0x5299, 0x529A, 0xA75C}, {0x529B, 0x529C, 0xA75E}, + {0x529B, 0x529C, 0xA75E}, {0x529D, 0x529E, 0xA760}, {0x529D, 0x529E, 0xA760}, {0x529F, 0x52A0, 0xA762}, + {0x529F, 0x52A0, 0xA762}, {0x52A1, 0x52A2, 0xA764}, {0x52A1, 0x52A2, 0xA764}, {0x52A3, 0x52A4, 0xA766}, + {0x52A3, 0x52A4, 0xA766}, {0x52A5, 0x52A6, 0xA768}, {0x52A5, 0x52A6, 0xA768}, {0x52A7, 0x52A8, 0xA76A}, + {0x52A7, 0x52A8, 0xA76A}, {0x52A9, 0x52AA, 0xA76C}, {0x52A9, 0x52AA, 0xA76C}, {0x52AB, 0x52AC, 0xA76E}, + {0x52AB, 0x52AC, 0xA76E}, {0x52AD, 0x52AD, 0xA770}, {0x52AE, 0x52AE, 0xA771}, {0x52AF, 0x52AF, 0xA772}, + {0x52B0, 0x52B0, 0xA773}, {0x52B1, 0x52B1, 0xA774}, {0x52B2, 0x52B2, 0xA775}, {0x52B3, 0x52B3, 0xA776}, + {0x52B4, 0x52B4, 0xA777}, {0x52B5, 0x52B5, 0xA778}, {0x52B6, 0x52B7, 0xA779}, {0x52B6, 0x52B7, 0xA779}, + {0x52B8, 0x52B9, 0xA77B}, {0x52B8, 0x52B9, 0xA77B}, {0x52BA, 0x1CDB, 0xA77D}, {0x52BB, 0x52BC, 0xA77E}, + {0x52BB, 0x52BC, 0xA77E}, {0x52BD, 0x52BE, 0xA780}, {0x52BD, 0x52BE, 0xA780}, {0x52BF, 0x52C0, 0xA782}, + {0x52BF, 0x52C0, 0xA782}, {0x52C1, 0x52C2, 0xA784}, {0x52C1, 0x52C2, 0xA784}, {0x52C3, 0x52C4, 0xA786}, + {0x52C3, 0x52C4, 0xA786}, {0x52C5, 0x52C5, 0xA788}, {0x52C6, 0x52C6, 0xA789}, {0x52C7, 0x52C7, 0xA78A}, + {0x52C8, 0x52C9, 0xA78B}, {0x52C8, 0x52C9, 0xA78B}, {0x52CA, 0x52CA, 0xA78D}, {0x52CB, 0x52CB, 0xA78E}, + {0x52CC, 0x52CC, 0xA78F}, {0x52CD, 0x52CD, 0xA790}, {0x52CE, 0x52CE, 0xA791}, {0x52CF, 0x52CF, 0xA792}, + {0x52D0, 0x52D0, 0xA793}, {0x52D1, 0x52D1, 0xA794}, {0x52D2, 0x52D2, 0xA795}, {0x52D3, 0x52D3, 0xA796}, + {0x52D4, 0x52D4, 0xA797}, {0x52D5, 0x52D5, 0xA798}, {0x52D6, 0x52D6, 0xA799}, {0x52D7, 0x52D7, 0xA79A}, + {0x52D8, 0x52D8, 0xA79B}, {0x52D9, 0x52D9, 0xA79C}, {0x52DA, 0x52DA, 0xA79D}, {0x52DB, 0x52DB, 0xA79E}, + {0x52DC, 0x52DC, 0xA79F}, {0x52DD, 0x52DD, 0xA7A0}, {0x52DE, 0x52DE, 0xA7A1}, {0x52DF, 0x52DF, 0xA7A2}, + {0x52E0, 0x52E0, 0xA7A3}, {0x52E1, 0x52E1, 0xA7A4}, {0x52E2, 0x52E2, 0xA7A5}, {0x52E3, 0x52E3, 0xA7A6}, + {0x52E4, 0x52E4, 0xA7A7}, {0x52E5, 0x52E5, 0xA7A8}, {0x52E6, 0x52E6, 0xA7A9}, {0x52E7, 0x52E7, 0xA7AA}, + {0x52E8, 0x52E8, 0xA7AB}, {0x52E9, 0x52E9, 0xA7AC}, {0x52EA, 0x52EA, 0xA7AD}, {0x52EB, 0x52EB, 0xA7AE}, + {0x52EC, 0x52EC, 0xA7AF}, {0x52ED, 0x52ED, 0xA7B0}, {0x52EE, 0x52EE, 0xA7B1}, {0x52EF, 0x52EF, 0xA7B2}, + {0x52F0, 0x52F0, 0xA7B3}, {0x52F1, 0x52F1, 0xA7B4}, {0x52F2, 0x52F2, 0xA7B5}, {0x52F3, 0x52F3, 0xA7B6}, + {0x52F4, 0x52F4, 0xA7B7}, {0x52F5, 0x52F5, 0xA7B8}, {0x52F6, 0x52F6, 0xA7B9}, {0x52F7, 0x52F7, 0xA7BA}, + {0x52F8, 0x52F8, 0xA7BB}, {0x52F9, 0x52F9, 0xA7BC}, {0x52FA, 0x52FA, 0xA7BD}, {0x52FB, 0x52FB, 0xA7BE}, + {0x52FC, 0x52FC, 0xA7BF}, {0x52FD, 0x52FD, 0xA7C0}, {0x52FE, 0x52FE, 0xA7C1}, {0x52FF, 0x52FF, 0xA7C2} +}; + +static GS_UNICASE_CHARACTER planeA2[] = { + {0xA200, 0xA200, 0x003F}, {0xA201, 0xA201, 0x003F}, {0xA202, 0xA202, 0x003F}, {0xA203, 0xA203, 0x003F}, + {0xA204, 0xA204, 0x003F}, {0xA205, 0xA205, 0x003F}, {0xA206, 0xA206, 0x003F}, {0xA207, 0xA207, 0x003F}, + {0xA208, 0xA208, 0x003F}, {0xA209, 0xA209, 0x003F}, {0xA20A, 0xA20A, 0x003F}, {0xA20B, 0xA20B, 0x003F}, + {0xA20C, 0xA20C, 0x003F}, {0xA20D, 0xA20D, 0x003F}, {0xA20E, 0xA20E, 0x003F}, {0xA20F, 0xA20F, 0x003F}, + {0xA210, 0xA210, 0x003F}, {0xA211, 0xA211, 0x003F}, {0xA212, 0xA212, 0x003F}, {0xA213, 0xA213, 0x003F}, + {0xA214, 0xA214, 0x003F}, {0xA215, 0xA215, 0x003F}, {0xA216, 0xA216, 0x003F}, {0xA217, 0xA217, 0x003F}, + {0xA218, 0xA218, 0x003F}, {0xA219, 0xA219, 0x003F}, {0xA21A, 0xA21A, 0x003F}, {0xA21B, 0xA21B, 0x003F}, + {0xA21C, 0xA21C, 0x003F}, {0xA21D, 0xA21D, 0x003F}, {0xA21E, 0xA21E, 0x003F}, {0xA21F, 0xA21F, 0x003F}, + {0xA220, 0xA220, 0x003F}, {0xA221, 0xA221, 0x003F}, {0xA222, 0xA222, 0x003F}, {0xA223, 0xA223, 0x003F}, + {0xA224, 0xA224, 0x003F}, {0xA225, 0xA225, 0x003F}, {0xA226, 0xA226, 0x003F}, {0xA227, 0xA227, 0x003F}, + {0xA228, 0xA228, 0x003F}, {0xA229, 0xA229, 0x003F}, {0xA22A, 0xA22A, 0x003F}, {0xA22B, 0xA22B, 0x003F}, + {0xA22C, 0xA22C, 0x003F}, {0xA22D, 0xA22D, 0x003F}, {0xA22E, 0xA22E, 0x003F}, {0xA22F, 0xA22F, 0x003F}, + {0xA230, 0xA230, 0x003F}, {0xA231, 0xA231, 0x003F}, {0xA232, 0xA232, 0x003F}, {0xA233, 0xA233, 0x003F}, + {0xA234, 0xA234, 0x003F}, {0xA235, 0xA235, 0x003F}, {0xA236, 0xA236, 0x003F}, {0xA237, 0xA237, 0x003F}, + {0xA238, 0xA238, 0x003F}, {0xA239, 0xA239, 0x003F}, {0xA23A, 0xA23A, 0x003F}, {0xA23B, 0xA23B, 0x003F}, + {0xA23C, 0xA23C, 0x003F}, {0xA23D, 0xA23D, 0x003F}, {0xA23E, 0xA23E, 0x003F}, {0xA23F, 0xA23F, 0x003F}, + {0xA240, 0xA240, 0xE526}, {0xA241, 0xA241, 0xE527}, {0xA242, 0xA242, 0xE528}, {0xA243, 0xA243, 0xE529}, + {0xA244, 0xA244, 0xE52A}, {0xA245, 0xA245, 0xE52B}, {0xA246, 0xA246, 0xE52C}, {0xA247, 0xA247, 0xE52D}, + {0xA248, 0xA248, 0xE52E}, {0xA249, 0xA249, 0xE52F}, {0xA24A, 0xA24A, 0xE530}, {0xA24B, 0xA24B, 0xE531}, + {0xA24C, 0xA24C, 0xE532}, {0xA24D, 0xA24D, 0xE533}, {0xA24E, 0xA24E, 0xE534}, {0xA24F, 0xA24F, 0xE535}, + {0xA250, 0xA250, 0xE536}, {0xA251, 0xA251, 0xE537}, {0xA252, 0xA252, 0xE538}, {0xA253, 0xA253, 0xE539}, + {0xA254, 0xA254, 0xE53A}, {0xA255, 0xA255, 0xE53B}, {0xA256, 0xA256, 0xE53C}, {0xA257, 0xA257, 0xE53D}, + {0xA258, 0xA258, 0xE53E}, {0xA259, 0xA259, 0xE53F}, {0xA25A, 0xA25A, 0xE540}, {0xA25B, 0xA25B, 0xE541}, + {0xA25C, 0xA25C, 0xE542}, {0xA25D, 0xA25D, 0xE543}, {0xA25E, 0xA25E, 0xE544}, {0xA25F, 0xA25F, 0xE545}, + {0xA260, 0xA260, 0xE546}, {0xA261, 0xA261, 0xE547}, {0xA262, 0xA262, 0xE548}, {0xA263, 0xA263, 0xE549}, + {0xA264, 0xA264, 0xE54A}, {0xA265, 0xA265, 0xE54B}, {0xA266, 0xA266, 0xE54C}, {0xA267, 0xA267, 0xE54D}, + {0xA268, 0xA268, 0xE54E}, {0xA269, 0xA269, 0xE54F}, {0xA26A, 0xA26A, 0xE550}, {0xA26B, 0xA26B, 0xE551}, + {0xA26C, 0xA26C, 0xE552}, {0xA26D, 0xA26D, 0xE553}, {0xA26E, 0xA26E, 0xE554}, {0xA26F, 0xA26F, 0xE555}, + {0xA270, 0xA270, 0xE556}, {0xA271, 0xA271, 0xE557}, {0xA272, 0xA272, 0xE558}, {0xA273, 0xA273, 0xE559}, + {0xA274, 0xA274, 0xE55A}, {0xA275, 0xA275, 0xE55B}, {0xA276, 0xA276, 0xE55C}, {0xA277, 0xA277, 0xE55D}, + {0xA278, 0xA278, 0xE55E}, {0xA279, 0xA279, 0xE55F}, {0xA27A, 0xA27A, 0xE560}, {0xA27B, 0xA27B, 0xE561}, + {0xA27C, 0xA27C, 0xE562}, {0xA27D, 0xA27D, 0xE563}, {0xA27E, 0xA27E, 0xE564}, {0xA27F, 0xA27F, 0x003F}, + {0xA280, 0xA280, 0xE565}, {0xA281, 0xA281, 0xE566}, {0xA282, 0xA282, 0xE567}, {0xA283, 0xA283, 0xE568}, + {0xA284, 0xA284, 0xE569}, {0xA285, 0xA285, 0xE56A}, {0xA286, 0xA286, 0xE56B}, {0xA287, 0xA287, 0xE56C}, + {0xA288, 0xA288, 0xE56D}, {0xA289, 0xA289, 0xE56E}, {0xA28A, 0xA28A, 0xE56F}, {0xA28B, 0xA28B, 0xE570}, + {0xA28C, 0xA28C, 0xE571}, {0xA28D, 0xA28D, 0xE572}, {0xA28E, 0xA28E, 0xE573}, {0xA28F, 0xA28F, 0xE574}, + {0xA290, 0xA290, 0xE575}, {0xA291, 0xA291, 0xE576}, {0xA292, 0xA292, 0xE577}, {0xA293, 0xA293, 0xE578}, + {0xA294, 0xA294, 0xE579}, {0xA295, 0xA295, 0xE57A}, {0xA296, 0xA296, 0xE57B}, {0xA297, 0xA297, 0xE57C}, + {0xA298, 0xA298, 0xE57D}, {0xA299, 0xA299, 0xE57E}, {0xA29A, 0xA29A, 0xE57F}, {0xA29B, 0xA29B, 0xE580}, + {0xA29C, 0xA29C, 0xE581}, {0xA29D, 0xA29D, 0xE582}, {0xA29E, 0xA29E, 0xE583}, {0xA29F, 0xA29F, 0xE584}, + {0xA2A0, 0xA2A0, 0xE585}, {0xA2F1, 0xA2A1, 0x2160}, {0xA2F2, 0xA2A2, 0x2161}, {0xA2F3, 0xA2A3, 0x2162}, + {0xA2F4, 0xA2A4, 0x2163}, {0xA2F5, 0xA2A5, 0x2164}, {0xA2F6, 0xA2A6, 0x2165}, {0xA2F7, 0xA2A7, 0x2166}, + {0xA2F8, 0xA2A8, 0x2167}, {0xA2F9, 0xA2A9, 0x2168}, {0xA2FA, 0xA2AA, 0x2169}, {0xA2AB, 0xA2AB, 0xE766}, + {0xA2AC, 0xA2AC, 0xE767}, {0xA2AD, 0xA2AD, 0xE768}, {0xA2AE, 0xA2AE, 0xE769}, {0xA2AF, 0xA2AF, 0xE76A}, + {0xA2B0, 0xA2B0, 0xE76B}, {0xA2B1, 0xA2B1, 0x2488}, {0xA2B2, 0xA2B2, 0x2489}, {0xA2B3, 0xA2B3, 0x248A}, + {0xA2B4, 0xA2B4, 0x248B}, {0xA2B5, 0xA2B5, 0x248C}, {0xA2B6, 0xA2B6, 0x248D}, {0xA2B7, 0xA2B7, 0x248E}, + {0xA2B8, 0xA2B8, 0x248F}, {0xA2B9, 0xA2B9, 0x2490}, {0xA2BA, 0xA2BA, 0x2491}, {0xA2BB, 0xA2BB, 0x2492}, + {0xA2BC, 0xA2BC, 0x2493}, {0xA2BD, 0xA2BD, 0x2494}, {0xA2BE, 0xA2BE, 0x2495}, {0xA2BF, 0xA2BF, 0x2496}, + {0xA2C0, 0xA2C0, 0x2497}, {0xA2C1, 0xA2C1, 0x2498}, {0xA2C2, 0xA2C2, 0x2499}, {0xA2C3, 0xA2C3, 0x249A}, + {0xA2C4, 0xA2C4, 0x249B}, {0xA2C5, 0xA2C5, 0x2474}, {0xA2C6, 0xA2C6, 0x2475}, {0xA2C7, 0xA2C7, 0x2476}, + {0xA2C8, 0xA2C8, 0x2477}, {0xA2C9, 0xA2C9, 0x2478}, {0xA2CA, 0xA2CA, 0x2479}, {0xA2CB, 0xA2CB, 0x247A}, + {0xA2CC, 0xA2CC, 0x247B}, {0xA2CD, 0xA2CD, 0x247C}, {0xA2CE, 0xA2CE, 0x247D}, {0xA2CF, 0xA2CF, 0x247E}, + {0xA2D0, 0xA2D0, 0x247F}, {0xA2D1, 0xA2D1, 0x2480}, {0xA2D2, 0xA2D2, 0x2481}, {0xA2D3, 0xA2D3, 0x2482}, + {0xA2D4, 0xA2D4, 0x2483}, {0xA2D5, 0xA2D5, 0x2484}, {0xA2D6, 0xA2D6, 0x2485}, {0xA2D7, 0xA2D7, 0x2486}, + {0xA2D8, 0xA2D8, 0x2487}, {0xA2D9, 0xA2D9, 0x2460}, {0xA2DA, 0xA2DA, 0x2461}, {0xA2DB, 0xA2DB, 0x2462}, + {0xA2DC, 0xA2DC, 0x2463}, {0xA2DD, 0xA2DD, 0x2464}, {0xA2DE, 0xA2DE, 0x2465}, {0xA2DF, 0xA2DF, 0x2466}, + {0xA2E0, 0xA2E0, 0x2467}, {0xA2E1, 0xA2E1, 0x2468}, {0xA2E2, 0xA2E2, 0x2469}, {0xA2E3, 0xA2E3, 0x20AC}, + {0xA2E4, 0xA2E4, 0xE76D}, {0xA2E5, 0xA2E5, 0x3220}, {0xA2E6, 0xA2E6, 0x3221}, {0xA2E7, 0xA2E7, 0x3222}, + {0xA2E8, 0xA2E8, 0x3223}, {0xA2E9, 0xA2E9, 0x3224}, {0xA2EA, 0xA2EA, 0x3225}, {0xA2EB, 0xA2EB, 0x3226}, + {0xA2EC, 0xA2EC, 0x3227}, {0xA2ED, 0xA2ED, 0x3228}, {0xA2EE, 0xA2EE, 0x3229}, {0xA2EF, 0xA2EF, 0xE76E}, + {0xA2F0, 0xA2F0, 0xE76F}, {0xA2F1, 0xA2A1, 0x2160}, {0xA2F2, 0xA2A2, 0x2161}, {0xA2F3, 0xA2A3, 0x2162}, + {0xA2F4, 0xA2A4, 0x2163}, {0xA2F5, 0xA2A5, 0x2164}, {0xA2F6, 0xA2A6, 0x2165}, {0xA2F7, 0xA2A7, 0x2166}, + {0xA2F8, 0xA2A8, 0x2167}, {0xA2F9, 0xA2A9, 0x2168}, {0xA2FA, 0xA2AA, 0x2169}, {0xA2FB, 0x20B0, 0x216A}, + {0xA2FC, 0x20B1, 0x216B}, {0xA2FD, 0xA2FD, 0xE770}, {0xA2FE, 0xA2FE, 0xE771}, {0xA2FF, 0xA2FF, 0x003F} +}; + +static GS_UNICASE_CHARACTER planeA3[] = { + {0xA300, 0xA300, 0x003F}, {0xA301, 0xA301, 0x003F}, {0xA302, 0xA302, 0x003F}, {0xA303, 0xA303, 0x003F}, + {0xA304, 0xA304, 0x003F}, {0xA305, 0xA305, 0x003F}, {0xA306, 0xA306, 0x003F}, {0xA307, 0xA307, 0x003F}, + {0xA308, 0xA308, 0x003F}, {0xA309, 0xA309, 0x003F}, {0xA30A, 0xA30A, 0x003F}, {0xA30B, 0xA30B, 0x003F}, + {0xA30C, 0xA30C, 0x003F}, {0xA30D, 0xA30D, 0x003F}, {0xA30E, 0xA30E, 0x003F}, {0xA30F, 0xA30F, 0x003F}, + {0xA310, 0xA310, 0x003F}, {0xA311, 0xA311, 0x003F}, {0xA312, 0xA312, 0x003F}, {0xA313, 0xA313, 0x003F}, + {0xA314, 0xA314, 0x003F}, {0xA315, 0xA315, 0x003F}, {0xA316, 0xA316, 0x003F}, {0xA317, 0xA317, 0x003F}, + {0xA318, 0xA318, 0x003F}, {0xA319, 0xA319, 0x003F}, {0xA31A, 0xA31A, 0x003F}, {0xA31B, 0xA31B, 0x003F}, + {0xA31C, 0xA31C, 0x003F}, {0xA31D, 0xA31D, 0x003F}, {0xA31E, 0xA31E, 0x003F}, {0xA31F, 0xA31F, 0x003F}, + {0xA320, 0xA320, 0x003F}, {0xA321, 0xA321, 0x003F}, {0xA322, 0xA322, 0x003F}, {0xA323, 0xA323, 0x003F}, + {0xA324, 0xA324, 0x003F}, {0xA325, 0xA325, 0x003F}, {0xA326, 0xA326, 0x003F}, {0xA327, 0xA327, 0x003F}, + {0xA328, 0xA328, 0x003F}, {0xA329, 0xA329, 0x003F}, {0xA32A, 0xA32A, 0x003F}, {0xA32B, 0xA32B, 0x003F}, + {0xA32C, 0xA32C, 0x003F}, {0xA32D, 0xA32D, 0x003F}, {0xA32E, 0xA32E, 0x003F}, {0xA32F, 0xA32F, 0x003F}, + {0xA330, 0xA330, 0x003F}, {0xA331, 0xA331, 0x003F}, {0xA332, 0xA332, 0x003F}, {0xA333, 0xA333, 0x003F}, + {0xA334, 0xA334, 0x003F}, {0xA335, 0xA335, 0x003F}, {0xA336, 0xA336, 0x003F}, {0xA337, 0xA337, 0x003F}, + {0xA338, 0xA338, 0x003F}, {0xA339, 0xA339, 0x003F}, {0xA33A, 0xA33A, 0x003F}, {0xA33B, 0xA33B, 0x003F}, + {0xA33C, 0xA33C, 0x003F}, {0xA33D, 0xA33D, 0x003F}, {0xA33E, 0xA33E, 0x003F}, {0xA33F, 0xA33F, 0x003F}, + {0xA340, 0xA340, 0xE586}, {0xA341, 0xA341, 0xE587}, {0xA342, 0xA342, 0xE588}, {0xA343, 0xA343, 0xE589}, + {0xA344, 0xA344, 0xE58A}, {0xA345, 0xA345, 0xE58B}, {0xA346, 0xA346, 0xE58C}, {0xA347, 0xA347, 0xE58D}, + {0xA348, 0xA348, 0xE58E}, {0xA349, 0xA349, 0xE58F}, {0xA34A, 0xA34A, 0xE590}, {0xA34B, 0xA34B, 0xE591}, + {0xA34C, 0xA34C, 0xE592}, {0xA34D, 0xA34D, 0xE593}, {0xA34E, 0xA34E, 0xE594}, {0xA34F, 0xA34F, 0xE595}, + {0xA350, 0xA350, 0xE596}, {0xA351, 0xA351, 0xE597}, {0xA352, 0xA352, 0xE598}, {0xA353, 0xA353, 0xE599}, + {0xA354, 0xA354, 0xE59A}, {0xA355, 0xA355, 0xE59B}, {0xA356, 0xA356, 0xE59C}, {0xA357, 0xA357, 0xE59D}, + {0xA358, 0xA358, 0xE59E}, {0xA359, 0xA359, 0xE59F}, {0xA35A, 0xA35A, 0xE5A0}, {0xA35B, 0xA35B, 0xE5A1}, + {0xA35C, 0xA35C, 0xE5A2}, {0xA35D, 0xA35D, 0xE5A3}, {0xA35E, 0xA35E, 0xE5A4}, {0xA35F, 0xA35F, 0xE5A5}, + {0xA360, 0xA360, 0xE5A6}, {0xA361, 0xA361, 0xE5A7}, {0xA362, 0xA362, 0xE5A8}, {0xA363, 0xA363, 0xE5A9}, + {0xA364, 0xA364, 0xE5AA}, {0xA365, 0xA365, 0xE5AB}, {0xA366, 0xA366, 0xE5AC}, {0xA367, 0xA367, 0xE5AD}, + {0xA368, 0xA368, 0xE5AE}, {0xA369, 0xA369, 0xE5AF}, {0xA36A, 0xA36A, 0xE5B0}, {0xA36B, 0xA36B, 0xE5B1}, + {0xA36C, 0xA36C, 0xE5B2}, {0xA36D, 0xA36D, 0xE5B3}, {0xA36E, 0xA36E, 0xE5B4}, {0xA36F, 0xA36F, 0xE5B5}, + {0xA370, 0xA370, 0xE5B6}, {0xA371, 0xA371, 0xE5B7}, {0xA372, 0xA372, 0xE5B8}, {0xA373, 0xA373, 0xE5B9}, + {0xA374, 0xA374, 0xE5BA}, {0xA375, 0xA375, 0xE5BB}, {0xA376, 0xA376, 0xE5BC}, {0xA377, 0xA377, 0xE5BD}, + {0xA378, 0xA378, 0xE5BE}, {0xA379, 0xA379, 0xE5BF}, {0xA37A, 0xA37A, 0xE5C0}, {0xA37B, 0xA37B, 0xE5C1}, + {0xA37C, 0xA37C, 0xE5C2}, {0xA37D, 0xA37D, 0xE5C3}, {0xA37E, 0xA37E, 0xE5C4}, {0xA37F, 0xA37F, 0x003F}, + {0xA380, 0xA380, 0xE5C5}, {0xA381, 0xA381, 0xE5C6}, {0xA382, 0xA382, 0xE5C7}, {0xA383, 0xA383, 0xE5C8}, + {0xA384, 0xA384, 0xE5C9}, {0xA385, 0xA385, 0xE5CA}, {0xA386, 0xA386, 0xE5CB}, {0xA387, 0xA387, 0xE5CC}, + {0xA388, 0xA388, 0xE5CD}, {0xA389, 0xA389, 0xE5CE}, {0xA38A, 0xA38A, 0xE5CF}, {0xA38B, 0xA38B, 0xE5D0}, + {0xA38C, 0xA38C, 0xE5D1}, {0xA38D, 0xA38D, 0xE5D2}, {0xA38E, 0xA38E, 0xE5D3}, {0xA38F, 0xA38F, 0xE5D4}, + {0xA390, 0xA390, 0xE5D5}, {0xA391, 0xA391, 0xE5D6}, {0xA392, 0xA392, 0xE5D7}, {0xA393, 0xA393, 0xE5D8}, + {0xA394, 0xA394, 0xE5D9}, {0xA395, 0xA395, 0xE5DA}, {0xA396, 0xA396, 0xE5DB}, {0xA397, 0xA397, 0xE5DC}, + {0xA398, 0xA398, 0xE5DD}, {0xA399, 0xA399, 0xE5DE}, {0xA39A, 0xA39A, 0xE5DF}, {0xA39B, 0xA39B, 0xE5E0}, + {0xA39C, 0xA39C, 0xE5E1}, {0xA39D, 0xA39D, 0xE5E2}, {0xA39E, 0xA39E, 0xE5E3}, {0xA39F, 0xA39F, 0xE5E4}, + {0xA3A0, 0xA3A0, 0xE5E5}, {0xA3A1, 0xA3A1, 0xFF01}, {0xA3A2, 0xA3A2, 0xFF02}, {0xA3A3, 0xA3A3, 0xFF03}, + {0xA3A4, 0xA3A4, 0xFFE5}, {0xA3A5, 0xA3A5, 0xFF05}, {0xA3A6, 0xA3A6, 0xFF06}, {0xA3A7, 0xA3A7, 0xFF07}, + {0xA3A8, 0xA3A8, 0xFF08}, {0xA3A9, 0xA3A9, 0xFF09}, {0xA3AA, 0xA3AA, 0xFF0A}, {0xA3AB, 0xA3AB, 0xFF0B}, + {0xA3AC, 0xA3AC, 0xFF0C}, {0xA3AD, 0xA3AD, 0xFF0D}, {0xA3AE, 0xA3AE, 0xFF0E}, {0xA3AF, 0xA3AF, 0xFF0F}, + {0xA3B0, 0xA3B0, 0xFF10}, {0xA3B1, 0xA3B1, 0xFF11}, {0xA3B2, 0xA3B2, 0xFF12}, {0xA3B3, 0xA3B3, 0xFF13}, + {0xA3B4, 0xA3B4, 0xFF14}, {0xA3B5, 0xA3B5, 0xFF15}, {0xA3B6, 0xA3B6, 0xFF16}, {0xA3B7, 0xA3B7, 0xFF17}, + {0xA3B8, 0xA3B8, 0xFF18}, {0xA3B9, 0xA3B9, 0xFF19}, {0xA3BA, 0xA3BA, 0xFF1A}, {0xA3BB, 0xA3BB, 0xFF1B}, + {0xA3BC, 0xA3BC, 0xFF1C}, {0xA3BD, 0xA3BD, 0xFF1D}, {0xA3BE, 0xA3BE, 0xFF1E}, {0xA3BF, 0xA3BF, 0xFF1F}, + {0xA3C0, 0xA3C0, 0xFF20}, {0xA3C1, 0xA3E1, 0xFF21}, {0xA3C2, 0xA3E2, 0xFF22}, {0xA3C3, 0xA3E3, 0xFF23}, + {0xA3C4, 0xA3E4, 0xFF24}, {0xA3C5, 0xA3E5, 0xFF25}, {0xA3C6, 0xA3E6, 0xFF26}, {0xA3C7, 0xA3E7, 0xFF27}, + {0xA3C8, 0xA3E8, 0xFF28}, {0xA3C9, 0xA3E9, 0xFF29}, {0xA3CA, 0xA3EA, 0xFF2A}, {0xA3CB, 0xA3EB, 0xFF2B}, + {0xA3CC, 0xA3EC, 0xFF2C}, {0xA3CD, 0xA3ED, 0xFF2D}, {0xA3CE, 0xA3EE, 0xFF2E}, {0xA3CF, 0xA3EF, 0xFF2F}, + {0xA3D0, 0xA3F0, 0xFF30}, {0xA3D1, 0xA3F1, 0xFF31}, {0xA3D2, 0xA3F2, 0xFF32}, {0xA3D3, 0xA3F3, 0xFF33}, + {0xA3D4, 0xA3F4, 0xFF34}, {0xA3D5, 0xA3F5, 0xFF35}, {0xA3D6, 0xA3F6, 0xFF36}, {0xA3D7, 0xA3F7, 0xFF37}, + {0xA3D8, 0xA3F8, 0xFF38}, {0xA3D9, 0xA3F9, 0xFF39}, {0xA3DA, 0xA3FA, 0xFF3A}, {0xA3DB, 0xA3DB, 0xFF3B}, + {0xA3DC, 0xA3DC, 0xFF3C}, {0xA3DD, 0xA3DD, 0xFF3D}, {0xA3DE, 0xA3DE, 0xFF3E}, {0xA3DF, 0xA3DF, 0xFF3F}, + {0xA3E0, 0xA3E0, 0xFF40}, {0xA3C1, 0xA3E1, 0xFF21}, {0xA3C2, 0xA3E2, 0xFF22}, {0xA3C3, 0xA3E3, 0xFF23}, + {0xA3C4, 0xA3E4, 0xFF24}, {0xA3C5, 0xA3E5, 0xFF25}, {0xA3C6, 0xA3E6, 0xFF26}, {0xA3C7, 0xA3E7, 0xFF27}, + {0xA3C8, 0xA3E8, 0xFF28}, {0xA3C9, 0xA3E9, 0xFF29}, {0xA3CA, 0xA3EA, 0xFF2A}, {0xA3CB, 0xA3EB, 0xFF2B}, + {0xA3CC, 0xA3EC, 0xFF2C}, {0xA3CD, 0xA3ED, 0xFF2D}, {0xA3CE, 0xA3EE, 0xFF2E}, {0xA3CF, 0xA3EF, 0xFF2F}, + {0xA3D0, 0xA3F0, 0xFF30}, {0xA3D1, 0xA3F1, 0xFF31}, {0xA3D2, 0xA3F2, 0xFF32}, {0xA3D3, 0xA3F3, 0xFF33}, + {0xA3D4, 0xA3F4, 0xFF34}, {0xA3D5, 0xA3F5, 0xFF35}, {0xA3D6, 0xA3F6, 0xFF36}, {0xA3D7, 0xA3F7, 0xFF37}, + {0xA3D8, 0xA3F8, 0xFF38}, {0xA3D9, 0xA3F9, 0xFF39}, {0xA3DA, 0xA3FA, 0xFF3A}, {0xA3FB, 0xA3FB, 0xFF5B}, + {0xA3FC, 0xA3FC, 0xFF5C}, {0xA3FD, 0xA3FD, 0xFF5D}, {0xA3FE, 0xA3FE, 0xFFE3}, {0xA3FF, 0xA3FF, 0x003F} +}; + +static GS_UNICASE_CHARACTER planeA6[] = { + {0xA600, 0xA600, 0x003F}, {0xA601, 0xA601, 0x003F}, {0xA602, 0xA602, 0x003F}, {0xA603, 0xA603, 0x003F}, + {0xA604, 0xA604, 0x003F}, {0xA605, 0xA605, 0x003F}, {0xA606, 0xA606, 0x003F}, {0xA607, 0xA607, 0x003F}, + {0xA608, 0xA608, 0x003F}, {0xA609, 0xA609, 0x003F}, {0xA60A, 0xA60A, 0x003F}, {0xA60B, 0xA60B, 0x003F}, + {0xA60C, 0xA60C, 0x003F}, {0xA60D, 0xA60D, 0x003F}, {0xA60E, 0xA60E, 0x003F}, {0xA60F, 0xA60F, 0x003F}, + {0xA610, 0xA610, 0x003F}, {0xA611, 0xA611, 0x003F}, {0xA612, 0xA612, 0x003F}, {0xA613, 0xA613, 0x003F}, + {0xA614, 0xA614, 0x003F}, {0xA615, 0xA615, 0x003F}, {0xA616, 0xA616, 0x003F}, {0xA617, 0xA617, 0x003F}, + {0xA618, 0xA618, 0x003F}, {0xA619, 0xA619, 0x003F}, {0xA61A, 0xA61A, 0x003F}, {0xA61B, 0xA61B, 0x003F}, + {0xA61C, 0xA61C, 0x003F}, {0xA61D, 0xA61D, 0x003F}, {0xA61E, 0xA61E, 0x003F}, {0xA61F, 0xA61F, 0x003F}, + {0xA620, 0xA620, 0x003F}, {0xA621, 0xA621, 0x003F}, {0xA622, 0xA622, 0x003F}, {0xA623, 0xA623, 0x003F}, + {0xA624, 0xA624, 0x003F}, {0xA625, 0xA625, 0x003F}, {0xA626, 0xA626, 0x003F}, {0xA627, 0xA627, 0x003F}, + {0xA628, 0xA628, 0x003F}, {0xA629, 0xA629, 0x003F}, {0xA62A, 0xA62A, 0x003F}, {0xA62B, 0xA62B, 0x003F}, + {0xA62C, 0xA62C, 0x003F}, {0xA62D, 0xA62D, 0x003F}, {0xA62E, 0xA62E, 0x003F}, {0xA62F, 0xA62F, 0x003F}, + {0xA630, 0xA630, 0x003F}, {0xA631, 0xA631, 0x003F}, {0xA632, 0xA632, 0x003F}, {0xA633, 0xA633, 0x003F}, + {0xA634, 0xA634, 0x003F}, {0xA635, 0xA635, 0x003F}, {0xA636, 0xA636, 0x003F}, {0xA637, 0xA637, 0x003F}, + {0xA638, 0xA638, 0x003F}, {0xA639, 0xA639, 0x003F}, {0xA63A, 0xA63A, 0x003F}, {0xA63B, 0xA63B, 0x003F}, + {0xA63C, 0xA63C, 0x003F}, {0xA63D, 0xA63D, 0x003F}, {0xA63E, 0xA63E, 0x003F}, {0xA63F, 0xA63F, 0x003F}, + {0xA640, 0xA640, 0xE6A6}, {0xA641, 0xA641, 0xE6A7}, {0xA642, 0xA642, 0xE6A8}, {0xA643, 0xA643, 0xE6A9}, + {0xA644, 0xA644, 0xE6AA}, {0xA645, 0xA645, 0xE6AB}, {0xA646, 0xA646, 0xE6AC}, {0xA647, 0xA647, 0xE6AD}, + {0xA648, 0xA648, 0xE6AE}, {0xA649, 0xA649, 0xE6AF}, {0xA64A, 0xA64A, 0xE6B0}, {0xA64B, 0xA64B, 0xE6B1}, + {0xA64C, 0xA64C, 0xE6B2}, {0xA64D, 0xA64D, 0xE6B3}, {0xA64E, 0xA64E, 0xE6B4}, {0xA64F, 0xA64F, 0xE6B5}, + {0xA650, 0xA650, 0xE6B6}, {0xA651, 0xA651, 0xE6B7}, {0xA652, 0xA652, 0xE6B8}, {0xA653, 0xA653, 0xE6B9}, + {0xA654, 0xA654, 0xE6BA}, {0xA655, 0xA655, 0xE6BB}, {0xA656, 0xA656, 0xE6BC}, {0xA657, 0xA657, 0xE6BD}, + {0xA658, 0xA658, 0xE6BE}, {0xA659, 0xA659, 0xE6BF}, {0xA65A, 0xA65A, 0xE6C0}, {0xA65B, 0xA65B, 0xE6C1}, + {0xA65C, 0xA65C, 0xE6C2}, {0xA65D, 0xA65D, 0xE6C3}, {0xA65E, 0xA65E, 0xE6C4}, {0xA65F, 0xA65F, 0xE6C5}, + {0xA660, 0xA660, 0xE6C6}, {0xA661, 0xA661, 0xE6C7}, {0xA662, 0xA662, 0xE6C8}, {0xA663, 0xA663, 0xE6C9}, + {0xA664, 0xA664, 0xE6CA}, {0xA665, 0xA665, 0xE6CB}, {0xA666, 0xA666, 0xE6CC}, {0xA667, 0xA667, 0xE6CD}, + {0xA668, 0xA668, 0xE6CE}, {0xA669, 0xA669, 0xE6CF}, {0xA66A, 0xA66A, 0xE6D0}, {0xA66B, 0xA66B, 0xE6D1}, + {0xA66C, 0xA66C, 0xE6D2}, {0xA66D, 0xA66D, 0xE6D3}, {0xA66E, 0xA66E, 0xE6D4}, {0xA66F, 0xA66F, 0xE6D5}, + {0xA670, 0xA670, 0xE6D6}, {0xA671, 0xA671, 0xE6D7}, {0xA672, 0xA672, 0xE6D8}, {0xA673, 0xA673, 0xE6D9}, + {0xA674, 0xA674, 0xE6DA}, {0xA675, 0xA675, 0xE6DB}, {0xA676, 0xA676, 0xE6DC}, {0xA677, 0xA677, 0xE6DD}, + {0xA678, 0xA678, 0xE6DE}, {0xA679, 0xA679, 0xE6DF}, {0xA67A, 0xA67A, 0xE6E0}, {0xA67B, 0xA67B, 0xE6E1}, + {0xA67C, 0xA67C, 0xE6E2}, {0xA67D, 0xA67D, 0xE6E3}, {0xA67E, 0xA67E, 0xE6E4}, {0xA67F, 0xA67F, 0x003F}, + {0xA680, 0xA680, 0xE6E5}, {0xA681, 0xA681, 0xE6E6}, {0xA682, 0xA682, 0xE6E7}, {0xA683, 0xA683, 0xE6E8}, + {0xA684, 0xA684, 0xE6E9}, {0xA685, 0xA685, 0xE6EA}, {0xA686, 0xA686, 0xE6EB}, {0xA687, 0xA687, 0xE6EC}, + {0xA688, 0xA688, 0xE6ED}, {0xA689, 0xA689, 0xE6EE}, {0xA68A, 0xA68A, 0xE6EF}, {0xA68B, 0xA68B, 0xE6F0}, + {0xA68C, 0xA68C, 0xE6F1}, {0xA68D, 0xA68D, 0xE6F2}, {0xA68E, 0xA68E, 0xE6F3}, {0xA68F, 0xA68F, 0xE6F4}, + {0xA690, 0xA690, 0xE6F5}, {0xA691, 0xA691, 0xE6F6}, {0xA692, 0xA692, 0xE6F7}, {0xA693, 0xA693, 0xE6F8}, + {0xA694, 0xA694, 0xE6F9}, {0xA695, 0xA695, 0xE6FA}, {0xA696, 0xA696, 0xE6FB}, {0xA697, 0xA697, 0xE6FC}, + {0xA698, 0xA698, 0xE6FD}, {0xA699, 0xA699, 0xE6FE}, {0xA69A, 0xA69A, 0xE6FF}, {0xA69B, 0xA69B, 0xE700}, + {0xA69C, 0xA69C, 0xE701}, {0xA69D, 0xA69D, 0xE702}, {0xA69E, 0xA69E, 0xE703}, {0xA69F, 0xA69F, 0xE704}, + {0xA6A0, 0xA6A0, 0xE705}, {0xA6A1, 0xA6C1, 0x0391}, {0xA6A2, 0xA6C2, 0x0392}, {0xA6A3, 0xA6C3, 0x0393}, + {0xA6A4, 0xA6C4, 0x0394}, {0xA6A5, 0xA6C5, 0x0395}, {0xA6A6, 0xA6C6, 0x0396}, {0xA6A7, 0xA6C7, 0x0397}, + {0xA6A8, 0xA6C8, 0x0398}, {0xA6A9, 0xA6C9, 0x0399}, {0xA6AA, 0xA6CA, 0x039A}, {0xA6AB, 0xA6CB, 0x039B}, + {0xA6AC, 0xA6CC, 0x039C}, {0xA6AD, 0xA6CD, 0x039D}, {0xA6AE, 0xA6CE, 0x039E}, {0xA6AF, 0xA6CF, 0x039F}, + {0xA6B0, 0xA6D0, 0x03A0}, {0xA6B1, 0xA6D1, 0x03A1}, {0xA6B2, 0xA6D2, 0x03A3}, {0xA6B3, 0xA6D3, 0x03A4}, + {0xA6B4, 0xA6D4, 0x03A5}, {0xA6B5, 0xA6D5, 0x03A6}, {0xA6B6, 0xA6D6, 0x03A7}, {0xA6B7, 0xA6D7, 0x03A8}, + {0xA6B8, 0xA6D8, 0x03A9}, {0xA6B9, 0xA6B9, 0xE785}, {0xA6BA, 0xA6BA, 0xE786}, {0xA6BB, 0xA6BB, 0xE787}, + {0xA6BC, 0xA6BC, 0xE788}, {0xA6BD, 0xA6BD, 0xE789}, {0xA6BE, 0xA6BE, 0xE78A}, {0xA6BF, 0xA6BF, 0xE78B}, + {0xA6C0, 0xA6C0, 0xE78C}, {0xA6A1, 0xA6C1, 0x0391}, {0xA6A2, 0xA6C2, 0x03D0}, {0xA6A3, 0xA6C3, 0x0393}, + {0xA6A4, 0xA6C4, 0x0394}, {0xA6A5, 0xA6C5, 0x03F5}, {0xA6A6, 0xA6C6, 0x0396}, {0xA6A7, 0xA6C7, 0x0397}, + {0xA6A8, 0xA6C8, 0x03D1}, {0xA6A9, 0xA6C9, 0x0345}, {0xA6AA, 0xA6CA, 0x03F0}, {0xA6AB, 0xA6CB, 0x039B}, + {0xA6AC, 0xA6CC, 0x00B5}, {0xA6AD, 0xA6CD, 0x039D}, {0xA6AE, 0xA6CE, 0x039E}, {0xA6AF, 0xA6CF, 0x039F}, + {0xA6B0, 0xA6D0, 0x03D6}, {0xA6B1, 0xA6D1, 0x03F1}, {0xA6B2, 0xA6D2, 0x03C2}, {0xA6B3, 0xA6D3, 0x03A4}, + {0xA6B4, 0xA6D4, 0x03A5}, {0xA6B5, 0xA6D5, 0x03D5}, {0xA6B6, 0xA6D6, 0x03A7}, {0xA6B7, 0xA6D7, 0x03A8}, + {0xA6B8, 0xA6D8, 0x2126}, {0xA6D9, 0xA6D9, 0xE78D}, {0xA6DA, 0xA6DA, 0xE78E}, {0xA6DB, 0xA6DB, 0xE78F}, + {0xA6DC, 0xA6DC, 0xE790}, {0xA6DD, 0xA6DD, 0xE791}, {0xA6DE, 0xA6DE, 0xE792}, {0xA6DF, 0xA6DF, 0xE793}, + {0xA6E0, 0xA6E0, 0xFE35}, {0xA6E1, 0xA6E1, 0xFE36}, {0xA6E2, 0xA6E2, 0xFE39}, {0xA6E3, 0xA6E3, 0xFE3A}, + {0xA6E4, 0xA6E4, 0xFE3F}, {0xA6E5, 0xA6E5, 0xFE40}, {0xA6E6, 0xA6E6, 0xFE3D}, {0xA6E7, 0xA6E7, 0xFE3E}, + {0xA6E8, 0xA6E8, 0xFE41}, {0xA6E9, 0xA6E9, 0xFE42}, {0xA6EA, 0xA6EA, 0xFE43}, {0xA6EB, 0xA6EB, 0xFE44}, + {0xA6EC, 0xA6EC, 0xE794}, {0xA6ED, 0xA6ED, 0xE795}, {0xA6EE, 0xA6EE, 0xFE3B}, {0xA6EF, 0xA6EF, 0xFE3C}, + {0xA6F0, 0xA6F0, 0xFE37}, {0xA6F1, 0xA6F1, 0xFE38}, {0xA6F2, 0xA6F2, 0xFE31}, {0xA6F3, 0xA6F3, 0xE796}, + {0xA6F4, 0xA6F4, 0xFE33}, {0xA6F5, 0xA6F5, 0xFE34}, {0xA6F6, 0xA6F6, 0xE797}, {0xA6F7, 0xA6F7, 0xE798}, + {0xA6F8, 0xA6F8, 0xE799}, {0xA6F9, 0xA6F9, 0xE79A}, {0xA6FA, 0xA6FA, 0xE79B}, {0xA6FB, 0xA6FB, 0xE79C}, + {0xA6FC, 0xA6FC, 0xE79D}, {0xA6FD, 0xA6FD, 0xE79E}, {0xA6FE, 0xA6FE, 0xE79F}, {0xA6FF, 0xA6FF, 0x003F} +}; + +static GS_UNICASE_CHARACTER planeA7[] = { + {0xA700, 0xA700, 0x003F}, {0xA701, 0xA701, 0x003F}, {0xA702, 0xA702, 0x003F}, {0xA703, 0xA703, 0x003F}, + {0xA704, 0xA704, 0x003F}, {0xA705, 0xA705, 0x003F}, {0xA706, 0xA706, 0x003F}, {0xA707, 0xA707, 0x003F}, + {0xA708, 0xA708, 0x003F}, {0xA709, 0xA709, 0x003F}, {0xA70A, 0xA70A, 0x003F}, {0xA70B, 0xA70B, 0x003F}, + {0xA70C, 0xA70C, 0x003F}, {0xA70D, 0xA70D, 0x003F}, {0xA70E, 0xA70E, 0x003F}, {0xA70F, 0xA70F, 0x003F}, + {0xA710, 0xA710, 0x003F}, {0xA711, 0xA711, 0x003F}, {0xA712, 0xA712, 0x003F}, {0xA713, 0xA713, 0x003F}, + {0xA714, 0xA714, 0x003F}, {0xA715, 0xA715, 0x003F}, {0xA716, 0xA716, 0x003F}, {0xA717, 0xA717, 0x003F}, + {0xA718, 0xA718, 0x003F}, {0xA719, 0xA719, 0x003F}, {0xA71A, 0xA71A, 0x003F}, {0xA71B, 0xA71B, 0x003F}, + {0xA71C, 0xA71C, 0x003F}, {0xA71D, 0xA71D, 0x003F}, {0xA71E, 0xA71E, 0x003F}, {0xA71F, 0xA71F, 0x003F}, + {0xA720, 0xA720, 0x003F}, {0xA721, 0xA721, 0x003F}, {0xA722, 0xA722, 0x003F}, {0xA723, 0xA723, 0x003F}, + {0xA724, 0xA724, 0x003F}, {0xA725, 0xA725, 0x003F}, {0xA726, 0xA726, 0x003F}, {0xA727, 0xA727, 0x003F}, + {0xA728, 0xA728, 0x003F}, {0xA729, 0xA729, 0x003F}, {0xA72A, 0xA72A, 0x003F}, {0xA72B, 0xA72B, 0x003F}, + {0xA72C, 0xA72C, 0x003F}, {0xA72D, 0xA72D, 0x003F}, {0xA72E, 0xA72E, 0x003F}, {0xA72F, 0xA72F, 0x003F}, + {0xA730, 0xA730, 0x003F}, {0xA731, 0xA731, 0x003F}, {0xA732, 0xA732, 0x003F}, {0xA733, 0xA733, 0x003F}, + {0xA734, 0xA734, 0x003F}, {0xA735, 0xA735, 0x003F}, {0xA736, 0xA736, 0x003F}, {0xA737, 0xA737, 0x003F}, + {0xA738, 0xA738, 0x003F}, {0xA739, 0xA739, 0x003F}, {0xA73A, 0xA73A, 0x003F}, {0xA73B, 0xA73B, 0x003F}, + {0xA73C, 0xA73C, 0x003F}, {0xA73D, 0xA73D, 0x003F}, {0xA73E, 0xA73E, 0x003F}, {0xA73F, 0xA73F, 0x003F}, + {0xA740, 0xA740, 0xE706}, {0xA741, 0xA741, 0xE707}, {0xA742, 0xA742, 0xE708}, {0xA743, 0xA743, 0xE709}, + {0xA744, 0xA744, 0xE70A}, {0xA745, 0xA745, 0xE70B}, {0xA746, 0xA746, 0xE70C}, {0xA747, 0xA747, 0xE70D}, + {0xA748, 0xA748, 0xE70E}, {0xA749, 0xA749, 0xE70F}, {0xA74A, 0xA74A, 0xE710}, {0xA74B, 0xA74B, 0xE711}, + {0xA74C, 0xA74C, 0xE712}, {0xA74D, 0xA74D, 0xE713}, {0xA74E, 0xA74E, 0xE714}, {0xA74F, 0xA74F, 0xE715}, + {0xA750, 0xA750, 0xE716}, {0xA751, 0xA751, 0xE717}, {0xA752, 0xA752, 0xE718}, {0xA753, 0xA753, 0xE719}, + {0xA754, 0xA754, 0xE71A}, {0xA755, 0xA755, 0xE71B}, {0xA756, 0xA756, 0xE71C}, {0xA757, 0xA757, 0xE71D}, + {0xA758, 0xA758, 0xE71E}, {0xA759, 0xA759, 0xE71F}, {0xA75A, 0xA75A, 0xE720}, {0xA75B, 0xA75B, 0xE721}, + {0xA75C, 0xA75C, 0xE722}, {0xA75D, 0xA75D, 0xE723}, {0xA75E, 0xA75E, 0xE724}, {0xA75F, 0xA75F, 0xE725}, + {0xA760, 0xA760, 0xE726}, {0xA761, 0xA761, 0xE727}, {0xA762, 0xA762, 0xE728}, {0xA763, 0xA763, 0xE729}, + {0xA764, 0xA764, 0xE72A}, {0xA765, 0xA765, 0xE72B}, {0xA766, 0xA766, 0xE72C}, {0xA767, 0xA767, 0xE72D}, + {0xA768, 0xA768, 0xE72E}, {0xA769, 0xA769, 0xE72F}, {0xA76A, 0xA76A, 0xE730}, {0xA76B, 0xA76B, 0xE731}, + {0xA76C, 0xA76C, 0xE732}, {0xA76D, 0xA76D, 0xE733}, {0xA76E, 0xA76E, 0xE734}, {0xA76F, 0xA76F, 0xE735}, + {0xA770, 0xA770, 0xE736}, {0xA771, 0xA771, 0xE737}, {0xA772, 0xA772, 0xE738}, {0xA773, 0xA773, 0xE739}, + {0xA774, 0xA774, 0xE73A}, {0xA775, 0xA775, 0xE73B}, {0xA776, 0xA776, 0xE73C}, {0xA777, 0xA777, 0xE73D}, + {0xA778, 0xA778, 0xE73E}, {0xA779, 0xA779, 0xE73F}, {0xA77A, 0xA77A, 0xE740}, {0xA77B, 0xA77B, 0xE741}, + {0xA77C, 0xA77C, 0xE742}, {0xA77D, 0xA77D, 0xE743}, {0xA77E, 0xA77E, 0xE744}, {0xA77F, 0xA77F, 0x003F}, + {0xA780, 0xA780, 0xE745}, {0xA781, 0xA781, 0xE746}, {0xA782, 0xA782, 0xE747}, {0xA783, 0xA783, 0xE748}, + {0xA784, 0xA784, 0xE749}, {0xA785, 0xA785, 0xE74A}, {0xA786, 0xA786, 0xE74B}, {0xA787, 0xA787, 0xE74C}, + {0xA788, 0xA788, 0xE74D}, {0xA789, 0xA789, 0xE74E}, {0xA78A, 0xA78A, 0xE74F}, {0xA78B, 0xA78B, 0xE750}, + {0xA78C, 0xA78C, 0xE751}, {0xA78D, 0xA78D, 0xE752}, {0xA78E, 0xA78E, 0xE753}, {0xA78F, 0xA78F, 0xE754}, + {0xA790, 0xA790, 0xE755}, {0xA791, 0xA791, 0xE756}, {0xA792, 0xA792, 0xE757}, {0xA793, 0xA793, 0xE758}, + {0xA794, 0xA794, 0xE759}, {0xA795, 0xA795, 0xE75A}, {0xA796, 0xA796, 0xE75B}, {0xA797, 0xA797, 0xE75C}, + {0xA798, 0xA798, 0xE75D}, {0xA799, 0xA799, 0xE75E}, {0xA79A, 0xA79A, 0xE75F}, {0xA79B, 0xA79B, 0xE760}, + {0xA79C, 0xA79C, 0xE761}, {0xA79D, 0xA79D, 0xE762}, {0xA79E, 0xA79E, 0xE763}, {0xA79F, 0xA79F, 0xE764}, + {0xA7A0, 0xA7A0, 0xE765}, {0xA7A1, 0xA7D1, 0x0410}, {0xA7A2, 0xA7D2, 0x0411}, {0xA7A3, 0xA7D3, 0x0412}, + {0xA7A4, 0xA7D4, 0x0413}, {0xA7A5, 0xA7D5, 0x0414}, {0xA7A6, 0xA7D6, 0x0415}, {0xA7A7, 0xA7D7, 0x0401}, + {0xA7A8, 0xA7D8, 0x0416}, {0xA7A9, 0xA7D9, 0x0417}, {0xA7AA, 0xA7DA, 0x0418}, {0xA7AB, 0xA7DB, 0x0419}, + {0xA7AC, 0xA7DC, 0x041A}, {0xA7AD, 0xA7DD, 0x041B}, {0xA7AE, 0xA7DE, 0x041C}, {0xA7AF, 0xA7DF, 0x041D}, + {0xA7B0, 0xA7E0, 0x041E}, {0xA7B1, 0xA7E1, 0x041F}, {0xA7B2, 0xA7E2, 0x0420}, {0xA7B3, 0xA7E3, 0x0421}, + {0xA7B4, 0xA7E4, 0x0422}, {0xA7B5, 0xA7E5, 0x0423}, {0xA7B6, 0xA7E6, 0x0424}, {0xA7B7, 0xA7E7, 0x0425}, + {0xA7B8, 0xA7E8, 0x0426}, {0xA7B9, 0xA7E9, 0x0427}, {0xA7BA, 0xA7EA, 0x0428}, {0xA7BB, 0xA7EB, 0x0429}, + {0xA7BC, 0xA7EC, 0x042A}, {0xA7BD, 0xA7ED, 0x042B}, {0xA7BE, 0xA7EE, 0x042C}, {0xA7BF, 0xA7EF, 0x042D}, + {0xA7C0, 0xA7F0, 0x042E}, {0xA7C1, 0xA7F1, 0x042F}, {0xA7C2, 0xA7C2, 0xE7A0}, {0xA7C3, 0xA7C3, 0xE7A1}, + {0xA7C4, 0xA7C4, 0xE7A2}, {0xA7C5, 0xA7C5, 0xE7A3}, {0xA7C6, 0xA7C6, 0xE7A4}, {0xA7C7, 0xA7C7, 0xE7A5}, + {0xA7C8, 0xA7C8, 0xE7A6}, {0xA7C9, 0xA7C9, 0xE7A7}, {0xA7CA, 0xA7CA, 0xE7A8}, {0xA7CB, 0xA7CB, 0xE7A9}, + {0xA7CC, 0xA7CC, 0xE7AA}, {0xA7CD, 0xA7CD, 0xE7AB}, {0xA7CE, 0xA7CE, 0xE7AC}, {0xA7CF, 0xA7CF, 0xE7AD}, + {0xA7D0, 0xA7D0, 0xE7AE}, {0xA7A1, 0xA7D1, 0x0410}, {0xA7A2, 0xA7D2, 0x0411}, {0xA7A3, 0xA7D3, 0x0412}, + {0xA7A4, 0xA7D4, 0x0413}, {0xA7A5, 0xA7D5, 0x0414}, {0xA7A6, 0xA7D6, 0x0415}, {0xA7A7, 0xA7D7, 0x0401}, + {0xA7A8, 0xA7D8, 0x0416}, {0xA7A9, 0xA7D9, 0x0417}, {0xA7AA, 0xA7DA, 0x0418}, {0xA7AB, 0xA7DB, 0x0419}, + {0xA7AC, 0xA7DC, 0x041A}, {0xA7AD, 0xA7DD, 0x041B}, {0xA7AE, 0xA7DE, 0x041C}, {0xA7AF, 0xA7DF, 0x041D}, + {0xA7B0, 0xA7E0, 0x041E}, {0xA7B1, 0xA7E1, 0x041F}, {0xA7B2, 0xA7E2, 0x0420}, {0xA7B3, 0xA7E3, 0x0421}, + {0xA7B4, 0xA7E4, 0x0422}, {0xA7B5, 0xA7E5, 0x0423}, {0xA7B6, 0xA7E6, 0x0424}, {0xA7B7, 0xA7E7, 0x0425}, + {0xA7B8, 0xA7E8, 0x0426}, {0xA7B9, 0xA7E9, 0x0427}, {0xA7BA, 0xA7EA, 0x0428}, {0xA7BB, 0xA7EB, 0x0429}, + {0xA7BC, 0xA7EC, 0x042A}, {0xA7BD, 0xA7ED, 0x042B}, {0xA7BE, 0xA7EE, 0x042C}, {0xA7BF, 0xA7EF, 0x042D}, + {0xA7C0, 0xA7F0, 0x042E}, {0xA7C1, 0xA7F1, 0x042F}, {0xA7F2, 0xA7F2, 0xE7AF}, {0xA7F3, 0xA7F3, 0xE7B0}, + {0xA7F4, 0xA7F4, 0xE7B1}, {0xA7F5, 0xA7F5, 0xE7B2}, {0xA7F6, 0xA7F6, 0xE7B3}, {0xA7F7, 0xA7F7, 0xE7B4}, + {0xA7F8, 0xA7F8, 0xE7B5}, {0xA7F9, 0xA7F9, 0xE7B6}, {0xA7FA, 0xA7FA, 0xE7B7}, {0xA7FB, 0xA7FB, 0xE7B8}, + {0xA7FC, 0xA7FC, 0xE7B9}, {0xA7FD, 0xA7FD, 0xE7BA}, {0xA7FE, 0xA7FE, 0xE7BB}, {0xA7FF, 0xA7FF, 0x003F} +}; + +static GS_UNICASE_CHARACTER planeA8[] = { + {0xA800, 0xA800, 0x003F}, {0xA801, 0xA801, 0x003F}, {0xA802, 0xA802, 0x003F}, {0xA803, 0xA803, 0x003F}, + {0xA804, 0xA804, 0x003F}, {0xA805, 0xA805, 0x003F}, {0xA806, 0xA806, 0x003F}, {0xA807, 0xA807, 0x003F}, + {0xA808, 0xA808, 0x003F}, {0xA809, 0xA809, 0x003F}, {0xA80A, 0xA80A, 0x003F}, {0xA80B, 0xA80B, 0x003F}, + {0xA80C, 0xA80C, 0x003F}, {0xA80D, 0xA80D, 0x003F}, {0xA80E, 0xA80E, 0x003F}, {0xA80F, 0xA80F, 0x003F}, + {0xA810, 0xA810, 0x003F}, {0xA811, 0xA811, 0x003F}, {0xA812, 0xA812, 0x003F}, {0xA813, 0xA813, 0x003F}, + {0xA814, 0xA814, 0x003F}, {0xA815, 0xA815, 0x003F}, {0xA816, 0xA816, 0x003F}, {0xA817, 0xA817, 0x003F}, + {0xA818, 0xA818, 0x003F}, {0xA819, 0xA819, 0x003F}, {0xA81A, 0xA81A, 0x003F}, {0xA81B, 0xA81B, 0x003F}, + {0xA81C, 0xA81C, 0x003F}, {0xA81D, 0xA81D, 0x003F}, {0xA81E, 0xA81E, 0x003F}, {0xA81F, 0xA81F, 0x003F}, + {0xA820, 0xA820, 0x003F}, {0xA821, 0xA821, 0x003F}, {0xA822, 0xA822, 0x003F}, {0xA823, 0xA823, 0x003F}, + {0xA824, 0xA824, 0x003F}, {0xA825, 0xA825, 0x003F}, {0xA826, 0xA826, 0x003F}, {0xA827, 0xA827, 0x003F}, + {0xA828, 0xA828, 0x003F}, {0xA829, 0xA829, 0x003F}, {0xA82A, 0xA82A, 0x003F}, {0xA82B, 0xA82B, 0x003F}, + {0xA82C, 0xA82C, 0x003F}, {0xA82D, 0xA82D, 0x003F}, {0xA82E, 0xA82E, 0x003F}, {0xA82F, 0xA82F, 0x003F}, + {0xA830, 0xA830, 0x003F}, {0xA831, 0xA831, 0x003F}, {0xA832, 0xA832, 0x003F}, {0xA833, 0xA833, 0x003F}, + {0xA834, 0xA834, 0x003F}, {0xA835, 0xA835, 0x003F}, {0xA836, 0xA836, 0x003F}, {0xA837, 0xA837, 0x003F}, + {0xA838, 0xA838, 0x003F}, {0xA839, 0xA839, 0x003F}, {0xA83A, 0xA83A, 0x003F}, {0xA83B, 0xA83B, 0x003F}, + {0xA83C, 0xA83C, 0x003F}, {0xA83D, 0xA83D, 0x003F}, {0xA83E, 0xA83E, 0x003F}, {0xA83F, 0xA83F, 0x003F}, + {0xA840, 0xA840, 0x02CA}, {0xA841, 0xA841, 0x02CB}, {0xA842, 0xA842, 0x02D9}, {0xA843, 0xA843, 0x2013}, + {0xA844, 0xA844, 0x2015}, {0xA845, 0xA845, 0x2025}, {0xA846, 0xA846, 0x2035}, {0xA847, 0xA847, 0x2105}, + {0xA848, 0xA848, 0x2109}, {0xA849, 0xA849, 0x2196}, {0xA84A, 0xA84A, 0x2197}, {0xA84B, 0xA84B, 0x2198}, + {0xA84C, 0xA84C, 0x2199}, {0xA84D, 0xA84D, 0x2215}, {0xA84E, 0xA84E, 0x221F}, {0xA84F, 0xA84F, 0x2223}, + {0xA850, 0xA850, 0x2252}, {0xA851, 0xA851, 0x2266}, {0xA852, 0xA852, 0x2267}, {0xA853, 0xA853, 0x22BF}, + {0xA854, 0xA854, 0x2550}, {0xA855, 0xA855, 0x2551}, {0xA856, 0xA856, 0x2552}, {0xA857, 0xA857, 0x2553}, + {0xA858, 0xA858, 0x2554}, {0xA859, 0xA859, 0x2555}, {0xA85A, 0xA85A, 0x2556}, {0xA85B, 0xA85B, 0x2557}, + {0xA85C, 0xA85C, 0x2558}, {0xA85D, 0xA85D, 0x2559}, {0xA85E, 0xA85E, 0x255A}, {0xA85F, 0xA85F, 0x255B}, + {0xA860, 0xA860, 0x255C}, {0xA861, 0xA861, 0x255D}, {0xA862, 0xA862, 0x255E}, {0xA863, 0xA863, 0x255F}, + {0xA864, 0xA864, 0x2560}, {0xA865, 0xA865, 0x2561}, {0xA866, 0xA866, 0x2562}, {0xA867, 0xA867, 0x2563}, + {0xA868, 0xA868, 0x2564}, {0xA869, 0xA869, 0x2565}, {0xA86A, 0xA86A, 0x2566}, {0xA86B, 0xA86B, 0x2567}, + {0xA86C, 0xA86C, 0x2568}, {0xA86D, 0xA86D, 0x2569}, {0xA86E, 0xA86E, 0x256A}, {0xA86F, 0xA86F, 0x256B}, + {0xA870, 0xA870, 0x256C}, {0xA871, 0xA871, 0x256D}, {0xA872, 0xA872, 0x256E}, {0xA873, 0xA873, 0x256F}, + {0xA874, 0xA874, 0x2570}, {0xA875, 0xA875, 0x2571}, {0xA876, 0xA876, 0x2572}, {0xA877, 0xA877, 0x2573}, + {0xA878, 0xA878, 0x2581}, {0xA879, 0xA879, 0x2582}, {0xA87A, 0xA87A, 0x2583}, {0xA87B, 0xA87B, 0x2584}, + {0xA87C, 0xA87C, 0x2585}, {0xA87D, 0xA87D, 0x2586}, {0xA87E, 0xA87E, 0x2587}, {0xA87F, 0xA87F, 0x003F}, + {0xA880, 0xA880, 0x2588}, {0xA881, 0xA881, 0x2589}, {0xA882, 0xA882, 0x258A}, {0xA883, 0xA883, 0x258B}, + {0xA884, 0xA884, 0x258C}, {0xA885, 0xA885, 0x258D}, {0xA886, 0xA886, 0x258E}, {0xA887, 0xA887, 0x258F}, + {0xA888, 0xA888, 0x2593}, {0xA889, 0xA889, 0x2594}, {0xA88A, 0xA88A, 0x2595}, {0xA88B, 0xA88B, 0x25BC}, + {0xA88C, 0xA88C, 0x25BD}, {0xA88D, 0xA88D, 0x25E2}, {0xA88E, 0xA88E, 0x25E3}, {0xA88F, 0xA88F, 0x25E4}, + {0xA890, 0xA890, 0x25E5}, {0xA891, 0xA891, 0x2609}, {0xA892, 0xA892, 0x2295}, {0xA893, 0xA893, 0x3012}, + {0xA894, 0xA894, 0x301D}, {0xA895, 0xA895, 0x301E}, {0xA896, 0xA896, 0xE7BC}, {0xA897, 0xA897, 0xE7BD}, + {0xA898, 0xA898, 0xE7BE}, {0xA899, 0xA899, 0xE7BF}, {0xA89A, 0xA89A, 0xE7C0}, {0xA89B, 0xA89B, 0xE7C1}, + {0xA89C, 0xA89C, 0xE7C2}, {0xA89D, 0xA89D, 0xE7C3}, {0xA89E, 0xA89E, 0xE7C4}, {0xA89F, 0xA89F, 0xE7C5}, + {0xA8A0, 0xA8A0, 0xE7C6}, {0x00EC, 0xA8A1, 0x0100}, {0x00BB, 0xA8A2, 0x00C1}, {0x01B1, 0xA8A3, 0x01CD}, + {0x00BA, 0xA8A4, 0x00C0}, {0x00FD, 0xA8A5, 0x0112}, {0x00C3, 0xA8A6, 0x00C9}, {0x0104, 0xA8A7, 0x011A}, + {0x00C2, 0xA8A8, 0x00C8}, {0x0113, 0xA8A9, 0x012A}, {0x00C7, 0xA8AA, 0x00CD}, {0x01B2, 0xA8AB, 0x01CF}, + {0x00C6, 0xA8AC, 0x00CC}, {0x0132, 0xA8AD, 0x014C}, {0x00CD, 0xA8AE, 0x00D3}, {0x01B3, 0xA8AF, 0x01D1}, + {0x00CC, 0xA8B0, 0x00D2}, {0x014F, 0xA8B1, 0x016A}, {0x00D3, 0xA8B2, 0x00DA}, {0x01B4, 0xA8B3, 0x01D3}, + {0x00D2, 0xA8B4, 0x00D9}, {0x01B5, 0xA8B5, 0x01D5}, {0x01B6, 0xA8B6, 0x01D7}, {0x01B7, 0xA8B7, 0x01D9}, + {0x01B8, 0xA8B8, 0x01DB}, {0x00D5, 0xA8B9, 0x00DC}, {0x00C4, 0xA8BA, 0x00CA}, {0x2AAD, 0xA8BB, 0x2C6D}, + {0x1DA0, 0xA8BC, 0x1E3E}, {0x012B, 0xA8BD, 0x0143}, {0x012E, 0xA8BE, 0x0147}, {0x01D4, 0xA8BF, 0x01F8}, + {0xA8C0, 0xA8C0, 0x0261}, {0xA8C1, 0xA8C1, 0xE7C9}, {0xA8C2, 0xA8C2, 0xE7CA}, {0xA8C3, 0xA8C3, 0xE7CB}, + {0xA8C4, 0xA8C4, 0xE7CC}, {0xA8C5, 0xA8C5, 0x3105}, {0xA8C6, 0xA8C6, 0x3106}, {0xA8C7, 0xA8C7, 0x3107}, + {0xA8C8, 0xA8C8, 0x3108}, {0xA8C9, 0xA8C9, 0x3109}, {0xA8CA, 0xA8CA, 0x310A}, {0xA8CB, 0xA8CB, 0x310B}, + {0xA8CC, 0xA8CC, 0x310C}, {0xA8CD, 0xA8CD, 0x310D}, {0xA8CE, 0xA8CE, 0x310E}, {0xA8CF, 0xA8CF, 0x310F}, + {0xA8D0, 0xA8D0, 0x3110}, {0xA8D1, 0xA8D1, 0x3111}, {0xA8D2, 0xA8D2, 0x3112}, {0xA8D3, 0xA8D3, 0x3113}, + {0xA8D4, 0xA8D4, 0x3114}, {0xA8D5, 0xA8D5, 0x3115}, {0xA8D6, 0xA8D6, 0x3116}, {0xA8D7, 0xA8D7, 0x3117}, + {0xA8D8, 0xA8D8, 0x3118}, {0xA8D9, 0xA8D9, 0x3119}, {0xA8DA, 0xA8DA, 0x311A}, {0xA8DB, 0xA8DB, 0x311B}, + {0xA8DC, 0xA8DC, 0x311C}, {0xA8DD, 0xA8DD, 0x311D}, {0xA8DE, 0xA8DE, 0x311E}, {0xA8DF, 0xA8DF, 0x311F}, + {0xA8E0, 0xA8E0, 0x3120}, {0xA8E1, 0xA8E1, 0x3121}, {0xA8E2, 0xA8E2, 0x3122}, {0xA8E3, 0xA8E3, 0x3123}, + {0xA8E4, 0xA8E4, 0x3124}, {0xA8E5, 0xA8E5, 0x3125}, {0xA8E6, 0xA8E6, 0x3126}, {0xA8E7, 0xA8E7, 0x3127}, + {0xA8E8, 0xA8E8, 0x3128}, {0xA8E9, 0xA8E9, 0x3129}, {0xA8EA, 0xA8EA, 0xE7CD}, {0xA8EB, 0xA8EB, 0xE7CE}, + {0xA8EC, 0xA8EC, 0xE7CF}, {0xA8ED, 0xA8ED, 0xE7D0}, {0xA8EE, 0xA8EE, 0xE7D1}, {0xA8EF, 0xA8EF, 0xE7D2}, + {0xA8F0, 0xA8F0, 0xE7D3}, {0xA8F1, 0xA8F1, 0xE7D4}, {0xA8F2, 0xA8F2, 0xE7D5}, {0xA8F3, 0xA8F3, 0xE7D6}, + {0xA8F4, 0xA8F4, 0xE7D7}, {0xA8F5, 0xA8F5, 0xE7D8}, {0xA8F6, 0xA8F6, 0xE7D9}, {0xA8F7, 0xA8F7, 0xE7DA}, + {0xA8F8, 0xA8F8, 0xE7DB}, {0xA8F9, 0xA8F9, 0xE7DC}, {0xA8FA, 0xA8FA, 0xE7DD}, {0xA8FB, 0xA8FB, 0xE7DE}, + {0xA8FC, 0xA8FC, 0xE7DF}, {0xA8FD, 0xA8FD, 0xE7E0}, {0xA8FE, 0xA8FE, 0xE7E1}, {0xA8FF, 0xA8FF, 0x003F} +}; + +static GS_UNICASE_CHARACTER planeE6[] = { + {0xE600, 0xE600, 0x103B8}, {0xE601, 0xE601, 0x103B9}, {0xE602, 0xE602, 0x103BA}, {0xE603, 0xE603, 0x103BB}, + {0xE604, 0xE604, 0x103BC}, {0xE605, 0xE605, 0x103BD}, {0xE606, 0xE606, 0x103BE}, {0xE607, 0xE607, 0x103BF}, + {0xE608, 0xE608, 0x103C0}, {0xE609, 0xE609, 0x103C1}, {0xE60A, 0xE60A, 0x103C2}, {0xE60B, 0xE60B, 0x103C3}, + {0xE60C, 0xE60C, 0x103C4}, {0xE60D, 0xE60D, 0x103C5}, {0xE60E, 0xE60E, 0x103C6}, {0xE60F, 0xE60F, 0x103C7}, + {0xE610, 0xE610, 0x103C8}, {0xE611, 0xE611, 0x103C9}, {0xE612, 0xE612, 0x103CA}, {0xE613, 0xE613, 0x103CB}, + {0xE614, 0xE614, 0x103CC}, {0xE615, 0xE615, 0x103CD}, {0xE616, 0xE616, 0x103CE}, {0xE617, 0xE617, 0x103CF}, + {0xE618, 0xE618, 0x103D0}, {0xE619, 0xE619, 0x103D1}, {0xE61A, 0xE61A, 0x103D2}, {0xE61B, 0xE61B, 0x103D3}, + {0xE61C, 0xE61C, 0x103D4}, {0xE61D, 0xE61D, 0x103D5}, {0xE61E, 0xE61E, 0x103D6}, {0xE61F, 0xE61F, 0x103D7}, + {0xE620, 0xE620, 0x103D8}, {0xE621, 0xE621, 0x103D9}, {0xE622, 0xE622, 0x103DA}, {0xE623, 0xE623, 0x103DB}, + {0xE624, 0xE624, 0x103DC}, {0xE625, 0xE625, 0x103DD}, {0xE626, 0xE626, 0x103DE}, {0xE627, 0xE627, 0x103DF}, + {0xE628, 0xE628, 0x103E0}, {0xE629, 0xE629, 0x103E1}, {0xE62A, 0xE62A, 0x103E2}, {0xE62B, 0xE62B, 0x103E3}, + {0xE62C, 0xE62C, 0x103E4}, {0xE62D, 0xE62D, 0x103E5}, {0xE62E, 0xE62E, 0x103E6}, {0xE62F, 0xE62F, 0x103E7}, + {0xE630, 0xE630, 0x103E8}, {0xE631, 0xE631, 0x103E9}, {0xE632, 0xE632, 0x103EA}, {0xE633, 0xE633, 0x103EB}, + {0xE634, 0xE634, 0x103EC}, {0xE635, 0xE635, 0x103ED}, {0xE636, 0xE636, 0x103EE}, {0xE637, 0xE637, 0x103EF}, + {0xE638, 0xE638, 0x103F0}, {0xE639, 0xE639, 0x103F1}, {0xE63A, 0xE63A, 0x103F2}, {0xE63B, 0xE63B, 0x103F3}, + {0xE63C, 0xE63C, 0x103F4}, {0xE63D, 0xE63D, 0x103F5}, {0xE63E, 0xE63E, 0x103F6}, {0xE63F, 0xE63F, 0x103F7}, + {0xE640, 0xE640, 0x103F8}, {0xE641, 0xE641, 0x103F9}, {0xE642, 0xE642, 0x103FA}, {0xE643, 0xE643, 0x103FB}, + {0xE644, 0xE644, 0x103FC}, {0xE645, 0xE645, 0x103FD}, {0xE646, 0xE646, 0x103FE}, {0xE647, 0xE647, 0x103FF}, + {0xE648, 0xE670, 0x10400}, {0xE649, 0xE671, 0x10401}, {0xE64A, 0xE672, 0x10402}, {0xE64B, 0xE673, 0x10403}, + {0xE64C, 0xE674, 0x10404}, {0xE64D, 0xE675, 0x10405}, {0xE64E, 0xE676, 0x10406}, {0xE64F, 0xE677, 0x10407}, + {0xE650, 0xE678, 0x10408}, {0xE651, 0xE679, 0x10409}, {0xE652, 0xE67A, 0x1040A}, {0xE653, 0xE67B, 0x1040B}, + {0xE654, 0xE67C, 0x1040C}, {0xE655, 0xE67D, 0x1040D}, {0xE656, 0xE67E, 0x1040E}, {0xE657, 0xE67F, 0x1040F}, + {0xE658, 0xE680, 0x10410}, {0xE659, 0xE681, 0x10411}, {0xE65A, 0xE682, 0x10412}, {0xE65B, 0xE683, 0x10413}, + {0xE65C, 0xE684, 0x10414}, {0xE65D, 0xE685, 0x10415}, {0xE65E, 0xE686, 0x10416}, {0xE65F, 0xE687, 0x10417}, + {0xE660, 0xE688, 0x10418}, {0xE661, 0xE689, 0x10419}, {0xE662, 0xE68A, 0x1041A}, {0xE663, 0xE68B, 0x1041B}, + {0xE664, 0xE68C, 0x1041C}, {0xE665, 0xE68D, 0x1041D}, {0xE666, 0xE68E, 0x1041E}, {0xE667, 0xE68F, 0x1041F}, + {0xE668, 0xE690, 0x10420}, {0xE669, 0xE691, 0x10421}, {0xE66A, 0xE692, 0x10422}, {0xE66B, 0xE693, 0x10423}, + {0xE66C, 0xE694, 0x10424}, {0xE66D, 0xE695, 0x10425}, {0xE66E, 0xE696, 0x10426}, {0xE66F, 0xE697, 0x10427}, + {0xE648, 0xE670, 0x10400}, {0xE649, 0xE671, 0x10401}, {0xE64A, 0xE672, 0x10402}, {0xE64B, 0xE673, 0x10403}, + {0xE64C, 0xE674, 0x10404}, {0xE64D, 0xE675, 0x10405}, {0xE64E, 0xE676, 0x10406}, {0xE64F, 0xE677, 0x10407}, + {0xE650, 0xE678, 0x10408}, {0xE651, 0xE679, 0x10409}, {0xE652, 0xE67A, 0x1040A}, {0xE653, 0xE67B, 0x1040B}, + {0xE654, 0xE67C, 0x1040C}, {0xE655, 0xE67D, 0x1040D}, {0xE656, 0xE67E, 0x1040E}, {0xE657, 0xE67F, 0x1040F}, + {0xE658, 0xE680, 0x10410}, {0xE659, 0xE681, 0x10411}, {0xE65A, 0xE682, 0x10412}, {0xE65B, 0xE683, 0x10413}, + {0xE65C, 0xE684, 0x10414}, {0xE65D, 0xE685, 0x10415}, {0xE65E, 0xE686, 0x10416}, {0xE65F, 0xE687, 0x10417}, + {0xE660, 0xE688, 0x10418}, {0xE661, 0xE689, 0x10419}, {0xE662, 0xE68A, 0x1041A}, {0xE663, 0xE68B, 0x1041B}, + {0xE664, 0xE68C, 0x1041C}, {0xE665, 0xE68D, 0x1041D}, {0xE666, 0xE68E, 0x1041E}, {0xE667, 0xE68F, 0x1041F}, + {0xE668, 0xE690, 0x10420}, {0xE669, 0xE691, 0x10421}, {0xE66A, 0xE692, 0x10422}, {0xE66B, 0xE693, 0x10423}, + {0xE66C, 0xE694, 0x10424}, {0xE66D, 0xE695, 0x10425}, {0xE66E, 0xE696, 0x10426}, {0xE66F, 0xE697, 0x10427}, + {0xE698, 0xE698, 0x10450}, {0xE699, 0xE699, 0x10451}, {0xE69A, 0xE69A, 0x10452}, {0xE69B, 0xE69B, 0x10453}, + {0xE69C, 0xE69C, 0x10454}, {0xE69D, 0xE69D, 0x10455}, {0xE69E, 0xE69E, 0x10456}, {0xE69F, 0xE69F, 0x10457}, + {0xE6A0, 0xE6A0, 0x10458}, {0xE6A1, 0xE6A1, 0x10459}, {0xE6A2, 0xE6A2, 0x1045A}, {0xE6A3, 0xE6A3, 0x1045B}, + {0xE6A4, 0xE6A4, 0x1045C}, {0xE6A5, 0xE6A5, 0x1045D}, {0xE6A6, 0xE6A6, 0x1045E}, {0xE6A7, 0xE6A7, 0x1045F}, + {0xE6A8, 0xE6A8, 0x10460}, {0xE6A9, 0xE6A9, 0x10461}, {0xE6AA, 0xE6AA, 0x10462}, {0xE6AB, 0xE6AB, 0x10463}, + {0xE6AC, 0xE6AC, 0x10464}, {0xE6AD, 0xE6AD, 0x10465}, {0xE6AE, 0xE6AE, 0x10466}, {0xE6AF, 0xE6AF, 0x10467}, + {0xE6B0, 0xE6B0, 0x10468}, {0xE6B1, 0xE6B1, 0x10469}, {0xE6B2, 0xE6B2, 0x1046A}, {0xE6B3, 0xE6B3, 0x1046B}, + {0xE6B4, 0xE6B4, 0x1046C}, {0xE6B5, 0xE6B5, 0x1046D}, {0xE6B6, 0xE6B6, 0x1046E}, {0xE6B7, 0xE6B7, 0x1046F}, + {0xE6B8, 0xE6B8, 0x10470}, {0xE6B9, 0xE6B9, 0x10471}, {0xE6BA, 0xE6BA, 0x10472}, {0xE6BB, 0xE6BB, 0x10473}, + {0xE6BC, 0xE6BC, 0x10474}, {0xE6BD, 0xE6BD, 0x10475}, {0xE6BE, 0xE6BE, 0x10476}, {0xE6BF, 0xE6BF, 0x10477}, + {0xE6C0, 0xE6C0, 0x10478}, {0xE6C1, 0xE6C1, 0x10479}, {0xE6C2, 0xE6C2, 0x1047A}, {0xE6C3, 0xE6C3, 0x1047B}, + {0xE6C4, 0xE6C4, 0x1047C}, {0xE6C5, 0xE6C5, 0x1047D}, {0xE6C6, 0xE6C6, 0x1047E}, {0xE6C7, 0xE6C7, 0x1047F}, + {0xE6C8, 0xE6C8, 0x10480}, {0xE6C9, 0xE6C9, 0x10481}, {0xE6CA, 0xE6CA, 0x10482}, {0xE6CB, 0xE6CB, 0x10483}, + {0xE6CC, 0xE6CC, 0x10484}, {0xE6CD, 0xE6CD, 0x10485}, {0xE6CE, 0xE6CE, 0x10486}, {0xE6CF, 0xE6CF, 0x10487}, + {0xE6D0, 0xE6D0, 0x10488}, {0xE6D1, 0xE6D1, 0x10489}, {0xE6D2, 0xE6D2, 0x1048A}, {0xE6D3, 0xE6D3, 0x1048B}, + {0xE6D4, 0xE6D4, 0x1048C}, {0xE6D5, 0xE6D5, 0x1048D}, {0xE6D6, 0xE6D6, 0x1048E}, {0xE6D7, 0xE6D7, 0x1048F}, + {0xE6D8, 0xE6D8, 0x10490}, {0xE6D9, 0xE6D9, 0x10491}, {0xE6DA, 0xE6DA, 0x10492}, {0xE6DB, 0xE6DB, 0x10493}, + {0xE6DC, 0xE6DC, 0x10494}, {0xE6DD, 0xE6DD, 0x10495}, {0xE6DE, 0xE6DE, 0x10496}, {0xE6DF, 0xE6DF, 0x10497}, + {0xE6E0, 0xE6E0, 0x10498}, {0xE6E1, 0xE6E1, 0x10499}, {0xE6E2, 0xE6E2, 0x1049A}, {0xE6E3, 0xE6E3, 0x1049B}, + {0xE6E4, 0xE6E4, 0x1049C}, {0xE6E5, 0xE6E5, 0x1049D}, {0xE6E6, 0xE6E6, 0x1049E}, {0xE6E7, 0xE6E7, 0x1049F}, + {0xE6E8, 0xE6E8, 0x104A0}, {0xE6E9, 0xE6E9, 0x104A1}, {0xE6EA, 0xE6EA, 0x104A2}, {0xE6EB, 0xE6EB, 0x104A3}, + {0xE6EC, 0xE6EC, 0x104A4}, {0xE6ED, 0xE6ED, 0x104A5}, {0xE6EE, 0xE6EE, 0x104A6}, {0xE6EF, 0xE6EF, 0x104A7}, + {0xE6F0, 0xE6F0, 0x104A8}, {0xE6F1, 0xE6F1, 0x104A9}, {0xE6F2, 0xE6F2, 0x104AA}, {0xE6F3, 0xE6F3, 0x104AB}, + {0xE6F4, 0xE6F4, 0x104AC}, {0xE6F5, 0xE6F5, 0x104AD}, {0xE6F6, 0xE6F6, 0x104AE}, {0xE6F7, 0xE6F7, 0x104AF}, + {0xE6F8, 0xE6F8, 0x104B0}, {0xE6F9, 0xE6F9, 0x104B1}, {0xE6FA, 0xE6FA, 0x104B2}, {0xE6FB, 0xE6FB, 0x104B3}, + {0xE6FC, 0xE6FC, 0x104B4}, {0xE6FD, 0xE6FD, 0x104B5}, {0xE6FE, 0xE6FE, 0x104B6}, {0xE6FF, 0xE6FF, 0x104B7} +}; + +const static GS_UNICASE_CHARACTER* gb18030_unicase_pages[256] = { + plane00, plane01, plane02, plane03, plane04, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + plane10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, plane1D, plane1E, plane1F, + plane20, NULL, NULL, plane23, NULL, NULL, NULL, NULL, + NULL, NULL, plane2A, plane2B, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, plane51, plane52, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, planeA2, planeA3, NULL, NULL, planeA6, planeA7, + planeA8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, planeE6, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* Unicode-4.0.0 case folding information */ +GS_UNICASE_PAGES gb10030_unicase = { + gb18030_unicase_pages +}; + +static inline uint get_gb18030_code(const GS_UCHAR* str_value, size_t mblen) +{ + uint r = 0; + switch(mblen) { + case 1: + r = str_value[0]; + break; + case 2: + r = (str_value[0] << 8) + str_value[1]; + break; + case 4: + r = (str_value[0] << 24) + (str_value[1] << 16) + (str_value[2] << 8) + str_value[3]; + break; + default: + Assert(0); + break; + } + return r; +} + +/* gb18030 code to diff */ +static uint gb18030_4_bytes_code_to_diff(uint code) +{ + uint diff = 0; + diff += ((code >> 24) & 0xFF) - MB_MIN_ODD_BYTE; + diff *= 10; + diff += ((code >> 16) & 0xFF) - MB_MIN_EVEN_BYTE_4; + diff *= 126; + diff += ((code >> 8) & 0xFF) - MB_MIN_ODD_BYTE; + diff *= 10; + diff += (code & 0xFF) - MB_MIN_EVEN_BYTE_4; + return diff; +} + +/* gb18030 char to diff */ +static inline uint gb18030_4_bytes_chs_to_diff(const GS_UCHAR *s) +{ + uint code = (s[0] - MB_MIN_ODD_BYTE) * 12600 + + (s[1] - MB_MIN_EVEN_BYTE_4) * 1260 + + (s[2] - MB_MIN_ODD_BYTE) * 10 + + (s[3] - MB_MIN_EVEN_BYTE_4); + return code; +} + +/* diff to gb18030 code */ +static uint diff_to_gb18030_4_bytes_code(GS_UCHAR* s, uint slen, uint diff) +{ + if (diff > MAX_GB18030_DIFF || slen < 4) { + return 0; + } + + s[3] = (GS_UCHAR)(diff % 10) + MB_MIN_EVEN_BYTE_4; + diff /= 10; + s[2] = (GS_UCHAR)(diff % 126) + MB_MIN_ODD_BYTE; + diff /= 126; + s[1] = (GS_UCHAR)(diff % 10) + MB_MIN_EVEN_BYTE_4; + s[0] = (GS_UCHAR)(diff / 10) + MB_MIN_ODD_BYTE; + + return 4; +} + +/* get chinese character pinyin weight */ +static uint get_weight_if_chinese_character(uint code) +{ + if (code >= PINYIN_2_BYTE_START && code <= PINYIN_2_BYTE_END) { + uint idx = (((code >> 8) & 0xFF) - MB_MIN_ODD_BYTE) * 0xBE + + (code & 0xFF) - MB_MIN_EVEN_BYTE_2; + if ((code & 0xFF) > 0x7F) { + idx -= 0x01; + } + return PINYIN_WEIGHT_BASE + gb18030_2_weight_py[idx]; + } else if (code >= PINYIN_4_BYTE_1_START && code <= PINYIN_4_BYTE_1_END) { + uint idx = gb18030_4_bytes_code_to_diff(code) - PINYIN_4_1_DIFF; + return PINYIN_WEIGHT_BASE + gb18030_4_weight_py_p1[idx]; + } else if (code >= PINYIN_4_BYTE_2_START && code <= PINYIN_4_BYTE_2_END) { + uint idx = gb18030_4_bytes_code_to_diff(code) - PINYIN_4_2_DIFF; + return PINYIN_WEIGHT_BASE + gb18030_4_weight_py_p2[idx]; + } + return PINYIN_WEIGHT_BASE; +} + +/* unicase code to gb18030 */ +static int caseinfo_code_to_gb18030(uint code) +{ + if ((code >= MIN_2_BYTE_UNICASE && code <= MAX_2_BYTE_UNICASE) || + code < UNICASE_4_BYTE_OFFSET) { + return code; + } else { + int len; + GS_UCHAR gb[4]; + + if (code >= UNICASE_4_BYTE_OFFSET && code < MIN_2_BYTE_UNICASE) { + code -= UNICASE_4_BYTE_OFFSET; + } else if (code >= (MIN_3_BYTE_FROM_UNI & 0xFFFF) && + code <= (MAX_3_BYTE_FROM_UNI & 0xFFFF)) { + code += (MIN_3_BYTE_FROM_UNI & 0xFF0000); + } else { + Assert(0); + } + len = diff_to_gb18030_4_bytes_code(gb, 4, code); + + return len == 4 ? get_gb18030_code(gb, 4) : 0; + } +} + +/* get weight for non chinese character */ +static uint get_weight_for_other_character(const GS_UCHAR* str, size_t mblen) +{ + uint diff = 0; + uint upper_code = 0; + const GS_UNICASE_CHARACTER* temp_page = NULL; + switch(mblen) { + case 1: + upper_code = gb18030_unicase_pages[0][(GS_UCHAR) str[0]].upper; + break; + case 2: + temp_page = gb18030_unicase_pages[(GS_UCHAR) str[0]]; + upper_code = temp_page ? temp_page[(GS_UCHAR) str[1]].upper : 0; + break; + case 4: + diff = gb18030_4_bytes_chs_to_diff(str); + if (diff < MIN_2_BYTE_UNICASE - UNICASE_4_BYTE_OFFSET){ + upper_code = diff + UNICASE_4_BYTE_OFFSET; + } else if (diff >= MIN_3_BYTE_FROM_UNI && diff <= MAX_3_BYTE_FROM_UNI) { + upper_code = (diff & 0xFFFF); + } else { + upper_code = 0; + break; + } + temp_page = gb18030_unicase_pages[(upper_code >> 8) & 0xFF]; + upper_code = temp_page ? temp_page[(GS_UCHAR)(upper_code & 0xFF)].upper : 0; + break; + default: + /* keep compiler quiet */ + break; + } + + return upper_code ? caseinfo_code_to_gb18030(upper_code) : 0; +} + +/* return the weight for a multi-byte gb18030 code */ +static uint get_weight_for_mbchar(const GS_UCHAR* str_value, size_t mblen) +{ + uint weight, caseup_code, code = get_gb18030_code(str_value, mblen); + if (code == 0xFE39FE39) { /* max gb18030 code */ + return 0xFFFFFFFF; + } + + weight = get_weight_if_chinese_character(code); + if (weight > PINYIN_WEIGHT_BASE) { + return weight; + } + + caseup_code = get_weight_for_other_character(str_value, mblen); + if (caseup_code == 0) { + caseup_code = code; + } + weight = (caseup_code <= 0xFFFF) ? caseup_code : + COMMON_WEIGHT_BASE + gb18030_4_bytes_code_to_diff(caseup_code); + + return weight; +} + +static int get_gb18030_code_len(const GS_UCHAR* s_start, const GS_UCHAR* s_end) +{ + if (s_end - s_start <= 0) { + return 0; + } else if (s_end - s_start == 1 || !is_gb18030_code_odd(s_start[0])) { + /* if the first byte encoding code is not between 0x81 and 0xFE, + * May be 1 byte characters or non GB18030 characters + */ + return 1; + } else if (is_gb18030_mblen_2(s_start[1])) { + return 2; + } else if (s_end - s_start > 3 && is_gb18030_mblen_4(s_start[1]) && + is_gb18030_code_odd(s_start[2]) && is_gb18030_mblen_4(s_start[3])) { + return 4; + } + + /* the code is non GB18030 characters */ + return 1; +} + +static int strnncoll_gb18030(const GS_UCHAR** arg1, size_t len1, + const GS_UCHAR** arg2, size_t len2) +{ + const GS_UCHAR* arg1_start = *arg1; + const GS_UCHAR* arg2_start = *arg2; + const GS_UCHAR* arg1_end = arg1_start + len1; + const GS_UCHAR* arg2_end = arg2_start + len2; + + while (arg1_start < arg1_end && arg2_start < arg2_end) { + int wchar1_len = get_gb18030_code_len(arg1_start, arg1_end); + int wchar2_len = get_gb18030_code_len(arg2_start, arg2_end); + + if (wchar1_len > 1 && wchar2_len > 1) { + uint wchar1 = get_weight_for_mbchar(arg1_start, wchar1_len); + uint wchar2 = get_weight_for_mbchar(arg2_start, wchar2_len); + + if (wchar1 != wchar2) { + return wchar1 > wchar2 ? 1 : -1; + } + NEXT_WORD_POS(arg1_start, wchar1_len); + NEXT_WORD_POS(arg2_start, wchar2_len); + } else if (wchar1_len == 1 && wchar2_len == 1) { + GS_UCHAR arg1_order = one_bytes_gb18030_sort_order[*arg1_start++]; + GS_UCHAR arg2_order = one_bytes_gb18030_sort_order[*arg2_start++]; + if (arg1_order != arg2_order) { + return (int)(arg1_order - arg2_order); + } + } else { + return wchar1_len == 1 ? -1 : 1; + } + } + *arg1 = arg1_start; + *arg2 = arg2_start; + + return 0; +} + +int strnncoll_gb18030_chinese_ci_pad_space(const GS_UCHAR* arg1, size_t len1, + const GS_UCHAR* arg2, size_t len2) +{ + const GS_UCHAR* arg1_end = arg1 + len1; + const GS_UCHAR* arg2_end = arg2 + len2; + int res = strnncoll_gb18030(&arg1, len1, &arg2, len2); + + if (!res && ((arg1 != arg1_end) || (arg2 != arg2_end))) { + int swap = 1; + if (len1 < len2) { + arg1 = arg2; + arg1_end = arg2_end; + swap = -1; + res = -res; + } + for (; arg1 < arg1_end; arg1++) { + if (*arg1 != ' ') { + return (*arg1 < ' ') ? -swap : swap; + } + } + } + return res; +} + +/* + * policy_hash_combine + * Returns a combine hash of 2 unit32 values. + */ +uint32_t policy_hash_combine(uint32_t seed, uint32_t value) +{ + seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); + return seed; +} + +static uint32 get_gb18030_code_and_length(const GS_UCHAR *src, const GS_UCHAR* end, uint32* code) +{ + uint len; + if (src >= end) { + return 0; + } else if (is_gb18030_mblen_1(src[0])) { + *code = src[0]; + return 1; + } else { + len = get_gb18030_code_len(src, end); + } + *code = get_gb18030_code(src, len); + return len; +} + +Datum hash_gb18030_chinese_pad_space(const GS_UCHAR *key, size_t len) +{ + uint32 remove_space_len = bpchartruelen((char*)key, len); + uint32 code_len = 0; + uint32 gb_weight; + const GS_UCHAR *end = key + remove_space_len; + uint32 result = 0; + + while((code_len = get_gb18030_code_and_length(key, end, &gb_weight)) != 0) { + gb_weight = get_weight_for_mbchar(key, code_len); + result = policy_hash_combine(result, hash_uint32(gb_weight)); + key += code_len; + } + return UInt32GetDatum(result); +} + +static int get_current_gb18030_weight(GS_UCHAR** s_start, GS_UCHAR** s_end, uint* weight) +{ + const GS_UCHAR* str_start = *s_start; + const GS_UCHAR* str_end = *s_end; + + int wchar_len = get_gb18030_code_len(str_start, str_end); + if (wchar_len > 1) { + *weight = get_weight_for_mbchar(str_start, wchar_len); + } else if (wchar_len == 1) { + *weight = one_bytes_gb18030_sort_order[*str_start]; + } else { + *weight = 0x0; + } + + return wchar_len; +} + +/* +* while collation is gb18030_chinese_ci, return the like syntax result +* p point to like str +* t point to compare str +*/ +int matchtext_gb18030(GS_UCHAR* t, int tlen, GS_UCHAR* p, int plen) +{ + if (plen == 1 && *p == '%') { + return LIKE_TRUE; + } + + uint p_word = 0; + uint t_word = 0; + GS_UCHAR word_escape = '\\'; + GS_UCHAR word_one = '_'; + GS_UCHAR word_many = '%'; + + GS_UCHAR* p_word_end = p + plen; + GS_UCHAR* t_word_end = t + tlen; + + check_stack_depth(); + while (p < p_word_end && t < t_word_end) { + int p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + int t_word_bytes = get_current_gb18030_weight(&t, &t_word_end, &t_word); + + if (p_word == word_escape) { + NEXT_WORD_POS(p, p_word_bytes); + if (p < p_word_end) { + p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + } else { + ereport(ERROR, (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), + errmsg("LIKE pattern must not end with escape character"))); + } + + if (p_word != t_word) { + return LIKE_FALSE; + } + } else if (p_word == word_many) { + NEXT_WORD_POS(p, p_word_bytes); + p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + + while (p < p_word_end) { + if (p_word == word_many) { + NEXT_WORD_POS(p, p_word_bytes); + p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + } else if (p_word == word_one) { + if (t >= t_word_end) { + return LIKE_ABORT; + } + NEXT_WORD_POS(t, t_word_bytes); + t_word_bytes = get_current_gb18030_weight(&t, &t_word_end, &t_word); + NEXT_WORD_POS(p, p_word_bytes); + p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + } else { + /* Reached a non-wildcard pattern char */ + break; + } + } + + /* If we're at end of pattern, match: we have a trailing % which matches any remaining text string. */ + if (p >= p_word_end) { + return LIKE_TRUE; + } + + if (p_word == word_escape) { + if (p_word_end - p < 2) { + ereport(ERROR, (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), + errmsg("LIKE pattern must not end with escape character"))); + } + NEXT_WORD_POS(p, p_word_bytes); + p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + } + + while (t_word_end - t > 0) { + if (t_word == p_word) { + int matched = matchtext_gb18030(t, t_word_end - t, p, p_word_end - p); + if (matched != LIKE_FALSE) { + return matched; + } + } + NEXT_WORD_POS(t, t_word_bytes); + t_word_bytes = get_current_gb18030_weight(&t, &t_word_end, &t_word); + } + return LIKE_ABORT; + } else if (p_word == word_one) { + NEXT_WORD_POS(p, p_word_bytes); + p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + + NEXT_WORD_POS(t, t_word_bytes); + t_word_bytes = get_current_gb18030_weight(&t, &t_word_end, &t_word); + continue; + } else if (p_word != t_word) { + return LIKE_FALSE; + } + + NEXT_WORD_POS(p, p_word_bytes); + NEXT_WORD_POS(t, t_word_bytes); + } + + if (t_word_end - t > 0) { + return LIKE_FALSE; + } + if (p_word_end - p > 0) { + while (p < p_word_end) { + int p_word_bytes = get_current_gb18030_weight(&p, &p_word_end, &p_word); + p += p_word_bytes; + if (p_word != word_many) { + return LIKE_FALSE; + } + } + } + if (p >= p_word_end) { + return LIKE_TRUE; + } + + return LIKE_ABORT; +} \ No newline at end of file diff --git a/src/common/backend/catalog/gs_gbk_collation.cpp b/src/common/backend/catalog/gs_gbk_collation.cpp new file mode 100644 index 000000000..3efa0e216 --- /dev/null +++ b/src/common/backend/catalog/gs_gbk_collation.cpp @@ -0,0 +1,2535 @@ +#include "postgres.h" +#include "knl/knl_variable.h" + +#include "catalog/pg_collation.h" +#include "utils/builtins.h" +#include "utils/syscache.h" +#include "parser/parse_type.h" +#include "access/hash.h" +#include "utils/lsyscache.h" +#include "catalog/gs_collation.h" + +/* unit16 for 2 bytes gbk code */ +typedef uint16 gbk_wchar; + +#define GBK_FIRST_WCHAR(ch) ((GS_UCHAR)((ch >> 8) & 0xFF)) +#define GBK_SECOND_WCHAR(ch) ((GS_UCHAR)(ch & 0xFF)) +#define GBKCODE(c1, c2) (((uint)(GS_UCHAR)(c1) << 8) | (GS_UCHAR)(c2)) + +static GS_UCHAR one_bytes_gbk_sort_order[] = +{ + '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '\\', ']', '[', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '{', '|', '}', 'Y', '\177', + (GS_UCHAR) '\200', (GS_UCHAR) '\201', (GS_UCHAR) '\202', (GS_UCHAR) '\203', (GS_UCHAR) '\204', (GS_UCHAR) '\205', (GS_UCHAR) '\206', (GS_UCHAR) '\207', + (GS_UCHAR) '\210', (GS_UCHAR) '\211', (GS_UCHAR) '\212', (GS_UCHAR) '\213', (GS_UCHAR) '\214', (GS_UCHAR) '\215', (GS_UCHAR) '\216', (GS_UCHAR) '\217', + (GS_UCHAR) '\220', (GS_UCHAR) '\221', (GS_UCHAR) '\222', (GS_UCHAR) '\223', (GS_UCHAR) '\224', (GS_UCHAR) '\225', (GS_UCHAR) '\226', (GS_UCHAR) '\227', + (GS_UCHAR) '\230', (GS_UCHAR) '\231', (GS_UCHAR) '\232', (GS_UCHAR) '\233', (GS_UCHAR) '\234', (GS_UCHAR) '\235', (GS_UCHAR) '\236', (GS_UCHAR) '\237', + (GS_UCHAR) '\240', (GS_UCHAR) '\241', (GS_UCHAR) '\242', (GS_UCHAR) '\243', (GS_UCHAR) '\244', (GS_UCHAR) '\245', (GS_UCHAR) '\246', (GS_UCHAR) '\247', + (GS_UCHAR) '\250', (GS_UCHAR) '\251', (GS_UCHAR) '\252', (GS_UCHAR) '\253', (GS_UCHAR) '\254', (GS_UCHAR) '\255', (GS_UCHAR) '\256', (GS_UCHAR) '\257', + (GS_UCHAR) '\260', (GS_UCHAR) '\261', (GS_UCHAR) '\262', (GS_UCHAR) '\263', (GS_UCHAR) '\264', (GS_UCHAR) '\265', (GS_UCHAR) '\266', (GS_UCHAR) '\267', + (GS_UCHAR) '\270', (GS_UCHAR) '\271', (GS_UCHAR) '\272', (GS_UCHAR) '\273', (GS_UCHAR) '\274', (GS_UCHAR) '\275', (GS_UCHAR) '\276', (GS_UCHAR) '\277', + (GS_UCHAR) '\300', (GS_UCHAR) '\301', (GS_UCHAR) '\302', (GS_UCHAR) '\303', (GS_UCHAR) '\304', (GS_UCHAR) '\305', (GS_UCHAR) '\306', (GS_UCHAR) '\307', + (GS_UCHAR) '\310', (GS_UCHAR) '\311', (GS_UCHAR) '\312', (GS_UCHAR) '\313', (GS_UCHAR) '\314', (GS_UCHAR) '\315', (GS_UCHAR) '\316', (GS_UCHAR) '\317', + (GS_UCHAR) '\320', (GS_UCHAR) '\321', (GS_UCHAR) '\322', (GS_UCHAR) '\323', (GS_UCHAR) '\324', (GS_UCHAR) '\325', (GS_UCHAR) '\326', (GS_UCHAR) '\327', + (GS_UCHAR) '\330', (GS_UCHAR) '\331', (GS_UCHAR) '\332', (GS_UCHAR) '\333', (GS_UCHAR) '\334', (GS_UCHAR) '\335', (GS_UCHAR) '\336', (GS_UCHAR) '\337', + (GS_UCHAR) '\340', (GS_UCHAR) '\341', (GS_UCHAR) '\342', (GS_UCHAR) '\343', (GS_UCHAR) '\344', (GS_UCHAR) '\345', (GS_UCHAR) '\346', (GS_UCHAR) '\347', + (GS_UCHAR) '\350', (GS_UCHAR) '\351', (GS_UCHAR) '\352', (GS_UCHAR) '\353', (GS_UCHAR) '\354', (GS_UCHAR) '\355', (GS_UCHAR) '\356', (GS_UCHAR) '\357', + (GS_UCHAR) '\360', (GS_UCHAR) '\361', (GS_UCHAR) '\362', (GS_UCHAR) '\363', (GS_UCHAR) '\364', (GS_UCHAR) '\365', (GS_UCHAR) '\366', (GS_UCHAR) '\367', + (GS_UCHAR) '\370', (GS_UCHAR) '\371', (GS_UCHAR) '\372', (GS_UCHAR) '\373', (GS_UCHAR) '\374', (GS_UCHAR) '\375', (GS_UCHAR) '\376', (GS_UCHAR) '\377', +}; + +static uint16_t two_bytes_gbk_sort_order[]= +{ + 8653, 14277, 17116, 11482, 11160, 2751, 14613, 3913, 13337, 9827, + 19496, 1759, 8105, 7103, 7836, 5638, 2223, 21433, 5878, 8006, + 4851, 18766, 18879, 16728, 8129, 6200, 19133, 6389, 2500, 19084, + 16228, 5074, 8130, 5900, 6201, 3985, 14597, 11566, 8588, 8769, + 15885, 11411, 11965, 1961, 18012, 18303, 12242, 14118, 11490, 12911, + 15015, 4367, 3184, 2093, 20937, 5710, 5108, 10560, 9993, 18982, + 8393, 10697, 14620, 19558, 14970, 15193, 5359, 18189, 12666, 18192, + 3310, 18659, 17358, 7973, 18673, 19537, 3404, 9723, 4221, 16486, + 7023, 13648, 16310, 1049, 1726, 4799, 15534, 4366, 17133, 4192, + 6219, 5118, 1804, 2360, 2279, 14279, 13740, 4511, 2361, 12906, + 16650, 18590, 4723, 2001, 16313, 3594, 21026, 12146, 19561, 3800, + 4161, 16774, 18892, 17657, 7025, 892, 7917, 12245, 3394, 4813, + 11902, 3189, 20002, 2365, 12964, 18115, 17660, 20227, 17182, 11907, + 11671, 17562, 17864, 21131, 13423, 1361, 12246, 18897, 14978, 18848, + 20727, 5902, 10726, 21241, 1906, 13424, 1408, 20519, 3038, 18495, + 20446, 1431, 17138, 13464, 14558, 1221, 6720, 6137, 17348, 5268, + 4448, 11313, 1760, 6172, 6870, 5744, 13541, 3044, 17701, 14368, + 16114, 5051, 9142, 18776, 5669, 19089, 11088, 17867, 925, 10395, + 4372, 10578, 2138, 2554, 18118, 21087, 13862, 7461, 14983, 3322, + 15305, 11844, 7924, 8087, 2542, 20701, 21772, 2754, 10490, 8218, + 14800, 15869, 14436, 16119, 1814, 11543, 17398, 16069, 19659, 17020, + 17844, 5694, 8833, 16744, 18925, 4957, 9812, 6852, 8036, 12966, + 14038, 12145, 16833, 11165, 17076, 17756, 3673, 2367, 20916, 9143, + 14927, 6885, 17486, 7469, 1661, 2827, 4627, 18198, 1307, 19711, + 17637, 2595, 2262, 20807, 1764, 8150, 18547, 3192, 9711, 16262, + 9144, 2006, 21629, 5311, 15743, 14733, 10991, 15402, 2916, 17724, + 12195, 12622, 5141, 8039, 15169, 7780, 4568, 20835, 21575, 10580, + 15022, 9470, 6853, 3926, 21563, 1342, 16745, 8181, 11526, 1947, + 7402, 18641, 14145, 13149, 19222, 2468, 12920, 13916, 21077, 2968, + 16438, 19667, 1768, 15632, 18374, 4738, 15517, 16655, 4309, 2374, + 14492, 8602, 3679, 2103, 1312, 18681, 6613, 18604, 20451, 2755, + 18218, 19473, 17854, 20316, 3003, 4998, 1391, 20938, 11169, 7049, + 18861, 17577, 18091, 1937, 4085, 2059, 20633, 15948, 1313, 20138, + 7785, 16439, 15081, 20955, 15117, 17065, 19924, 13831, 11913, 20062, + 7568, 10703, 3717, 15480, 6047, 7790, 16867, 14223, 12971, 8429, + 2008, 2833, 14026, 1317, 17493, 19411, 18551, 15452, 15257, 18504, + 4441, 1769, 7249, 20128, 5509, 1970, 9420, 19365, 20190, 21617, + 12202, 15041, 2871, 19676, 20388, 21674, 14258, 2901, 8058, 5970, + 20472, 13257, 18226, 3694, 17591, 10279, 1318, 12409, 7901, 9794, + 10416, 10769, 12876, 17154, 15455, 19298, 3970, 21327, 14228, 13095, + 8096, 16072, 21748, 12581, 9326, 2311, 5683, 12641, 3583, 2184, + 16464, 6969, 1795, 6778, 2880, 15819, 3433, 7674, 4713, 17297, + 8231, 4333, 9995, 1841, 5558, 17155, 17298, 11283, 18694, 7946, + 7311, 13129, 4753, 21149, 905, 14010, 18821, 8532, 11873, 2190, + 19006, 3456, 8874, 7433, 2841, 7680, 14143, 20130, 1993, 1699, + 976, 15361, 2736, 2154, 9202, 11685, 7951, 12982, 11008, 16763, + 11829, 13327, 11686, 2299, 9940, 10507, 8917, 1277, 19790, 1636, + 20143, 21002, 15011, 19443, 6026, 13299, 2455, 9667, 15612, 16477, + 10261, 2811, 2202, 13674, 14760, 6818, 9691, 10624, 20145, 11940, + 15524, 18349, 9437, 11578, 20132, 17736, 4121, 4122, 16023, 2280, + 4371, 4373, 7873, 18307, 14602, 14695, 13054, 5410, 6065, 14389, + 3979, 1137, 5411, 6672, 16311, 11632, 9829, 19575, 5901, 15708, + 12553, 7165, 18983, 10860, 13664, 18242, 10848, 2049, 8075, 5579, + 8083, 10863, 21136, 5445, 17851, 19132, 8597, 18771, 11054, 14631, + 10997, 8292, 8803, 11246, 4999, 17559, 11134, 15369, 5155, 6407, + 12054, 4857, 11265, 12834, 7322, 15057, 10937, 15984, 5544, 8040, + 13291, 3961, 5142, 19101, 869, 9631, 2009, 11315, 21404, 3172, + 14941, 4204, 7947, 9997, 16906, 4035, 4476, 4477, 8171, 2818, + 20725, 4724, 11453, 20868, 4725, 4729, 8565, 5109, 12490, 8862, + 5920, 13737, 2888, 6930, 12963, 3223, 6934, 3395, 16243, 8397, + 9475, 4858, 13515, 3777, 11266, 10029, 21028, 1671, 7765, 7766, + 14169, 2221, 5328, 2907, 8951, 4225, 4416, 7770, 3046, 8014, + 3975, 10636, 20236, 19825, 3248, 8717, 2140, 2908, 3249, 9477, + 4628, 2225, 12676, 2909, 21564, 5167, 1225, 4186, 13266, 4017, + 7471, 7146, 18214, 6890, 4195, 16037, 16688, 5583, 14497, 7476, + 3286, 8566, 2910, 2862, 2232, 16038, 10417, 9492, 12234, 14190, + 8793, 5573, 6486, 20322, 21455, 9734, 8317, 10143, 5781, 7681, + 5782, 7500, 7501, 15466, 7188, 7511, 7512, 21003, 2203, 21693, + 11350, 9540, 21212, 18183, 7918, 8754, 17511, 20869, 18899, 21160, + 11356, 9315, 8364, 8798, 18460, 16189, 17483, 11415, 8897, 7771, + 9917, 8718, 7926, 5228, 11270, 2644, 9269, 19404, 8719, 8367, + 13267, 10400, 1914, 2157, 8584, 11171, 3964, 17881, 16785, 18951, + 18052, 16616, 14500, 9323, 10418, 12410, 14661, 6963, 7570, 7668, + 13601, 17386, 18995, 8437, 4460, 8346, 15920, 8318, 3387, 10734, + 18057, 18058, 10525, 9654, 2390, 13675, 13603, 20000, 8106, 1260, + 10824, 1426, 5075, 5076, 18887, 12175, 8174, 15558, 5269, 4304, + 5380, 3287, 8156, 5386, 11605, 8142, 18768, 7580, 8641, 6319, + 13425, 4478, 13147, 2019, 8900, 6331, 19668, 5756, 6769, 3381, + 9009, 9730, 9735, 15160, 4036, 8167, 13489, 17009, 8667, 18308, + 13439, 18112, 11735, 21667, 14617, 17010, 16290, 16291, 17515, 3368, + 7050, 14841, 5636, 16826, 17573, 7760, 18493, 13306, 14312, 2619, + 17868, 13609, 8991, 7038, 4310, 16881, 14020, 16422, 20565, 5941, + 18174, 3642, 20346, 12080, 856, 13144, 18158, 20908, 10800, 15630, + 14340, 15837, 21707, 4629, 2060, 19870, 9632, 3718, 7902, 994, + 5762, 18391, 9647, 2312, 9199, 9648, 18281, 18342, 19911, 5367, + 9950, 13834, 13513, 8771, 9414, 4057, 21302, 1963, 1964, 1967, + 902, 3349, 14697, 5602, 1071, 13959, 14621, 21428, 7288, 15079, + 7039, 16495, 13949, 3111, 5580, 13365, 2615, 4109, 6202, 11213, + 10792, 17918, 21538, 3226, 18658, 11985, 6862, 18734, 2752, 13232, + 7838, 1907, 4252, 6223, 16703, 11495, 18037, 3974, 6301, 5226, + 8514, 10487, 5267, 10892, 12763, 16706, 7702, 20003, 2616, 14457, + 16083, 16587, 4296, 14513, 8355, 12171, 16590, 10670, 13651, 3646, + 14626, 21132, 15826, 17015, 18911, 12792, 12461, 21545, 17848, 18912, + 17396, 3277, 13516, 5918, 16115, 12548, 1673, 4864, 18438, 6078, + 5880, 3263, 16211, 21784, 1909, 15296, 17183, 6884, 12796, 4417, + 4299, 17021, 21137, 14801, 17484, 8852, 6512, 15560, 4300, 17921, + 5819, 9342, 15900, 17742, 19525, 3869, 11715, 17703, 12554, 6040, + 19865, 10267, 12549, 10804, 21670, 6091, 17277, 9319, 12531, 9840, + 1060, 11215, 10514, 15170, 4892, 5904, 14898, 19534, 5469, 5470, + 1128, 5922, 18937, 7270, 15971, 17189, 16263, 9474, 13382, 2369, + 20210, 18177, 3976, 12767, 3618, 13236, 10885, 5397, 15621, 8770, + 9830, 9310, 14121, 21573, 16634, 19148, 12803, 4381, 13051, 956, + 20237, 3755, 19551, 15744, 9169, 16852, 866, 11893, 21439, 3680, + 6197, 17412, 17324, 16086, 16747, 16602, 3834, 5510, 12770, 12771, + 3420, 16198, 21552, 1421, 3198, 6097, 18178, 12772, 20576, 9831, + 17200, 19226, 5584, 20226, 5822, 10609, 11641, 3599, 13550, 15387, + 5361, 15481, 952, 3426, 19731, 20581, 21103, 2153, 16223, 19719, + 20139, 18533, 11172, 6356, 20044, 6584, 6585, 6954, 21058, 16397, + 14150, 17888, 6618, 4199, 11775, 9843, 19732, 14051, 2564, 13093, + 18379, 3377, 12174, 1968, 19359, 16350, 19294, 12243, 1294, 5362, + 20214, 6898, 15645, 18557, 6146, 13005, 14084, 19366, 6272, 17534, + 10713, 2104, 5894, 13900, 16200, 6964, 12093, 16692, 12975, 21496, + 9358, 16216, 7314, 15280, 3056, 14008, 5363, 11510, 13001, 1474, + 997, 9724, 21709, 20612, 11383, 15441, 7715, 2684, 7622, 8585, + 15456, 14192, 872, 17497, 10281, 17428, 6338, 6779, 5831, 11989, + 17156, 20245, 2293, 12512, 3560, 10705, 6367, 5040, 15465, 18663, + 14003, 7716, 17498, 6462, 10721, 13660, 9327, 17501, 6973, 9010, + 17433, 6024, 10669, 13098, 2842, 15393, 3436, 18133, 4283, 21749, + 4461, 2571, 6707, 1986, 2900, 3138, 3434, 19771, 9090, 16900, + 12816, 6022, 9736, 17830, 6708, 19167, 18099, 11781, 14950, 18337, + 19249, 3270, 20404, 21152, 11875, 6791, 17596, 7723, 19933, 884, + 19376, 8877, 19687, 12164, 3544, 17647, 4150, 3457, 17648, 12338, + 19127, 21715, 11831, 3635, 9259, 15329, 6901, 17127, 18710, 4191, + 12352, 21112, 7195, 7956, 2300, 18061, 10887, 15701, 10319, 6808, + 1859, 19445, 11794, 19170, 6436, 10969, 6216, 20594, 9522, 10157, + 5898, 11567, 11326, 18410, 9674, 10340, 10229, 11345, 3447, 2456, + 12439, 12340, 17368, 10889, 17057, 4224, 8845, 18285, 2207, 19263, + 3872, 9117, 15331, 17456, 2995, 6523, 6919, 21337, 11803, 17457, + 1936, 9533, 2248, 2161, 9697, 19072, 10607, 20163, 15100, 6199, + 20287, 7392, 20107, 21238, 9225, 11809, 13650, 10203, 6717, 19085, + 11816, 16035, 8643, 19823, 8084, 12359, 20004, 3059, 6719, 4253, + 5838, 15886, 15982, 5839, 13638, 13780, 5840, 15341, 5842, 19140, + 6854, 5923, 10582, 5843, 2868, 16398, 19872, 13534, 8824, 12598, + 19879, 19880, 18208, 16051, 16004, 16005, 16039, 10567, 6783, 19020, + 10539, 10550, 18184, 16018, 15868, 12573, 10392, 8863, 8172, 19697, + 12845, 12846, 21424, 3476, 12833, 17119, 14167, 11764, 11357, 7264, + 20873, 18048, 18901, 13220, 4667, 8756, 16106, 4705, 1432, 8009, + 3665, 7966, 7128, 2587, 7967, 12053, 15477, 13430, 20832, 5587, + 15350, 8076, 18496, 4801, 10396, 13339, 5438, 18013, 1074, 10032, + 21247, 4985, 6322, 20909, 989, 3323, 12104, 11235, 7138, 6138, + 10512, 3008, 2621, 19090, 6306, 4110, 20541, 4877, 5674, 18543, + 4231, 5748, 2116, 18465, 17517, 14702, 1762, 6233, 3281, 8548, + 3479, 6000, 954, 17677, 17278, 1186, 4803, 1097, 18938, 19207, + 5954, 17874, 2917, 13191, 1374, 4557, 13610, 19406, 8518, 7240, + 3675, 9306, 8357, 7882, 20573, 9913, 6446, 1915, 8078, 18661, + 3600, 18200, 13551, 15199, 13252, 16268, 8298, 10602, 20739, 8775, + 2704, 3928, 15450, 1948, 2829, 1375, 8603, 4214, 18952, 20841, + 21403, 12685, 8299, 11653, 8726, 9031, 11701, 7331, 5169, 19721, + 4311, 5546, 9471, 4548, 18163, 9032, 972, 14386, 11607, 15974, + 2517, 6540, 1462, 9789, 5823, 21324, 1244, 19595, 10838, 7744, + 13909, 18685, 5360, 21578, 19596, 6619, 4318, 18552, 1268, 3013, + 10906, 2309, 16148, 12551, 4773, 21079, 7858, 7887, 6198, 5174, + 2935, 8605, 12479, 9418, 17729, 6610, 4093, 16233, 17928, 17030, + 7062, 8871, 19299, 19417, 8569, 15122, 14579, 11123, 16618, 2526, + 15997, 13618, 21060, 9639, 12203, 1209, 20185, 4112, 15728, 16751, + 20767, 18053, 20711, 898, 5381, 18272, 8607, 16540, 17592, 10190, + 5887, 9300, 2294, 12204, 1384, 2426, 10427, 10374, 11972, 12978, + 10920, 11384, 16040, 14865, 10301, 1622, 2072, 20975, 20512, 8617, + 3765, 2439, 20849, 7172, 5829, 13045, 7943, 3700, 3174, 18392, + 15307, 20290, 12928, 16506, 21383, 13068, 14230, 14231, 1088, 12583, + 8875, 3942, 4462, 13626, 4146, 3217, 3701, 14505, 4242, 4245, + 15413, 3587, 11432, 4684, 6631, 15414, 3271, 18690, 21282, 7502, + 1039, 13032, 13072, 8748, 19021, 12316, 3766, 7551, 18665, 1852, + 15419, 9243, 8322, 6513, 3492, 13684, 12987, 18062, 9260, 16999, + 906, 18151, 3529, 13911, 7957, 9427, 8940, 10341, 18286, 15427, + 16481, 6514, 10263, 10264, 13950, 9675, 9985, 2208, 18070, 18291, + 9406, 1106, 16240, 14024, 21355, 18735, 10727, 21254, 21358, 6353, + 9064, 6357, 17889, 9070, 14715, 10820, 4147, 14718, 18755, 5496, + 7582, 4769, 20373, 1592, 15166, 13637, 10033, 3251, 17753, 17613, + 11596, 17130, 19916, 10850, 4182, 13264, 11964, 5447, 12805, 11003, + 11047, 2440, 20269, 5601, 5209, 15535, 15370, 18300, 1406, 6926, + 20037, 7229, 1056, 4359, 3596, 12118, 8363, 17518, 3735, 18497, + 6573, 8553, 20360, 1351, 6662, 4610, 3780, 18127, 1363, 1032, + 16617, 12536, 16800, 1037, 7571, 9731, 4203, 19993, 7572, 14677, + 4715, 6902, 1527, 10540, 2376, 3886, 12847, 8131, 11926, 2135, + 17136, 4517, 7104, 6221, 3365, 4816, 8031, 5875, 16599, 21029, + 11997, 5995, 21069, 20005, 4807, 2552, 8400, 21341, 18361, 11496, + 17629, 4669, 4726, 16292, 4072, 1075, 21429, 20521, 11523, 19918, + 15958, 17185, 18913, 4247, 11358, 1436, 14370, 4248, 6080, 17849, + 4434, 20728, 11236, 1173, 4817, 10034, 21539, 13666, 14173, 18439, + 10741, 21482, 8275, 13754, 3952, 7040, 5056, 17377, 6456, 8339, + 5443, 7327, 7328, 11738, 20834, 20673, 17273, 6182, 5675, 8491, + 8847, 18364, 11314, 9918, 12150, 4302, 19527, 18255, 14375, 14566, + 5749, 13543, 15020, 6234, 17279, 14316, 2502, 17574, 10805, 4827, + 11443, 8723, 2979, 2980, 15870, 17708, 11546, 19581, 12503, 11626, + 20926, 5924, 21344, 12472, 16076, 17280, 16710, 18256, 16748, 16841, + 18260, 19582, 14989, 9609, 8190, 21375, 12628, 17194, 21440, 3929, + 10404, 879, 4249, 10275, 11146, 3095, 12550, 8191, 1949, 10054, + 17413, 14766, 12773, 6692, 5001, 16647, 16648, 15405, 4581, 4582, + 15709, 11654, 13552, 8046, 7979, 12868, 3756, 17726, 6421, 16231, + 9150, 19109, 21097, 11614, 5002, 10583, 973, 9033, 19149, 18201, + 8192, 9622, 3737, 17195, 6447, 6480, 3483, 18605, 11564, 13964, + 7294, 15949, 19734, 16351, 3689, 13838, 10941, 3378, 13918, 13178, + 6693, 16657, 12924, 2936, 11189, 5005, 7831, 4086, 18806, 21080, + 6620, 11148, 932, 19228, 17929, 7745, 16352, 20747, 13345, 15635, + 17584, 16171, 9790, 10871, 13670, 14932, 12361, 16502, 16199, 3132, + 6358, 7791, 1245, 17817, 15950, 5715, 21662, 18558, 19882, 13796, + 13901, 10132, 10944, 12039, 1026, 10672, 9002, 13206, 20689, 19883, + 7746, 13800, 11302, 19235, 15124, 11752, 15542, 12085, 9276, 11609, + 1235, 12346, 18996, 19759, 17966, 10773, 18749, 8627, 19370, 11703, + 5719, 7905, 21307, 20246, 5908, 9361, 20563, 6426, 6427, 1034, + 13922, 10677, 12423, 5487, 16758, 13099, 16174, 20438, 11193, 17210, + 17211, 11392, 9864, 9712, 6490, 5723, 3572, 20852, 17832, 18753, + 6482, 16901, 9011, 13705, 18396, 2181, 7625, 10946, 4534, 4463, + 17161, 19022, 6168, 7724, 4536, 14680, 15209, 13033, 9774, 17945, + 17649, 11755, 3943, 19023, 1971, 907, 11742, 11832, 10673, 15800, + 2738, 7958, 3028, 19632, 12437, 13822, 13876, 11528, 18236, 15363, + 19255, 12988, 19972, 11154, 1403, 14431, 17732, 11711, 4037, 10186, + 19849, 9247, 18411, 10100, 7696, 11743, 9249, 17172, 19264, 14855, + 6822, 13579, 11104, 9538, 10541, 18292, 21213, 9251, 8394, 21477, + 17662, 14984, 15342, 19522, 21318, 15232, 11216, 3096, 12869, 18145, + 11682, 21506, 9501, 18022, 1877, 11517, 11798, 19265, 10542, 13830, + 13303, 7230, 13858, 18591, 18772, 8010, 21395, 21223, 6229, 14563, + 18794, 15793, 14603, 2503, 13642, 5375, 17403, 20364, 3516, 14419, + 6659, 11115, 8804, 1950, 20141, 19831, 13343, 6142, 20637, 7482, + 11825, 1770, 6541, 13226, 14576, 11826, 7938, 11847, 20963, 19677, + 1247, 8885, 11827, 8312, 13229, 6339, 14584, 11828, 14425, 16469, + 17560, 8886, 6784, 8533, 19039, 18830, 1257, 13187, 2705, 1258, + 4762, 10511, 4124, 12519, 21303, 4828, 8724, 7588, 21305, 18092, + 14812, 4131, 3527, 7762, 4393, 4394, 14764, 14280, 11327, 9907, + 17242, 17243, 9046, 16304, 9904, 10796, 16305, 16306, 16307, 18541, + 4232, 8998, 21059, 5110, 5515, 16061, 5115, 5116, 17012, 1390, + 7844, 15716, 3798, 14519, 20669, 17576, 11649, 16842, 16843, 10758, + 10309, 12474, 15684, 4631, 17585, 10500, 2084, 17597, 8329, 8391, + 9883, 8392, 21237, 17624, 11692, 16188, 17134, 9579, 4288, 3503, + 6742, 10206, 13743, 16775, 5949, 14364, 2765, 18725, 19947, 1157, + 18592, 981, 16777, 7768, 4290, 4670, 16248, 12907, 12663, 7839, + 21769, 21770, 18498, 8276, 5161, 18015, 12501, 9591, 15773, 13432, + 4865, 16137, 12288, 1030, 8924, 13433, 12525, 15774, 10036, 2589, + 12463, 2091, 1185, 15898, 18016, 1588, 6083, 8721, 10649, 4303, + 4990, 3826, 10399, 4363, 4375, 5057, 13530, 18786, 11438, 14567, + 926, 16386, 6533, 11113, 9552, 7139, 3954, 16387, 19529, 5502, + 9919, 18545, 7610, 4258, 17519, 1884, 13639, 4736, 11585, 9555, + 19464, 17281, 13793, 3517, 14382, 2504, 15985, 5349, 5231, 17082, + 19141, 19665, 9307, 8616, 17234, 13611, 2695, 15316, 9955, 6478, + 8193, 9151, 11248, 9034, 9035, 21671, 5547, 18164, 5179, 10584, + 10585, 10055, 4187, 20740, 19151, 3965, 5926, 20741, 16440, 12301, + 7787, 21672, 8823, 3930, 19152, 21490, 20275, 6621, 19597, 18474, + 4742, 13395, 18475, 15636, 18862, 20956, 14654, 4319, 21271, 8594, + 10518, 18318, 10942, 5932, 6955, 6586, 15855, 16795, 19598, 21579, + 9193, 8712, 18267, 18268, 16447, 21580, 2121, 15200, 8679, 13179, + 12699, 15998, 4113, 16882, 16619, 2010, 15485, 13801, 7795, 870, + 10133, 16801, 13060, 1368, 3719, 12950, 19418, 11778, 3238, 14580, + 13968, 15043, 21588, 7596, 9858, 8628, 2233, 3853, 2076, 3890, + 15978, 10302, 20433, 20434, 998, 2031, 13447, 13009, 3175, 21713, + 3524, 3525, 16958, 19760, 12160, 10221, 17387, 2085, 1796, 13182, + 7626, 18232, 9328, 20458, 9866, 9867, 7890, 4243, 21738, 7721, + 8441, 18574, 7627, 18575, 8442, 20405, 19024, 18023, 11593, 18705, + 18706, 18824, 11788, 17251, 7074, 17601, 8707, 5724, 3710, 1040, + 21730, 16369, 13823, 3530, 10114, 7818, 19688, 19975, 19196, 13859, + 7823, 9660, 5732, 10230, 10231, 19319, 16937, 8244, 2209, 19345, + 8961, 18287, 11599, 13580, 2359, 3159, 10543, 3729, 3730, 11805, + 18293, 18294, 18354, 8989, 18295, 8861, 6605, 7968, 2341, 9938, + 8768, 12561, 12562, 13406, 20792, 20522, 18795, 7897, 15252, 13598, + 12240, 4852, 20087, 3876, 11763, 4648, 12010, 20874, 6409, 3412, + 3325, 11359, 4866, 11367, 18927, 18928, 12467, 12835, 8356, 13863, + 14839, 14878, 13123, 20625, 14523, 13643, 3336, 5707, 12475, 20508, + 7408, 16232, 3339, 14148, 12687, 4061, 6287, 20780, 17818, 16400, + 18969, 1192, 12480, 3839, 5382, 12040, 15543, 11124, 7309, 15602, + 6704, 21044, 14193, 1623, 5847, 20247, 11469, 1193, 8019, 2236, + 20985, 6342, 1492, 1504, 20496, 11136, 13073, 2171, 4685, 11015, + 1195, 2739, 11224, 2793, 7816, 17258, 9214, 7318, 1761, 5147, + 7112, 15831, 20270, 5689, 10886, 13188, 4163, 18175, 1124, 7840, + 21342, 18140, 3047, 15899, 18853, 20918, 15766, 20919, 17405, 15986, + 5754, 8835, 10998, 19501, 1885, 1763, 2547, 9152, 7051, 15026, + 14808, 13284, 19736, 11210, 15061, 2064, 17327, 4633, 8155, 4327, + 16448, 10191, 17124, 15062, 20964, 1923, 13258, 8159, 8160, 10282, + 19210, 3348, 10428, 18997, 2788, 16006, 14951, 17645, 11211, 2313, + 16759, 4637, 5691, 8789, 8878, 1513, 13034, 9999, 9884, 10342, + 7208, 19346, 17173, 15845, 19387, 9539, 15847, 18074, 3612, 12524, + 6721, 11524, 6722, 4706, 8251, 18309, 20183, 18728, 4413, 14016, + 4414, 14663, 3799, 6402, 16674, 3664, 7583, 1095, 14412, 20469, + 15536, 4954, 3649, 2329, 20674, 18787, 8365, 14285, 19827, 8041, + 3781, 20470, 7589, 13024, 12198, 1463, 14347, 15407, 7422, 5256, + 4428, 1475, 8794, 7429, 1682, 17439, 3437, 5832, 7552, 6264, + 11065, 5836, 16239, 8476, 7122, 10397, 6770, 6771, 18825, 18826, + 18836, 19941, 19942, 16558, 18365, 19706, 2556, 3782, 19419, 12386, + 2582, 21425, 16167, 7028, 21030, 16314, 3597, 10037, 4867, 16320, + 16834, 16192, 2543, 20927, 8042, 3094, 20798, 3097, 16984, 7154, + 20939, 3065, 21098, 9153, 17578, 7857, 7477, 14656, 7295, 1595, + 5007, 16449, 1210, 16883, 20750, 12413, 15649, 3561, 20754, 1676, + 2686, 2387, 18576, 6792, 10927, 10271, 17338, 1280, 13490, 9371, + 13717, 3895, 5069, 13719, 5093, 18895, 14619, 16819, 4457, 19220, + 11238, 16588, 16780, 7029, 17016, 7841, 16249, 3061, 19702, 12664, + 3190, 15371, 16092, 12908, 6842, 17740, 16318, 17139, 8623, 8277, + 18915, 1238, 11239, 12128, 8801, 1174, 11583, 15810, 5542, 8283, + 19457, 3670, 15969, 19460, 4821, 17017, 1437, 19436, 17979, 3064, + 1738, 6656, 18038, 12251, 14802, 16835, 15386, 19400, 11360, 8772, + 14633, 17022, 9344, 6183, 8902, 11416, 20884, 17520, 15767, 3827, + 6041, 5750, 12620, 17485, 14929, 6328, 13340, 6723, 2645, 18788, + 17743, 5604, 10010, 2624, 14282, 13531, 19953, 12179, 3554, 6754, + 17406, 10801, 19407, 19828, 12258, 19955, 19722, 15988, 7855, 20577, + 10011, 6042, 13150, 15685, 1916, 12969, 16845, 10742, 18954, 6179, + 2544, 16786, 9484, 9295, 3066, 18955, 9610, 11603, 4312, 16788, + 3098, 3557, 2322, 10985, 9623, 5646, 5641, 12629, 8777, 15745, + 10586, 16868, 8604, 5796, 11702, 4142, 5857, 20398, 19836, 7885, + 7161, 9956, 19723, 6106, 13553, 15406, 15689, 11772, 2981, 6832, + 17639, 4282, 15278, 21613, 7332, 19412, 3558, 11608, 20063, 3840, + 2970, 13315, 2065, 1573, 6835, 21581, 15637, 1324, 17930, 16353, + 5277, 16450, 1465, 17931, 6587, 11173, 19413, 12806, 14256, 19110, + 2421, 10875, 12840, 8731, 900, 13156, 18319, 13919, 21614, 13998, + 19229, 13624, 5383, 20021, 15132, 12707, 18560, 15042, 6665, 7064, + 5516, 8313, 2911, 11704, 17535, 8570, 20769, 19420, 2042, 18131, + 14446, 1834, 8586, 17035, 6859, 19422, 18507, 9640, 14053, 15544, + 19118, 17896, 15382, 20067, 11316, 5407, 3101, 12414, 11470, 5848, + 2665, 1985, 1980, 1978, 3176, 11284, 20476, 15945, 1035, 14866, + 5648, 13627, 20215, 8161, 9726, 11995, 15044, 7944, 19212, 10523, + 14260, 16041, 10744, 12882, 14352, 13297, 3707, 20853, 10283, 8383, + 12648, 12643, 19772, 12491, 9860, 3115, 19442, 2687, 20986, 15946, + 2474, 12817, 13449, 12214, 1335, 13328, 7628, 2661, 9737, 12494, + 9012, 6786, 2533, 19214, 19215, 16992, 16993, 3438, 15415, 4244, + 4177, 15139, 8454, 2074, 17434, 4465, 4714, 9329, 9362, 17212, + 11285, 9868, 16760, 1987, 8443, 3139, 17304, 15442, 14485, 12280, + 19025, 17162, 11876, 3439, 15443, 8022, 15032, 6985, 16515, 6520, + 13218, 13213, 8323, 2043, 8750, 19256, 19026, 10001, 14089, 8534, + 6504, 908, 18238, 9098, 17128, 2669, 19633, 19217, 3316, 11048, + 910, 11016, 4136, 12731, 11353, 9205, 10989, 2740, 21004, 11955, + 2792, 18512, 1860, 21010, 8942, 8918, 19446, 4850, 10158, 11225, + 2540, 6809, 2254, 9248, 6506, 17972, 13691, 2256, 7209, 8336, + 6524, 14358, 9808, 11563, 11076, 15525, 8477, 21363, 5186, 19944, + 5244, 7323, 3962, 3835, 1943, 7276, 20814, 8973, 20456, 13010, + 5259, 7430, 19761, 18334, 17044, 20461, 17050, 17052, 13492, 6403, + 6405, 4289, 14622, 15676, 10851, 3752, 14272, 18796, 18858, 18320, + 13367, 9372, 4512, 13896, 20126, 20502, 3797, 19543, 8815, 5950, + 14365, 2095, 16110, 5497, 16776, 3566, 13744, 2096, 12909, 7265, + 19564, 1029, 16825, 20875, 20905, 3567, 18301, 8908, 1583, 8173, + 16589, 6347, 19948, 13234, 14413, 20763, 20038, 16250, 11622, 12542, + 12543, 1073, 1020, 20229, 20006, 1739, 20880, 11540, 12559, 18593, + 20671, 20312, 18440, 6068, 11675, 18672, 2642, 12253, 7231, 10952, + 13434, 2822, 7233, 20423, 12100, 11484, 12910, 16116, 1125, 3651, + 8284, 9079, 12829, 12861, 6169, 11818, 5398, 3221, 2622, 17521, + 2054, 6683, 1109, 20920, 9081, 4212, 4213, 11887, 20702, 5270, + 7704, 3956, 11486, 9920, 20313, 10367, 3828, 8407, 9912, 8256, + 18196, 17190, 19661, 16120, 1820, 5350, 15671, 2509, 14122, 8758, + 10939, 11888, 8182, 12193, 7403, 14178, 13957, 17523, 2101, 4770, + 7655, 8183, 6886, 15989, 12544, 20274, 15038, 18649, 8414, 16254, + 1917, 21752, 18677, 20375, 10368, 15058, 16121, 1188, 16434, 16294, + 13198, 14335, 11249, 10977, 4962, 3511, 16649, 8358, 19962, 21612, + 15746, 15973, 1355, 13958, 21757, 16656, 12631, 2512, 14067, 10572, + 13292, 5170, 3655, 6855, 12688, 14737, 12872, 10056, 18202, 20742, + 9832, 5590, 11679, 6891, 18375, 20766, 1952, 1731, 15687, 21643, + 8751, 12006, 7737, 11319, 5333, 10992, 14052, 12235, 11944, 7413, + 20748, 8118, 7414, 18273, 11558, 6209, 12344, 16354, 13999, 11761, + 14657, 21615, 20712, 18094, 6624, 1596, 18476, 6588, 18321, 21705, + 17819, 8705, 7046, 15690, 9113, 9121, 2422, 8120, 15995, 6694, + 5325, 2707, 17426, 17586, 12922, 2106, 1289, 18553, 16355, 3565, + 16605, 21616, 5326, 5451, 13240, 13802, 13619, 2711, 15246, 15234, + 13803, 12205, 8685, 18561, 3522, 20817, 11914, 9109, 13419, 17244, + 7939, 11219, 4328, 2922, 14191, 15318, 20350, 12042, 9641, 15545, + 6359, 20965, 16202, 17095, 16606, 13043, 15730, 20641, 4329, 11939, + 13563, 20368, 16752, 14349, 8638, 13804, 13990, 2234, 15265, 8122, + 2685, 2894, 5849, 4775, 3702, 12812, 15070, 9770, 2475, 2568, + 5649, 10429, 10303, 21619, 5080, 6428, 20369, 13046, 15531, 6487, + 11516, 7546, 5720, 19339, 1004, 20987, 11782, 10745, 2253, 8795, + 2767, 14353, 16042, 7675, 2169, 12884, 1662, 7594, 18566, 5458, + 12885, 6974, 12417, 9313, 4151, 17301, 13910, 5783, 20142, 19007, + 17213, 2477, 11592, 6276, 5697, 3272, 11727, 9998, 20770, 6709, + 7682, 7117, 2025, 15459, 3406, 1797, 2375, 8390, 17435, 1358, + 4973, 21451, 16175, 12569, 13241, 4148, 6463, 7683, 15325, 13131, + 16643, 7435, 19378, 11574, 10380, 21452, 20254, 12571, 2992, 6993, + 3467, 14090, 13276, 7756, 8860, 3388, 17543, 18699, 1043, 8324, + 18700, 4343, 10993, 11066, 7118, 15364, 3531, 9246, 8267, 18656, + 13908, 18715, 18711, 11688, 6903, 7819, 1717, 11833, 5263, 21005, + 7817, 9093, 11343, 7524, 17550, 9943, 15396, 1121, 15086, 10320, + 10570, 13706, 21006, 18513, 9453, 1932, 14761, 3157, 11732, 17259, + 8542, 9676, 9130, 6569, 19320, 10343, 10265, 12893, 12894, 12899, + 9215, 17174, 19266, 10930, 2173, 19321, 3154, 17554, 14359, 10645, + 10933, 11077, 2580, 20146, 10544, 15397, 9698, 3731, 16207, 3470, + 7698, 9252, 9704, 5767, 5771, 6957, 18101, 8654, 18849, 5096, + 1140, 12527, 3715, 8802, 11271, 16783, 6092, 2057, 2828, 5274, + 17882, 7710, 2416, 20634, 4197, 19671, 1129, 17883, 4198, 11776, + 3738, 4188, 18970, 8713, 18381, 6958, 15960, 17494, 4200, 18478, + 17067, 11280, 873, 874, 3633, 20715, 14821, 9870, 13450, 17754, + 18870, 7685, 14235, 7686, 21462, 19040, 9775, 1521, 9528, 17504, + 17505, 18011, 12669, 12677, 8419, 20377, 20378, 1147, 19690, 9221, + 16487, 14459, 7291, 7296, 19678, 7717, 15962, 4011, 19137, 12994, + 13466, 20429, 21443, 21447, 21453, 13211, 9972, 21463, 2846, 4106, + 21215, 7846, 5998, 12151, 19461, 11481, 12678, 12263, 10127, 4830, + 4569, 7982, 20546, 18863, 14293, 7483, 4368, 20996, 4466, 12391, + 4467, 20414, 8881, 15223, 19646, 7123, 7156, 6895, 17513, 15764, + 15348, 3667, 17805, 2222, 18456, 14564, 11240, 11241, 16084, 2931, + 16740, 1302, 1158, 7769, 14460, 6416, 4564, 5768, 17920, 4651, + 13221, 6324, 18251, 20273, 4565, 14437, 8285, 18467, 1742, 17981, + 12528, 20675, 10041, 6038, 11368, 1593, 17872, 6829, 21627, 14637, + 4625, 3870, 16539, 3924, 878, 1743, 983, 10210, 8927, 15794, + 14574, 6661, 17923, 8964, 8848, 7656, 7929, 20929, 15903, 6271, + 5059, 17362, 5957, 8521, 17282, 9030, 21142, 16846, 14496, 20578, + 20579, 5961, 6045, 16271, 15748, 21444, 21722, 21126, 14210, 11681, + 16870, 12775, 20768, 18971, 961, 16277, 9958, 2268, 16325, 17473, + 4602, 17975, 18813, 20068, 6698, 17857, 11253, 18643, 19350, 14773, + 16456, 13275, 10876, 11552, 7423, 18479, 2937, 18567, 15281, 12600, + 7676, 8573, 5236, 16622, 2324, 12813, 6052, 18393, 9649, 7183, + 10986, 20150, 17598, 6053, 11393, 3076, 11708, 20482, 6787, 5977, + 17968, 2874, 9874, 15444, 8023, 12418, 9973, 16994, 19027, 7189, + 6675, 3350, 18695, 18696, 9655, 15420, 15927, 17477, 4639, 14429, + 20556, 6027, 19041, 17388, 17691, 14198, 7688, 1278, 8067, 18405, + 911, 18712, 13881, 11019, 9668, 2434, 8943, 3863, 3864, 18635, + 6920, 10483, 13827, 10236, 10646, 10545, 14163, 15526, 18355, 21216, + 19936, 18904, 6325, 14734, 2028, 14470, 20288, 1984, 17891, 6772, + 19191, 13158, 4664, 12324, 1141, 10042, 4606, 13468, 11921, 15795, + 9298, 21708, 11298, 6609, 16087, 12635, 19232, 21586, 16342, 15928, + 9305, 9330, 10237, 12445, 14794, 15622, 13718, 1053, 4209, 3505, + 9582, 13370, 8108, 1407, 2494, 3042, 13898, 12854, 19565, 16680, + 18079, 4479, 21541, 13747, 16113, 3668, 10797, 2553, 18905, 5077, + 5370, 18773, 7584, 14171, 16293, 8133, 10798, 16977, 19860, 4621, + 3922, 17141, 2932, 14727, 6475, 17634, 11859, 2753, 15018, 19951, + 7925, 6942, 10831, 1438, 984, 4672, 18918, 4818, 11541, 6417, + 18159, 3988, 17654, 18530, 4279, 20540, 20056, 21718, 14461, 3671, + 10325, 15019, 11542, 17145, 14990, 16978, 5598, 4878, 11369, 18930, + 18674, 18679, 14638, 11766, 1414, 18789, 11678, 9105, 6085, 12036, + 4480, 21036, 3332, 3009, 18518, 4822, 14731, 14306, 15021, 14376, + 11545, 19408, 20921, 20314, 3416, 5467, 12563, 990, 4879, 1816, + 4233, 1400, 20361, 14991, 21256, 12130, 14627, 5599, 2118, 18599, + 8149, 10174, 10898, 9600, 13786, 20199, 13996, 19405, 18087, 12800, + 20626, 18797, 17351, 20707, 9612, 14076, 8590, 1730, 13728, 1115, + 13729, 1765, 21485, 2719, 18941, 3049, 7472, 21719, 4379, 4400, + 19713, 4440, 5399, 20394, 9613, 19097, 18942, 14643, 4893, 13865, + 18798, 8821, 13311, 14040, 18042, 4234, 2918, 11418, 20093, 11959, + 19223, 7782, 10175, 20449, 18088, 13977, 20635, 1287, 15839, 9083, + 8048, 1826, 1356, 13929, 16855, 9278, 10177, 4739, 12632, 16593, + 8497, 5125, 15113, 13389, 19504, 10268, 12182, 21359, 3681, 17925, + 15994, 20213, 19535, 1457, 3622, 5928, 20813, 13761, 1314, 7409, + 6581, 16272, 11937, 7244, 15777, 7157, 17414, 10492, 8890, 2079, + 4675, 15024, 14993, 4001, 13223, 19335, 8195, 9065, 21441, 2164, + 16441, 8049, 9485, 1732, 17122, 4802, 15566, 20941, 9154, 9720, + 21415, 9489, 12807, 1750, 10589, 3067, 12973, 12700, 1958, 2177, + 20582, 4613, 12019, 1206, 6836, 2519, 20201, 9633, 19738, 19739, + 5551, 5813, 3967, 5172, 16326, 3257, 4489, 2466, 20454, 12776, + 19839, 18322, 19740, 13535, 18972, 13732, 12637, 21417, 4914, 9159, + 21645, 21646, 4658, 2395, 13272, 11658, 16278, 10412, 6019, 7748, + 2723, 8257, 8226, 2520, 21758, 13002, 18147, 12304, 21445, 21499, + 1690, 12201, 3903, 2804, 2269, 10970, 6448, 7415, 5716, 17031, + 3539, 5774, 3739, 20815, 13600, 11483, 4965, 5335, 12236, 14225, + 18807, 14390, 4216, 5014, 16457, 16361, 7297, 21587, 7347, 18814, + 16955, 18388, 18328, 7348, 19679, 6110, 16663, 12369, 1476, 18535, + 5825, 17823, 13967, 18480, 9122, 18274, 1353, 6699, 8975, 7859, + 8976, 14937, 4748, 16173, 7052, 11471, 10877, 8831, 6364, 15860, + 19611, 19481, 3070, 17992, 18505, 20643, 12370, 18691, 7796, 18692, + 14887, 19602, 16362, 10915, 15692, 7058, 7797, 13854, 6628, 9380, + 13564, 17332, 14606, 15409, 16542, 14408, 2779, 12309, 7300, 18998, + 20435, 4929, 11948, 11127, 5527, 7497, 15300, 18609, 14133, 19889, + 21557, 11307, 15133, 7310, 18568, 7806, 6674, 5148, 12929, 10706, + 19890, 13809, 14585, 20820, 16547, 15861, 13805, 15490, 20380, 14943, + 14506, 8690, 16890, 5522, 12644, 5215, 15238, 12043, 15547, 5289, + 2939, 20652, 11894, 7070, 5455, 13011, 12953, 10921, 17901, 5184, + 21420, 16154, 13096, 18523, 3721, 7301, 20976, 3526, 10222, 14042, + 16962, 6975, 9771, 6788, 19373, 12983, 5864, 5087, 5088, 16043, + 6488, 14108, 3179, 12211, 19513, 7574, 6431, 6596, 5784, 11783, + 19008, 5199, 8631, 5725, 5726, 10747, 20588, 21351, 9382, 9302, + 2427, 3077, 9502, 17769, 13277, 14867, 15892, 5652, 20250, 15140, + 9392, 10377, 9824, 11135, 10286, 2347, 15141, 8693, 1628, 10435, + 8123, 20614, 20325, 14755, 10748, 11476, 18525, 15782, 12212, 21285, + 14134, 13572, 7358, 3078, 6976, 18233, 18030, 4423, 18102, 20856, + 21710, 3109, 12603, 14824, 6489, 9018, 20659, 14236, 16908, 2943, + 3767, 4430, 11338, 16764, 13698, 10016, 10150, 13104, 17305, 13956, + 4494, 20440, 9353, 20031, 14892, 4152, 2480, 15500, 11009, 15148, + 8456, 15421, 6793, 6986, 11941, 16176, 11841, 13935, 15929, 20295, + 4689, 13329, 13672, 6191, 12935, 5489, 10184, 9364, 5200, 16995, + 14508, 21558, 14031, 7083, 3981, 7995, 7513, 2845, 3312, 14758, + 7555, 10004, 11581, 19193, 6801, 14199, 21731, 17970, 2484, 5149, + 8239, 21734, 19042, 12606, 4757, 6738, 3493, 7196, 15214, 12496, + 2537, 2812, 21294, 6802, 7084, 7835, 7303, 14686, 7436, 13036, + 3547, 18872, 1660, 15033, 14328, 9661, 19171, 15580, 15366, 11155, + 12734, 16046, 1734, 6907, 7202, 12892, 11690, 11836, 18759, 5223, + 7525, 19218, 11897, 13288, 18340, 12735, 11140, 20559, 5788, 2945, + 7000, 8981, 12517, 3592, 2794, 5299, 11156, 19448, 21012, 6670, + 12895, 9430, 9397, 13995, 10385, 9669, 3158, 10527, 11228, 6814, + 11979, 10481, 21007, 5204, 4039, 19906, 9677, 4643, 21465, 15088, + 9750, 7602, 2798, 13302, 21190, 10348, 18289, 9683, 21191, 2458, + 7824, 4352, 15099, 6508, 11800, 19802, 10238, 9134, 7646, 17260, + 5738, 8268, 17458, 10103, 19270, 7384, 19200, 19492, 19326, 17341, + 11884, 1869, 2211, 9222, 8270, 14857, 14362, 21736, 3113, 13582, + 13493, 2022, 8170, 19809, 10630, 9701, 3160, 10546, 3472, 8481, + 18296, 9253, 9228, 21217, 9411, 9575, 1108, 11572, 19816, 10106, + 5687, 6517, 12857, 17808, 2331, 2825, 12804, 8582, 18943, 8415, + 17025, 17875, 6069, 9000, 9273, 8891, 14905, 862, 17820, 2629, + 13239, 8606, 8893, 8608, 2873, 5568, 19113, 19613, 17429, 18697, + 16694, 15460, 7948, 11973, 6343, 15695, 6518, 17833, 12166, 16996, + 17502, 17837, 16910, 9776, 2847, 19043, 4350, 19637, 2994, 6526, + 1911, 1912, 8286, 12915, 2596, 14082, 2630, 14086, 21061, 15203, + 15204, 9650, 20251, 19624, 9656, 5733, 4287, 20567, 11361, 11362, + 18595, 14464, 17876, 8421, 12838, 13390, 15114, 13269, 18973, 15961, + 18686, 1977, 6837, 3849, 20653, 20047, 16543, 2763, 15696, 7949, + 14264, 19168, 3788, 8162, 9019, 3165, 3389, 4080, 7556, 9803, + 1719, 4040, 7378, 7385, 21257, 13293, 18956, 14123, 8704, 13125, + 18554, 18129, 6773, 13628, 6970, 11974, 6737, 4103, 18760, 17463, + 5637, 10935, 877, 7830, 12293, 2197, 10829, 10830, 12290, 9911, + 7237, 13997, 11460, 16169, 18089, 4401, 13794, 17235, 8221, 13391, + 4002, 11963, 12138, 8227, 4189, 1392, 14019, 10878, 14001, 14749, + 16184, 6111, 15323, 14021, 10479, 11433, 9507, 15930, 13816, 20410, + 14071, 20411, 11022, 10386, 3868, 8398, 12785, 18461, 11633, 1712, + 14377, 12801, 16847, 13253, 18205, 3934, 18508, 20026, 20762, 1727, + 3474, 14876, 9373, 11693, 4515, 5741, 1683, 20271, 11161, 3776, + 19946, 2881, 16244, 4518, 3320, 16111, 10794, 13371, 12447, 12849, + 16675, 16676, 16020, 8132, 20793, 20876, 12855, 8011, 8012, 13939, + 8490, 6225, 13589, 1584, 5137, 21027, 12072, 8402, 6390, 11853, + 17866, 17869, 20007, 18302, 3413, 19454, 6411, 6881, 11856, 10893, + 11109, 2678, 12073, 1411, 20877, 12056, 21372, 20089, 10122, 20230, + 4728, 10953, 20092, 16118, 9594, 11089, 18779, 4425, 15717, 14926, + 8925, 8085, 8177, 18919, 7234, 21033, 6746, 1340, 20232, 21196, + 19437, 5466, 6326, 12178, 3039, 2590, 15105, 2462, 14981, 8217, + 18039, 14462, 8404, 4871, 7106, 5640, 3414, 19139, 21089, 18675, + 6685, 20127, 2505, 16388, 6308, 7465, 14994, 4376, 17705, 4881, + 14075, 20887, 19205, 16712, 8657, 10654, 967, 15679, 11417, 9442, + 18739, 11091, 13545, 12529, 17465, 17570, 15107, 8903, 13152, 8279, + 12469, 17744, 20923, 5676, 11294, 16683, 13435, 18931, 8037, 14521, + 12239, 2224, 7927, 9925, 13383, 16435, 5925, 10806, 19465, 1821, + 3996, 6240, 18944, 19334, 9236, 5943, 9556, 5331, 9787, 2951, + 4771, 18945, 15905, 9322, 7242, 2680, 8090, 15171, 2467, 12153, + 17283, 14440, 9076, 12453, 5958, 7977, 11723, 15972, 17490, 15872, + 4259, 16085, 9614, 14879, 14995, 9444, 14880, 4024, 20015, 6180, + 17728, 14711, 2982, 20493, 8778, 16273, 16125, 3931, 16635, 8196, + 14343, 9816, 6833, 15317, 13154, 3556, 8372, 5511, 5858, 5962, + 21099, 12232, 6046, 2264, 12633, 4546, 2598, 10405, 8222, 9445, + 20611, 12476, 15747, 19725, 11655, 10406, 11118, 8050, 10058, 10587, + 13473, 19726, 11725, 1619, 6334, 19837, 9155, 13254, 12949, 20890, + 19184, 1827, 1343, 19832, 16603, 13965, 4583, 19833, 8711, 7158, + 14344, 14079, 12690, 12343, 16858, 19835, 13840, 6589, 7416, 11927, + 13397, 15856, 4743, 16636, 15639, 16356, 13868, 2066, 6099, 18323, + 6248, 11097, 10835, 19230, 18324, 6210, 14493, 10943, 20116, 6845, + 11533, 5758, 2653, 4321, 9791, 12808, 12809, 10910, 15727, 3118, + 16401, 1969, 6764, 1831, 17856, 7060, 7411, 4788, 18974, 19208, + 14577, 7749, 20638, 15453, 19603, 1467, 11277, 14526, 15975, 14474, + 19414, 8228, 3968, 16054, 7670, 13398, 15464, 10220, 6896, 19874, + 11559, 1178, 19508, 13557, 21347, 9845, 2178, 17201, 2956, 6144, + 21500, 10759, 19295, 9119, 4744, 10277, 16402, 17092, 19296, 12506, + 7940, 5777, 15282, 19885, 9727, 18607, 11004, 21405, 2527, 15381, + 3290, 16203, 5419, 14055, 20320, 14581, 10603, 10688, 16363, 20117, + 16802, 16544, 13006, 20243, 14529, 871, 20023, 19114, 15127, 15290, + 14530, 863, 12065, 2837, 16620, 2011, 11220, 5286, 6049, 6673, + 17036, 3626, 20966, 19240, 7798, 5258, 15176, 7713, 6775, 19158, + 5194, 14849, 2958, 17495, 19750, 17782, 6429, 1478, 1624, 20977, + 7595, 8809, 14451, 14261, 11128, 1000, 10375, 6397, 19441, 2235, + 4533, 19372, 5803, 10762, 13286, 19619, 7174, 18171, 2345, 16989, + 7175, 10304, 10223, 7907, 5850, 3102, 20854, 5089, 13030, 7718, + 3071, 2961, 16044, 11996, 15605, 18664, 16959, 11129, 15491, 14262, + 5975, 9728, 16204, 2609, 5113, 12206, 21572, 8630, 12187, 20495, + 2697, 17902, 6879, 7499, 18230, 2902, 9861, 3185, 15650, 7549, + 3103, 19341, 6258, 17658, 14820, 5650, 3104, 9047, 17903, 20978, + 12349, 8444, 7722, 12508, 3487, 6789, 7811, 16761, 12009, 7075, + 16410, 15146, 12956, 17045, 17046, 15253, 4178, 11286, 13955, 15142, + 20657, 3105, 18999, 20988, 16237, 15394, 18100, 9013, 18645, 16007, + 13982, 6167, 1505, 2192, 14780, 12602, 9969, 16411, 14095, 14088, + 2534, 8099, 6491, 7629, 9363, 3218, 6277, 5938, 20028, 10192, + 6278, 4935, 6054, 6122, 17214, 7503, 14197, 17047, 1038, 10378, + 11848, 19634, 10003, 14486, 3458, 6599, 20255, 17604, 19780, 14681, + 18024, 10085, 10782, 21520, 19379, 6794, 1994, 9801, 3768, 18707, + 6550, 20660, 10783, 3407, 19029, 15210, 12351, 8325, 15326, 13215, + 21459, 11877, 5833, 7953, 12165, 14091, 7085, 16516, 2810, 15332, + 15034, 15884, 14092, 21234, 9744, 11102, 14544, 14825, 11137, 11849, + 19312, 19313, 11017, 7959, 12732, 7197, 21716, 16667, 15553, 19197, + 19128, 4133, 3029, 6904, 13300, 9261, 8537, 885, 16413, 1701, + 5533, 12941, 19314, 1702, 9094, 4642, 2014, 10888, 7526, 16478, + 10666, 20155, 10454, 9662, 19447, 18514, 10384, 15013, 20997, 19355, + 4038, 16334, 6715, 17614, 12048, 14432, 1638, 2200, 11226, 10159, + 7375, 14097, 2539, 5536, 1706, 6914, 17311, 10344, 13242, 13826, + 9678, 8070, 17452, 19323, 15190, 16484, 6507, 18047, 21188, 10232, + 9181, 4137, 4537, 6383, 9182, 14762, 10097, 19324, 11103, 7217, + 9806, 7528, 19267, 9986, 19065, 7382, 2210, 3359, 13676, 7450, + 9216, 4504, 14870, 19851, 21470, 4763, 14360, 9433, 9217, 3112, + 13491, 19388, 12943, 4452, 8473, 18429, 19327, 13983, 20164, 10547, + 18419, 9534, 11105, 14250, 15398, 3471, 7699, 2249, 19329, 6064, + 21214, 9266, 9226, 11577, 16241, 10551, 18111, 17265, 18432, 5152, + 18436, 19820, 5668, 17394, 17395, 6679, 6203, 21322, 20357, 17563, + 2639, 20109, 12794, 21034, 4673, 11860, 16561, 12560, 18920, 12254, + 8580, 12058, 8581, 12097, 11457, 9905, 5670, 17663, 5671, 5672, + 1567, 3282, 17079, 20734, 21198, 8710, 20525, 4882, 1078, 17571, + 17572, 10118, 21411, 12108, 15354, 18500, 15887, 14207, 16389, 6658, + 21091, 7657, 17877, 6186, 13592, 6579, 17760, 17761, 17236, 19142, + 16686, 21093, 18548, 14644, 16345, 15906, 18043, 20114, 8583, 17083, + 17974, 20736, 12532, 6727, 5679, 2381, 6689, 2412, 6757, 9927, + 4902, 8091, 2382, 12596, 15840, 21435, 15874, 5886, 9299, 14182, + 17884, 2650, 13795, 6355, 16860, 14740, 6143, 18051, 8837, 8422, + 17415, 16861, 21360, 8525, 3682, 17580, 7053, 16793, 10493, 18376, + 8223, 10013, 9039, 6857, 16088, 16871, 3203, 16719, 6211, 8304, + 4966, 16661, 3068, 4789, 12481, 13316, 13966, 16872, 13317, 17669, + 18975, 7618, 19741, 5182, 12305, 5517, 16327, 14475, 5569, 14290, + 14291, 11634, 5336, 16357, 2424, 6147, 8993, 21062, 17068, 6700, + 4790, 9796, 17681, 7671, 1479, 19233, 21230, 16458, 16032, 14211, + 16885, 11929, 11930, 2182, 18227, 8092, 8097, 10963, 16505, 20340, + 7936, 13322, 13855, 6591, 4490, 13402, 15205, 18481, 9934, 7752, + 20216, 5570, 19990, 11554, 14664, 9847, 5456, 15492, 2357, 4362, + 1842, 6667, 17539, 17041, 16805, 19992, 6118, 6149, 16892, 20027, + 11515, 14213, 13323, 18623, 11130, 9732, 19304, 16753, 5408, 18394, + 13052, 1494, 1629, 3079, 10436, 7359, 10287, 12213, 15178, 19011, + 15893, 8445, 21592, 6432, 18822, 20989, 16509, 10181, 5978, 11975, + 13712, 8098, 9051, 3163, 20296, 7366, 16912, 16913, 19012, 17503, + 2668, 6635, 2240, 18698, 18103, 18400, 18104, 13075, 8536, 3573, + 4179, 14399, 7632, 4690, 14958, 19781, 9974, 8100, 14299, 4691, + 18105, 9258, 10947, 15533, 19030, 8101, 10987, 8024, 8025, 19309, + 19044, 18025, 9206, 15383, 1996, 16919, 13631, 21622, 9751, 6739, + 21208, 10093, 16371, 19045, 17549, 20557, 6803, 3299, 11934, 1757, + 13882, 6156, 18066, 7961, 2742, 3549, 18631, 6157, 9262, 1641, + 13824, 9670, 11406, 13972, 10528, 9131, 992, 18071, 8944, 14917, + 9891, 9684, 10349, 8463, 9900, 18415, 16939, 17617, 10239, 18716, + 1999, 13688, 19981, 9263, 3114, 2702, 5658, 8338, 2392, 11075, + 15527, 9264, 21218, 9254, 10107, 19822, 20533, 20731, 12109, 2465, + 16403, 5936, 8446, 18652, 21685, 4404, 2899, 8671, 20171, 3850, + 13012, 19374, 13037, 12060, 2338, 7339, 2893, 19614, 20341, 1553, + 1200, 1843, 2895, 19515, 4041, 2471, 11852, 8109, 15294, 13748, + 10790, 4544, 5162, 18363, 5246, 1303, 14992, 19530, 5248, 11439, + 3653, 13599, 13548, 21566, 10808, 8760, 12870, 9490, 12552, 5173, + 15593, 1345, 13558, 2957, 7254, 4749, 8686, 8229, 2786, 17042, + 1329, 10661, 7863, 10679, 14022, 16510, 9508, 4153, 15931, 13105, + 16920, 9671, 4042, 9945, 12024, 12395, 1866, 16940, 2714, 16419, + 13701, 2715, 1072, 7105, 2148, 21426, 5242, 8645, 1807, 6302, + 18190, 19135, 4458, 21357, 8910, 21070, 11455, 12255, 8219, 18780, + 17675, 16139, 10039, 12256, 11676, 18596, 19523, 18040, 3396, 1811, + 23007, 23008, 23009, 23010, 23011, 23012, 23013, 23014, 23015, 23016, + 23017, 23018, 23019, 23020, 23021, 23022, 23023, 23024, 23025, 23026, + 23027, 23028, 23029, 23030, 23031, 23032, 23033, 23034, 23035, 23036, + 23037, 23038, 23039, 23040, 23041, 23042, 23043, 23044, 23045, 23046, + 23047, 23048, 23049, 23050, 23051, 23052, 23053, 23054, 23055, 23056, + 23057, 23058, 23059, 23060, 23061, 23062, 23063, 23064, 23065, 23066, + 23067, 23068, 23069, 23070, 23071, 23072, 23073, 23074, 23075, 23076, + 23077, 23078, 23079, 23080, 23081, 23082, 23083, 23084, 23085, 23086, + 23087, 23088, 23089, 23090, 23091, 23092, 23093, 23094, 23095, 23096, + 23097, 23098, 23099, 23100, 23101, 23102, 11, 34, 37, 328, + 70, 72, 68, 118, 23934, 6, 66, 74, 330, 75, + 76, 77, 78, 109, 112, 88, 90, 92, 94, 96, + 98, 100, 102, 114, 115, 104, 106, 131, 132, 133, + 151, 143, 144, 136, 135, 146, 145, 134, 152, 137, + 165, 142, 140, 167, 124, 147, 148, 158, 155, 154, + 153, 138, 157, 163, 164, 159, 160, 431, 150, 149, + 339, 338, 327, 79, 80, 443, 18, 323, 321, 322, + 331, 325, 491, 335, 336, 176, 178, 177, 175, 174, + 169, 168, 171, 170, 332, 185, 189, 183, 187, 334, + 23103, 23104, 23105, 23106, 23107, 23108, 23109, 23110, 23111, 23112, + 23113, 23114, 23115, 23116, 23117, 23118, 23119, 23120, 23121, 23122, + 23123, 23124, 23125, 23126, 23127, 23128, 23129, 23130, 23131, 23132, + 23133, 23134, 23135, 23136, 23137, 23138, 23139, 23140, 23141, 23142, + 23143, 23144, 23145, 23146, 23147, 23148, 23149, 23150, 23151, 23152, + 23153, 23154, 23155, 23156, 23157, 23158, 23159, 23160, 23161, 23162, + 23163, 23164, 23165, 23166, 23167, 23168, 23169, 23170, 23171, 23172, + 23173, 23174, 23175, 23176, 23177, 23178, 23179, 23180, 23181, 23182, + 23183, 23184, 23185, 23186, 23187, 23188, 23189, 23190, 23191, 23192, + 23193, 23194, 23195, 23196, 23197, 23198, 345, 352, 359, 366, + 373, 380, 387, 394, 401, 407, 23679, 23680, 23681, 23682, + 23683, 23684, 344, 351, 358, 365, 372, 379, 386, 393, + 400, 406, 410, 413, 416, 418, 420, 422, 424, 426, + 428, 430, 343, 350, 357, 364, 371, 378, 385, 392, + 399, 405, 409, 412, 415, 417, 419, 421, 423, 425, + 427, 429, 342, 349, 356, 363, 370, 377, 384, 391, + 398, 404, 23685, 23686, 18727, 4412, 14015, 14972, 16730, 10188, + 12616, 1048, 8127, 14553, 23687, 23688, 346, 353, 360, 367, + 374, 381, 388, 395, 402, 408, 411, 414, 23689, 23690, + 23199, 23200, 23201, 23202, 23203, 23204, 23205, 23206, 23207, 23208, + 23209, 23210, 23211, 23212, 23213, 23214, 23215, 23216, 23217, 23218, + 23219, 23220, 23221, 23222, 23223, 23224, 23225, 23226, 23227, 23228, + 23229, 23230, 23231, 23232, 23233, 23234, 23235, 23236, 23237, 23238, + 23239, 23240, 23241, 23242, 23243, 23244, 23245, 23246, 23247, 23248, + 23249, 23250, 23251, 23252, 23253, 23254, 23255, 23256, 23257, 23258, + 23259, 23260, 23261, 23262, 23263, 23264, 23265, 23266, 23267, 23268, + 23269, 23270, 23271, 23272, 23273, 23274, 23275, 23276, 23277, 23278, + 23279, 23280, 23281, 23282, 23283, 23284, 23285, 23286, 23287, 23288, + 23289, 23290, 23291, 23292, 23293, 23294, 13, 14, 16, 324, + 20, 22, 1, 24, 27, 30, 121, 32, 3, 36, + 38, 340, 341, 348, 355, 362, 369, 376, 383, 390, + 397, 40, 43, 126, 128, 130, 45, 47, 432, 439, + 441, 447, 449, 456, 459, 462, 464, 470, 472, 477, + 481, 487, 492, 498, 500, 502, 504, 506, 509, 520, + 522, 524, 526, 528, 48, 50, 51, 52, 53, 57, + 433, 440, 442, 448, 450, 457, 460, 463, 465, 471, + 473, 478, 482, 488, 493, 499, 501, 503, 505, 507, + 510, 521, 523, 525, 527, 529, 60, 62, 64, 69, + 23295, 23296, 23297, 23298, 23299, 23300, 23301, 23302, 23303, 23304, + 23305, 23306, 23307, 23308, 23309, 23310, 23311, 23312, 23313, 23314, + 23315, 23316, 23317, 23318, 23319, 23320, 23321, 23322, 23323, 23324, + 23325, 23326, 23327, 23328, 23329, 23330, 23331, 23332, 23333, 23334, + 23335, 23336, 23337, 23338, 23339, 23340, 23341, 23342, 23343, 23344, + 23345, 23346, 23347, 23348, 23349, 23350, 23351, 23352, 23353, 23354, + 23355, 23356, 23357, 23358, 23359, 23360, 23361, 23362, 23363, 23364, + 23365, 23366, 23367, 23368, 23369, 23370, 23371, 23372, 23373, 23374, + 23375, 23376, 23377, 23378, 23379, 23380, 23381, 23382, 23383, 23384, + 23385, 23386, 23387, 23388, 23389, 23390, 645, 647, 649, 651, + 653, 655, 658, 660, 662, 664, 667, 669, 671, 673, + 675, 677, 680, 682, 684, 686, 688, 690, 692, 694, + 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, + 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, + 736, 738, 740, 742, 744, 746, 748, 750, 752, 754, + 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, + 776, 778, 780, 782, 784, 786, 788, 790, 792, 794, + 796, 798, 800, 802, 804, 806, 808, 810, 812, 23691, + 23692, 23693, 23694, 23695, 23696, 23697, 23698, 23699, 23700, 23701, + 23391, 23392, 23393, 23394, 23395, 23396, 23397, 23398, 23399, 23400, + 23401, 23402, 23403, 23404, 23405, 23406, 23407, 23408, 23409, 23410, + 23411, 23412, 23413, 23414, 23415, 23416, 23417, 23418, 23419, 23420, + 23421, 23422, 23423, 23424, 23425, 23426, 23427, 23428, 23429, 23430, + 23431, 23432, 23433, 23434, 23435, 23436, 23437, 23438, 23439, 23440, + 23441, 23442, 23443, 23444, 23445, 23446, 23447, 23448, 23449, 23450, + 23451, 23452, 23453, 23454, 23455, 23456, 23457, 23458, 23459, 23460, + 23461, 23462, 23463, 23464, 23465, 23466, 23467, 23468, 23469, 23470, + 23471, 23472, 23473, 23474, 23475, 23476, 23477, 23478, 23479, 23480, + 23481, 23482, 23483, 23484, 23485, 23486, 644, 646, 648, 650, + 652, 654, 657, 659, 661, 663, 666, 668, 670, 672, + 674, 676, 679, 681, 683, 685, 687, 689, 691, 693, + 695, 697, 699, 701, 703, 705, 707, 709, 711, 713, + 715, 717, 719, 721, 723, 725, 727, 729, 731, 733, + 735, 737, 739, 741, 743, 745, 747, 749, 751, 753, + 755, 757, 759, 761, 763, 765, 767, 769, 771, 773, + 775, 777, 779, 781, 783, 785, 787, 789, 791, 793, + 795, 797, 799, 801, 803, 805, 807, 809, 811, 656, + 665, 678, 23702, 23703, 23704, 23705, 23706, 23707, 23708, 23709, + 23487, 23488, 23489, 23490, 23491, 23492, 23493, 23494, 23495, 23496, + 23497, 23498, 23499, 23500, 23501, 23502, 23503, 23504, 23505, 23506, + 23507, 23508, 23509, 23510, 23511, 23512, 23513, 23514, 23515, 23516, + 23517, 23518, 23519, 23520, 23521, 23522, 23523, 23524, 23525, 23526, + 23527, 23528, 23529, 23530, 23531, 23532, 23533, 23534, 23535, 23536, + 23537, 23538, 23539, 23540, 23541, 23542, 23543, 23544, 23545, 23546, + 23547, 23548, 23549, 23550, 23551, 23552, 23553, 23554, 23555, 23556, + 23557, 23558, 23559, 23560, 23561, 23562, 23563, 23564, 23565, 23566, + 23567, 23568, 23569, 23570, 23571, 23572, 23573, 23574, 23575, 23576, + 23577, 23578, 23579, 23580, 23581, 23582, 530, 532, 534, 536, + 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, + 558, 560, 562, 564, 566, 568, 570, 572, 574, 576, + 23710, 23711, 23712, 23713, 23714, 23715, 23716, 23717, 531, 533, + 535, 537, 539, 541, 543, 545, 547, 549, 551, 553, + 555, 557, 559, 561, 563, 565, 567, 569, 571, 573, + 575, 577, 23718, 23719, 23720, 23721, 23722, 23723, 23724, 25, + 28, 110, 113, 89, 91, 93, 95, 97, 99, 101, + 103, 23725, 23726, 105, 107, 61, 65, 8, 23727, 82, + 87, 23728, 23729, 23730, 23731, 23732, 23733, 23734, 23735, 23736, + 23583, 23584, 23585, 23586, 23587, 23588, 23589, 23590, 23591, 23592, + 23593, 23594, 23595, 23596, 23597, 23598, 23599, 23600, 23601, 23602, + 23603, 23604, 23605, 23606, 23607, 23608, 23609, 23610, 23611, 23612, + 23613, 23614, 23615, 23616, 23617, 23618, 23619, 23620, 23621, 23622, + 23623, 23624, 23625, 23626, 23627, 23628, 23629, 23630, 23631, 23632, + 23633, 23634, 23635, 23636, 23637, 23638, 23639, 23640, 23641, 23642, + 23643, 23644, 23645, 23646, 23647, 23648, 23649, 23650, 23651, 23652, + 23653, 23654, 23655, 23656, 23657, 23658, 23659, 23660, 23661, 23662, + 23663, 23664, 23665, 23666, 23667, 23668, 23669, 23670, 23671, 23672, + 23673, 23674, 23675, 23676, 23677, 23678, 578, 580, 582, 584, + 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, + 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, + 626, 628, 630, 632, 634, 636, 638, 640, 642, 23737, + 23738, 23739, 23740, 23741, 23742, 23743, 23744, 23745, 23746, 23747, + 23748, 23749, 23750, 23751, 579, 581, 583, 585, 587, 589, + 591, 593, 595, 597, 599, 601, 603, 605, 607, 609, + 611, 613, 615, 617, 619, 621, 623, 625, 627, 629, + 631, 633, 635, 637, 639, 641, 643, 23752, 23753, 23754, + 23755, 23756, 23757, 23758, 23759, 23760, 23761, 23762, 23763, 23764, + 71, 58, 73, 5, 7, 329, 81, 446, 458, 190, + 184, 186, 188, 123, 139, 141, 156, 161, 162, 166, + 197, 204, 209, 210, 211, 217, 218, 219, 225, 226, + 227, 233, 234, 235, 245, 246, 247, 256, 257, 258, + 267, 268, 269, 278, 279, 280, 297, 298, 299, 212, + 220, 236, 228, 300, 301, 302, 303, 307, 309, 311, + 313, 315, 317, 319, 318, 316, 314, 312, 310, 308, + 304, 320, 305, 306, 172, 173, 179, 180, 181, 182, + 337, 122, 333, 116, 117, 23765, 23766, 23767, 23768, 23769, + 23770, 23771, 23772, 23773, 23774, 23775, 437, 434, 436, 435, + 455, 451, 454, 452, 469, 466, 468, 467, 497, 494, + 496, 495, 515, 511, 514, 512, 519, 516, 518, 517, + 513, 453, 438, 23776, 489, 490, 23777, 461, 23778, 23779, + 23780, 23781, 813, 814, 815, 816, 817, 818, 819, 820, + 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, + 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, + 841, 842, 843, 844, 845, 846, 847, 848, 849, 23782, + 23783, 23784, 23785, 23786, 23787, 23788, 23789, 23790, 23791, 23792, + 23793, 23794, 23795, 23796, 23797, 23798, 23799, 23800, 23801, 23802, + 347, 354, 361, 368, 375, 382, 389, 396, 403, 20773, + 484, 474, 486, 445, 475, 483, 444, 476, 479, 480, + 485, 41, 326, 67, 23803, 508, 21167, 23804, 4, 23805, + 23806, 23807, 23935, 9, 10, 23936, 23937, 119, 23938, 23939, + 83, 84, 85, 86, 54, 55, 56, 31, 33, 35, + 42, 39, 44, 12, 23, 26, 59, 63, 108, 111, + 15, 21, 29, 120, 2, 125, 129, 127, 49, 17, + 19, 46, 23808, 23809, 23810, 23811, 23812, 23813, 23814, 23815, + 23816, 23817, 23818, 23819, 23820,0, 23821, 23822, 23823, 23824, + 23825, 23826, 23827, 23828, 23829, 23830, 23831, 23832, 23833, 191, + 192, 198, 199, 193, 194, 200, 201, 195, 196, 202, + 203, 205, 206, 207, 208, 213, 214, 215, 216, 221, + 222, 223, 224, 229, 230, 231, 232, 237, 238, 239, + 240, 241, 242, 243, 244, 248, 249, 250, 251, 252, + 253, 254, 255, 259, 260, 261, 262, 263, 264, 265, + 266, 270, 271, 272, 273, 274, 275, 276, 277, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 23834, 23835, 23836, 23837, 23838, + 23839, 23840, 23841, 23842, 23843, 23844, 23845, 23846, 23847, 23848, + 8829, 17231, 6535, 6086, 20542, 7042, 18120, 14179, 15314, 15901, + 9317, 10807, 16850, 17084, 1310, 20931, 18257, 14124, 5959, 7983, + 12018, 4587, 17416, 1130, 12691, 1620, 19209, 9156, 7333, 12998, + 9036, 18384, 21630, 20942, 20743, 18167, 9930, 2092, 21583, 5037, + 4745, 16637, 19875, 2869, 16031, 18206, 17531, 7250, 1549, 19478, + 18563, 15235, 1836, 11304, 15065, 10689, 19887, 3315, 19763, 14531, + 6021, 13003, 18986, 20644, 2012, 6025, 10777, 7575, 11431, 2185, + 1002, 5217, 3180, 1359, 1506, 1495, 6633, 1901, 9970, 17909, + 15926, 18626, 14914, 17436, 14719, 4149, 7725, 5316, 8386, 4033, + 6795, 8879, 17252, 17253, 11834, 1558, 21785, 21786, 21787, 21788, + 21789, 21790, 21791, 21792, 21793, 21794, 21795, 21796, 21797, 21798, + 21799, 21800, 21801, 21802, 21803, 21804, 21805, 21806, 21807, 21808, + 21809, 21810, 21811, 21812, 21813, 21814, 21815, 21816, 21817, 21818, + 21819, 21820, 21821, 21822, 21823, 21824, 21825, 21826, 21827, 21828, + 21829, 21830, 21831, 21832, 21833, 21834, 21835, 21836, 21837, 21838, + 21839, 21840, 21841, 21842, 21843, 21844, 21845, 21846, 21847, 21848, + 21849, 21850, 21851, 21852, 21853, 21854, 21855, 21856, 21857, 21858, + 21859, 21860, 21861, 21862, 21863, 21864, 21865, 21866, 21867, 21868, + 21869, 21870, 21871, 21872, 21873, 21874, 21875, 21876, 21877, 21878, + 6905, 11896, 11018, 9944, 11594, 5692, 14720, 10345, 15311, 17313, + 11073, 13677, 11600, 10627, 17262, 12754, 8479, 11208, 21486, 10333, + 15102, 13369, 5048, 9375, 1054, 6226, 3669, 2883, 5098, 19567, + 12765, 19568, 2317, 6231, 16742, 4819, 7847, 18193, 10973, 1202, + 19952, 8405, 20040, 8406, 7324, 3397, 12430, 12996, 18932, 951, + 12470, 4883, 17960, 3000, 5431, 7289, 14307, 3007, 13669, 14466, + 14378, 15344, 21686, 10176, 1444, 20623, 7883, 7706, 7474, 9616, + 5680, 17147, 21094, 18216, 17786, 18471, 17853, 15109, 13192, 19144, + 18090, 1242, 17380, 17085, 5708, 2681, 17878, 12154, 9347, 3452, + 19224, 16567, 4261, 2513, 15633, 16750, 21879, 21880, 21881, 21882, + 21883, 21884, 21885, 21886, 21887, 21888, 21889, 21890, 21891, 21892, + 21893, 21894, 21895, 21896, 21897, 21898, 21899, 21900, 21901, 21902, + 21903, 21904, 21905, 21906, 21907, 21908, 21909, 21910, 21911, 21912, + 21913, 21914, 21915, 21916, 21917, 21918, 21919, 21920, 21921, 21922, + 21923, 21924, 21925, 21926, 21927, 21928, 21929, 21930, 21931, 21932, + 21933, 21934, 21935, 21936, 21937, 21938, 21939, 21940, 21941, 21942, + 21943, 21944, 21945, 21946, 21947, 21948, 21949, 21950, 21951, 21952, + 21953, 21954, 21955, 21956, 21957, 21958, 21959, 21960, 21961, 21962, + 21963, 21964, 21965, 21966, 21967, 21968, 21969, 21970, 21971, 21972, + 16716, 2510, 8526, 10903, 1315, 15875, 17286, 2830, 5964, 17964, + 18262, 17987, 17789, 4903, 16862, 10059, 9624, 7886, 15277, 4741, + 16257, 3760, 12433, 20430, 14083, 11250, 19742, 9160, 11251, 14501, + 16404, 15749, 2834, 1377, 2472, 4330, 2270, 1378, 10413, 5626, + 3784, 1321, 12999, 21418, 13200, 4454, 7888, 4062, 7860, 6701, + 19680, 10917, 2940, 17937, 15646, 17682, 3347, 13842, 11254, 7350, + 16459, 13920, 6592, 17537, 2863, 7424, 21326, 2323, 9797, 13565, + 4098, 18168, 6630, 10141, 14536, 13811, 15283, 18569, 16545, 16756, + 20654, 7945, 19306, 10691, 15548, 10144, 9651, 9282, 15761, 13013, + 3229, 8438, 20536, 1694, 14752, 2296, 21973, 21974, 21975, 21976, + 21977, 21978, 21979, 21980, 21981, 21982, 21983, 21984, 21985, 21986, + 21987, 21988, 21989, 21990, 21991, 21992, 21993, 21994, 21995, 21996, + 21997, 21998, 21999, 22000, 22001, 22002, 22003, 22004, 22005, 22006, + 22007, 22008, 22009, 22010, 22011, 22012, 22013, 22014, 22015, 22016, + 22017, 22018, 22019, 22020, 22021, 22022, 22023, 22024, 22025, 22026, + 22027, 22028, 22029, 22030, 22031, 22032, 22033, 22034, 22035, 22036, + 22037, 22038, 22039, 22040, 22041, 22042, 22043, 22044, 22045, 22046, + 22047, 22048, 22049, 22050, 22051, 22052, 22053, 22054, 22055, 22056, + 22057, 22058, 22059, 22060, 22061, 22062, 22063, 22064, 22065, 22066, + 9052, 21308, 3080, 18756, 12724, 8021, 20202, 13409, 1006, 9772, + 10979, 19169, 6464, 16517, 16723, 3574, 17793, 20297, 18106, 13480, + 3494, 9975, 9876, 13330, 15149, 5727, 8026, 4496, 7891, 10151, + 6988, 6796, 8027, 912, 20204, 3459, 7689, 5816, 15446, 6804, + 6553, 14096, 15216, 15737, 2813, 19638, 7962, 10346, 1705, 14771, + 21717, 9211, 17004, 7203, 17971, 13927, 16668, 5090, 9398, 4043, + 9679, 21013, 13850, 9709, 20158, 13332, 15702, 5736, 15188, 9135, + 10240, 10350, 9685, 9265, 19271, 11078, 17342, 13335, 5659, 3552, + 20166, 6564, 1812, 1822, 20848, 9705, 14696, 17347, 13055, 1161, + 12167, 4566, 3398, 4797, 11233, 16212, 22067, 22068, 22069, 22070, + 22071, 22072, 22073, 22074, 22075, 22076, 22077, 22078, 22079, 22080, + 22081, 22082, 22083, 22084, 22085, 22086, 22087, 22088, 22089, 22090, + 22091, 22092, 22093, 22094, 22095, 22096, 22097, 22098, 22099, 22100, + 22101, 22102, 22103, 22104, 22105, 22106, 22107, 22108, 22109, 22110, + 22111, 22112, 22113, 22114, 22115, 22116, 22117, 22118, 22119, 22120, + 22121, 22122, 22123, 22124, 22125, 22126, 22127, 22128, 22129, 22130, + 22131, 22132, 22133, 22134, 22135, 22136, 22137, 22138, 22139, 22140, + 22141, 22142, 22143, 22144, 22145, 22146, 22147, 22148, 22149, 22150, + 22151, 22152, 22153, 22154, 22155, 22156, 22157, 22158, 22159, 22160, + 6350, 18790, 1138, 8373, 2289, 2560, 10201, 3484, 11035, 21378, + 12482, 1554, 21148, 10202, 3018, 19241, 12814, 17208, 10305, 3708, + 11976, 21309, 10017, 16765, 3445, 16627, 19259, 18343, 15724, 5934, + 2291, 13265, 14383, 2227, 2228, 13930, 15091, 14397, 10393, 4786, + 20334, 4856, 12451, 3878, 13590, 10995, 1440, 8146, 15241, 10123, + 11440, 20011, 4884, 5330, 7849, 4885, 15720, 11441, 15587, 7543, + 16196, 4895, 11547, 11444, 11445, 2058, 15723, 5061, 1451, 3266, + 20943, 10563, 12032, 18741, 6481, 19604, 19605, 11447, 8527, 18957, + 10129, 3842, 6483, 3455, 21380, 7592, 2530, 2325, 16105, 9393, + 2111, 10152, 3859, 10020, 7559, 2744, 22161, 22162, 22163, 22164, + 22165, 22166, 22167, 22168, 22169, 22170, 22171, 22172, 22173, 22174, + 22175, 22176, 22177, 22178, 22179, 22180, 22181, 22182, 22183, 22184, + 22185, 22186, 22187, 22188, 22189, 22190, 22191, 22192, 22193, 22194, + 22195, 22196, 22197, 22198, 22199, 22200, 22201, 22202, 22203, 22204, + 22205, 22206, 22207, 22208, 22209, 22210, 22211, 22212, 22213, 22214, + 22215, 22216, 22217, 22218, 22219, 22220, 22221, 22222, 22223, 22224, + 22225, 22226, 22227, 22228, 22229, 22230, 22231, 22232, 22233, 22234, + 22235, 22236, 22237, 22238, 22239, 22240, 22241, 22242, 22243, 22244, + 22245, 22246, 22247, 22248, 22249, 22250, 22251, 22252, 22253, 22254, + 12354, 3866, 3867, 7773, 3417, 14744, 20979, 11522, 1412, 5163, + 21124, 17120, 17806, 2446, 18041, 12674, 17062, 3191, 1445, 21628, + 18004, 20808, 4436, 20891, 4630, 8185, 14183, 11699, 15601, 15889, + 7738, 16442, 6730, 15388, 2651, 10960, 8055, 17418, 15976, 10812, + 17419, 15158, 12565, 4201, 14713, 18987, 1369, 20510, 5627, 10676, + 9961, 7166, 15752, 935, 2656, 1481, 11255, 4114, 8681, 18181, + 3134, 14449, 21064, 20980, 19764, 4751, 18483, 2428, 15999, 5830, + 16571, 6595, 8842, 19119, 8448, 16903, 5616, 19013, 2896, 6780, + 11925, 3722, 20516, 14453, 3142, 19031, 21634, 15089, 14093, 3815, + 10313, 10314, 13216, 4943, 9879, 13106, 22255, 22256, 22257, 22258, + 22259, 22260, 22261, 22262, 22263, 22264, 22265, 22266, 22267, 22268, + 22269, 22270, 22271, 22272, 22273, 22274, 22275, 22276, 22277, 22278, + 22279, 22280, 22281, 22282, 22283, 22284, 22285, 22286, 22287, 22288, + 22289, 22290, 22291, 22292, 22293, 22294, 22295, 22296, 22297, 22298, + 22299, 22300, 22301, 22302, 22303, 22304, 22305, 22306, 22307, 22308, + 22309, 22310, 22311, 22312, 22313, 22314, 22315, 22316, 22317, 22318, + 22319, 22320, 22321, 22322, 22323, 22324, 22325, 22326, 22327, 22328, + 22329, 22330, 22331, 22332, 22333, 22334, 22335, 22336, 22337, 22338, + 22339, 22340, 22341, 22342, 22343, 22344, 22345, 22346, 22347, 22348, + 10154, 9331, 17220, 4640, 3390, 19213, 6155, 17221, 5617, 16373, + 11889, 19795, 16417, 19383, 9428, 9663, 14784, 3446, 10006, 10007, + 1681, 7210, 2577, 18515, 7757, 20761, 10891, 9692, 6922, 9185, + 7009, 17978, 19348, 19201, 19392, 15399, 3732, 10647, 10554, 10555, + 1775, 1778, 1079, 4426, 4427, 13140, 1389, 20208, 10861, 11998, + 3040, 10047, 11370, 7043, 12233, 5191, 4263, 5968, 1468, 2727, + 12976, 875, 17476, 6055, 6676, 6056, 20256, 3188, 6057, 17480, + 18701, 6059, 7691, 916, 17694, 6671, 9686, 12406, 6134, 7731, + 5119, 12121, 13399, 13620, 20323, 5528, 8503, 8504, 21150, 20327, + 20328, 20443, 4044, 12766, 19283, 1286, 852, 851, 860, 861, + 857, 859, 858, 868, 876, 882, 881, 891, 901, 893, + 896, 941, 928, 924, 955, 966, 974, 965, 970, 969, + 979, 982, 985, 987, 993, 1005, 1009, 1023, 1031, 1033, + 1042, 1041, 1058, 1061, 1052, 1051, 1055, 1062, 1047, 1059, + 1050, 1076, 1084, 1093, 1090, 12005, 1094, 1105, 1098, 1096, + 1111, 1114, 1112, 1120, 1113, 1126, 1127, 1131, 1145, 1142, + 1146, 1139, 1143, 1144, 1159, 1160, 1172, 1175, 1171, 1183, + 1170, 1169, 1176, 1184, 1187, 1189, 1199, 1201, 1197, 1205, + 1214, 1203, 1215, 1204, 1208, 1223, 1224, 1220, 1230, 1780, + 20526, 6087, 6094, 1781, 16266, 19553, 4527, 4967, 13400, 3540, + 10420, 20432, 9504, 7908, 17904, 7356, 12044, 942, 10339, 17862, + 21113, 3495, 947, 5537, 9687, 5138, 16340, 12795, 19913, 15721, + 17636, 17023, 4733, 11245, 11295, 14640, 20012, 12031, 4567, 10866, + 17275, 14645, 18444, 20737, 18600, 14384, 6887, 3311, 20680, 8930, + 8186, 14441, 10957, 11371, 21261, 20628, 14646, 3832, 11700, 21568, + 2356, 1747, 11093, 10214, 15909, 3871, 3683, 11623, 11299, 17988, + 20709, 18472, 11377, 21078, 11372, 10912, 13094, 5969, 6565, 2548, + 3240, 8376, 4264, 10760, 17289, 16874, 9077, 14212, 15753, 5814, + 16235, 9473, 14665, 13324, 9935, 20751, 1853, 1236, 1240, 1243, + 1239, 1237, 1262, 1261, 1273, 1263, 1270, 1279, 1285, 1290, + 1288, 1284, 1295, 1323, 1305, 1297, 1306, 1308, 1298, 1301, + 1319, 1320, 1311, 1339, 1350, 1349, 1357, 1364, 1365, 1373, + 1380, 1387, 1381, 1393, 1402, 1405, 1423, 1417, 1413, 1496, + 1483, 1501, 1429, 1449, 1443, 1427, 1433, 1480, 1430, 1456, + 1493, 1428, 1488, 1511, 1523, 1519, 1448, 1563, 1546, 1550, + 1568, 1569, 1590, 1591, 1580, 1605, 1606, 1608, 1598, 1615, + 1614, 1630, 1654, 1666, 1665, 1672, 1680, 1687, 1689, 1700, + 1691, 1686, 1713, 1729, 1728, 1744, 1735, 1740, 1746, 1745, + 9494, 9172, 15206, 8380, 12347, 6839, 10421, 5195, 21127, 19620, + 6840, 10704, 17125, 17716, 6705, 5815, 20118, 2971, 7351, 10964, + 6291, 17939, 15762, 17905, 4443, 16666, 5780, 11053, 16623, 8812, + 3489, 2399, 13325, 11395, 4702, 20257, 20518, 19032, 3789, 8796, + 11396, 14893, 3085, 10290, 2572, 10750, 5728, 6600, 14894, 16921, + 12586, 14430, 9909, 2391, 7518, 18702, 17913, 11423, 5785, 7519, + 18713, 917, 6810, 7442, 20560, 10929, 2758, 14072, 11842, 18068, + 18634, 6910, 11023, 11157, 12440, 11158, 9431, 8945, 17951, 11159, + 6923, 10352, 11028, 10241, 5660, 10767, 17006, 15528, 8622, 21239, + 13193, 19743, 14907, 20244, 8482, 14416, 1766, 1758, 1779, 1791, + 1798, 1776, 1785, 1777, 1829, 1815, 1835, 1825, 1844, 1805, + 1809, 1828, 1790, 1845, 1830, 1810, 1808, 1898, 1894, 1897, + 1896, 1920, 1904, 1905, 1908, 1929, 1919, 1910, 1931, 1938, + 1944, 1940, 1939, 1941, 1953, 1956, 1946, 1951, 1957, 1959, + 1972, 1962, 1975, 1974, 1976, 1983, 1991, 2004, 2007, 2000, + 2003, 2021, 2026, 2027, 2034, 2029, 2041, 2052, 2067, 2051, + 2050, 2055, 2083, 2088, 2105, 2094, 2119, 2120, 2117, 2128, + 2122, 2127, 2137, 2142, 2139, 2145, 2150, 2152, 2166, 2165, + 2186, 2180, 2175, 2183, 2229, 2220, 2230, 2255, 2261, 2265, + 6285, 19332, 21100, 7690, 20298, 19940, 1104, 3897, 12790, 21542, + 16782, 20568, 8817, 5164, 3370, 8409, 9603, 4823, 16562, 4280, + 8624, 20888, 7851, 1685, 4297, 20569, 15195, 16213, 7878, 11373, + 8187, 19715, 10638, 16144, 4306, 11446, 21225, 11910, 12454, 10048, + 12122, 9378, 1782, 12534, 19430, 8931, 8759, 13555, 21171, 5682, + 4313, 12839, 10408, 16443, 895, 17287, 18263, 12184, 9348, 6244, + 13270, 16498, 13091, 2089, 8761, 13614, 2252, 9283, 6212, 19606, + 17421, 17093, 1207, 10269, 19415, 2371, 2385, 18385, 14130, 9067, + 5518, 2090, 6449, 10371, 2437, 11932, 15030, 21448, 8763, 18329, + 21381, 8779, 2528, 12708, 21631, 13294, 2306, 2285, 2287, 2278, + 2286, 2281, 2305, 2310, 2318, 2321, 2319, 2335, 2328, 2332, + 2342, 2346, 2348, 2340, 2354, 2355, 2364, 2373, 2388, 2384, + 2378, 2389, 2394, 2404, 2407, 2403, 2417, 2405, 2406, 2408, + 2449, 2445, 2478, 2447, 2501, 2536, 2493, 2495, 2507, 2521, + 2518, 2535, 2498, 2496, 2545, 2546, 2550, 2551, 2569, 2592, + 2597, 2585, 2588, 2584, 2586, 2625, 2620, 2618, 2614, 2640, + 2648, 2638, 2646, 2675, 2676, 2693, 2694, 2703, 2709, 2733, + 2724, 2735, 2728, 2726, 2729, 2716, 2721, 2756, 2750, 2760, + 2766, 2764, 2791, 2774, 2796, 2778, 2785, 2775, 2772, 2808, + 9962, 8501, 1793, 11256, 7352, 6148, 13621, 9465, 19159, 16754, + 12709, 10591, 11591, 13923, 18276, 3907, 16152, 19236, 8734, 16465, + 14913, 20655, 4100, 17099, 3488, 15648, 11612, 15732, 12815, 4175, + 4752, 13629, 13069, 10692, 5387, 15143, 4269, 10146, 14954, 15497, + 6465, 12273, 8996, 15734, 17102, 12649, 9738, 16511, 20050, 4115, + 9114, 12030, 18577, 21312, 2195, 12820, 1008, 12190, 10193, 10382, + 8620, 2903, 2441, 19121, 9424, 12390, 12821, 12822, 3181, 21599, + 2993, 10596, 6994, 14238, 9332, 20299, 7520, 17053, 3911, 3770, + 1800, 20104, 13077, 3608, 9664, 7521, 16922, 20497, 13108, 7443, + 19791, 21391, 6128, 8738, 20260, 9454, 2803, 2805, 2851, 2836, + 2838, 2819, 2854, 2859, 2861, 2872, 2864, 2867, 2879, 2882, + 2890, 2892, 21361, 2898, 2444, 2905, 2912, 2913, 2920, 2926, + 2915, 2933, 2938, 2963, 2950, 2954, 2948, 2974, 2976, 2983, + 3001, 3012, 3021, 3022, 3019, 3017, 3014, 3006, 3037, 3045, + 3053, 3043, 3084, 3069, 2889, 3058, 3057, 3093, 3117, 3123, + 3141, 3143, 3130, 3153, 3164, 3162, 3177, 3170, 3171, 3196, + 3204, 3205, 3200, 3207, 3215, 3220, 3225, 3231, 3232, 3228, + 3255, 3252, 3260, 3267, 3274, 3291, 3295, 3308, 3309, 3313, + 3317, 3318, 3354, 3329, 3333, 3319, 3335, 3342, 3330, 3344, + 7820, 2814, 18717, 13633, 3496, 18873, 12281, 12282, 19642, 12426, + 12824, 919, 8701, 7379, 19796, 13928, 12125, 3032, 1861, 18516, + 10710, 17224, 8946, 9400, 9432, 21017, 9680, 9688, 4505, 13636, + 12126, 19272, 9693, 10242, 10243, 11408, 14858, 5661, 9223, 1934, + 18297, 13775, 19949, 15295, 10699, 17566, 18531, 12671, 1362, 4125, + 21071, 21072, 18737, 14570, 19531, 20924, 15776, 4991, 11114, 15161, + 10955, 2151, 10494, 19666, 16717, 21262, 5755, 17086, 20809, 5232, + 5233, 14881, 7934, 14443, 5062, 9066, 3684, 15570, 5552, 5647, + 21724, 10070, 10414, 3520, 20845, 1469, 2807, 6702, 19510, 19115, + 21507, 6897, 20646, 19928, 16720, 17245, 3331, 3372, 3367, 3364, + 3366, 3373, 3403, 3399, 3410, 3427, 3411, 3422, 3423, 3415, + 3421, 3425, 3451, 3464, 3465, 3480, 3481, 3500, 3518, 3532, + 3515, 3513, 3519, 3512, 3534, 3545, 3535, 3541, 3537, 3562, + 3555, 3564, 3579, 3568, 3569, 3580, 3589, 3584, 3582, 3603, + 3595, 3606, 3617, 3619, 3623, 3613, 3620, 20383, 3628, 3650, + 3648, 3663, 3693, 3685, 3674, 3666, 3677, 3692, 3723, 3716, + 3720, 3740, 3736, 3734, 3769, 3751, 3745, 3746, 3747, 3750, + 3757, 3759, 3758, 3761, 3786, 3775, 3790, 3779, 3774, 3806, + 3801, 3802, 3805, 3821, 3820, 3854, 3858, 3824, 3836, 3848, + 18482, 20818, 18748, 10918, 14938, 3695, 1326, 20656, 19424, 7176, + 5237, 15494, 14944, 10707, 15324, 5018, 17941, 12725, 19792, 6989, + 15008, 2196, 3441, 5786, 15217, 9568, 11879, 11071, 3533, 9672, + 19982, 20829, 20167, 9459, 13835, 17581, 15967, 13720, 21543, 2115, + 18921, 17143, 11714, 13342, 4709, 6039, 20013, 20801, 7974, 20802, + 19709, 8836, 1177, 12259, 11650, 9619, 19466, 12260, 1823, 10049, + 11716, 21755, 20810, 8288, 6872, 15910, 20945, 6873, 6101, 19102, + 21492, 20946, 13731, 4075, 21265, 11871, 5008, 5212, 20276, 14882, + 9068, 5127, 7987, 15640, 15996, 18209, 10599, 10423, 5555, 21760, + 21408, 1211, 6966, 20967, 9071, 9466, 3873, 3880, 3875, 3881, + 3887, 3889, 3906, 3898, 3894, 3914, 3918, 3919, 3941, 3944, + 3948, 3957, 3950, 3955, 3949, 3958, 3978, 3987, 3984, 3990, + 3994, 3998, 4005, 3977, 4020, 4023, 4029, 4058, 4025, 4060, + 4064, 4063, 4070, 4078, 4071, 4073, 4076, 4069, 4087, 4090, + 4101, 4091, 4092, 4094, 4111, 4123, 4119, 4120, 4145, 4141, + 4155, 4143, 4170, 4162, 4169, 4166, 4171, 4196, 4184, 4181, + 4193, 4211, 4219, 4208, 4240, 4236, 4226, 4237, 4235, 4268, + 4257, 4267, 4255, 4273, 4251, 4256, 4305, 4286, 4293, 4326, + 4316, 4308, 4360, 4370, 4369, 4396, 4395, 4399, 4398, 4411, + 12208, 9994, 21675, 19752, 10565, 10566, 18751, 17043, 1575, 7177, + 4930, 1497, 11949, 7753, 21065, 21589, 17827, 2452, 3542, 9799, + 21513, 19773, 17910, 20990, 5218, 5529, 13812, 15211, 13833, 7190, + 8632, 1988, 10980, 21008, 7178, 10445, 15095, 6990, 19343, 16596, + 13353, 9102, 19033, 6642, 13165, 7119, 17444, 12587, 7635, 21421, + 15934, 21735, 10508, 15219, 11881, 14098, 6811, 13673, 11957, 19797, + 12427, 7211, 16066, 16597, 2486, 6911, 8947, 10510, 1645, 14100, + 21422, 9542, 3161, 18186, 19547, 14379, 8015, 18615, 9318, 18601, + 1234, 1748, 16197, 21202, 7707, 3803, 16689, 5712, 2891, 18619, + 17422, 2514, 8807, 3431, 21449, 17824, 4418, 4424, 4437, 4442, + 4433, 4432, 4439, 4449, 4453, 4469, 4456, 4459, 4468, 4492, + 4481, 4483, 4499, 4475, 4485, 4510, 4514, 4521, 4522, 4516, + 4520, 4519, 4541, 4542, 4539, 4556, 4555, 4553, 4554, 4560, + 4561, 4563, 4575, 4585, 4578, 4580, 4576, 4600, 4608, 4609, + 4619, 4624, 4620, 4622, 4626, 4650, 4661, 4647, 4652, 4646, + 4649, 4668, 4680, 4671, 4701, 4707, 4704, 4708, 4711, 4712, + 4721, 4731, 4730, 4750, 4737, 4747, 4722, 4732, 4740, 4772, + 4768, 4777, 4780, 4785, 4784, 4800, 4806, 4812, 4843, 4820, + 4841, 4860, 4869, 4924, 4913, 4880, 4904, 4854, 4876, 4870, + 15094, 5614, 21419, 16641, 16205, 18210, 13326, 18578, 18579, 15799, + 2349, 15735, 3816, 8326, 9877, 16914, 16809, 8957, 2897, 20531, + 8894, 8895, 2485, 3210, 9880, 20221, 3168, 13134, 13333, 4013, + 20225, 10266, 13170, 2820, 14560, 4986, 12858, 2826, 6236, 12675, + 6016, 14467, 4654, 11209, 13505, 21263, 10050, 10216, 1767, 1117, + 15001, 6249, 8056, 3810, 18988, 14815, 8052, 13509, 12456, 9505, + 21320, 2086, 3575, 3219, 16224, 8072, 8612, 8073, 9377, 12194, + 2593, 10802, 21199, 16252, 7658, 15162, 13222, 18161, 21374, 19867, + 6002, 2081, 12295, 18859, 3932, 14186, 17088, 21204, 11505, 5473, + 13155, 11275, 1226, 2061, 12156, 10060, 4894, 4901, 4919, 4912, + 4853, 4952, 4951, 4964, 4959, 4960, 4956, 4963, 4968, 4953, + 4971, 4994, 5000, 5034, 5013, 4989, 5004, 4980, 4987, 4978, + 5016, 4982, 5006, 4979, 4983, 4981, 5015, 4984, 5045, 5044, + 5052, 5070, 5085, 5078, 5079, 5081, 5091, 5092, 5097, 5103, + 5104, 5099, 5123, 5128, 5120, 5124, 5150, 5153, 5156, 5166, + 5165, 5160, 5159, 5158, 5180, 5181, 5201, 5187, 5190, 5198, + 5188, 5202, 5213, 5220, 5219, 5227, 5250, 5257, 5255, 5240, + 5253, 5251, 5247, 5254, 5273, 5279, 5275, 5281, 5272, 5283, + 5313, 5308, 5309, 5317, 5319, 5320, 5332, 5327, 5329, 5344, + 11905, 4905, 4487, 5126, 4528, 14605, 10857, 14651, 13312, 11276, + 10656, 5775, 13442, 2602, 19111, 18620, 1422, 9084, 7665, 15245, + 13869, 6960, 6007, 21081, 9161, 3454, 2069, 4838, 16000, 9495, + 9286, 8258, 5628, 7425, 5935, 15941, 17098, 20969, 2522, 15163, + 21278, 21761, 15857, 2070, 5235, 5112, 8905, 20024, 11962, 17475, + 12547, 9163, 21648, 12021, 1499, 5314, 15358, 5600, 19556, 7357, + 20552, 6398, 20755, 14154, 21128, 10431, 9963, 8529, 4931, 20324, + 5486, 12886, 8530, 2927, 2073, 21676, 1875, 17942, 1555, 15248, + 17248, 12492, 17686, 6371, 14539, 19939, 2941, 10524, 16696, 3945, + 14915, 7077, 7800, 17687, 10967, 4535, 5348, 5352, 5354, 5364, + 5369, 5368, 5376, 5379, 5371, 5378, 5366, 5374, 5365, 5394, + 5395, 5396, 5404, 5403, 5415, 5412, 5414, 5429, 5428, 5442, + 5439, 5441, 5446, 5481, 5474, 5462, 5485, 5461, 5465, 5464, + 5463, 5524, 5495, 5513, 5504, 5500, 5501, 5543, 5545, 5541, + 5553, 5564, 5563, 5582, 5585, 5589, 5594, 5596, 5597, 5603, + 5612, 5605, 5607, 5608, 5606, 5629, 5625, 5663, 5642, 5657, + 5639, 5667, 5688, 5695, 5717, 5702, 5699, 5711, 5698, 5701, + 5706, 5742, 5753, 5746, 5751, 5773, 5769, 5779, 5772, 5765, + 5799, 5800, 5812, 5828, 5821, 5841, 5856, 5868, 5872, 5879, + 2875, 4754, 21288, 6262, 13163, 13350, 11202, 12984, 5488, 14588, + 20032, 6124, 15501, 19974, 2713, 13971, 20758, 11789, 12986, 17478, + 5388, 12086, 4067, 21460, 2789, 14159, 21289, 13016, 10227, 7367, + 1927, 6805, 1515, 3634, 3086, 18237, 14110, 3166, 12318, 12404, + 19798, 16045, 20258, 14160, 5787, 18832, 6434, 2241, 8813, 12497, + 20219, 6995, 10307, 2075, 11731, 15268, 3167, 3793, 15269, 9383, + 9810, 17445, 1862, 11141, 14161, 3497, 9885, 3392, 4975, 7444, + 11287, 9022, 3357, 7639, 15249, 9333, 17453, 10460, 14689, 20135, + 12781, 12023, 12736, 12321, 5133, 8333, 10461, 10455, 18288, 3461, + 14012, 21296, 5424, 12896, 9758, 14690, 5883, 5882, 5884, 5893, + 5890, 5892, 5891, 5906, 5910, 5916, 5933, 5915, 5929, 5931, + 5917, 5944, 5942, 5983, 5982, 5956, 5953, 5981, 5955, 5963, + 5951, 5948, 5993, 5999, 6003, 6029, 6028, 6023, 6018, 6035, + 6034, 6044, 6036, 6043, 6067, 6070, 6096, 6102, 6093, 6074, + 6079, 6076, 6075, 6100, 6114, 6089, 6081, 6098, 6151, 6150, + 6152, 6139, 6166, 6165, 6170, 6173, 6174, 6176, 6178, 6177, + 6190, 6192, 6184, 6204, 6205, 6207, 6239, 6247, 6235, 6224, + 6220, 6222, 6286, 6284, 6288, 6300, 6305, 6310, 6303, 6321, + 6318, 6323, 6366, 6352, 6363, 6351, 6373, 6349, 6372, 6360, + 9218, 9024, 19647, 19977, 6031, 20667, 15367, 15704, 11801, 2745, + 18839, 12746, 15615, 21338, 21157, 4472, 14789, 21156, 12944, 21473, + 15617, 10469, 10353, 7389, 16187, 19328, 19812, 9187, 10246, 13171, + 9764, 9227, 12904, 19984, 21054, 13495, 9765, 1566, 4108, 21702, + 9543, 14550, 10632, 19331, 19986, 21475, 19821, 4482, 14371, 20570, + 14380, 11917, 6088, 11647, 3227, 20507, 12863, 20374, 1418, 1163, + 16789, 14125, 8625, 13837, 1419, 15197, 19145, 20574, 11094, 15377, + 6420, 5107, 8294, 11378, 21145, 2563, 15115, 6250, 15913, 2062, + 9960, 21348, 1118, 9312, 4384, 13443, 6107, 17294, 4920, 9561, + 19968, 10432, 8232, 12716, 1132, 20479, 6348, 6391, 6393, 6410, + 6401, 6412, 6404, 6444, 6455, 6454, 6461, 6460, 6476, 6474, + 6473, 6477, 6501, 6499, 6498, 6500, 6511, 6516, 6531, 6537, + 6530, 6566, 6576, 6580, 6575, 6590, 6593, 6582, 6578, 6574, + 6570, 6607, 6611, 6617, 6641, 6639, 6644, 6612, 6614, 6623, + 6629, 6660, 6664, 6657, 6663, 6678, 6684, 6696, 6713, 6682, + 6731, 6718, 6774, 6735, 6785, 6741, 6763, 6760, 6758, 6761, + 6744, 6756, 6743, 6745, 6752, 6749, 6830, 6828, 6831, 6846, + 6843, 6856, 6867, 6871, 6875, 6874, 6888, 6882, 6894, 6906, + 6883, 6892, 6929, 6935, 6952, 6936, 6965, 6978, 6949, 6971, + 5865, 6450, 14029, 15498, 1577, 11182, 21633, 7505, 9509, 17606, + 4847, 11952, 1336, 5531, 17783, 7259, 21352, 15505, 14032, 4717, + 7598, 11340, 14033, 14034, 11956, 2670, 9826, 8882, 1880, 6558, + 14787, 7212, 17314, 16048, 11806, 9689, 21783, 3638, 11807, 15809, + 9267, 14923, 8111, 5372, 20764, 8113, 19524, 7143, 2143, 21139, + 18085, 19938, 6237, 19549, 5249, 16253, 13755, 16564, 13384, 11502, + 21487, 15959, 11862, 4804, 7147, 14736, 2952, 12261, 20708, 14126, + 6241, 20892, 7045, 4656, 20016, 13758, 3402, 7884, 4570, 3193, + 8138, 20094, 1064, 4831, 20948, 12639, 2710, 6245, 20095, 17027, + 4906, 17582, 14388, 1788, 21266, 13507, 6938, 6932, 6944, 6987, + 6928, 6941, 6947, 6953, 6961, 7026, 7033, 7057, 7069, 7092, + 7061, 7024, 7041, 7047, 7030, 7032, 7063, 7031, 7108, 7101, + 7109, 7102, 7168, 7131, 7187, 7136, 7126, 7159, 7135, 7155, + 7142, 7153, 7152, 7124, 7125, 7140, 7130, 7134, 7129, 7148, + 7127, 7257, 7236, 7228, 7232, 7241, 7227, 7268, 7278, 7292, + 7287, 7293, 7307, 7312, 7304, 7306, 7305, 7308, 7320, 7330, + 7319, 7317, 7334, 7321, 7349, 7329, 7325, 7326, 7316, 7341, + 7401, 7410, 7400, 7432, 7418, 7397, 7404, 7426, 7399, 7407, + 7406, 7467, 7498, 7494, 7491, 7468, 7458, 7495, 7504, 7459, + 10061, 21267, 14318, 5144, 18503, 4907, 16147, 20682, 3340, 2831, + 14524, 21042, 17196, 21688, 8079, 1179, 13475, 11379, 14809, 21720, + 8933, 7984, 13763, 6008, 17588, 7792, 21174, 2725, 5592, 1119, + 8431, 8934, 6362, 3051, 6542, 5337, 15540, 17532, 8840, 7666, + 13560, 5071, 10657, 17991, 1366, 17290, 4915, 5318, 15914, 13798, + 15804, 19112, 9419, 17589, 8377, 5063, 3843, 15940, 14934, 7591, + 17353, 6765, 8432, 7427, 8381, 2570, 16607, 20713, 10498, 2523, + 13403, 14750, 1198, 15942, 17427, 6544, 13180, 5355, 17781, 15647, + 17792, 17538, 6255, 17038, 4921, 15841, 15186, 4130, 9072, 4839, + 7991, 6424, 20819, 18270, 8095, 4776, 7470, 7475, 7464, 7463, + 7478, 7486, 7473, 7462, 7548, 7539, 7540, 7542, 7538, 7561, + 7569, 7567, 7566, 7565, 7581, 7593, 7585, 7631, 7616, 7634, + 7617, 7615, 7606, 7607, 7611, 7614, 7609, 8468, 7663, 7662, + 7660, 7650, 7661, 7652, 7648, 7654, 7687, 7653, 7667, 7711, + 7719, 7708, 7709, 7701, 7712, 7747, 7736, 7735, 7739, 7751, + 7733, 7805, 7767, 7763, 8220, 7772, 7788, 7799, 7808, 7777, + 7778, 7832, 7829, 7842, 7867, 7843, 7848, 7854, 7837, 7850, + 7853, 7845, 7869, 7889, 7871, 7874, 7870, 7876, 7894, 7898, + 7904, 7895, 7903, 7923, 7942, 7930, 7941, 7922, 7932, 7931, + 7167, 17898, 13734, 21590, 2398, 4220, 9652, 10521, 9822, 2734, + 13594, 14319, 12717, 21406, 12719, 16283, 12980, 17299, 14717, 16407, + 15572, 16284, 5175, 16330, 1371, 21384, 1955, 5866, 3206, 10592, + 10180, 12779, 20457, 1500, 2988, 10080, 11150, 12647, 13160, 15733, + 21591, 5804, 21649, 16894, 21514, 17730, 9835, 7909, 4590, 13931, + 11258, 19765, 21620, 4491, 10522, 17906, 19242, 14284, 12720, 17911, + 17335, 7360, 8735, 17302, 13924, 11151, 6979, 4102, 2699, 3709, + 11259, 10841, 19892, 17599, 1253, 14955, 13351, 1556, 6568, 5340, + 3082, 11178, 16512, 5021, 16470, 15956, 5421, 11203, 17544, 9800, + 21593, 1601, 5807, 19122, 15651, 5574, 7919, 7920, 7975, 7992, + 7972, 7989, 7986, 7996, 7969, 7980, 7993, 7990, 7971, 8005, + 8030, 8017, 8016, 8064, 8060, 8054, 8068, 8034, 8043, 8059, + 8051, 8044, 8032, 8088, 8093, 8119, 8110, 8107, 8135, 8137, + 8128, 8134, 8126, 8139, 8152, 8153, 8143, 8144, 8157, 8145, + 8154, 8147, 8213, 8176, 8178, 8184, 8175, 8180, 8224, 8216, + 8250, 8254, 8253, 8252, 8315, 8278, 8301, 8273, 8282, 8303, + 8320, 8311, 8290, 8272, 8300, 8287, 8293, 8341, 8345, 8340, + 8366, 8374, 8354, 8370, 8389, 8478, 8401, 8418, 8413, 8458, + 8412, 8396, 8399, 8410, 8489, 8499, 8494, 8487, 8488, 8519, + 20998, 20073, 2479, 2194, 3351, 17103, 19893, 21621, 17834, 14484, + 16366, 5341, 14114, 19310, 7954, 19034, 21386, 11709, 1194, 5530, + 12046, 21153, 7368, 3004, 13574, 14868, 20076, 17105, 3182, 7191, + 13817, 15551, 5027, 20033, 20693, 5221, 13907, 6376, 20131, 15608, + 17306, 15147, 20694, 21635, 15552, 6668, 1960, 1516, 4779, 3144, + 9516, 15270, 18339, 17000, 21637, 9395, 21332, 12989, 10785, 20858, + 10509, 11400, 12392, 9745, 18000, 21623, 6996, 14200, 15220, 10526, + 1372, 18758, 14058, 11323, 13047, 6848, 17166, 7198, 14144, 17799, + 13663, 18001, 15224, 13080, 20301, 21765, 20826, 14241, 14035, 9981, + 19799, 4501, 9886, 2337, 21741, 7527, 8515, 8528, 8522, 8516, + 8524, 8545, 8544, 8546, 10204, 8552, 8554, 8571, 8559, 8567, + 8589, 8593, 8591, 8598, 8600, 8614, 8626, 8629, 8633, 8637, + 8644, 8639, 8647, 8655, 8656, 8659, 8664, 8668, 8669, 8670, + 8680, 8695, 8692, 8673, 8702, 8703, 8708, 8714, 8715, 8716, + 8720, 8725, 8741, 8745, 8743, 8744, 8757, 8755, 8773, 8786, + 8785, 8787, 8790, 8797, 8800, 8805, 8819, 8820, 8826, 8830, + 8843, 8832, 8841, 8846, 8853, 8855, 8857, 8856, 8864, 8872, + 8866, 8865, 8884, 8892, 8896, 8904, 8909, 8929, 8926, 8932, + 8923, 8922, 8950, 8954, 8952, 8955, 8971, 8963, 8977, 8992, + 13709, 2243, 13936, 17800, 6812, 6495, 21698, 16928, 13049, 20034, + 3300, 14487, 6815, 7213, 14099, 7445, 7562, 6559, 13081, 3089, + 7868, 7694, 1531, 2204, 19057, 11885, 15225, 19058, 14141, 13884, + 7218, 1708, 12959, 9219, 12590, 18072, 12747, 12225, 18637, 11409, + 9457, 17555, 21701, 8948, 19449, 17915, 9401, 17176, 2212, 7697, + 10354, 2213, 19276, 1945, 13689, 17180, 21712, 21703, 10667, 17007, + 9255, 9412, 9809, 6227, 13749, 21244, 20700, 3829, 17026, 19231, + 15568, 20065, 17291, 3173, 17568, 4808, 4809, 12626, 1789, 12483, + 17382, 20548, 5176, 19250, 5654, 21742, 15425, 2017, 12825, 16628, + 19268, 9402, 15432, 10355, 14973, 5154, 9008, 9004, 9005, 9028, + 9029, 9062, 9075, 9080, 9078, 9089, 9088, 9103, 9104, 9115, + 9124, 9120, 9127, 9106, 9148, 9141, 9173, 9196, 9192, 9191, + 9190, 9204, 9195, 9188, 9200, 9198, 9237, 9235, 9244, 9238, + 9256, 9257, 9279, 9281, 9274, 9277, 9270, 9296, 9308, 9311, + 9314, 9316, 9340, 9341, 9343, 9360, 9357, 9356, 9379, 9369, + 9388, 9396, 9425, 9422, 9446, 9426, 9417, 9451, 9440, 9443, + 9441, 9463, 9464, 9469, 9476, 9478, 9486, 9514, 9515, 9479, + 9480, 9493, 9558, 9549, 9550, 9566, 9547, 9482, 9605, 9581, + 9611, 9583, 9578, 9585, 9618, 9577, 9584, 9630, 9590, 9598, + 13649, 14373, 5471, 21226, 8188, 10999, 11247, 5591, 15642, 8378, + 4916, 14394, 5593, 21450, 19753, 962, 4444, 14945, 10708, 10182, + 1101, 4446, 2350, 16518, 1507, 7199, 2690, 10185, 8387, 11142, + 20561, 10621, 12322, 7014, 7020, 10548, 11086, 3283, 18469, 19502, + 19500, 4676, 1065, 18521, 5506, 12997, 20172, 5189, 18958, 21268, + 18808, 13799, 13645, 13044, 6545, 17295, 18990, 18509, 13014, 12933, + 19625, 5342, 19899, 4502, 14203, 4694, 14204, 9780, 11891, 13053, + 5405, 2682, 4657, 6242, 2647, 3194, 4908, 17089, 12172, 9107, + 12264, 10189, 20949, 13476, 16951, 17533, 16878, 8706, 6767, 6695, + 17423, 14153, 6256, 7547, 3543, 14155, 9634, 9580, 9626, 9588, + 9597, 9576, 9503, 9553, 9710, 9721, 9718, 9714, 9757, 9725, + 9716, 9717, 9715, 9766, 9768, 9793, 9786, 9785, 9783, 9819, + 9813, 9815, 9820, 9811, 9828, 9842, 9846, 9844, 9839, 9841, + 9869, 9855, 9856, 9854, 9875, 9857, 9853, 9352, 9902, 9908, + 9881, 9859, 9906, 9914, 9933, 9926, 9915, 9929, 9959, 9952, + 9979, 9977, 9953, 9951, 9988, 9957, 9996, 10012, 10009, 10027, + 10044, 10067, 10078, 10079, 10051, 10028, 10063, 10046, 10030, 10052, + 10035, 10112, 10116, 10115, 10119, 10128, 10140, 10130, 10138, 10126, + 10121, 10145, 10125, 10173, 10187, 10205, 10218, 10207, 10217, 10226, + 2662, 17943, 2667, 21594, 16297, 6710, 6295, 6153, 12393, 9746, + 13485, 1012, 9982, 12173, 13135, 1014, 6816, 17952, 3550, 9339, + 5432, 5435, 5433, 3833, 13915, 4377, 4084, 15836, 12265, 2599, + 13519, 7246, 8295, 2780, 10600, 7071, 20259, 10291, 7001, 9365, + 6915, 19450, 6509, 18906, 13195, 20018, 3371, 6243, 20837, 20838, + 20683, 2383, 20745, 19505, 16215, 15770, 4385, 18207, 15813, 14106, + 6050, 14504, 9936, 7994, 1424, 3660, 5851, 16572, 17907, 12484, + 3072, 3908, 3909, 15864, 8264, 3083, 8956, 9739, 9740, 16624, + 9016, 9747, 9752, 3087, 14478, 15045, 15843, 9023, 11795, 20859, + 3393, 11837, 13142, 7531, 15844, 15846, 10219, 10258, 10260, 10257, + 10280, 10273, 10300, 10306, 10310, 10308, 10323, 10321, 10335, 10322, + 10327, 10369, 10365, 10366, 10372, 10466, 10422, 10316, 10425, 10401, + 10411, 10444, 10415, 10398, 10394, 10434, 10474, 10486, 10496, 10488, + 10491, 10505, 10497, 10499, 10515, 10519, 10513, 10516, 10419, 10517, + 10531, 10532, 10530, 10536, 10557, 10558, 10561, 10562, 10571, 10579, + 10574, 10573, 10576, 10577, 10601, 10612, 10620, 10608, 10613, 10616, + 10617, 10618, 10640, 10658, 10650, 10653, 10651, 10671, 10675, 10684, + 10685, 10686, 10682, 10701, 10714, 10712, 10715, 10718, 10728, 10729, + 10725, 10730, 10749, 10746, 10743, 10761, 10780, 10768, 10775, 10776, + 10247, 20545, 14996, 15128, 20554, 18888, 13372, 8740, 2045, 5245, + 3614, 6572, 2617, 13750, 13891, 19917, 2099, 5919, 4674, 12129, + 12074, 19459, 13652, 16591, 12673, 12291, 16831, 16832, 8742, 3830, + 1446, 1080, 1817, 13469, 15722, 21544, 4607, 20803, 11696, 12180, + 21570, 4824, 17192, 11442, 13437, 8674, 2623, 18443, 12075, 2557, + 17745, 4380, 6188, 21571, 5709, 2511, 15796, 3195, 10900, 17524, + 17525, 10731, 17526, 11815, 16604, 16594, 17764, 8053, 19506, 6181, + 9931, 14184, 15876, 10904, 2955, 14444, 7274, 15592, 8343, 7054, + 17763, 17666, 16126, 2515, 16070, 4003, 11606, 12332, 5512, 9461, + 20509, 15201, 7750, 9833, 14872, 1621, 10770, 10795, 10803, 10799, + 10994, 10793, 10817, 10825, 10833, 10840, 10827, 10828, 10856, 10849, + 10864, 10865, 10872, 10881, 10867, 10890, 10896, 10895, 10902, 10922, + 10926, 10916, 10894, 10899, 10907, 10945, 10936, 10938, 10954, 10959, + 10951, 10958, 10971, 10983, 10990, 11001, 11036, 11021, 11005, 11037, + 11034, 11046, 11045, 11096, 11064, 11072, 11067, 11057, 11060, 11055, + 11085, 11116, 11112, 11111, 11132, 11117, 11121, 11149, 11145, 11147, + 11170, 11162, 11166, 11168, 11175, 11181, 11188, 11190, 11191, 11204, + 11198, 11200, 11207, 11206, 11221, 11217, 11234, 11268, 11264, 11274, + 11273, 11272, 11292, 11311, 11293, 11300, 11291, 11318, 11321, 11325, + 10590, 12368, 5874, 13561, 2924, 3428, 11628, 11514, 13764, 14445, + 2985, 8199, 3969, 12308, 5846, 16664, 10919, 13921, 4173, 2657, + 10615, 11988, 3696, 936, 11611, 14847, 20069, 21063, 13843, 16001, + 16461, 7672, 7255, 4099, 1482, 2292, 12954, 16218, 14714, 15495, + 15134, 21382, 19001, 9862, 7072, 12312, 17540, 10502, 11977, 2297, + 10437, 5853, 12078, 2853, 7577, 4844, 21310, 10438, 7630, 19353, + 10480, 18031, 2077, 15932, 11710, 9878, 3209, 5729, 17440, 15598, + 4497, 20857, 7633, 6344, 3208, 18724, 17336, 15189, 4716, 21295, + 3409, 8880, 11880, 8459, 2848, 8361, 9129, 9777, 16103, 12737, + 3213, 1720, 18067, 11618, 16669, 20188, 11331, 11346, 11332, 11333, + 11339, 11336, 11349, 11352, 11355, 11376, 11391, 11401, 11364, 11386, + 11385, 11366, 11420, 11413, 11428, 11437, 11435, 11434, 11436, 11429, + 11467, 11475, 11468, 11464, 11474, 11450, 11452, 11472, 11458, 11479, + 11485, 11491, 11621, 11501, 11494, 11499, 11497, 11521, 11518, 11519, + 11531, 11529, 11544, 11539, 11549, 11568, 11584, 11604, 11602, 11613, + 11615, 11625, 11627, 11493, 11635, 11636, 11642, 11665, 11648, 11646, + 11643, 11674, 11673, 11698, 11707, 11697, 11705, 18231, 11712, 11713, + 11729, 11728, 11724, 11737, 11741, 11744, 11747, 11758, 11760, 11769, + 11799, 11771, 11786, 11787, 11768, 11817, 11823, 11822, 11830, 11819, + 17312, 1642, 17733, 9056, 9132, 18239, 10351, 6921, 20098, 10644, + 13496, 20189, 10549, 11670, 20099, 12859, 16654, 5696, 9980, 5693, + 7647, 7162, 5193, 2761, 11152, 11790, 5278, 7488, 3845, 20816, + 17766, 15359, 17271, 2100, 13616, 19682, 17688, 8265, 8163, 17671, + 14339, 8136, 15389, 14673, 15458, 12611, 12612, 5631, 6496, 15763, + 17100, 3507, 4484, 12000, 15378, 4486, 2866, 10331, 10066, 17090, + 13319, 12084, 8849, 4922, 20217, 4778, 9497, 19616, 9287, 15880, + 1846, 11740, 8205, 6638, 21595, 1602, 11477, 3857, 3983, 1216, + 2110, 19035, 2015, 10292, 3355, 18032, 18632, 3577, 3462, 13039, + 10387, 18874, 7091, 7532, 6916, 12748, 11821, 11845, 11851, 11855, + 11861, 11858, 11870, 11869, 11866, 11886, 11901, 11908, 11912, 11915, + 11928, 11924, 11923, 11936, 11954, 11958, 11942, 11961, 11968, 11971, + 11969, 11992, 11986, 11987, 11994, 12001, 11999, 12004, 12011, 12012, + 12007, 12014, 12017, 12020, 12016, 12027, 12026, 12034, 12033, 12037, + 12045, 12061, 12062, 12055, 12059, 12071, 12081, 12083, 12094, 12098, + 12099, 12103, 12102, 12107, 12110, 12117, 12119, 12127, 12131, 12137, + 12141, 12139, 12135, 12155, 12148, 12147, 12163, 12168, 12181, 12177, + 12183, 12215, 12199, 12209, 12200, 12207, 12217, 12218, 12192, 12210, + 12231, 12237, 12250, 12257, 12284, 12247, 12252, 12272, 12306, 12292, + 10389, 10356, 2216, 14861, 7370, 12455, 18412, 18428, 2040, 9374, + 15833, 15771, 7605, 12191, 18896, 2097, 11144, 5094, 19700, 6408, + 21561, 6750, 15167, 20902, 16093, 16427, 12791, 16560, 13721, 4862, + 21245, 6445, 8403, 7133, 1021, 2773, 10862, 13776, 5996, 19136, + 19498, 18907, 13139, 12331, 3672, 3616, 9596, 19429, 1304, 18852, + 21250, 11677, 1813, 1741, 17779, 18597, 17144, 6232, 20347, 3923, + 3823, 11765, 6327, 10897, 14463, 5565, 1441, 16492, 4875, 21479, + 20882, 7144, 3063, 11749, 18017, 5271, 9604, 13789, 2155, 2410, + 19710, 6011, 21562, 9922, 16714, 4185, 5705, 3048, 5444, 5677, + 7613, 19579, 21484, 4438, 10819, 21073, 12299, 12307, 12294, 12285, + 12327, 12333, 12350, 12341, 12355, 12363, 12360, 12358, 12381, 12389, + 12387, 12399, 12408, 12416, 12419, 12425, 12435, 12431, 12443, 12449, + 12450, 12462, 12464, 12477, 12458, 12460, 12473, 12459, 12466, 12500, + 12502, 12505, 12511, 12533, 12539, 12526, 12535, 12540, 12558, 12566, + 12555, 12575, 12578, 12576, 12580, 12594, 12592, 12593, 12597, 12595, + 12601, 12614, 12613, 12636, 12638, 12624, 12630, 12619, 12615, 12623, + 12646, 12621, 12618, 12667, 12701, 12668, 12670, 12692, 12686, 12680, + 12660, 12715, 12672, 12659, 12698, 12769, 12760, 12756, 12758, 12762, + 12797, 12798, 12818, 12783, 12787, 12788, 12789, 12793, 12784, 12827, + 12856, 21200, 6536, 4825, 5058, 3284, 2878, 7976, 4378, 968, + 13088, 2594, 12471, 7879, 9345, 14805, 21343, 3285, 2056, 19580, + 4074, 16436, 9481, 3997, 4829, 13730, 19146, 1918, 20042, 15173, + 2506, 2413, 16715, 1674, 16851, 5353, 21264, 11375, 21346, 21756, + 16122, 13385, 15256, 2414, 12196, 11000, 17725, 7978, 2370, 8495, + 18259, 3253, 5960, 3254, 7272, 16315, 19468, 11863, 14289, 17284, + 16601, 7783, 11548, 11461, 16026, 11637, 10818, 3050, 3686, 13470, + 3933, 21644, 9108, 10409, 16499, 11773, 9037, 12577, 20115, 5211, + 5860, 10588, 2722, 2921, 20453, 10978, 9487, 1266, 13237, 8359, + 13196, 3656, 7740, 7900, 13092, 15355, 12836, 12837, 12862, 12848, + 12860, 12867, 12842, 12851, 12878, 12843, 12873, 12919, 12937, 12917, + 12918, 12912, 12932, 12952, 12947, 12957, 12970, 12972, 12962, 12979, + 12995, 12990, 13004, 12991, 13026, 13028, 13025, 13041, 13074, 13067, + 13065, 13056, 13090, 13107, 13086, 13087, 13115, 13132, 13130, 13126, + 13122, 13119, 13124, 13138, 13141, 13143, 13146, 13148, 13174, 13173, + 13172, 13194, 13199, 13204, 13190, 13210, 13201, 13228, 13235, 13245, + 13247, 13246, 13248, 13249, 13255, 13278, 13271, 13273, 13268, 13282, + 13283, 13290, 13318, 13308, 13341, 13336, 13338, 13392, 13373, 13366, + 13381, 13375, 13446, 13421, 13440, 13422, 13441, 13431, 13429, 13474, + 5334, 6458, 13177, 930, 16324, 1376, 21125, 7336, 9992, 15438, + 15726, 3538, 6394, 6103, 2934, 2290, 6538, 4632, 9157, 14149, + 18315, 18805, 14308, 7160, 5611, 2063, 20684, 16182, 8116, 1459, + 18961, 11002, 1282, 12123, 3902, 13346, 8682, 17383, 16296, 19673, + 19674, 5009, 9792, 17934, 11560, 2068, 16638, 2969, 17424, 1551, + 11465, 933, 19297, 9085, 9086, 7545, 11176, 21759, 21780, 21665, + 13841, 16985, 18688, 934, 13477, 7342, 4917, 10520, 7343, 12170, + 6251, 6252, 6289, 18386, 15977, 21503, 13274, 11098, 6626, 14391, + 5082, 21146, 7489, 16452, 1832, 16358, 7163, 4095, 18621, 15175, + 13562, 20639, 6838, 14528, 9194, 21585, 13504, 13506, 13511, 13522, + 13514, 13533, 13585, 13540, 13575, 13544, 13539, 13554, 13547, 13588, + 13597, 13596, 13605, 13604, 13607, 13608, 13623, 13625, 13615, 13613, + 13644, 13646, 13658, 13662, 13665, 13668, 13680, 13686, 13687, 13685, + 13690, 13695, 13702, 13707, 13710, 13711, 13716, 13715, 13713, 13726, + 13752, 13742, 13738, 13736, 13746, 13745, 13772, 13773, 13778, 13784, + 13790, 13807, 13791, 13818, 13810, 13806, 13792, 13788, 13829, 13839, + 13836, 13857, 13864, 13885, 13873, 13877, 13861, 13893, 13892, 13890, + 13895, 13906, 13914, 13912, 13933, 13944, 13943, 13951, 13952, 13960, + 13962, 13978, 13979, 13988, 14002, 14005, 14000, 14009, 14014, 14017, + 18534, 19838, 10913, 19989, 14810, 21325, 5613, 13671, 18005, 9007, + 16453, 19509, 15066, 19116, 14532, 2959, 14582, 19991, 20647, 13870, + 9643, 13606, 19888, 9644, 8261, 16887, 2776, 17846, 16002, 10135, + 6899, 3741, 12977, 21666, 12537, 3242, 19840, 2781, 19754, 12041, + 12579, 11511, 16956, 4681, 20025, 13969, 2013, 11061, 15236, 11305, + 15067, 10136, 16957, 5477, 9280, 5086, 3259, 15488, 10639, 17938, + 18608, 5778, 21618, 5801, 21781, 15779, 2071, 12157, 9197, 14395, + 9301, 10074, 3811, 15780, 10858, 15891, 21207, 938, 9729, 3073, + 12485, 13348, 7910, 2962, 7809, 16408, 16057, 2033, 19774, 19002, + 8233, 1484, 10376, 1924, 20480, 9391, 14025, 14027, 14041, 14043, + 14050, 14054, 14056, 14066, 14068, 14085, 14074, 14077, 14107, 14111, + 14127, 14120, 14115, 14119, 14116, 14117, 14142, 14147, 14152, 14158, + 14162, 14180, 14218, 14170, 14164, 14168, 14194, 14175, 14205, 14206, + 14234, 14240, 14237, 14224, 14216, 14220, 14232, 14259, 14253, 14255, + 14274, 14273, 14278, 14281, 14270, 14287, 14286, 14292, 14288, 14304, + 14303, 14309, 14310, 14315, 14313, 14314, 14321, 14323, 14332, 14329, + 14334, 14346, 14350, 14341, 14348, 14342, 14338, 14337, 14385, 14363, + 14369, 14366, 14367, 14387, 14381, 14372, 14407, 14414, 14415, 14422, + 14438, 14435, 14447, 14442, 14458, 14455, 14476, 14465, 14454, 14483, + 13031, 10779, 18277, 10081, 7164, 1625, 5805, 5945, 3629, 10433, + 14354, 14263, 3630, 18056, 1883, 3704, 3243, 14398, 17996, 6368, + 1007, 11100, 10284, 21045, 12513, 7573, 11131, 3074, 11754, 6781, + 8384, 19162, 14195, 19117, 5852, 2425, 6430, 14131, 8810, 12981, + 10678, 2020, 20249, 9510, 16471, 7078, 12934, 14507, 11011, 11991, + 2237, 3742, 13934, 9423, 19626, 13101, 2787, 6466, 7361, 10722, + 20029, 1229, 19487, 10446, 13697, 4337, 15652, 4616, 8449, 4638, + 13872, 4686, 9017, 14891, 18182, 17835, 5022, 3490, 16722, 3946, + 14956, 17441, 17048, 10224, 20074, 14298, 7362, 15239, 10086, 19783, + 17104, 15010, 11878, 17946, 20077, 19775, 14490, 14498, 14499, 14468, + 14494, 14512, 14511, 14522, 14520, 14527, 14516, 14510, 14514, 14552, + 14556, 14568, 14559, 14555, 14572, 14571, 14562, 14561, 14595, 14596, + 14599, 14604, 14601, 14600, 14618, 14616, 14609, 14612, 14639, 14623, + 14635, 14675, 14649, 14625, 14636, 14662, 14679, 14642, 14614, 14624, + 14660, 14630, 14610, 14615, 14634, 14632, 14628, 14629, 14698, 14699, + 14703, 14701, 14705, 14710, 14709, 14706, 14716, 14708, 14756, 14728, + 14738, 14735, 14724, 14751, 14726, 14746, 14739, 14745, 14722, 14768, + 14767, 14770, 14782, 14774, 14783, 14776, 14779, 14775, 14777, 21229, + 14795, 14799, 14803, 14797, 14796, 14804, 14818, 14807, 14814, 14819, + 16964, 6058, 909, 6797, 6798, 7192, 3030, 17333, 16299, 11222, + 9468, 7554, 1995, 14400, 13035, 9748, 8691, 19900, 3297, 15698, + 15469, 20407, 15240, 17163, 4498, 3892, 17607, 5532, 14781, 7514, + 6015, 13994, 18059, 18628, 1134, 4134, 12438, 16476, 11835, 2741, + 10716, 12400, 12823, 20205, 2432, 20662, 4408, 11689, 19315, 3110, + 17446, 12733, 4447, 7437, 17912, 8982, 1579, 3818, 11138, 9207, + 7960, 13331, 13166, 17249, 17222, 15151, 10482, 19052, 17914, 17561, + 19053, 9116, 9429, 7726, 3636, 20898, 1292, 18633, 11403, 6601, + 1639, 15087, 15426, 16058, 13334, 13109, 16528, 10160, 6806, 11980, + 5224, 20082, 1256, 9681, 14785, 21189, 14806, 14831, 14833, 14836, + 14835, 14837, 14838, 14845, 14843, 14851, 14848, 14864, 14871, 14875, + 14885, 14883, 14886, 14895, 14888, 14889, 14897, 14906, 14903, 14902, + 14933, 14952, 14949, 14928, 14924, 14922, 14921, 14968, 15004, 14974, + 15003, 14971, 14976, 14977, 14986, 14969, 15017, 15039, 15036, 15051, + 15050, 15048, 15047, 15049, 15063, 15072, 15084, 14911, 15090, 15092, + 15101, 15110, 15111, 15118, 15131, 15123, 15126, 15112, 15104, 15106, + 15159, 15164, 15165, 15168, 15183, 15184, 15182, 15192, 15207, 15194, + 15218, 15202, 15208, 15196, 15229, 15242, 15243, 15264, 15260, 15254, + 15266, 15276, 15275, 15279, 15273, 15299, 15292, 15293, 7828, 15306, + 887, 10021, 17953, 13243, 9184, 16186, 16814, 13937, 13938, 12741, + 10347, 15097, 16067, 10816, 20085, 12498, 19692, 18069, 7214, 8082, + 17954, 13359, 15098, 8104, 4796, 1882, 13678, 19066, 17261, 19804, + 8245, 9781, 9782, 19199, 13040, 19269, 10233, 15964, 6453, 19979, + 10101, 18587, 10931, 5991, 8962, 9220, 7219, 3498, 10789, 9458, + 9403, 6497, 4764, 20827, 16533, 8987, 6510, 9535, 7221, 9435, + 6515, 10628, 7015, 8988, 10471, 7393, 14013, 15618, 9409, 13595, + 17464, 19080, 10552, 10982, 1669, 14930, 17409, 2832, 6335, 17814, + 3236, 4911, 17821, 10373, 6396, 6051, 7623, 8309, 1275, 18279, + 20462, 20463, 8958, 1703, 17054, 14830, 15308, 15313, 15333, 15328, + 15345, 15352, 15351, 15347, 15376, 15379, 15368, 15373, 15372, 15384, + 15391, 15385, 15395, 15392, 15400, 15423, 15410, 15416, 15412, 15403, + 15435, 15439, 15436, 15457, 15451, 15448, 15449, 15462, 15484, 15486, + 15479, 15482, 15499, 15478, 15502, 15516, 15521, 15518, 15532, 15530, + 15539, 15537, 15546, 15538, 15569, 15563, 15562, 15567, 15564, 15584, + 15585, 15590, 15613, 15603, 15600, 15604, 15624, 15623, 15626, 15625, + 15638, 15654, 15656, 15634, 15670, 15691, 15699, 15686, 15682, 15678, + 15677, 15707, 15710, 15729, 15715, 15725, 15718, 15754, 15750, 15768, + 15772, 15775, 15801, 15807, 15811, 15816, 15827, 15830, 15834, 15838, + 3778, 13376, 2463, 14515, 8411, 20571, 14331, 19550, 5921, 21548, + 17360, 4547, 4307, 1066, 2626, 12865, 16565, 19957, 19958, 8496, + 12681, 15908, 12682, 19868, 8416, 6728, 13197, 12683, 21076, 11462, + 16316, 4677, 4678, 6004, 4995, 13655, 12112, 11657, 3341, 12478, + 2600, 8296, 9628, 5003, 20338, 5436, 12302, 1873, 17198, 3783, + 1675, 1749, 20396, 15817, 5514, 19293, 5280, 3052, 6732, 10813, + 5010, 9932, 18747, 17203, 9635, 18976, 12486, 7793, 14333, 18809, + 16328, 11381, 13157, 5759, 13321, 9350, 17684, 7861, 13404, 7279, + 16078, 2372, 1328, 5971, 17965, 20714, 4970, 17246, 9288, 1485, + 19841, 19511, 7801, 3429, 3762, 6733, 15832, 15849, 15853, 15850, + 15851, 15871, 15878, 15888, 15904, 15917, 15933, 15895, 15911, 15897, + 15912, 15938, 15937, 15939, 15936, 15944, 15947, 15954, 15953, 15965, + 15966, 15968, 15970, 15983, 15987, 15992, 15990, 15993, 16017, 16019, + 16025, 16030, 16034, 16056, 16059, 16071, 16079, 16080, 16075, 16082, + 16091, 16102, 16117, 16109, 16127, 16146, 16134, 16132, 16141, 16172, + 16168, 16179, 16181, 16193, 16190, 16201, 16194, 16191, 16208, 16214, + 16222, 16226, 16238, 16229, 16234, 16251, 16255, 16242, 16256, 16247, + 16282, 16264, 16265, 16280, 16270, 16261, 16269, 16289, 16295, 16308, + 16312, 16309, 16321, 16317, 16319, 16339, 16341, 16337, 16336, 16344, + 15031, 8206, 12721, 19766, 8531, 14946, 10593, 9653, 3855, 15573, + 9048, 5937, 5976, 1213, 4604, 16466, 4144, 19845, 15291, 12955, + 13945, 11661, 16467, 9836, 3935, 4334, 1166, 3705, 16331, 1979, + 11099, 2187, 9125, 7067, 15865, 10883, 17836, 11153, 7755, 14586, + 17944, 18335, 13845, 16367, 5023, 19894, 10968, 16513, 13925, 17546, + 17071, 19245, 14540, 2700, 15468, 21180, 21596, 15653, 19895, 11012, + 9128, 4032, 13352, 16963, 16644, 19994, 13510, 19307, 7550, 1150, + 14959, 3054, 16917, 16613, 9749, 1151, 13819, 7086, 16697, 17798, + 5984, 18827, 1395, 6467, 18871, 4079, 11536, 6126, 6377, 6736, + 10693, 19037, 16577, 19311, 15609, 21047, 16374, 16360, 16343, 16379, + 16384, 16391, 16381, 16393, 16395, 16378, 16406, 16396, 16428, 16444, + 16429, 16423, 16424, 16425, 16426, 16489, 16507, 16491, 16493, 16494, + 16501, 16527, 16490, 16503, 16500, 16497, 16508, 16488, 16548, 16541, + 16566, 16557, 16563, 16559, 16586, 16595, 16592, 16598, 16611, 16610, + 16625, 16630, 16642, 16632, 16640, 16646, 16665, 16653, 16659, 16651, + 16681, 16679, 16685, 16672, 16677, 16684, 16682, 16701, 16707, 16711, + 16705, 16704, 16702, 16741, 16729, 16746, 16731, 16757, 16733, 16743, + 16734, 16772, 16803, 16791, 16781, 16770, 16771, 16787, 16784, 16827, + 16893, 16828, 16821, 16863, 16829, 16869, 16899, 16823, 16888, 16849, + 2016, 15014, 12728, 15788, 14266, 3713, 10452, 16524, 21009, 2430, + 13482, 12319, 19639, 7522, 10293, 13231, 19198, 7557, 16580, 17447, + 10786, 20593, 20616, 10681, 5837, 10155, 3088, 9519, 10765, 17448, + 2301, 11404, 21711, 14961, 13356, 15597, 20860, 12222, 7692, 13486, + 1678, 9887, 5764, 17002, 7120, 21314, 4605, 9334, 8461, 8462, + 19172, 2201, 7640, 11595, 17454, 11427, 2701, 18108, 14962, 2795, + 2487, 3463, 9570, 14243, 18875, 8029, 3301, 12826, 3033, 17369, + 14355, 13219, 19325, 2160, 9673, 20280, 17955, 21209, 20264, 17510, + 10823, 17619, 12749, 13828, 7451, 6032, 21471, 7826, 1709, 6073, + 4508, 9434, 7825, 9138, 11289, 9690, 16875, 16844, 16824, 16853, + 16904, 16817, 16854, 16891, 16859, 16884, 16820, 16873, 16966, 16952, + 16950, 16948, 16954, 16983, 16982, 16979, 17013, 17034, 17011, 17018, + 17070, 17063, 17073, 17110, 17101, 17096, 17077, 17074, 17080, 17117, + 17123, 17121, 17118, 17149, 17153, 17135, 17132, 17158, 17137, 17188, + 17187, 17199, 17197, 17184, 17191, 17186, 17206, 17232, 17233, 17269, + 17293, 17266, 17296, 17288, 17292, 17274, 17285, 17272, 17270, 17320, + 17323, 17343, 17321, 17334, 17337, 17328, 17318, 17354, 17352, 17349, + 17364, 17359, 17357, 17379, 17378, 17389, 17385, 17376, 17381, 17417, + 17420, 17438, 17399, 17487, 17451, 17425, 17407, 17404, 17468, 17472, + 13417, 11808, 10357, 4082, 17461, 21194, 10248, 9537, 10249, 12092, + 18646, 12326, 11569, 5540, 19277, 14790, 16944, 1981, 13498, 13584, + 1982, 10757, 7827, 21219, 21423, 6608, 11919, 12132, 21082, 10733, + 4420, 8555, 11230, 17060, 8615, 19923, 13471, 10069, 17989, 14811, + 15915, 10270, 17207, 6374, 16514, 3546, 2689, 16519, 3548, 21401, + 5121, 19572, 18781, 4826, 4655, 7774, 21038, 3400, 18935, 21074, + 7852, 20805, 17527, 13653, 20806, 8492, 2158, 6687, 13654, 16145, + 10111, 1267, 18618, 21778, 1452, 14317, 8297, 6140, 18019, 20681, + 18801, 12013, 1783, 3598, 4996, 5798, 20934, 20950, 13656, 18947, + 16123, 11503, 5416, 17985, 20575, 13438, 17471, 17481, 17489, 17482, + 17492, 17491, 17488, 17507, 17506, 17508, 17509, 17547, 17512, 17522, + 17536, 17514, 17529, 17516, 17530, 17558, 17579, 17569, 17618, 17603, + 17564, 17565, 17590, 17575, 17650, 17631, 17642, 17635, 17632, 17643, + 17630, 17627, 17664, 17667, 17676, 17683, 17680, 17679, 17674, 17696, + 17704, 17699, 17698, 17697, 17717, 17721, 17719, 17722, 17720, 17735, + 17734, 17746, 17737, 17741, 17749, 17750, 17755, 17757, 17762, 17780, + 17895, 17790, 17784, 17788, 17787, 17831, 17804, 17828, 17815, 17826, + 17811, 17845, 17847, 17899, 17887, 17870, 17863, 17865, 17879, 17871, + 17893, 17890, 17885, 17886, 17919, 17927, 17922, 17962, 17963, 17959, + 19727, 11058, 1784, 1792, 2631, 2627, 8838, 13762, 7590, 7479, + 11380, 7789, 4382, 13866, 21172, 5713, 19103, 8550, 17710, 14105, + 9038, 11753, 14813, 7252, 9069, 9562, 8344, 14392, 5282, 20685, + 10131, 7169, 18993, 1899, 21350, 14884, 13647, 9559, 17794, 2168, + 9042, 15571, 19930, 10075, 2632, 2271, 2730, 9834, 12142, 4589, + 5802, 18331, 4030, 20981, 12777, 12710, 5863, 8753, 12640, 15694, + 14674, 4932, 2698, 17595, 3856, 9049, 4088, 17795, 17796, 19931, + 5019, 19623, 16055, 18333, 6706, 12115, 3383, 20048, 15303, 5422, + 6502, 13814, 19932, 11535, 8102, 2129, 1152, 14046, 11756, 19251, + 7865, 6505, 8844, 9741, 9511, 14542, 17973, 17977, 17984, 17983, + 18006, 18007, 18014, 18010, 18029, 18036, 18049, 18054, 18093, 18077, + 18080, 18075, 18078, 18076, 18123, 18116, 18113, 18114, 18122, 18117, + 18138, 18141, 18142, 18144, 18139, 18137, 18157, 18154, 18162, 18165, + 18170, 18166, 18180, 18176, 18185, 18188, 18221, 18212, 18223, 18215, + 18220, 18261, 18245, 18258, 18271, 18250, 18243, 18248, 18278, 18266, + 18253, 18252, 18305, 18313, 18314, 18310, 18332, 18371, 18380, 18401, + 18360, 18367, 18387, 18368, 18366, 18382, 18369, 18377, 18373, 18442, + 18437, 18446, 18445, 18457, 18452, 18459, 18462, 18453, 18468, 18455, + 18501, 18494, 18502, 18499, 18520, 18524, 18538, 18536, 18529, 18570, + 10506, 19038, 3822, 17611, 17167, 16525, 1658, 2035, 7193, 14109, + 1232, 1508, 4944, 7438, 21333, 7439, 3211, 7088, 3391, 20105, + 4500, 1857, 17390, 18107, 1677, 13699, 10764, 9208, 1027, 20261, + 5789, 2047, 15221, 11882, 2172, 9779, 3460, 14786, 15447, 1533, + 9212, 4947, 20899, 15340, 14788, 16219, 14691, 1122, 17552, 1870, + 2459, 9186, 10244, 16974, 17178, 9224, 20600, 3361, 8271, 20168, + 14549, 7456, 19077, 9231, 18187, 16822, 4781, 5011, 4798, 1103, + 6132, 7017, 7022, 7460, 5609, 1594, 18372, 5714, 8423, 12377, + 10870, 11119, 11120, 11218, 14652, 15002, 2167, 20686, 8433, 11125, + 15805, 9733, 18624, 20982, 8505, 16960, 18562, 18540, 18565, 18550, + 18555, 18544, 18598, 18603, 18616, 18617, 18636, 18642, 18644, 18648, + 18647, 18662, 18660, 18657, 18669, 18682, 18666, 18667, 18668, 18687, + 18671, 18683, 18726, 18744, 18733, 18745, 18743, 18736, 18731, 18732, + 18818, 18770, 18812, 18804, 18767, 18800, 18820, 18774, 18777, 18785, + 18835, 18864, 18855, 18857, 18844, 18843, 18850, 18845, 18885, 18903, + 18917, 18909, 18893, 18881, 18902, 19048, 18966, 18991, 18933, 18891, + 18992, 18984, 19009, 18884, 18880, 18946, 18985, 18923, 18889, 18948, + 18908, 18894, 19047, 18960, 18922, 19093, 19094, 19086, 19098, 19095, + 19088, 19091, 19134, 19155, 19153, 19150, 19181, 19178, 19179, 19183, + 14214, 16368, 17049, 15756, 19635, 9245, 4344, 4065, 13183, 12095, + 7200, 11312, 19316, 5459, 13526, 20464, 7963, 5618, 3578, 7529, + 10622, 13527, 7380, 16418, 8470, 13529, 10625, 9250, 14433, 3639, + 5623, 18362, 15751, 13378, 7881, 3124, 20951, 2363, 7048, 3430, + 3657, 6484, 13566, 5287, 14667, 5760, 7833, 6860, 13407, 17685, + 11662, 6980, 10439, 20326, 1518, 17692, 14267, 5390, 21014, 18026, + 2850, 16932, 18840, 10470, 8475, 16942, 18422, 16946, 18249, 3899, + 4992, 13379, 13380, 7705, 7145, 4524, 18124, 3804, 6274, 2102, + 15586, 17812, 7784, 3418, 13759, 18125, 19147, 14221, 12802, 16124, + 7150, 18126, 19163, 4262, 4659, 18203, 19203, 19221, 19247, 19227, + 19261, 19219, 19243, 19289, 19290, 19291, 19288, 19305, 19284, 19318, + 19286, 19340, 19338, 19351, 19349, 19357, 19361, 19360, 19382, 19362, + 19364, 19368, 19423, 19421, 19399, 19401, 19409, 19397, 19410, 19403, + 19428, 19438, 19432, 19439, 19433, 19452, 19453, 19456, 19472, 19455, + 19458, 19477, 19499, 19495, 19494, 19518, 19520, 19539, 19532, 19517, + 19519, 19545, 19552, 19557, 19570, 19612, 19617, 19610, 19622, 19562, + 19574, 19608, 19573, 19600, 19554, 19588, 19592, 19559, 19583, 19658, + 19653, 19656, 19662, 19655, 19663, 19657, 19694, 19720, 19699, 19705, + 19696, 19745, 19733, 19712, 19737, 19749, 19724, 19708, 19704, 19756, + 18532, 15052, 14424, 19154, 17640, 8425, 17469, 11624, 2418, 19475, + 20893, 17747, 4572, 17668, 2333, 14345, 18264, 13980, 21407, 17855, + 18962, 18963, 15119, 2565, 6071, 14393, 6108, 17894, 20687, 21273, + 20781, 5448, 21556, 20399, 5519, 5012, 7420, 3846, 10071, 3658, + 18522, 11590, 12064, 21147, 5145, 18977, 8302, 18622, 20367, 16149, + 18810, 13508, 20549, 12487, 1471, 17752, 13445, 1083, 3292, 21689, + 15541, 21232, 3015, 20584, 19416, 17858, 18095, 18994, 6666, 6112, + 14668, 2126, 17496, 14534, 6175, 2144, 5452, 5761, 13567, 6776, + 7802, 6485, 5065, 17355, 16365, 14396, 2731, 3971, 11062, 11320, + 4332, 6703, 18275, 17748, 5595, 4422, 19714, 19735, 19744, 19717, + 19776, 19695, 19830, 19834, 19826, 19854, 19861, 19869, 19864, 19873, + 19891, 19858, 19857, 19866, 19886, 19884, 19876, 19912, 19919, 19929, + 19920, 19921, 19935, 19937, 19966, 19964, 19954, 19950, 19965, 19943, + 19956, 19961, 20017, 19999, 20014, 20001, 20041, 20035, 20055, 20075, + 20061, 20059, 20071, 20054, 20088, 20101, 20100, 20113, 20112, 20110, + 20120, 20121, 20124, 20125, 20137, 20144, 20149, 20152, 20173, 20184, + 20186, 20191, 20192, 20195, 20206, 20198, 20197, 20203, 20200, 20224, + 20218, 20212, 20209, 20207, 20220, 20234, 20231, 20228, 20233, 20277, + 20283, 20292, 20293, 20289, 20307, 20332, 20317, 20319, 20333, 20335, + 1772, 15798, 18815, 9421, 21176, 8906, 8850, 16693, 7179, 20983, + 13770, 3136, 9303, 4270, 8914, 16896, 15881, 3432, 1331, 2188, + 19541, 8764, 13127, 13181, 14834, 939, 19683, 17499, 2529, 7864, + 17300, 16695, 16806, 5238, 15054, 1890, 6782, 8062, 14899, 20716, + 14900, 4031, 6451, 2326, 14873, 7813, 8736, 13451, 3106, 17470, + 15212, 16332, 17215, 4617, 2573, 15327, 19014, 11487, 19164, 3814, + 12335, 21456, 2238, 2400, 21400, 7185, 12650, 15417, 21387, 16472, + 8207, 13287, 3947, 20783, 20252, 21650, 12887, 21457, 9849, 7506, + 2843, 17126, 10604, 14426, 1657, 6492, 12372, 19628, 3860, 17838, + 12380, 14682, 17947, 14683, 6861, 6493, 20339, 20337, 20348, 20362, + 20370, 20311, 20356, 20363, 20358, 20379, 20376, 20382, 20384, 20386, + 20389, 20412, 20392, 20401, 20395, 20391, 20427, 20424, 20436, 20428, + 20426, 20466, 20448, 20445, 20447, 20450, 20455, 20452, 20483, 20471, + 20475, 20477, 20468, 20494, 20492, 20504, 20500, 20503, 20506, 20501, + 20505, 20517, 20511, 20523, 20524, 20534, 20535, 20543, 20550, 20551, + 20538, 20553, 20537, 20564, 20566, 20572, 20583, 20592, 20602, 20603, + 20613, 20607, 20609, 20622, 20642, 20629, 20645, 20630, 20661, 20618, + 20619, 20620, 20672, 20679, 20670, 20720, 20705, 20719, 20699, 20752, + 20733, 20744, 20729, 20735, 20726, 20730, 20771, 20765, 20772, 20778, + 4345, 21083, 3711, 17548, 4939, 12605, 15866, 7515, 12780, 19784, + 21521, 21313, 16998, 6799, 19124, 943, 17217, 11555, 2431, 4783, + 21183, 18484, 18402, 6643, 17948, 5296, 11950, 12652, 11422, 18708, + 16520, 17689, 15611, 21114, 14239, 12516, 9020, 6669, 6908, 5264, + 19317, 11063, 17479, 11139, 17001, 13038, 2402, 18046, 15658, 15152, + 1217, 2613, 12890, 14688, 7578, 19902, 17612, 17449, 15554, 18582, + 18583, 20824, 19643, 1640, 3116, 9520, 11341, 11342, 14268, 20595, + 11324, 7446, 20262, 21692, 9755, 10294, 1998, 11981, 5817, 16967, + 21466, 1013, 1044, 7915, 20596, 18837, 6345, 7603, 10787, 2353, + 5988, 6469, 2245, 17839, 20302, 14103, 20777, 20779, 20776, 20774, + 20790, 20794, 20787, 20791, 20821, 20795, 20797, 20811, 20789, 20786, + 20796, 20842, 20833, 20843, 20844, 20830, 20836, 20831, 20872, 20885, + 20866, 20894, 20867, 20870, 20878, 20903, 20928, 20940, 20901, 20933, + 20970, 20911, 20917, 20907, 20958, 20932, 20968, 20914, 20913, 20944, + 20959, 20912, 20947, 21025, 21037, 21032, 21039, 21041, 21035, 21056, + 21055, 21075, 21067, 21068, 21085, 21088, 21084, 21090, 21086, 21104, + 21119, 21122, 21123, 21133, 21143, 21134, 21138, 21154, 21168, 21166, + 21175, 21159, 21170, 21169, 21162, 21203, 21195, 21201, 21231, 21224, + 21236, 21233, 21222, 21269, 21255, 21243, 21270, 21251, 21277, 21272, + 16933, 20329, 4138, 20785, 11597, 9213, 4278, 19356, 8464, 7003, + 21751, 7695, 1881, 6817, 21335, 11347, 20285, 20345, 14592, 13110, + 15428, 20286, 12608, 14488, 17956, 20222, 15431, 3468, 15227, 17175, + 7006, 7730, 9760, 11892, 18763, 888, 20415, 6740, 6819, 19067, + 19068, 14244, 13692, 11900, 12960, 4140, 15338, 6438, 21117, 6033, + 920, 19273, 7386, 19805, 7455, 6826, 4047, 20599, 17958, 20165, + 9436, 14434, 16535, 2250, 9702, 18841, 1611, 20601, 18423, 4355, + 2748, 16537, 2749, 18639, 2217, 13693, 19202, 9229, 2460, 17556, + 11810, 6528, 20169, 19082, 3473, 20422, 18433, 4056, 16108, 13741, + 17739, 17751, 1434, 21092, 14421, 17816, 21242, 21249, 21259, 21253, + 21293, 21298, 21299, 21301, 21304, 21317, 21329, 21328, 21330, 21345, + 21340, 21349, 21339, 21362, 21354, 21356, 21367, 21368, 21365, 21385, + 21373, 21376, 21399, 21402, 21413, 21410, 21409, 21414, 21446, 21430, + 21437, 21438, 21442, 21427, 21432, 21480, 21481, 21489, 21483, 21501, + 21491, 21478, 21553, 21476, 21536, 21554, 21537, 21560, 21567, 21559, + 21603, 21582, 21598, 21574, 21576, 21610, 21626, 21638, 21658, 21660, + 21661, 21663, 21668, 21669, 21673, 21687, 21681, 21682, 21683, 21704, + 21700, 21714, 21729, 21723, 21725, 21737, 21739, 21754, 21763, 21764, + 21773, 21779, 21766, 21767, 21777, 23849, 23850, 23851, 23852, 23853, + 12866, 6246, 17064, 7055, 6257, 5909, 6213, 16924, 16925, 9888, + 5946, 4048, 10251, 12768, 9563, 3570, 1394, 14823, 17309, 4758, + 21018, 21024, 18434, 18435, 2824, 6691, 16095, 18964, 18965, 7337, + 1068, 6313, 4323, 2777, 7355, 8746, 5066, 8310, 4842, 16897, + 1695, 21184, 7260, 4692, 16926, 1858, 16549, 6554, 3637, 21600, + 4696, 19059, 971, 12303, 11506, 12266, 5437, 11508, 19538, 11382, + 15005, 6546, 8747, 6113, 975, 9506, 11663, 1425, 19689, 7261, + 16033, 10826, 16927, 19049, 8332, 2769, 15429, 6527, 8484, 1299, + 20624, 19863, 4993, 1942, 5406, 15591, 18949, 6006, 16258, 12432, + 6893, 4529, 15390, 5645, 20242, 20952, 2817, 6927, 16768, 5073, + 11736, 13984, 12244, 5322, 2492, 5276, 11580, 4342, 5794, 19576, + 12420, 1404, 16107, 18527, 18539, 20788, 3641, 17661, 19206, 8968, + 19762, 5197, 15583, 21221, 7034, 11534, 11212, 6933, 12658, 11087, + 1806, 14078, 5526, 20268, 14336, 3250, 18312, 8430, 14942, 18704, + 18403, 4538, 12518, 5745, 8999, 1571, 20253, 5586, 19497, 3501, + 18883, 16585, 8008, 8816, 5766, 8560, 9118, 6945, 14219, 16230, + 8859, 12385, 8436, 13064, 6865, 19019, 8074, 16322, 13714, 3874, + 20491, 9367, 13976, 18886, 11451, 13739, 19654, 12329, 18155, 16209, + 16732, 2260, 2002, 8640, 21240, 11843, 8547, 19434, 18898, 5413, + 4419, 21274, 14659, 1472, 21509, 4421, 5776, 12379, 1572, 10720, + 3345, 14502, 8935, 4634, 15814, 18811, 2603, 10873, 6145, 1346, + 10424, 10014, 6777, 5067, 12371, 21510, 7298, 17900, 20278, 7673, + 5068, 20174, 7493, 19246, 18132, 20717, 14326, 1696, 1697, 13408, + 14327, 2886, 20176, 21108, 9174, 20151, 3055, 2401, 14275, 15757, + 12143, 5343, 17216, 10735, 7507, 15213, 5025, 15461, 3107, 3108, + 20993, 6981, 20515, 4066, 7955, 11260, 2972, 20078, 1255, 20119, + 9176, 4795, 2024, 6998, 14509, 913, 21334, 5030, 5460, 14011, + 20263, 9889, 19054, 1135, 2443, 16301, 21011, 21392, 1643, 19998, + 20308, 3448, 20159, 18413, 12589, 14245, 15896, 16133, 11672, 5039, + 7035, 4415, 19521, 8851, 8599, 21161, 18910, 15765, 2149, 7649, + 11867, 11414, 2717, 18306, 9599, 13377, 9551, 19660, 12452, 19402, + 14988, 4787, 12968, 13961, 12015, 21412, 14732, 10637, 16631, 1416, + 15680, 5610, 8774, 8291, 4710, 18311, 17528, 7151, 16346, 21611, + 10274, 15519, 1688, 11938, 2655, 16889, 8018, 7496, 7621, 8158, + 15919, 17940, 3386, 15894, 16104, 14330, 12852, 21684, 19976, 3150, + 3615, 16818, 18128, 6267, 5855, 2242, 8986, 1219, 12574, 6206, + 4899, 4855, 15103, 14979, 15952, 18304, 1819, 5795, 10869, 17583, + 10535, 12546, 1751, 19308, 10643, 9399, 1725, 6406, 9916, 17230, + 16303, 19330, 7964, 5409, 17225, 20177, 1540, 4049, 14772, 18420, + 18421, 18003, 10272, 5151, 20179, 19855, 1473, 21105, 4791, 19995, + 16865, 15916, 17039, 2473, 2482, 17106, 15507, 21657, 9606, 14222, + 13314, 13224, 17240, 21495, 8426, 13225, 2601, 3002, 2450, 3847, + 3604, 17033, 20400, 8434, 7068, 2605, 2783, 5572, 18045, 15806, + 4217, 5130, 15267, 3137, 16961, 20555, 15137, 19192, 8235, 7508, + 13630, 2989, 3187, 10440, 3491, 13354, 21522, 15655, 13456, 2671, + 6649, 13111, 13082, 7727, 20223, 15706, 4410, 20148, 16687, 8677, + 8427, 2436, 4549, 19963, 1099, 12694, 16183, 18978, 7490, 10072, + 10961, 8825, 3041, 12830, 21275, 8201, 15023, 11106, 21057, 11297, + 18241, 7764, 6273, 14215, 11967, 8274, 11620, 5499, 6066, 3643, + 20539, 13427, 18775, 8898, 9416, 5588, 7775, 6680, 14374, 5440, + 13542, 20775, 6851, 17850, 13120, 5229, 8911, 16836, 21640, 21436, + 16437, 19585, 14420, 2226, 15198, 2419, 7480, 18044, 18684, 4314, + 19728, 17926, 931, 3687, 21494, 12378, 11328, 3466, 15120, 14658, + 11122, 20585, 7428, 20284, 13097, 8439, 18397, 20403, 2457, 7759, + 7896, 4977, 16773, 12844, 8007, 1155, 3748, 21768, 1283, 17700, + 5054, 20925, 11767, 21642, 2919, 12298, 16349, 6615, 16445, 16965, + 5914, 13307, 8919, 10791, 16678, 4540, 1736, 12249, 1300, 18670, + 15815, 12038, 8306, 11659, 18816, 7170, 4238, 4239, 21177, 13568, + 21300, 17356, 2658, 1383, 20971, 7280, 1954, 3294, 8234, 14753, + 16008, 2839, 8063, 11780, 17432, 1925, 3222, 11449, 14754, 7677, + 13066, 11051, 7509, 12727, 16645, 16473, 7814, 7080, 11784, 8208, + 11785, 10594, 10441, 9467, 16286, 13573, 21677, 13164, 12651, 3140, + 21597, 12238, 20757, 19636, 4180, 2973, 19426, 3712, 20353, 2442, + 16156, 15504, 4940, 21678, 11951, 2132, 16073, 13018, 20441, 3724, + 15659, 7089, 10195, 20156, 1524, 2692, 10456, 9890, 15471, 3358, + 15153, 17003, 8997, 7204, 20861, 13020, 20862, 12050, 21601, 9754, + 20193, 11733, 16068, 8242, 17171, 21052, 3644, 15349, 7267, 20915, + 21163, 8867, 17019, 6532, 20057, 9608, 19333, 5230, 16837, 4889, + 12297, 15404, 18316, 8375, 18228, 19160, 20473, 12514, 14229, 21651, + 10098, 4761, 2771, 6571, 10724, 13465, 14311, 6077, 5306, 11033, + 17880, 17541, 15080, 17610, 8469, 19177, 12946, 3475, 2320, 14919, + 1581, 1352, 13396, 1354, 4301, 4435, 14769, 6984, 19377, 6154, + 16380, 16673, 5241, 20698, 8920, 12330, 18769, 9587, 12661, 1156, + 5100, 10259, 3749, 10324, 2379, 3647, 16136, 11644, 11456, 988, + 18194, 3825, 3951, 8561, 14177, 14271, 11601, 5055, 19138, 2508, + 14573, 5820, 18050, 9924, 19922, 20840, 957, 18953, 12300, 11739, + 1801, 3148, 8466, 10022, 15304, 13083, 13084, 9852, 4156, 5634, + 3303, 1537, 1538, 8334, 13137, 4160, 2746, 7010, 16767, 19983, + 11734, 20864, 9699, 21021, 2801, 4107, 16536, 10252, 10024, 17179, + 16538, 9230, 13682, 17623, 11811, 15339, 13500, 7098, 3155, 21696, + 17008, 8990, 8485, 10025, 3375, 4660, 15672, 4218, 5385, 9291, + 13735, 10641, 883, 6982, 8236, 8781, 8782, 18338, 10948, 8634, + 13458, 10295, 9366, 4222, 20863, 18414, 15674, 3551, 19279, 19817, + 2366, 20336, 5752, 8493, 19959, 17665, 3337, 17924, 4525, 13760, + 14185, 8912, 14742, 16097, 2420, 3343, 4315, 11507, 12695, 10836, + 13917, 8913, 12923, 21319, 6208, 6336, 12197, 16027, 14069, 3338, + 8822, 3838, 19108, 9462, 6312, 5285, 19881, 10772, 19369, 9821, + 2608, 17651, 12325, 19076, 2039, 7604, 11520, 4068, 12850, 6939, + 16246, 17738, 12761, 17319, 4861, 18247, 20009, 4863, 7132, 9589, + 4294, 8280, 12287, 20879, 13940, 17268, 2282, 3060, 13189, 16779, + 12965, 12665, 14172, 1586, 21246, 8791, 18851, 11365, 5102, 12421, + 10209, 1077, 11459, 8179, 13667, 13281, 2591, 4874, 10040, 11748, + 19204, 10854, 19285, 13310, 11243, 14305, 12967, 18791, 13694, 1447, + 3011, 8255, 15902, 6725, 21165, 15852, 13089, 4888, 13727, 17723, + 13546, 6751, 18086, 11296, 12799, 7612, 2679, 7541, 10652, 19287, + 13478, 8936, 3659, 10073, 3346, 991, 20688, 4530, 8907, 18506, + 12185, 1322, 5479, 5480, 12113, 21276, 13832, 4324, 1085, 21120, + 20895, 18556, 8683, 18979, 13256, 14669, 12488, 4386, 5401, 8230, + 7714, 5684, 10426, 8572, 13569, 21106, 20123, 20972, 14325, 9848, + 19768, 14297, 19485, 6567, 13641, 20587, 16285, 4972, 13260, 21109, + 11664, 10082, 20590, 20459, 9850, 21518, 6711, 16333, 2990, 5869, + 8609, 18869, 12216, 12985, 5808, 11730, 12493, 5630, 1333, 10595, + 12022, 9825, 13926, 13847, 7087, 18485, 17218, 2876, 3122, 2944, + 5297, 19490, 6215, 14757, 5028, 21523, 4941, 16550, 1360, 20442, + 19640, 16551, 8610, 5492, 20664, 17108, 12913, 5324, 7928, 10719, + 15231, 6238, 21141, 8601, 1401, 14575, 16633, 19503, 4260, 10901, + 19467, 9620, 15991, 17148, 4897, 15172, 19469, 3621, 17638, 16267, + 9275, 19225, 2953, 7985, 12693, 16864, 15028, 7899, 11532, 12634, + 1082, 14741, 2266, 15812, 19589, 6539, 1458, 4910, 16028, 3424, + 3201, 18222, 21664, 3482, 7335, 16276, 19292, 5475, 5965, 12828, + 4746, 13765, 17330, 16359, 2231, 8568, 12810, 9006, 16986, 4322, + 1246, 12002, 15858, 10278, 12028, 17933, 7251, 20648, 14533, 13904, + 11387, 4361, 1327, 16621, 6012, 7066, 9498, 1212, 7354, 14910, + 9309, 19302, 19755, 15135, 11007, 3980, 16990, 9773, 3135, 10015, + 19903, 10457, 7641, 2351, 21321, 16529, 6849, 18033, 20598, 7728, + 20465, 1892, 9355, 4697, 4470, 9984, 5302, 14101, 8613, 6560, + 18877, 7093, 21393, 4392, 19806, 7533, 6218, 9405, 12162, 9700, + 9703, 10358, 10026, 3321, 21095, 9818, 16546, 3016, 21726, 1600, + 9126, 3025, 18008, 1182, 1604, 1607, 1154, 3034, 1609, 1610, + 11872, 11874, 20695, 2978, 18729, 13774, 4513, 14557, 13897, 2162, + 5095, 19546, 18846, 12617, 20310, 16338, 16024, 21396, 3275, 5997, + 3276, 4254, 21031, 2380, 11694, 2643, 2409, 21252, 15559, 16140, + 13517, 6726, 3960, 19533, 11525, 18793, 7779, 9923, 18121, 4168, + 8089, 19470, 13386, 3678, 8045, 18860, 13479, 8811, 17917, 9899, + 6790, 18134, 8450, 13932, 21728, 7079, 11010, 4493, 12726, 6265, + 17608, 6214, 16370, 19036, 16626, 15085, 1517, 6014, 15365, 13879, + 18064, 17254, 5222, 9523, 6917, 13488, 6195, 4506, 11802, 11079, + 5393, 18929, 8916, 9713, 3265, 18926, 16840, 20182, 12111, 19451, + 9903, 5049, 5111, 14700, 10972, 16036, 2393, 4955, 1589, 1022, + 7776, 7651, 20091, 18940, 10605, 8520, 15760, 18650, 867, 11504, + 7110, 5845, 1116, 8194, 12545, 9928, 12921, 5643, 3841, 20318, + 18204, 13238, 19601, 960, 17932, 1771, 8970, 19926, 14747, 4364, + 2852, 7346, 14909, 20431, 11946, 14044, 10659, 19239, 20850, 5974, + 20610, 16790, 9719, 15289, 6729, 5507, 9158, 1344, 3256, 8428, + 1382, 19476, 21101, 7935, 19729, 2984, 15688, 3289, 19914, 11945, + 3485, 15185, 18326, 2604, 15643, 14578, 20640, 19479, 20066, 4325, + 5873, 3293, 16405, 11551, 18564, 2762, 18130, 15319, 3697, 2606, + 19915, 15129, 10690, 5651, 20481, 14676, 1935, 2663, 15138, 4176, + 3706, 10285, 2611, 3230, 13708, 12888, 17976, 19777, 18823, 4338, + 9873, 14684, 10736, 6552, 20408, 15607, 4409, 1559, 1562, 9524, + 19907, 19493, 10629, 9573, 15848, 12757, 14166, 19560, 13860, 16260, + 4814, 8642, 1684, 17628, 14411, 19856, 3214, 6876, 1191, 8281, + 1435, 16210, 8899, 5703, 14517, 8818, 20586, 17542, 10318, 21750, + 3151, 5132, 6598, 12337, 17718, 21461, 6868, 21706, 11576, 18882, + 15589, 3326, 14655, 1895, 2637, 6931, 8799, 3502, 9370, 20309, + 850, 18528, 4815, 4950, 18900, 3314, 9586, 4292, 1409, 1123, + 5818, 13233, 19180, 20090, 8543, 17061, 5581, 10117, 3920, 11820, + 4183, 11582, 19435, 14925, 8901, 6943, 14417, 6681, 3264, 9910, + 18784, 17400, 1442, 2999, 5673, 6747, 17758, 18738, 12025, 8868, + 4210, 7137, 11214, 11052, 20359, 11868, 5321, 11412, 10702, 2555, + 9320, 5347, 16709, 20315, 15274, 20211, 16839, 21776, 6946, 4782, + 20238, 11943, 11187, 9954, 21323, 20528, 15565, 6332, 3197, 14146, + 5053, 6082, 7036, 6304, 17702, 16949, 5718, 11935, 9289, 18254, + 2499, 3995, 10489, 4958, 16708, 9272, 7269, 5346, 1818, 17024, + 13518, 17466, 12627, 13250, 21096, 21641, 12465, 9149, 11651, 19471, + 1926, 17322, 8225, 19380, 13058, 18742, 10905, 13963, 1316, 14743, + 19672, 20060, 6311, 8966, 17325, 17326, 15059, 15483, 11301, 16880, + 13894, 2835, 21505, 21647, 18689, 16691, 17331, 20019, 13059, 19367, + 10874, 2343, 4840, 9898, 21306, 6425, 13062, 10771, 13063, 17859, + 3585, 1529, 18097, 1502, 20291, 16409, 20782, 10882, 9965, 3384, + 11013, 18703, 2046, 8876, 4755, 11014, 8939, 9778, 20154, 2198, + 19444, 6999, 18407, 2206, 20157, 6522, 19358, 3419, 1787, 3901, + 9268, 9621, 14832, 2855, 3837, 3268, 11550, 9488, 8969, 7742, + 19393, 9001, 8117, 15060, 19107, 2652, 7743, 10276, 8839, 16639, + 6762, 13205, 996, 15121, 4019, 8730, 11777, 6072, 2397, 15262, + 5284, 855, 11638, 6020, 3714, 880, 897, 14908, 5881, 15890, + 2566, 12158, 9460, 2030, 12411, 12642, 19238, 1370, 15082, 3605, + 11126, 12188, 8388, 9863, 12568, 2856, 7720, 11960, 13209, 10317, + 2082, 3571, 6013, 7952, 8453, 18754, 14004, 12276, 13875, 1930, + 6913, 11565, 16377, 7396, 11538, 10575, 6346, 10031, 19526, 19664, + 13251, 19669, 19897, 16382, 20910, 12149, 15515, 2718, 20239, 5844, + 16941, 20162, 9694, 19586, 18317, 21721, 10837, 3376, 4004, 20636, + 19871, 4833, 15711, 12831, 12507, 2732, 20129, 2987, 19540, 19211, + 12582, 21727, 5888, 16412, 10443, 9242, 18234, 15575, 20439, 15418, + 21388, 17219, 4021, 15445, 13412, 2964, 20079, 4431, 8698, 15074, + 2757, 3234, 20080, 19431, 986, 20372, 7599, 12405, 2244, 19800, + 9521, 20194, 18761, 7601, 15430, 12509, 11883, 19069, 18416, 19070, + 11745, 13887, 2747, 18424, 10104, 11081, 11082, 11746, 17673, 7732, + 14551, 11084, 18430, 1587, 14653, 14692, 9525, 7875, 5043, 18856, + 9897, 3508, 20527, 3884, 12504, 13388, 1081, 20632, 20839, 1067, + 10559, 4961, 11527, 3807, 14187, 13116, 16394, 16658, 10774, 20514, + 4934, 4464, 7027, 12759, 12853, 12662, 13426, 18156, 17267, 1028, + 2078, 9189, 1057, 6413, 8709, 3921, 7266, 17785, 3324, 5427, + 10852, 11237, 18914, 3953, 7703, 18081, 20732, 9321, 9145, 15025, + 18219, 5548, 17467, 5824, 8776, 8417, 13797, 18606, 16225, 20122, + 16399, 19599, 3237, 10299, 21498, 10908, 14503, 15029, 7114, 20513, + 9968, 3588, 1704, 18831, 3725, 2636, 4562, 3128, 18119, 18466, + 6307, 9146, 16981, 2288, 6622, 18559, 20756, 7684, 13499, 14165, + 13587, 13368, 964, 5690, 10683, 11857, 20039, 17075, 12106, 4623, + 13787, 8869, 14707, 15230, 1450, 8369, 9615, 19584, 17237, 19143, + 8806, 2885, 21551, 4488, 19590, 16690, 5966, 5171, 12696, 10810, + 13781, 3688, 15000, 17028, 18967, 2147, 14525, 16022, 16866, 11918, + 12871, 13394, 7481, 12267, 18653, 19185, 1092, 4550, 2423, 17712, + 3993, 19967, 12874, 4837, 1922, 11509, 17641, 4265, 8435, 4172, + 5418, 19186, 12925, 1165, 13989, 13722, 2336, 11864, 4662, 20045, + 18865, 13202, 12268, 5827, 6253, 19156, 8500, 3809, 18980, 21043, + 16987, 5083, 13782, 6878, 15380, 8649, 19877, 10336, 11639, 16569, + 4202, 21515, 11660, 16003, 14670, 11257, 5484, 8689, 10076, 1752, + 3020, 5523, 1837, 12269, 19757, 15006, 21762, 1889, 19483, 3763, + 7299, 20649, 14607, 14671, 15818, 8307, 15157, 18740, 5859, 10610, + 11656, 14322, 3131, 11059, 6361, 2123, 16451, 16504, 10911, 11588, + 20478, 8061, 8447, 9871, 17605, 18063, 6525, 2877, 6880, 15233, + 19161, 20865, 14554, 15476, 16094, 17014, 13753, 19703, 2641, 18783, + 17361, 1786, 19587, 6844, 2107, 15068, 11330, 17768, 7911, 14030, + 21331, 11571, 12328, 16736, 5743, 12105, 17759, 17350, 16170, 929, + 19670, 1455, 5338, 999, 7906, 2191, 17602, 10000, 19257, 17626, + 3504, 3224, 2251, 16738, 20904, 11993, 2677, 16737, 8579, 2316, + 2906, 15016, 1582, 11854, 6414, 2821, 12176, 3279, 18517, 21771, + 11645, 4868, 2330, 18916, 18778, 15943, 18213, 2053, 8562, 18082, + 12926, 14535, 15302, 17994, 20529, 1269, 6115, 1489, 14477, 2784, + 14583, 1838, 21279, 2659, 20096, 12522, 15918, 12927, 4925, 20385, + 10859, 12879, 4926, 9645, 19969, 12270, 18447, 1180, 1794, 7803, + 5420, 14817, 20753, 11448, 11683, 11779, 3698, 7256, 11473, 15440, + 14409, 18866, 14939, 8937, 8551, 1296, 15921, 17713, 6259, 7678, + 2633, 4405, 5315, 1753, 14587, 11421, 5877, 19165, 8506, 21107, + 2708, 17365, 15922, 11389, 9448, 6972, 19769, 17908, 13724, 21753, + 20984, 14226, 2664, 16991, 17714, 13571, 12271, 15820, 21181, 6292, + 11308, 8854, 18571, 17157, 17209, 17770, 8507, 2108, 9351, 7073, + 12334, 13871, 11101, 18752, 19120, 5685, 8722, 20058, 1309, 15037, + 12864, 8953, 9061, 18939, 15681, 13532, 13153, 17727, 4611, 2308, + 16323, 2720, 6333, 3199, 20064, 9003, 4320, 9472, 21377, 13117, + 1466, 15125, 12951, 19371, 8020, 13100, 2688, 2844, 10002, 11041, + 15741, 6714, 14842, 18244, 16385, 6228, 11267, 8646, 15315, 10475, + 9063, 8115, 9297, 19730, 2267, 17029, 16568, 6834, 4317, 13520, + 13617, 6116, 15731, 13622, 8618, 21353, 12035, 12992, 14874, 12786, + 14975, 2136, 4727, 19859, 11454, 11163, 4164, 11108, 5498, 1585, + 16600, 6010, 16383, 9376, 5101, 14798, 10208, 10326, 18441, 14985, + 4227, 10038, 10853, 10648, 17980, 12057, 16138, 6230, 11269, 7970, + 963, 3917, 19512, 14087, 8662, 12931, 14947, 11640, 3812, 5979, + 13947, 14678, 8765, 13411, 17437, 20591, 17797, 20187, 15627, 3261, + 5575, 6279, 19375, 4009, 10504, 10925, 9292, 16298, 17646, 20030, + 1334, 15144, 19778, 2189, 15882, 1850, 5980, 7282, 6263, 8347, + 4756, 2170, 16287, 20995, 14957, 8348, 6468, 19685, 15784, 8938, + 21458, 10568, 17715, 13230, 14452, 5939, 10569, 18654, 2790, 20305, + 8209, 17303, 4271, 10814, 12570, 9512, 12067, 13948, 2532, 5239, + 9565, 15596, 1733, 21286, 20718, 15979, 10183, 21732, 8328, 2315, + 19847, 7369, 5177, 3817, 15577, 2298, 10597, 8737, 10087, 12277, + 10447, 9518, 13017, 12144, 8362, 11261, 6534, 16432, 9921, 7238, + 20621, 19092, 6724, 21164, 7141, 17873, 6748, 15561, 18083, 7586, + 10124, 6392, 18084, 13899, 15108, 16713, 9147, 16392, 21434, 8342, + 2080, 1190, 16848, 10940, 6577, 21228, 12689, 16857, 15027, 4026, + 21416, 12342, 14482, 5143, 4601, 3099, 14423, 5644, 10407, 14846, + 17587, 18224, 11174, 7664, 15064, 6625, 17892, 12169, 7338, 17990, + 16660, 10909, 18389, 13207, 8732, 14351, 10821, 19301, 12599, 9642, + 13902, 15301, 6858, 1477, 17791, 4969, 15487, 12077, 11303, 6632, + 19303, 17430, 9240, 2032, 6340, 10660, 6594, 9798, 21179, 18750, + 10430, 17967, 5129, 14822, 14953, 14196, 14320, 15925, 2193, 9175, + 21733, 12219, 977, 12278, 17307, 18149, 21369, 9452, 854, 8783, + 15330, 9054, 4034, 16521, 2928, 21524, 20759, 1348, 11791, 21636, + 2965, 15422, 3910, 12729, 12936, 21389, 6991, 19785, 7914, 5632, + 10845, 2273, 15758, 16918, 9802, 15578, 5559, 3262, 14826, 20663, + 10448, 11040, 10449, 6452, 1659, 5046, 9164, 8749, 4551, 16762, + 11537, 16300, 6399, 3563, 17164, 17165, 6866, 9851, 4451, 10981, + 8575, 18450, 3609, 9804, 5835, 17255, 4081, 16011, 16414, 16288, + 5031, 13848, 7090, 4348, 8510, 20665, 15660, 20344, 6435, 18486, + 4105, 17109, 19641, 8766, 14479, 6646, 16479, 5032, 20532, 2112, + 13167, 14545, 6217, 8983, 11953, 13078, 15179, 9567, 3440, 20406, + 9743, 13878, 12585, 1522, 6030, 21464, 5990, 17616, 19322, 19978, + 4719, 6061, 1107, 11143, 5740, 3477, 11110, 19528, 2411, 11846, + 12880, 12883, 16804, 9865, 12889, 6549, 7441, 7440, 2977, 18191, + 16739, 8086, 20235, 18782, 4397, 7235, 8035, 3328, 6309, 12082, + 1886, 9557, 13387, 17410, 15683, 13640, 8965, 16347, 6583, 10410, + 2870, 6627, 13401, 17094, 1003, 5453, 15320, 10137, 17159, 9971, + 8327, 17609, 11205, 15222, 9110, 7121, 6759, 16053, 20957, 8651, + 20883, 6948, 4250, 2176, 16988, 8319, 2257, 8033, 11909, 11090, + 4909, 1464, 19811, 2377, 14901, 4577, 18246, 16735, 19701, 1410, + 13079, 6297, 15951, 21624, 6555, 18714, 11263, 7523, 4089, 7516, + 14960, 8984, 6381, 17949, 20606, 7821, 20666, 1560, 21050, 21527, + 17773, 18655, 10949, 12029, 865, 5072, 12938, 10928, 2113, 3302, + 1218, 17111, 9756, 15284, 8587, 18584, 18718, 11898, 16614, 13825, + 15510, 15285, 13021, 5300, 14916, 2929, 1863, 12051, 3273, 1397, + 14048, 5178, 21528, 16699, 19260, 6677, 15790, 10162, 8576, 15250, + 14138, 15075, 16302, 5225, 20722, 20723, 9293, 19055, 19905, 15523, + 11796, 16968, 7262, 5266, 10694, 8350, 15056, 21691, 15286, 15287, + 4759, 16553, 11489, 10388, 15288, 11982, 21680, 16047, 17777, 5656, + 18002, 9805, 14721, 10766, 11405, 10623, 7921, 21540, 5700, 11850, + 19563, 14980, 3278, 21118, 14174, 13145, 18195, 13703, 14730, 9784, + 7608, 12424, 2141, 9554, 12448, 16195, 17193, 15255, 3676, 16433, + 4281, 8047, 1655, 7786, 2263, 1454, 2174, 11911, 1024, 19925, + 15854, 16794, 5449, 11329, 12345, 899, 12434, 2567, 9500, 18229, + 13027, 12412, 2295, 9389, 20474, 16902, 14233, 1512, 11757, 10674, + 14853, 5047, 5042, 4859, 11903, 21497, 7761, 8395, 1222, 20180, + 14987, 4988, 21639, 18924, 11904, 15343, 17402, 6457, 12366, 9483, + 12697, 8728, 21366, 1966, 20962, 16799, 1036, 10139, 14227, 1627, + 3075, 20460, 7215, 17339, 14920, 19544, 21130, 5243, 16245, 8921, + 1534, 16530, 10165, 3611, 14036, 21625, 18838, 10462, 8767, 13022, + 3183, 12656, 2303, 15472, 10788, 19385, 2246, 4760, 8071, 1644, + 14827, 10315, 17801, 3090, 10234, 20160, 7530, 2038, 9529, 17131, + 16935, 8635, 14869, 1388, 20487, 12897, 2488, 10467, 6470, 7094, + 12591, 6820, 13023, 12510, 9987, 14102, 17802, 17315, 2489, 9025, + 14965, 10167, 11598, 6651, 12422, 15226, 4507, 13112, 13538, 18489, + 15473, 17392, 8471, 7642, 21744, 9892, 13169, 9336, 4139, 17656, + 20136, 7007, 7452, 21053, 3593, 18153, 19347, 4118, 8472, 11899, + 15705, 12610, 15822, 15823, 20499, 3893, 14246, 8558, 7453, 4644, + 15228, 10390, 8352, 6823, 19807, 9762, 20008, 12248, 14725, 5140, + 17567, 4872, 21135, 4873, 2823, 3327, 8834, 6001, 7587, 5351, + 17408, 15631, 10062, 12774, 4584, 14283, 5797, 4215, 14712, 10178, + 13593, 16274, 21493, 8729, 17329, 15641, 11201, 6766, 14935, 1597, + 5417, 21379, 11252, 7937, 20690, 13903, 5214, 9496, 18989, 7353, + 1692, 12388, 10778, 9390, 11322, 14057, 17545, 9872, 20294, 7553, + 12958, 13076, 6551, 21699, 18526, 6977, 2858, 20111, 19363, 3877, + 6937, 16431, 4653, 11242, 8408, 8672, 10212, 3753, 3334, 12530, + 11244, 7239, 4402, 5400, 17813, 18160, 6187, 18549, 10655, 16980, + 6690, 9767, 12703, 19234, 12702, 6395, 9040, 18325, 3100, 16279, + 21468, 13085, 12901, 21472, 9404, 1541, 15824, 6562, 17553, 4207, + 5871, 2491, 8337, 4698, 3304, 19073, 921, 21609, 18136, 3819, + 21292, 6196, 21394, 7016, 11691, 6135, 6924, 13263, 1710, 19275, + 9027, 11838, 17842, 7534, 7535, 12961, 2134, 21023, 11231, 9541, + 9407, 7018, 21695, 8949, 14276, 12230, 9139, 4052, 14918, 2997, + 10529, 1652, 1281, 10391, 17226, 8888, 10253, 4356, 10359, 7536, + 9232, 1872, 7394, 18640, 2218, 17345, 7537, 16947, 5664, 2023, + 11812, 9438, 3156, 13502, 12070, 10633, 21697, 10553, 20196, 11814, + 8486, 15529, 21220, 9233, 13985, 18463, 17706, 1265, 17711, 10811, + 18146, 20953, 17150, 19675, 12711, 2272, 2396, 8198, 10879, 19615, + 19927, 17097, 11610, 904, 15493, 7913, 6636, 19248, 3186, 3081, + 17969, 20484, 12584, 1997, 13484, 10450, 1528, 20161, 16609, 16463, + 20070, 15549, 16778, 1613, 12764, 2098, 10698, 9593, 12289, 11196, + 18594, 13941, 7398, 2802, 2497, 3062, 17397, 4543, 12003, 21248, + 11530, 20922, 20608, 10211, 8148, 12468, 10328, 17078, 17401, 19462, + 20886, 16180, 20799, 10043, 5430, 3652, 9601, 16142, 2464, 8658, + 9346, 18143, 13696, 20930, 20627, 5678, 12625, 15873, 9082, 8151, + 6479, 6185, 6755, 7781, 10533, 8368, 927, 17852, 4526, 5549, + 4900, 8420, 21550, 15259, 10057, 2806, 4679, 4027, 12974, 20547, + 20973, 19237, 6634, 21516, 1851, 15522, 13815, 1386, 10153, 6556, + 9136, 2215, 2283, 2284, 8140, 1025, 3852, 8457, 9901, 11080, + 10975, 10700, 14844, 14209, 6889, 10976, 18265, 1460, 5967, 1461, + 14188, 8557, 8650, 1367, 6254, 13953, 14039, 17204, 7492, 7344, + 11278, 17066, 14877, 4006, 20342, 11616, 20402, 12186, 17115, 10077, + 1599, 1490, 13954, 6119, 5615, 5291, 5260, 4445, 2840, 6275, + 5721, 11282, 14113, 9073, 9304, 10477, 15862, 14156, 8237, 19970, + 19971, 2239, 13523, 10019, 2274, 14137, 9074, 18235, 16578, 18280, + 4346, 6841, 19786, 16579, 6280, 1231, 6281, 13525, 18611, 16581, + 1168, 944, 16415, 19129, 9095, 13632, 10614, 2923, 9817, 5862, + 7484, 3690, 8197, 3119, 14448, 11553, 20321, 9795, 9239, 7065, + 12444, 8260, 13347, 4096, 2925, 2451, 10476, 2125, 8259, 17993, + 10914, 19300, 20651, 4614, 15322, 15247, 17594, 5196, 3178, 5216, + 14912, 1693, 13808, 21178, 17593, 7912, 13029, 12645, 2768, 15496, + 21182, 6370, 5131, 19973, 13279, 16159, 8455, 13103, 13214, 10381, + 21740, 16907, 8238, 19898, 9394, 18282, 10005, 1879, 2130, 19482, + 1001, 11363, 3129, 14254, 15742, 20043, 9788, 12402, 3379, 7059, + 1714, 19028, 13751, 4298, 5468, 8675, 10330, 20889, 18936, 20677, + 6330, 9607, 18546, 14648, 20936, 13549, 10402, 20580, 11726, 16329, + 9210, 4022, 13576, 12241, 15738, 11797, 15335, 8577, 6129, 13634, + 2904, 5619, 4012, 12782, 8959, 15512, 5621, 12401, 8621, 17058, + 6821, 2247, 12283, 3499, 6561, 15337, 16583, 16584, 5952, 8563, + 4018, 6768, 15321, 6548, 9368, 17659, 18890, 20900, 19087, 18454, + 3986, 4291, 14456, 12134, 5157, 20036, 20871, 12286, 2461, 4295, + 13428, 3645, 10110, 16135, 1737, 4228, 14729, 4229, 4374, 5747, + 19548, 8517, 13121, 17707, 2949, 4997, 17081, 14208, 14469, 12564, + 20703, 17276, 3514, 12136, 18950, 4127, 10581, 19100, 8189, 2415, + 10403, 14471, 17239, 19105, 21227, 18473, 13777, 17091, 2696, 18378, + 19106, 19591, 3602, 16348, 11774, 4128, 2986, 21504, 3121, 10442, + 9976, 16496, 7315, 12993, 7273, 7113, 7056, 8595, 3581, 5084, + 7431, 20175, 11970, 10045, 1921, 1385, 20306, 12353, 12556, 5038, + 9111, 5136, 6037, 15401, 5210, 20272, 17633, 20010, 5770, 6084, + 20140, 10855, 19707, 2307, 11695, 12679, 14495, 18678, 2339, 18370, + 6688, 1888, 5927, 5757, 17935, 8974, 903, 11306, 16089, 18065, + 18630, 16938, 11575, 1341, 14641, 8928, 18792, 20935, 21488, 5060, + 7933, 20710, 9170, 13393, 6962, 15454, 5020, 2163, 7149, 16953, + 3624, 19618, 5457, 7950, 13521, 7466, 7597, 12446, 10832, 5503, + 16749, 5550, 6959, 8305, 7340, 12362, 8661, 13151, 15258, 1110, + 959, 7741, 5064, 18327, 6697, 20046, 16797, 15489, 7171, 3523, + 995, 17040, 19188, 13991, 13704, 9966, 16060, 3586, 12314, 15187, + 19770, 17250, 4683, 11687, 4388, 6992, 3528, 19195, 20999, 10262, + 16936, 9658, 9665, 6141, 20812, 18968, 13203, 12875, 6543, 5454, + 8379, 6341, 20103, 19629, 2737, 15181, 5989, 6909, 14852, 5655, + 2797, 20106, 19384, 7002, 16929, 10197, 9526, 11556, 18027, 20108, + 7099, 7100, 11492, 4810, 14081, 11466, 4663, 12076, 20020, 2660, + 18448, 953, 11006, 3764, 3486, 6337, 3813, 11478, 2429, 20343, + 10083, 12653, 21110, 6266, 20409, 19125, 21290, 16101, 10088, 3973, + 19252, 16810, 10094, 10095, 6268, 19130, 5288, 1878, 10868, 11430, + 3202, 7485, 14018, 14748, 2314, 10473, 12604, 13494, 12415, 3506, + 17140, 2860, 3925, 18199, 19099, 8727, 20022, 12557, 2649, 7669, + 4028, 3851, 19514, 19862, 5854, 19945, 16652, 13785, 6606, 8013, + 13913, 15374, 5373, 21397, 11498, 18542, 12948, 10213, 3959, 8549, + 10329, 7290, 14439, 21140, 21775, 5566, 20676, 13467, 20804, 8038, + 5681, 3963, 18217, 8870, 13987, 5885, 12367, 20706, 11095, 16096, + 10611, 3247, 12101, 16275, 11759, 7988, 18225, 4603, 19607, 21584, + 3904, 7487, 3120, 11561, 11177, 16217, 4331, 14816, 2525, 19352, + 5290, 10501, 1715, 15606, 20991, 20371, 5534, 11020, 14059, 14201, + 10737, 10738, 20051, 10196, 11049, 1707, 16812, 16531, 9099, 16969, + 19060, 3449, 15620, 19808, 10235, 3360, 7095, 12079, 18491, 16420, + 16421, 17059, 7222, 11050, 11029, 9408, 9706, 6925, 890, 4645, + 3363, 10254, 10105, 923, 4765, 9708, 1259, 6160, 6161, 6163, + 1774, 13244, 15712, 20650, 2476, 13296, 8066, 8069, 15714, 4588, + 11180, 1271, 15759, 6824, 18721, 3885, 2124, 7345, 13766, 3625, + 4077, 16798, 13767, 13208, 11865, 19189, 13981, 11512, 11390, 21690, + 1181, 19004, 18625, 15574, 1133, 7754, 6260, 12114, 1754, 19123, + 5293, 15576, 7081, 940, 6171, 5402, 12832, 15842, 19354, 15180, + 15785, 17998, 8788, 1379, 15334, 20498, 9753, 10018, 19566, 16856, + 18746, 14151, 17644, 16909, 1616, 13986, 8308, 15069, 1634, 1635, + 14723, 5450, 5483, 6380, 4612, 6983, 9203, 19569, 12152, 10834, + 20393, 7981, 11680, 10134, 18868, 18458, 16430, 4165, 13050, 14569, + 6329, 21258, 17982, 15353, 18680, 18470, 16792, 5930, 10984, 2334, + 18383, 6365, 19751, 16364, 4097, 1227, 17936, 1552, 16077, 10120, + 10781, 14265, 20072, 19010, 19782, 4495, 15215, 17256, 8474, 3169, + 1612, 3536, 17897, 16911, 9592, 6415, 8077, 6422, 4586, 14611, + 14982, 17142, 20881, 13436, 6418, 4886, 21774, 11056, 20800, 3010, + 20631, 15769, 12704, 2179, 17037, 21454, 16997, 13679, 15588, 15434, + 1525, 9096, 9140, 17615, 1196, 4365, 13357, 13358, 6130, 13136, + 11480, 7371, 3610, 11966, 15555, 15336, 17551, 12052, 5303, 1535, + 9100, 15474, 10297, 5791, 13113, 18009, 7011, 7390, 7563, 2258, + 3305, 6440, 17263, 12905, 4053, 16220, 7395, 9234, 16390, 13768, + 4933, 10965, 13602, 5294, 16474, 13133, 5940, 2327, 9097, 13856, + 20083, 14356, 16482, 5301, 1136, 15556, 5426, 20084, 5205, 1536, + 16485, 6825, 4050, 16221, 4054, 4890, 8141, 17160, 17600, 17168, + 7004, 20102, 9381, 12220, 6650, 19258, 20086, 12226, 949, 19131, + 17372, 6441, 18676, 3888, 13285, 8967, 17384, 14890, 5907, 17822, + 18817, 17825, 5557, 15053, 8995, 12712, 4126, 7271, 6753, 11920, + 13757, 18519, 21565, 13612, 12877, 11279, 15595, 12819, 4132, 10884, + 10988, 5185, 11762, 19698, 3280, 18018, 11199, 6940, 5139, 3478, + 17809, 2368, 4167, 18197, 21431, 1547, 4734, 4450, 894, 9617, + 10215, 20349, 15907, 3654, 9112, 16143, 4896, 17709, 10809, 17087, + 13057, 20387, 3966, 11586, 5312, 16662, 12811, 4129, 1325, 3905, + 2438, 21121, 7807, 3703, 17995, 1574, 20589, 5806, 14045, 13298, + 13481, 4154, 3590, 7560, 1933, 11024, 1871, 8592, 20896, 4946, + 4976, 17807, 11167, 8792, 4158, 11197, 3369, 14491, 19829, 18799, + 15174, 21569, 2561, 11419, 9171, 7417, 3691, 15261, 18169, 11706, + 6009, 19758, 16259, 1148, 4174, 3631, 3385, 12066, 12538, 10113, + 2386, 8065, 9449, 6123, 13070, 4339, 4272, 16475, 7815, 9091, + 14427, 18828, 18829, 8697, 4116, 1603, 12457, 9450, 15808, 7283, + 15957, 6800, 8980, 7284, 10606, 15883, 2483, 19344, 19996, 6379, + 5985, 8028, 16062, 16063, 12436, 9177, 16064, 21529, 21530, 2930, + 3912, 9178, 15424, 5986, 12891, 8699, 3212, 8103, 13184, 18833, + 14006, 15663, 4275, 4351, 18283, 16608, 8611, 19395, 21315, 18284, + 17257, 17672, 18876, 19934, 14049, 3726, 3727, 7579, 8960, 9456, + 9337, 12407, 16227, 10740, 3149, 18588, 6062, 13114, 5562, 18135, + 18352, 6827, 2259, 13888, 11031, 1711, 15177, 12348, 13946, 15083, + 8978, 10880, 8694, 11310, 12403, 2481, 8619, 9978, 5538, 15835, + 1439, 13591, 15719, 4523, 20678, 14324, 16281, 16052, 4887, 5168, + 5505, 9636, 18330, 12311, 9241, 9517, 6997, 20300, 6095, 5653, + 8353, 7872, 5041, 18847, 12499, 20520, 9896, 16021, 2884, 14176, + 10974, 2146, 11916, 1913, 15375, 8289, 1162, 12914, 4545, 8648, + 3989, 6877, 1091, 19716, 20738, 5508, 8678, 12520, 1887, 1824, + 19960, 11463, 15437, 3754, 14904, 14650, 17986, 15298, 1453, 11652, + 12262, 4194, 8660, 9349, 4403, 19507, 2516, 7275, 11587, 18651, + 2470, 3808, 19104, 8564, 21173, 15877, 3915, 6459, 13556, 5876, + 17264, 12442, 10360, 10008, 11813, 13586, 15879, 8094, 12541, 19337, + 19394, 9455, 4735, 3916, 5571, 4927, 17069, 20437, 1626, 13993, + 1086, 15360, 9939, 5576, 17999, 14300, 8330, 1637, 14963, 16483, + 18488, 18586, 15077, 8578, 14061, 4471, 10166, 16971, 10198, 12396, + 12397, 10169, 1647, 1648, 1649, 9894, 1650, 14104, 4766, 17778, + 18464, 20425, 14940, 18572, 10142, 4579, 4473, 4599, 14565, 1965, + 6951, 3900, 14997, 16128, 20397, 16098, 13769, 19746, 8382, 2654, + 19190, 4531, 4532, 15237, 19187, 21280, 18819, 21782, 1491, 7834, + 15550, 1248, 3026, 15828, 15007, 1249, 14672, 4241, 5895, 13771, + 15755, 7679, 7281, 1755, 18573, 15923, 14128, 15803, 20746, 14080, + 2706, 15463, 958, 13867, 9325, 9162, 15594, 8762, 20304, 9560, + 5234, 4266, 3258, 10564, 10179, 8556, 7421, 9285, 13227, 8202, + 853, 13008, 11947, 1347, 3559, 8733, 9043, 5556, 6864, 12140, + 8360, 15411, 21512, 13161, 8574, 14948, 4335, 2109, 15071, 6547, + 864, 10312, 13015, 4636, 10923, 11397, 5292, 8349, 11488, 10147, + 19015, 7258, 1698, 1633, 15470, 10784, 10619, 19381, 21679, 17997, + 3607, 2199, 8460, 12588, 10383, 4135, 9209, 12607, 3152, 13019, + 3591, 6912, 21467, 19056, 2133, 1646, 21046, 14418, 3241, 20974, + 1415, 21546, 11374, 14765, 10495, 6956, 4835, 9284, 8687, 13733, + 3027, 17366, 18510, 8385, 4406, 9387, 16898, 1799, 11629, 4341, + 1891, 8535, 4010, 15145, 19630, 16905, 18580, 6847, 5870, 14685, + 7517, 21390, 1756, 17308, 1928, 18709, 3442, 4594, 20485, 16522, + 5633, 4347, 11931, 20081, 6382, 6647, 6807, 7372, 6298, 914, + 15509, 4665, 16526, 5535, 2114, 15055, 15511, 1864, 5203, 17055, + 9021, 10163, 15076, 15581, 18719, 16554, 11344, 15513, 10752, 1530, + 19803, 17776, 7916, 14037, 9026, 21336, 14247, 2672, 3450, 19071, + 7008, 13700, 2490, 16534, 17373, 20416, 4666, 5899, 11030, 18425, + 11351, 2219, 17374, 10634, 20170, 11573, 3896, 16112, 4230, 6090, + 9386, 16838, 3999, 8523, 5861, 5520, 20691, 7184, 14094, 11721, + 5035, 13681, 5704, 7659, 6048, 16886, 12515, 3831, 6423, 19398, + 8112, 19824, 1241, 20704, 5472, 3927, 10332, 13472, 2559, 14931, + 4383, 20954, 5567, 17765, 10534, 1833, 9491, 5521, 19748, 17205, + 15644, 16755, 11192, 937, 1291, 2960, 6369, 4336, 3023, 10924, + 16807, 18627, 7365, 19254, 20615, 10194, 9882, 7638, 8164, 19794, + 6437, 10459, 5662, 11619, 3879, 7734, 9595, 14217, 9602, 19463, + 5105, 8676, 3401, 20365, 12120, 21260, 17961, 7243, 18179, 18803, + 20960, 9324, 16796, 3239, 17202, 14129, 21206, 4635, 5554, 16460, + 19681, 19555, 3380, 9123, 19000, 6290, 2159, 10311, 7302, 14070, + 18693, 1839, 4682, 1847, 11684, 1503, 1854, 16010, 5911, 4595, + 7373, 945, 918, 17170, 19997, 4699, 12428, 17653, 10687, 19747, + 4774, 5973, 3699, 16153, 16129, 2607, 18096, 21281, 20822, 12159, + 17670, 13783, 13992, 20049, 16573, 20851, 3405, 10478, 19486, 1848, + 1251, 8440, 16155, 19005, 13448, 12567, 13452, 8080, 12523, 20530, + 19846, 12189, 21151, 8316, 21287, 11906, 8210, 12274, 20181, 7313, + 10084, 20692, 15346, 5026, 18511, 14608, 1509, 16157, 16158, 15009, + 10148, 10709, 12375, 15579, 21000, 13820, 15610, 3972, 18060, 13536, + 14401, 8081, 4407, 5896, 1855, 21185, 19126, 10663, 21111, 3443, + 5897, 10156, 8240, 15046, 13185, 10815, 2666, 11394, 1149, 7076, + 6640, 1632, 10642, 19342, 20390, 10225, 19194, 2712, 1153, 9179, + 19051, 3771, 12339, 3728, 13497, 18959, 15040, 16830, 13309, 21398, + 1570, 18602, 15797, 4007, 8688, 19621, 18055, 8314, 19684, 18730, + 2131, 11500, 13756, 7880, 10956, 12063, 3453, 7248, 5252, 8752, + 9722, 2524, 9769, 7419, 1656, 2809, 15693, 1486, 8203, 4190, + 3269, 1330, 1250, 10503, 1576, 9201, 2634, 20605, 13048, 13883, + 12069, 18173, 17810, 8498, 3216, 7877, 9415, 21547, 2362, 14999, + 6863, 9359, 15520, 11990, 10288, 7576, 11895, 11410, 3844, 3882, + 3374, 10065, 11824, 5826, 9015, 1010, 15408, 5903, 12684, 6005, + 9294, 5987, 16012, 17950, 16081, 8538, 4284, 2549, 17693, 15012, + 10458, 21370, 21116, 14357, 12376, 9057, 15582, 9165, 21602, 8739, + 12738, 12739, 18408, 4596, 14062, 18409, 5304, 18612, 16815, 12383, + 3091, 12384, 12942, 4597, 6652, 12940, 6869, 19648, 15666, 13537, + 17113, 21604, 8985, 13851, 14964, 5578, 16163, 5735, 15078, 12900, + 2541, 21015, 10168, 12228, 15614, 16972, 2044, 4045, 18417, 19908, + 21655, 14063, 14248, 12751, 21019, 14856, 10468, 16973, 10626, 20488, + 11407, 1046, 1973, 1651, 3092, 13461, 1542, 21020, 19810, 17841, + 6471, 1802, 15154, 17462, 9989, 20467, 4157, 10172, 16165, 2087, + 3773, 7643, 15825, 18426, 10635, 20418, 7794, 6109, 19336, 8684, + 5972, 4340, 21311, 11792, 10739, 14047, 6060, 13886, 12441, 6320, + 12916, 13374, 7107, 2156, 6686, 5310, 10996, 4898, 12296, 13942, + 17238, 6017, 7856, 5377, 3991, 19182, 2558, 5905, 5476, 6104, + 9629, 19474, 13657, 20366, 13344, 10068, 2469, 19536, 13320, 7277, + 11589, 20961, 14936, 13444, 15859, 9087, 12705, 7619, 18477, 10839, + 14450, 20562, 14296, 16721, 9499, 2782, 4923, 13007, 13259, 12722, + 16895, 19767, 4591, 5867, 5834, 19003, 12313, 15783, 13570, 16236, + 9290, 11039, 2942, 13813, 11562, 4936, 8979, 8696, 5024, 15073, + 19627, 19488, 10289, 13410, 1557, 10843, 13217, 1011, 10763, 10822, + 8003, 19078, 18722, 16131, 12429, 21158, 18431, 10255, 10485, 15619, + 17346, 7226, 14862, 8249, 16976, 6529, 9544, 1653, 13779, 19096, + 1617, 17678, 13176, 21577, 15116, 8972, 14854, 16446, 16454, 16455, + 19609, 5146, 18981, 980, 1272, 1332, 3005, 15673, 13071, 8858, + 16074, 5357, 12373, 19644, 15191, 1867, 17455, 12096, 1868, 3235, + 11348, 9893, 10298, 17459, 20178, 15675, 1723, 8889, 10361, 5192, + 13128, 8652, 13118, 9338, 14073, 9041, 3627, 4573, 17771, 13659, + 3435, 9050, 1716, 4429, 12275, 4455, 15697, 1274, 1510, 10844, + 4937, 4389, 13821, 13454, 5389, 9092, 12221, 21297, 14301, 15271, + 15700, 9666, 1718, 15703, 12224, 15035, 10680, 19901, 16916, 2574, + 15503, 12087, 14687, 6645, 2037, 12394, 15506, 16923, 17391, 21049, + 20486, 14840, 10846, 12223, 6813, 12049, 14242, 6918, 11042, 2205, + 9759, 11229, 9536, 4083, 13501, 4805, 19244, 13301, 17129, 14647, + 21197, 19577, 7044, 4059, 6950, 7405, 20544, 21549, 6419, 13313, + 12521, 3288, 14472, 20240, 5434, 9625, 14998, 15778, 7245, 1548, + 2562, 8808, 1470, 17241, 18269, 13559, 20749, 8502, 14666, 5183, + 12008, 14294, 17474, 13295, 20248, 13159, 21283, 13970, 12930, 16185, + 1498, 3382, 8780, 19843, 17431, 20658, 9014, 6637, 6293, 5423, + 4618, 9657, 1514, 2612, 15150, 11227, 3982, 10451, 4104, 5763, + 20760, 21605, 14896, 7447, 4223, 6384, 9133, 12750, 9761, 20696, + 12229, 10711, 14023, 10754, 10755, 14112, 17843, 9947, 12902, 12903, + 11570, 9101, 11839, 1724, 13683, 4000, 4008, 11617, 6282, 17056, + 4014, 5947, 4015, 4016, 8125, 19818, 19819, 18404, 4974, 17655, + 5734, 21606, 10199, 5737, 14269, 10962, 12713, 12714, 5050, 17829, + 19793, 16065, 12655, 9838, 5117, 12398, 1539, 12752, 17840, 2759, + 18356, 20419, 19594, 3510, 13723, 7804, 1070, 6261, 16130, 3632, + 7116, 19631, 4274, 13162, 14135, 5994, 16100, 11398, 7866, 14428, + 1167, 19896, 12315, 10379, 16574, 6375, 10338, 20097, 4559, 4687, + 11513, 19489, 12382, 11337, 6127, 17107, 3772, 20134, 3576, 1876, + 9183, 21155, 19571, 19578, 2683, 17032, 11770, 11922, 2865, 14181, + 18854, 1420, 21040, 1164, 4571, 5307, 10334, 21205, 20241, 16879, + 14295, 16462, 11038, 14704, 2036, 2691, 11026, 13175, 11750, 7247, + 13405, 14132, 1532, 3601, 13042, 15263, 7812, 15467, 16915, 17146, + 11092, 1063, 9627, 15802, 16876, 21502, 1992, 9964, 21632, 14028, + 6294, 20133, 3024, 17860, 13844, 13420, 7600, 5323, 7173, 18934, + 10064, 16877, 21284, 4615, 7434, 12364, 6125, 19046, 11107, 20846, + 12718, 12778, 18581, 3553, 4834, 13459, 8114, 8200, 9937, 21511, + 20147, 11557, 20604, 7544, 2628, 3883, 5106, 21144, 18802, 5482, + 13455, 5912, 12279, 10089, 16160, 1102, 13413, 12495, 4942, 1520, + 7201, 16523, 8211, 3791, 1856, 19491, 5810, 12317, 11718, 17690, + 15362, 1276, 5029, 20354, 8321, 5490, 14590, 3936, 3352, 15309, + 7822, 14759, 6316, 17370, 4390, 946, 16416, 20558, 21186, 19216, + 9941, 10664, 15935, 18834, 19050, 1773, 16480, 7636, 8828, 5730, + 17169, 5298, 6734, 9354, 4945, 8665, 17774, 4206, 8511, 15664, + 11179, 14302, 20355, 15272, 13186, 19645, 11630, 20597, 5811, 5358, + 15096, 16725, 13415, 14202, 12572, 6602, 15789, 9569, 14139, 14140, + 8666, 11025, 2538, 9527, 21659, 16930, 19427, 14403, 21531, 12742, + 13262, 17371, 11631, 2966, 7216, 3795, 3133, 16151, 17152, 11317, + 20897, 18395, 14537, 2531, 16009, 9447, 9053, 12133, 6378, 15657, + 17861, 5889, 15508, 9335, 1893, 7729, 16934, 8335, 9571, 18073, + 14598, 3244, 4159, 13304, 18021, 3145, 1679, 1264, 15297, 7412, + 4832, 13000, 20847, 4836, 14189, 9637, 16150, 7253, 1874, 15356, + 8994, 13061, 1487, 17247, 17151, 6967, 7620, 9823, 7180, 2975, + 6503, 2610, 20994, 3743, 1849, 20855, 7510, 3861, 2857, 21066, + 8266, 4205, 3233, 12374, 13846, 11793, 12047, 12654, 2799, 8465, + 12609, 4503, 3147, 21210, 10023, 2214, 9946, 21694, 17625, 20906, + 3785, 11388, 17767, 11402, 12320, 6354, 8424, 14257, 5478, 21508, + 13168, 5561, 21129, 3938, 9166, 4598, 11667, 19061, 9058, 10463, + 8165, 2276, 7998, 10598, 10099, 21653, 9530, 11043, 21607, 21016, + 11722, 6400, 19649, 3662, 14546, 14405, 6603, 15667, 6299, 17695, + 21193, 9137, 21608, 7205, 1564, 1565, 6604, 13581, 20281, 16375, + 16376, 19650, 2946, 13852, 3865, 6653, 9807, 18344, 13360, 13361, + 7448, 1399, 4353, 18490, 5036, 14007, 7383, 17072, 16178, 6385, + 14693, 13973, 17957, 16555, 7387, 6063, 16700, 12091, 14064, 10170, + 10696, 14594, 14547, 5622, 21534, 15616, 15312, 18589, 5305, 19396, + 12945, 12753, 16556, 13974, 14410, 9763, 1017, 9385, 6716, 11290, + 7223, 15792, 13462, 7391, 14406, 10756, 5384, 15136, 20992, 21555, + 13289, 8057, 19593, 9638, 16570, 15863, 7181, 12161, 4592, 14157, + 19173, 889, 17316, 10717, 2448, 8262, 1228, 15781, 21517, 19166, + 19686, 2991, 16670, 11164, 19878, 16164, 21364, 15244, 8371, 8204, + 10662, 8331, 2743, 13305, 10537, 16808, 20153, 11424, 1045, 10161, + 1338, 17652, 19480, 4558, 1100, 12489, 11717, 10337, 15093, 5017, + 6314, 15357, 5722, 7810, 16468, 4387, 7182, 7624, 17367, 18098, + 5356, 9513, 9742, 7363, 14589, 15787, 5809, 14136, 6597, 7186, + 13261, 10090, 21652, 4593, 9055, 2275, 5560, 11666, 11719, 3792, + 14543, 21526, 4718, 3862, 4349, 13355, 5033, 6648, 1561, 14060, + 16975, 13418, 1664, 7224, 7220, 21211, 7564, 13363, 21316, 19390, + 20489, 8636, 18035, 1667, 19813, 13463, 17393, 1803, 7700, 18109, + 15155, 6654, 21746, 14251, 14252, 4474, 5792, 9991, 18110, 11195, + 17005, 20303, 17344, 4720, 5624, 6317, 8883, 20282, 14065, 20420, + 5135, 5793, 14489, 9574, 2304, 9410, 14791, 922, 13889, 7225, + 17916, 6442, 14793, 9707, 9949, 10668, 11232, 20668, 17375, 4358, + 10362, 5666, 9545, 17181, 3509, 7111, 16099, 1069, 6117, 19484, + 20351, 1840, 12310, 8663, 15924, 20279, 6315, 8873, 20352, 8508, + 19425, 12730, 14402, 1396, 2302, 15661, 16552, 16372, 13577, 7558, + 12088, 7377, 16532, 16970, 6439, 5134, 1015, 12740, 15310, 5620, + 18585, 9384, 1663, 18034, 10753, 11288, 19386, 5790, 14249, 21745, + 9572, 3296, 18449, 3298, 13102, 10751, 7376, 8214, 13849, 5425, + 1337, 7862, 15955, 8827, 5493, 3661, 6296, 5295, 8700, 1526, + 10296, 12841, 8887, 1721, 4051, 10966, 1087, 18336, 9837, 17442, + 16335, 2578, 17363, 18398, 15829, 15557, 19389, 1618, 9044, 10842, + 13661, 15786, 7194, 21525, 17772, 13578, 8124, 1722, 6563, 9948, + 11335, 6712, 11068, 7115, 8509, 21235, 11070, 12745, 1016, 14361, + 9990, 3356, 2849, 19516, 17112, 18762, 13460, 4046, 9532, 13280, + 1989, 978, 4693, 19542, 16726, 18357, 16943, 13414, 5913, 20330, + 20417, 5635, 11751, 18867, 4928, 9646, 8121, 1900, 18390, 4891, + 3787, 6968, 4792, 13905, 5114, 14538, 4793, 11309, 1252, 19844, + 20823, 6433, 13212, 4845, 4688, 16575, 7364, 14541, 19779, 4811, + 18537, 8451, 8452, 12336, 6519, 20721, 1254, 18399, 18148, 20784, + 4552, 4794, 16576, 11978, 3353, 5261, 13874, 10091, 11223, 4938, + 16161, 11262, 9659, 1578, 21001, 5262, 19848, 3031, 13483, 17443, + 2575, 3444, 8212, 18610, 5491, 21048, 19787, 18451, 19788, 18150, + 15821, 19789, 15736, 19253, 4117, 16698, 4391, 5577, 915, 20825, + 18406, 6193, 17450, 7285, 9942, 21187, 18487, 15662, 6269, 10453, + 13880, 11425, 5265, 13725, 7637, 17775, 22349, 22350, 22351, 22352, + 22353, 22354, 22355, 22356, 22357, 22358, 22359, 22360, 22361, 22362, + 22363, 22364, 22365, 22366, 22367, 22368, 22369, 22370, 22371, 22372, + 22373, 22374, 22375, 22376, 22377, 22378, 22379, 22380, 22381, 22382, + 22383, 22384, 22385, 22386, 22387, 22388, 22389, 22390, 22391, 22392, + 22393, 22394, 22395, 22396, 22397, 22398, 22399, 22400, 22401, 22402, + 22403, 22404, 22405, 22406, 22407, 22408, 22409, 22410, 22411, 22412, + 22413, 22414, 22415, 22416, 22417, 22418, 22419, 22420, 22421, 22422, + 22423, 22424, 22425, 22426, 22427, 22428, 22429, 22430, 22431, 22432, + 22433, 22434, 22435, 22436, 22437, 22438, 22439, 22440, 22441, 22442, + 21115, 2576, 10665, 6194, 11720, 4285, 10538, 7286, 7206, 16013, + 6521, 16177, 1902, 16724, 8351, 19801, 1865, 8539, 8540, 1398, + 16931, 8541, 8241, 15980, 7997, 15665, 4276, 4277, 8915, 5539, + 16766, 14404, 9180, 7693, 12068, 10464, 12323, 14763, 4948, 948, + 21469, 12227, 13416, 12898, 1293, 3796, 10465, 13635, 7381, 8243, + 16029, 18152, 19850, 12743, 9531, 18720, 21371, 8784, 4246, 9059, + 14481, 12744, 7999, 19062, 19063, 8000, 21532, 9167, 3939, 12657, + 2967, 5345, 8215, 8467, 19064, 21743, 7005, 14828, 14829, 2673, + 11194, 13853, 950, 13362, 15668, 6386, 15669, 4354, 7758, 10847, + 4949, 2947, 16014, 18345, 6133, 19909, 22443, 22444, 22445, 22446, + 22447, 22448, 22449, 22450, 22451, 22452, 22453, 22454, 22455, 22456, + 22457, 22458, 22459, 22460, 22461, 22462, 22463, 22464, 22465, 22466, + 22467, 22468, 22469, 22470, 22471, 22472, 22473, 22474, 22475, 22476, + 22477, 22478, 22479, 22480, 22481, 22482, 22483, 22484, 22485, 22486, + 22487, 22488, 22489, 22490, 22491, 22492, 22493, 22494, 22495, 22496, + 22497, 22498, 22499, 22500, 22501, 22502, 22503, 22504, 22505, 22506, + 22507, 22508, 22509, 22510, 22511, 22512, 22513, 22514, 22515, 22516, + 22517, 22518, 22519, 22520, 22521, 22522, 22523, 22524, 22525, 22526, + 22527, 22528, 22529, 22530, 22531, 22532, 22533, 22534, 22535, 22536, + 12365, 9060, 10932, 6387, 19262, 2887, 16816, 8246, 3940, 2018, + 4574, 6388, 19274, 19910, 17177, 16615, 14548, 6158, 2800, 15514, + 17114, 13975, 10171, 7096, 5494, 7388, 15251, 5992, 3035, 3036, + 19074, 18638, 18418, 7012, 9695, 15739, 8814, 15628, 15629, 19075, + 16015, 10695, 17460, 5206, 15740, 2435, 7097, 16049, 20617, 1018, + 18614, 18764, 11983, 2674, 21022, 10200, 19391, 10484, 1543, 14859, + 21474, 19651, 16727, 8480, 19176, 15433, 14966, 7644, 19079, 6472, + 1544, 19278, 15156, 6655, 4509, 7645, 9895, 18427, 5208, 8169, + 17227, 17228, 16016, 10723, 21747, 19814, 19280, 10472, 16050, 17229, + 18028, 19081, 12356, 14792, 10631, 16945, 22537, 22538, 22539, 22540, + 22541, 22542, 22543, 22544, 22545, 22546, 22547, 22548, 22549, 22550, + 22551, 22552, 22553, 22554, 22555, 22556, 22557, 22558, 22559, 22560, + 22561, 22562, 22563, 22564, 22565, 22566, 22567, 22568, 22569, 22570, + 22571, 22572, 22573, 22574, 22575, 22576, 22577, 22578, 22579, 22580, + 22581, 22582, 22583, 22584, 22585, 22586, 22587, 22588, 22589, 22590, + 22591, 22592, 22593, 22594, 22595, 22596, 22597, 22598, 22599, 22600, + 22601, 22602, 22603, 22604, 22605, 22606, 22607, 22608, 22609, 22610, + 22611, 22612, 22613, 22614, 22615, 22616, 22617, 22618, 22619, 22620, + 22621, 22622, 22623, 22624, 22625, 22626, 22627, 22628, 22629, 22630, + 18842, 7021, 20267, 19652, 20421, 18723, 18492, 12357, 11840, 6443, + 11083, 19281, 11032, 3640, 19985, 19815, 9439, 1903, 10363, 6162, + 10256, 14863, 19988, 19282, 5665, 13503, 9546, 10556, 14518, 2005, + 17411, 10053, 18020, 6189, 21102, 16718, 9045, 12881, 5339, 19842, + 15130, 6120, 13349, 19016, 16612, 10149, 7082, 19017, 18757, 6557, + 20413, 11027, 14860, 10370, 7892, 10092, 7449, 17223, 3245, 7454, + 7457, 18298, 19440, 3125, 1631, 3126, 12116, 21291, 7374, 11069, + 19691, 10164, 2433, 8512, 9983, 11668, 8166, 8513, 8001, 9682, + 17340, 18290, 7263, 11074, 9696, 20490, 8004, 12755, 10108, 18299, + 3127, 10732, 6121, 2358, 4846, 11183, 22631, 22632, 22633, 22634, + 22635, 22636, 22637, 22638, 22639, 22640, 22641, 22642, 22643, 22644, + 22645, 22646, 22647, 22648, 22649, 22650, 22651, 22652, 22653, 22654, + 22655, 22656, 22657, 22658, 22659, 22660, 22661, 22662, 22663, 22664, + 22665, 22666, 22667, 22668, 22669, 22670, 22671, 22672, 22673, 22674, + 22675, 22676, 22677, 22678, 22679, 22680, 22681, 22682, 22683, 22684, + 22685, 22686, 22687, 22688, 22689, 22690, 22691, 22692, 22693, 22694, + 22695, 22696, 22697, 22698, 22699, 22700, 22701, 22702, 22703, 22704, + 22705, 22706, 22707, 22708, 22709, 22710, 22711, 22712, 22713, 22714, + 22715, 22716, 22717, 22718, 22719, 22720, 22721, 22722, 22723, 22724, + 11184, 4848, 12124, 13524, 13457, 11426, 4849, 17310, 9168, 11186, + 2581, 4767, 13453, 11185, 11334, 11354, 21654, 11933, 4700, 6616, + 7893, 5686, 15713, 15963, 6494, 8941, 6270, 2583, 6164, 19018, + 3408, 17051, 16090, 11399, 12939, 3744, 18341, 10950, 18346, 19980, + 3469, 18240, 18350, 18351, 20724, 20697, 3362, 1990, 18765, 10934, + 20444, 18359, 4055, 10364, 4703, 11281, 19904, 3146, 13528, 2352, + 16206, 21192, 20828, 11044, 1019, 1668, 16166, 1545, 2344, 11133, + 3891, 21519, 5525, 3937, 4695, 19852, 2277, 5207, 2048, 19853, + 15475, 15599, 14778, 4641, 16582, 1089, 3794, 16162, 21051, 13487, + 14480, 14591, 14593, 15867, 8247, 8002, 22725, 22726, 22727, 22728, + 22729, 22730, 22731, 22732, 22733, 22734, 22735, 22736, 22737, 22738, + 22739, 22740, 22741, 22742, 22743, 22744, 22745, 22746, 22747, 22748, + 22749, 22750, 22751, 22752, 22753, 22754, 22755, 22756, 22757, 22758, + 22759, 22760, 22761, 22762, 22763, 22764, 22765, 22766, 22767, 22768, + 22769, 22770, 22771, 22772, 22773, 22774, 22775, 22776, 22777, 22778, + 22779, 22780, 22781, 22782, 22783, 22784, 22785, 22786, 22787, 22788, + 22789, 22790, 22791, 22792, 22793, 22794, 22795, 22796, 22797, 22798, + 22799, 22800, 22801, 22802, 22803, 22804, 22805, 22806, 22807, 22808, + 22809, 22810, 22811, 22812, 22813, 22814, 22815, 22816, 22817, 22818, + 6850, 8248, 18353, 15981, 14967, 17317, 9413, 18629, 16811, 16813, + 6283, 17622, 6159, 17803, 16629, 20331, 11890, 11579, 12723, 20381, + 7207, 21533, 7013, 7019, 2635, 2453, 2454, 6131, 18172, 19174, + 17620, 1233, 20265, 14694, 21535, 2579, 18347, 8269, 15791, 10102, + 10096, 2770, 13583, 17621, 19175, 11804, 8168, 18613, 2996, 20052, + 19693, 2815, 18878, 11669, 20266, 2998, 13512, 20053, 18358, 11984, + 4357, 16671, 19083, 3246, 21656, 3733, 2816, 7965, 18211, 6105, + 19157, 10228, 12089, 5391, 12090, 18348, 10245, 10250, 5392, 8596, + 3306, 10109, 3307, 5731, 13364, 1670, 2914, 6136, 8483, 17557, + 19987, 9271, 9814, 5122, 9564, 9967, 22819, 22820, 22821, 22822, + 22823, 22824, 22825, 22826, 22827, 22828, 22829, 22830, 22831, 22832, + 22833, 22834, 22835, 22836, 22837, 22838, 22839, 22840, 22841, 22842, + 22843, 22844, 22845, 22846, 22847, 22848, 22849, 22850, 22851, 22852, + 22853, 22854, 22855, 22856, 22857, 22858, 22859, 22860, 22861, 22862, + 22863, 22864, 22865, 22866, 22867, 22868, 22869, 22870, 22871, 22872, + 22873, 22874, 22875, 22876, 22877, 22878, 22879, 22880, 22881, 22882, + 22883, 22884, 22885, 22886, 22887, 22888, 22889, 22890, 22891, 22892, + 22893, 22894, 22895, 22896, 22897, 22898, 22899, 22900, 22901, 22902, + 22903, 22904, 22905, 22906, 22907, 22908, 22909, 22910, 22911, 22912, + 16769, 6900, 14850, 19718, 12706, 4918, 8263, 9548, 886, 5739, + 14473, 3992, 7037, 17500, 17731, 3521, 23854, 23855, 23856, 23857, + 23858, 23859, 23860, 23861, 23862, 23863, 23864, 23865, 23866, 23867, + 23868, 23869, 23870, 23871, 23872, 23873, 23874, 23875, 23876, 23877, + 23878, 23879, 23880, 23881, 23882, 23883, 23884, 23885, 23886, 23887, + 23888, 23889, 23890, 23891, 23892, 23893, 23894, 23895, 23896, 23897, + 23898, 23899, 23900, 23901, 23902, 23903, 23904, 23905, 23906, 23907, + 23908, 23909, 23910, 23911, 23912, 23913, 23914, 23915, 23916, 23917, + 23918, 23919, 23920, 23921, 23922, 23923, 23924, 23925, 23926, 23927, + 23928, 23929, 23930, 23931, 23932, 23933, 22913, 22914, 22915, 22916, + 22917, 22918, 22919, 22920, 22921, 22922, 22923, 22924, 22925, 22926, + 22927, 22928, 22929, 22930, 22931, 22932, 22933, 22934, 22935, 22936, + 22937, 22938, 22939, 22940, 22941, 22942, 22943, 22944, 22945, 22946, + 22947, 22948, 22949, 22950, 22951, 22952, 22953, 22954, 22955, 22956, + 22957, 22958, 22959, 22960, 22961, 22962, 22963, 22964, 22965, 22966, + 22967, 22968, 22969, 22970, 22971, 22972, 22973, 22974, 22975, 22976, + 22977, 22978, 22979, 22980, 22981, 22982, 22983, 22984, 22985, 22986, + 22987, 22988, 22989, 22990, 22991, 22992, 22993, 22994, 22995, 22996, + 22997, 22998, 22999, 23000, 23001, 23002, 23003, 23004, 23005, 23006 +}; + +static gbk_wchar get_gbk_sorted_value(gbk_wchar code) +{ + pg_wchar wchar = GBK_SECOND_WCHAR(code); + wchar = wchar > 0x7F ? wchar - 0x41 : wchar - 0x40; + wchar += (GBK_FIRST_WCHAR(code) - 0x81) * 0xbe; + return 0x8100 + two_bytes_gbk_sort_order[wchar]; +} + +/* +* gbk_chinese_ci : string compare function. +* return value is 0, arg1 = arg2 +* return < 0 , arg1 < arg2 +* return > 0 , arg1 > arg2 +*/ +int strnncoll_gbk_chinese_ci_pad_space(const GS_UCHAR* arg1, size_t len1, + const GS_UCHAR* arg2, size_t len2) +{ + size_t length = Min(len1, len2); + pg_wchar wchar1, wchar2; + const GS_UCHAR* arg1_str = arg1; + const GS_UCHAR* arg2_str = arg2; + + while (length--) { + if ((length > 0) && pg_gbk_islegal(arg1_str, 2) && pg_gbk_islegal(arg2_str, 2)) { + /* sort for 2 bytes gbk code */ + wchar1 = GBKCODE(*arg1_str, *(arg1_str + 1)); + wchar2 = GBKCODE(*arg2_str, *(arg2_str + 1)); + if (wchar1 != wchar2) { + return ((int)get_gbk_sorted_value((gbk_wchar)wchar1) - (int)get_gbk_sorted_value((gbk_wchar)wchar2)); + } + NEXT_WORD_POS(arg1_str, 2); + NEXT_WORD_POS(arg2_str, 2); + /* for 2 bytes comparison, length needs to minus 1 once again */ + length--; + } else if (one_bytes_gbk_sort_order[*arg1_str++] != one_bytes_gbk_sort_order[*arg2_str++]) { + /* sort for 1 bytes gbk code */ + return ((int) one_bytes_gbk_sort_order[arg1_str[-1]] - (int)one_bytes_gbk_sort_order[arg2_str[-1]]); + } + } + + int res = 0; + if (len1 != len2) { + res = len1 > len2 ? compare_tail_space(arg1_str, len1 - len2, 1) : + compare_tail_space(arg2_str, len2 - len1, -1); + } + + return res; +} + +static void transform_gbk_sort_key(const GS_UCHAR *key, int len, GS_UCHAR* sort_key) +{ + for (int i = 0; i < len; i++) { + sort_key[i] = one_bytes_gbk_sort_order[(unsigned int) key[i]]; + } + sort_key[len] = '\0'; +} + +Datum hash_gbk_chinese_pad_space(const GS_UCHAR *key, size_t len) +{ + int remove_space_len = bpchartruelen((char*)key, len); + GS_UCHAR* sort_key = (GS_UCHAR*)palloc(sizeof(GS_UCHAR*) * (remove_space_len + 1)); + transform_gbk_sort_key(key, remove_space_len, sort_key); + + Datum res = hash_any(sort_key, remove_space_len); + pfree_ext(sort_key); + + return res; +} + +int matchtext_gbk_chinese(GS_UCHAR* s, int slen, GS_UCHAR* p, int plen) +{ + int remove_space_len = bpchartruelen((char*)s, slen); + GS_UCHAR* sort_s = (GS_UCHAR*)palloc(sizeof(GS_UCHAR*) * (remove_space_len + 1)); + GS_UCHAR* sort_p = (GS_UCHAR*)palloc(sizeof(GS_UCHAR*) * (remove_space_len + 1)); + transform_gbk_sort_key(s, remove_space_len, sort_s); + transform_gbk_sort_key(p, plen, sort_p); + + int res = GenericMatchText((char*)sort_s, remove_space_len, (char*)sort_p, plen); + pfree_ext(sort_s); + pfree_ext(sort_p); + + return res; +} \ No newline at end of file diff --git a/src/common/backend/catalog/gs_utf8_collation.cpp b/src/common/backend/catalog/gs_utf8_collation.cpp index 54a681828..b51e35d7e 100644 --- a/src/common/backend/catalog/gs_utf8_collation.cpp +++ b/src/common/backend/catalog/gs_utf8_collation.cpp @@ -31,7 +31,7 @@ #include "parser/parse_type.h" #include "access/hash.h" #include "utils/lsyscache.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" typedef struct GS_UNICASE_PAGES { GS_UINT32 **sort_page; @@ -475,62 +475,14 @@ static GS_UINT32 *unicase_sort_pages[256] = { * the character collation is set to 0xFFFD. */ #define GS_REPLACEMENT_CHARACTER 0xFFFD -#define NEXT_WORD_POS(p, p_word_bytes) ((p) += (p_word_bytes)) GS_UNICASE_INFO g_unicase_default = { unicase_sort_pages }; -static int strnncoll_utf8mb4_general_pad_space(const unsigned char* arg1, size_t len1, - const unsigned char* arg2, size_t len2); static int mb_wc_utf8mb4(const unsigned char* s, const unsigned char* end, GS_UINT32* wchar); -static int strnncoll_utf8mb4_bin_pad_space(const unsigned char* arg1, size_t len1, - const unsigned char* arg2, size_t len2); -Datum hash_utf8mb4_general_pad_space(const unsigned char *key, size_t len); -Datum hash_utf8mb4_bin_pad_space(const unsigned char *key); static int get_current_char_sorted_value(const unsigned char* cur_str, const unsigned char* str_end, GS_UINT32* next_word, const GS_UNICASE_INFO *uni_plane); -bool is_b_format_collation(Oid collation); -static int strnncoll_binary(const unsigned char* arg1, size_t len1, - const unsigned char* arg2, size_t len2); - -/* binary collation only support binary string types, such as : blob. */ -void check_binary_collation(Oid collation, Oid type_oid) -{ - if (collation == BINARY_COLLATION_OID && !DB_IS_CMPT(B_FORMAT)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Un-support feature"), - errdetail("this collation only support in B-format database"))); - } - - if (IsBinaryType(type_oid) && collation != BINARY_COLLATION_OID) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("binary collation only support binary type in B format"))); - } -} - -bool is_support_b_format_collation(Oid collation) -{ - if (is_b_format_collation(collation) && !DB_IS_CMPT(B_FORMAT)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Un-support feature"), - errdetail("this collation only support in B-format database"))); - } - return true; -} - -bool is_b_format_collation(Oid collation) -{ - if (COLLATION_IN_B_FORMAT(collation)) { -#ifdef ENABLE_MULTIPLE_NODES - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Un-support feature"), - errdetail("this collation is not currently supported "))); -#endif - return true; - } - return false; -} /* * In unicase_sort_pages array, Search for the sorting value based by the unicode value. @@ -550,59 +502,8 @@ static inline void sort_by_unicode(GS_UINT32 **test_sort, GS_UINT32 *wchar) } } -int varstr_cmp_by_builtin_collations(char* arg1, int len1, char* arg2, int len2, Oid collid) -{ - int result = 0; - switch (collid) { - case UTF8MB4_GENERAL_CI_COLLATION_OID: - case UTF8MB4_UNICODE_CI_COLLATION_OID: - case UTF8_GENERAL_CI_COLLATION_OID: - case UTF8_UNICODE_CI_COLLATION_OID: - result = strnncoll_utf8mb4_general_pad_space((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); - break; - case UTF8MB4_BIN_COLLATION_OID: - case UTF8_BIN_COLLATION_OID: - result = strnncoll_utf8mb4_bin_pad_space((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); - break; - case BINARY_COLLATION_OID: - result = strnncoll_binary((unsigned char*)arg1, len1, (unsigned char*)arg2, len2); - break; - default: - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Un-support feature"), - errdetail("this collation is not currently supported "))); - break; - } - - return result; -} - -Datum hash_text_by_builtin_colltions(const unsigned char *key, size_t len, Oid collid) -{ - Datum result = 0; - switch (collid) { - case UTF8MB4_GENERAL_CI_COLLATION_OID: - case UTF8MB4_UNICODE_CI_COLLATION_OID: - case UTF8_GENERAL_CI_COLLATION_OID: - case UTF8_UNICODE_CI_COLLATION_OID: - result = hash_utf8mb4_general_pad_space((unsigned char*)key, len); - break; - case UTF8MB4_BIN_COLLATION_OID: - case UTF8_BIN_COLLATION_OID: - result = hash_any((unsigned char*)key, bpchartruelen((char*)key, len)); - break; - default: - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Un-support feature"), - errdetail("this collation is not currently supported "))); - break; - } - - return result; -} - -static int strnncoll_binary(const unsigned char* arg1, size_t len1, - const unsigned char* arg2, size_t len2) +int strnncoll_binary(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2) { size_t len = len1 < len2 ? len1 : len2; int res = memcmp(arg1, arg2, len); @@ -629,11 +530,12 @@ static inline int bincmp_utf8mb4(const unsigned char *arg1, const unsigned char * return < 0 , arg1 < arg2 * return > 0 , arg1 > arg2 */ -static int strnncoll_utf8mb4_general_pad_space(const unsigned char* arg1, size_t len1, - const unsigned char* arg2, size_t len2) +int strnncoll_utf8mb4_general_pad_space(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2) { GS_UINT32 arg1_word = 0; GS_UINT32 arg2_word = 0; + int res = 0; const unsigned char* arg1_end = arg1 + len1; const unsigned char* arg2_end = arg2 + len2; @@ -654,24 +556,11 @@ static int strnncoll_utf8mb4_general_pad_space(const unsigned char* arg1, size_t NEXT_WORD_POS(arg2, arg2_bytes); } - int res = 0; - len1 = (size_t)(arg1_end - arg1); - len2 = (size_t)(arg2_end - arg2); - - if (len1 != len2) { - int swap = 1; - - if (len1 < len2) { - len1 = len2; - arg1 = arg2; - arg1_end = arg2_end; - swap = -1; - } - for (; arg1 < arg1_end; arg1++) { - if (*arg1 != ' ') { - return (*arg1 < ' ') ? -swap : swap; - } - } + int len1_space = arg1_end - arg1; + int len2_space = arg2_end - arg2; + if (len1_space != len2_space) { + res = len1_space > len2_space ? compare_tail_space(arg1, len1_space, 1) : + compare_tail_space(arg2, len2_space, -1); } return res; @@ -733,39 +622,6 @@ static int mb_wc_utf8mb4(const unsigned char* s, const unsigned char* end, GS_UI return bytes; } -/* -* string compare function for collation utf8mb4_bin. -*/ -static int strnncoll_utf8mb4_bin_pad_space(const unsigned char* arg1, size_t len1, - const unsigned char* arg2, size_t len2) -{ - size_t len = len1 < len2 ? len1 : len2; - const unsigned char* arg1_end = arg1 + len; - int res = 0; - - while (arg1 < arg1_end) { - if (*arg1++ != *arg2++) { - return ((int)arg1[-1] - (int)arg2[-1]); - } - } - - if (len1 != len2) { - int swap = 1; - if (len1 < len2) { - len1 = len2; - arg1 = arg2; - swap = -1; - res = -res; - } - for (arg1_end = arg1 + len1 - len; arg1 < arg1_end; arg1++) { - if (*arg1 != ' ') { - return (*arg1 < ' ') ? -swap : swap; - } - } - } - return res; -} - /* * while collation is utf8mb4_general_ci / utf8mb4_unicode_ci, * use distinct and group by with string type need to diff --git a/src/common/backend/catalog/heap.cpp b/src/common/backend/catalog/heap.cpp index 150e121d2..8986e059f 100644 --- a/src/common/backend/catalog/heap.cpp +++ b/src/common/backend/catalog/heap.cpp @@ -4073,7 +4073,7 @@ static Node* CookAutoIncDefault(ParseState* pstate, Relation rel, RawColumnDefau (void)find_coercion_pathway(INT16OID, atp->atttypid, COERCION_ASSIGNMENT, &autoinc->autoincin_funcid); (void)find_coercion_pathway(atp->atttypid, INT16OID, COERCION_ASSIGNMENT, &autoinc->autoincout_funcid); autoinc->expr = cookDefault(pstate, ((AutoIncrement*)colDef->raw_default)->expr, atp->atttypid, - atp->atttypmod, NameStr(atp->attname), colDef->generatedCol); + atp->atttypmod, atp->attcollation, NameStr(atp->attname), colDef->generatedCol); /* If relation is temp table, cooked default must be a constant of the auto increment start value. */ if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) { @@ -4172,8 +4172,8 @@ List* AddRelationNewConstraints( autoinc_attnum = colDef->attnum; expr = CookAutoIncDefault(pstate, rel, colDef, atp); } else { - expr = cookDefault(pstate, colDef->raw_default, atp->atttypid, atp->atttypmod, NameStr(atp->attname), - colDef->generatedCol); + expr = cookDefault(pstate, colDef->raw_default, atp->atttypid, atp->atttypmod, + atp->attcollation, NameStr(atp->attname), colDef->generatedCol); if (colDef->generatedCol == ATTRIBUTE_GENERATED_STORED) { pull_varattnos(expr, 1, &generated_by_attrs); } @@ -4181,8 +4181,8 @@ List* AddRelationNewConstraints( } if (colDef->update_expr != NULL) { - update_expr = cookDefault(pstate, colDef->update_expr, atp->atttypid, atp->atttypmod, NameStr(atp->attname), - colDef->generatedCol); + update_expr = cookDefault(pstate, colDef->update_expr, atp->atttypid, atp->atttypmod, + atp->attcollation, NameStr(atp->attname), colDef->generatedCol); } /* @@ -4585,8 +4585,8 @@ Node* parseParamRef(ParseState* pstate, ParamRef* pref) * type (and typmod atttypmod). attname is only needed in this case: * it is used in the error message, if any. */ -Node *cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, char *attname, - char generatedCol) +Node *cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, Oid attcollation, + char *attname, char generatedCol) { Node* expr = NULL; @@ -4658,21 +4658,28 @@ Node *cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 att */ if (OidIsValid(atttypid)) { Oid type_id = exprType(expr); - - expr = coerce_to_target_type(pstate, expr, type_id, atttypid, atttypmod, COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST, -1); - if (expr == NULL) - ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("column \"%s\" is of type %s but %s expression is of type %s", attname, format_type_be(atttypid), - generatedCol ? "generated column" : "default", format_type_be(type_id)), - errhint("You will need to rewrite or cast the expression."))); + if (type_is_set(atttypid)) { + expr = coerce_to_settype( + pstate, expr, type_id, atttypid, atttypmod, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1, attcollation); + } else { + expr = coerce_to_target_type(pstate, expr, type_id, atttypid, atttypmod, COERCION_ASSIGNMENT, + COERCE_IMPLICIT_CAST, -1); + if (expr == NULL) + ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("column \"%s\" is of type %s but %s expression is of type %s", attname, format_type_be(atttypid), + generatedCol ? "generated column" : "default", format_type_be(type_id)), + errhint("You will need to rewrite or cast the expression."))); + } } /* * Finally, take care of collations in the finished expression. */ assign_expr_collations(pstate, expr); - + if (DB_IS_CMPT(B_FORMAT) && OidIsValid(attcollation)) { + int attcharset = get_valid_charset_by_collation(attcollation); + expr = coerce_to_target_charset(expr, attcharset, atttypid, atttypmod, attcollation); + } return expr; } diff --git a/src/common/backend/catalog/namespace.cpp b/src/common/backend/catalog/namespace.cpp index 3310ebca6..74e1c11d4 100644 --- a/src/common/backend/catalog/namespace.cpp +++ b/src/common/backend/catalog/namespace.cpp @@ -80,7 +80,7 @@ #include "c.h" #include "pgstat.h" #include "catalog/pg_proc_fn.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" #ifdef ENABLE_MULTIPLE_NODES #include "streaming/planner.h" @@ -4078,18 +4078,30 @@ Oid get_collation_oid_with_lower_name(const char* collation_name, int charset) char* lower_coll_name = pstrdup(collation_name); lower_coll_name = pg_strtolower(lower_coll_name); if (charset == PG_INVALID_ENCODING) { + /* while charset is invalid, search collation by name only and don't care it's charset */ CatCList* list = NULL; HeapTuple coll_tup; - list = SearchSysCacheList1(COLLNAMEENCNSP, PointerGetDatum(lower_coll_name)); + + /* use origin collation name, search for all collate */ + list = SearchSysCacheList1(COLLNAMEENCNSP, PointerGetDatum(collation_name)); if (list->n_members == 1) { coll_tup = t_thrd.lsc_cxt.FetchTupleFromCatCList(list, 0); colloid = HeapTupleGetOid(coll_tup); + } else if (list->n_members == 0) { + ReleaseSysCacheList(list); + /* use lower collation name, search for b format colaltion again */ + list = SearchSysCacheList1(COLLNAMEENCNSP, PointerGetDatum(lower_coll_name)); + if (list->n_members == 1) { + coll_tup = t_thrd.lsc_cxt.FetchTupleFromCatCList(list, 0); + colloid = HeapTupleGetOid(coll_tup); + } } ReleaseSysCacheList(list); } else { colloid = GetSysCacheOid3(COLLNAMEENCNSP, PointerGetDatum(lower_coll_name), Int32GetDatum(charset), ObjectIdGetDatum(PG_CATALOG_NAMESPACE)); } + pfree_ext(lower_coll_name); return colloid; } diff --git a/src/common/backend/catalog/pg_collation.cpp b/src/common/backend/catalog/pg_collation.cpp index 7cd73ce47..7f32d43b7 100644 --- a/src/common/backend/catalog/pg_collation.cpp +++ b/src/common/backend/catalog/pg_collation.cpp @@ -31,6 +31,7 @@ #include "utils/rel_gs.h" #include "utils/syscache.h" #include "utils/snapmgr.h" +#include "lib/string.h" /* * CollationCreate @@ -165,3 +166,68 @@ void RemoveCollationById(Oid collationOid) heap_close(rel, RowExclusiveLock); } + +int get_charset_by_collation(Oid coll_oid) +{ + HeapTuple tp = NULL; + int result = PG_INVALID_ENCODING; + + /* The collation OID in B format has a rule, through which we can quickly get the charset from the OID. */ + if (COLLATION_IN_B_FORMAT(coll_oid)) { + return FAST_GET_CHARSET_BY_COLL(coll_oid); + } + + if (COLLATION_HAS_INVALID_ENCODING(coll_oid)) { + return result; + } + + tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid)); + if (!HeapTupleIsValid(tp)) { + return result; + } + Form_pg_collation coll_tup = (Form_pg_collation)GETSTRUCT(tp); + result = coll_tup->collencoding; + ReleaseSysCache(tp); + return result; +} + +int get_valid_charset_by_collation(Oid coll_oid) +{ + if (!DB_IS_CMPT(B_FORMAT)) { + return GetDatabaseEncoding(); + } + int charset = get_charset_by_collation(coll_oid); + if (charset == PG_INVALID_ENCODING) { + return GetDatabaseEncoding(); + } + return charset; +} + +Oid get_default_collation_by_charset(int charset, bool report_error) +{ + Oid coll_oid = InvalidOid; + Relation rel; + ScanKeyData key[2]; + SysScanDesc scan = NULL; + HeapTuple tup = NULL; + + rel = heap_open(CollationRelationId, AccessShareLock); + ScanKeyInit(&key[0], Anum_pg_collation_collencoding, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(charset)); + ScanKeyInit(&key[1], Anum_pg_collation_collisdef, BTEqualStrategyNumber, F_BOOLEQ, BoolGetDatum(true)); + + scan = systable_beginscan(rel, CollationEncDefIndexId, true, NULL, 2, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) { + coll_oid = HeapTupleGetOid(tup); + break; + } + systable_endscan(scan); + heap_close(rel, AccessShareLock); + + if (coll_oid == InvalidOid && report_error) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("default collation for encoding \"%s\" does not exist", + pg_encoding_to_char(charset)))); + } + return coll_oid; +} \ No newline at end of file diff --git a/src/common/backend/catalog/pg_set.cpp b/src/common/backend/catalog/pg_set.cpp index 11162e226..4d4e9fa09 100644 --- a/src/common/backend/catalog/pg_set.cpp +++ b/src/common/backend/catalog/pg_set.cpp @@ -36,6 +36,7 @@ #include "utils/fmgroids.h" #include "utils/syscache.h" #include "utils/snapmgr.h" +#include "catalog/gs_collation.h" static void checkSetLableValue(char *label) { @@ -49,7 +50,6 @@ static void checkSetLableValue(char *label) /* character length can not over 255 */ text *text_label = cstring_to_text(label); - if (text_length(PointerGetDatum(text_label)) > SETNAMELEN) { ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), @@ -58,13 +58,34 @@ static void checkSetLableValue(char *label) } } +void check_duplicate_value_by_collation(List* vals, Oid collation) +{ + if (!is_b_format_collation(collation)) { + return ; + } + + ListCell* lc = NULL; + foreach (lc, vals) { + ListCell* next_cell = lc->next; + char* lab = strVal(lfirst(lc)); + while(next_cell != NULL) { + char* next_lab = strVal(lfirst(next_cell)); + if (varstr_cmp_by_builtin_collations(lab, strlen(lab), next_lab, strlen(next_lab), collation) == 0) { + ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("set has duplicate key value \"%s\" = \"%s\"", lab, next_lab))); + } + next_cell = lnext(next_cell); + } + } +} + /* * SetValuesCreate * Create an entry in pg_set for each of the supplied set values. * * vals is a list of Value strings. */ -void SetValuesCreate(Oid setTypeOid, List* vals) +void SetValuesCreate(Oid setTypeOid, List* vals, Oid collation) { Relation pg_set = NULL; text *setlabel = NULL; @@ -90,6 +111,8 @@ void SetValuesCreate(Oid setTypeOid, List* vals) * probably not worth trying harder. */ + check_duplicate_value_by_collation(vals, collation); + pg_set = heap_open(SetRelationId, RowExclusiveLock); /* diff --git a/src/common/backend/libpq/pqformat.cpp b/src/common/backend/libpq/pqformat.cpp index 1d74e6dc1..64ad3678e 100644 --- a/src/common/backend/libpq/pqformat.cpp +++ b/src/common/backend/libpq/pqformat.cpp @@ -152,12 +152,12 @@ void pq_sendcountedtext(StringInfo buf, const char* str, int slen, bool countinc } } -void pq_sendcountedtext_printtup(StringInfo buf, const char* str, int slen) +void pq_sendcountedtext_printtup(StringInfo buf, const char* str, int slen, int src_encoding, void* convert_finfo) { char* p = (char*)str; - if (unlikely(u_sess->mb_cxt.DatabaseEncoding->encoding != u_sess->mb_cxt.ClientEncoding->encoding)) { - p = pg_server_to_client(str, slen); + if (unlikely(src_encoding != u_sess->mb_cxt.ClientEncoding->encoding)) { + p = pg_any_to_client(str, slen, src_encoding, convert_finfo); } if (unlikely(p != str)) { /* actual conversion has been done? */ slen = strlen(p); diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index 52e96b03c..199a10d7d 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -7425,6 +7425,16 @@ static CharsetCollateOptions *_copyCharsetcollateOptions(const CharsetCollateOpt return newnode; } +static CharsetClause *_copyCharsetClause(const CharsetClause* from) +{ + CharsetClause* newnode = makeNode(CharsetClause); + COPY_NODE_FIELD(arg); + COPY_SCALAR_FIELD(charset); + COPY_SCALAR_FIELD(is_binary); + COPY_LOCATION_FIELD(location); + return newnode; +} + static PrefixKey* _copyPrefixKey(const PrefixKey* from) { PrefixKey* newnode = makeNode(PrefixKey); @@ -8826,6 +8836,9 @@ void* copyObject(const void* from) case T_DolphinCallStmt: retval = _copyDolphinCallStmt((DolphinCallStmt *)from); break; + case T_CharsetClause: + retval = _copyCharsetClause((CharsetClause *)from); + break; default: ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("copyObject: unrecognized node type: %d", (int)nodeTag(from)))); diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index d78b8b385..e4af3675e 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -3477,6 +3477,14 @@ static bool _equalCharsetcollateOptions(const CharsetCollateOptions* a, const Ch return true; } +static bool _equalCharsetClause(const CharsetClause* a, const CharsetClause* b) +{ + COMPARE_NODE_FIELD(arg); + COMPARE_SCALAR_FIELD(charset); + COMPARE_SCALAR_FIELD(is_binary); + COMPARE_LOCATION_FIELD(location); +} + static bool _equalPrefixKey(const PrefixKey* a, const PrefixKey* b) { COMPARE_NODE_FIELD(arg); @@ -4443,6 +4451,9 @@ bool equal(const void* a, const void* b) retval = _equalCharsetcollateOptions((const CharsetCollateOptions *)a, (const CharsetCollateOptions *)b); break; + case T_CharsetClause: + retval = _equalCharsetClause((const CharsetClause*) a, (const CharsetClause*) b); + break; case T_PrefixKey: retval = _equalPrefixKey((PrefixKey *)a, (PrefixKey *)b); break; diff --git a/src/common/backend/nodes/outfuncs.cpp b/src/common/backend/nodes/outfuncs.cpp index 6dd70d313..33b65e94f 100755 --- a/src/common/backend/nodes/outfuncs.cpp +++ b/src/common/backend/nodes/outfuncs.cpp @@ -6036,6 +6036,15 @@ static void _outCharsetcollateOptions(StringInfo str, CharsetCollateOptions* nod WRITE_STRING_FIELD(collate); } +static void _outCharsetClause(StringInfo str, CharsetClause* node) +{ + WRITE_NODE_TYPE("CHARSET"); + WRITE_NODE_FIELD(arg); + WRITE_INT_FIELD(charset); + WRITE_BOOL_FIELD(is_binary); + WRITE_LOCATION_FIELD(location); +} + static void _outPrefixKey(StringInfo str, PrefixKey* node) { WRITE_NODE_TYPE("PREFIXKEY"); @@ -6950,6 +6959,9 @@ static void _outNode(StringInfo str, const void* obj) case T_CharsetCollateOptions: _outCharsetcollateOptions(str, (CharsetCollateOptions*)obj); break; + case T_CharsetClause: + _outCharsetClause(str, (CharsetClause*)obj); + break; case T_AutoIncrement: _outAutoIncrement(str, (AutoIncrement*)obj); break; diff --git a/src/common/backend/nodes/readfuncs.cpp b/src/common/backend/nodes/readfuncs.cpp index 097803597..5831a385e 100755 --- a/src/common/backend/nodes/readfuncs.cpp +++ b/src/common/backend/nodes/readfuncs.cpp @@ -6138,6 +6138,18 @@ static CharsetCollateOptions* _readCharsetcollateOptions() READ_DONE(); } +static CharsetClause* _readCharsetClause() +{ + READ_LOCALS(CharsetClause); + + READ_NODE_FIELD(arg); + READ_INT_FIELD(charset); + READ_BOOL_FIELD(is_binary); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + static PrefixKey* _readPrefixKey() { READ_LOCALS(PrefixKey); @@ -6645,6 +6657,8 @@ Node* parseNodeString(void) return_value = _readUserVar(); } else if (MATCH("CHARSETCOLLATE", 14)) { return_value = _readCharsetcollateOptions(); + } else if (MATCH("CHARSET", 7)) { + return_value = _readCharsetClause(); } else { ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index e97145377..1a9b8f89e 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -2713,6 +2713,7 @@ static void transformVariableSetStmt(ParseState* pstate, VariableSetStmt* stmt) newUserElem->name = userElem->name; Node *node = transformExprRecurse(pstate, (Node *)userElem->val); + assign_expr_collations(pstate, node); if (IsA(node, UserSetElem)) { newUserElem->name = list_concat(newUserElem->name, ((UserSetElem *)node)->name); @@ -3403,6 +3404,58 @@ static Query* transformSetOperationStmt(ParseState* pstate, SelectStmt* stmt) return qry; } +/* Find real target entry and convert its character set in UNION tree. */ +static void convert_set_operation_tree_charset(ParseState* pstate, Node* op_tree, + int arg_id, Oid target_collation, int target_charset) +{ + if (IsA(op_tree, SetOperationStmt)) { + SetOperationStmt* opstmt = (SetOperationStmt*)op_tree; + convert_set_operation_tree_charset(pstate, opstmt->larg, arg_id, target_collation, target_charset); + convert_set_operation_tree_charset(pstate, opstmt->rarg, arg_id, target_collation, target_charset); + return; + } + + Assert(IsA(op_tree, RangeTblRef)); + RangeTblRef* rtr = (RangeTblRef*)op_tree; + RangeTblEntry* rte = rt_fetch(rtr->rtindex, pstate->p_rtable); + TargetEntry* te = NULL; + int n = 0; + + foreach_cell(tmp_cell, rte->subquery->targetList) { + te = (TargetEntry*)lfirst(tmp_cell); + if (te->resjunk) { + continue; + } + if (++n > arg_id) { + break; + } + } + + te->expr = (Expr*)coerce_to_target_charset( + (Node*)te->expr, target_charset, exprType((Node*)te->expr), exprTypmod((Node*)te->expr), target_collation); +} + +/* Converts the character set of the query column on a side of the UNION. */ +static void convert_set_operation_charset(ParseState* pstate, Node* op_tree, TargetEntry* arg, + int arg_id, Oid target_collation, int target_charset) +{ + Node* arg_expr = (Node*)arg->expr; + Oid expr_type = exprType(arg_expr); + Oid expr_collation = exprCollation(arg_expr); + if (expr_collation == BINARY_COLLATION_OID || expr_collation == target_collation) { + return; + } + + if (!IsA(arg->expr, SetToDefault)) { + arg->expr = (Expr*)coerce_to_target_charset( + arg_expr, target_charset, expr_type, exprTypmod(arg_expr), target_collation); + return; + } + + Assert(IsA(op_tree, SetOperationStmt)); + convert_set_operation_tree_charset(pstate, op_tree, arg_id, target_collation, target_charset); +} + /* * transformSetOperationTree * Recursively transform leaves and internal nodes of a set-op tree @@ -3533,6 +3586,7 @@ static Node* transformSetOperationTree(ParseState* pstate, SelectStmt* stmt, boo ListCell* ltl = NULL; ListCell* rtl = NULL; const char* context = NULL; + int col_id = 0; context = (stmt->op == SETOP_UNION ? "UNION" : (stmt->op == SETOP_INTERSECT ? "INTERSECT" : "EXCEPT")); @@ -3664,7 +3718,13 @@ static Node* transformSetOperationTree(ParseState* pstate, SelectStmt* stmt, boo */ rescolcoll = select_common_collation(pstate, list_make2(lcolnode, rcolnode), (op->op == SETOP_UNION && op->all)); - + if (ENABLE_MULTI_CHARSET && rescolcoll != BINARY_COLLATION_OID) { + int res_charset = get_valid_charset_by_collation(rescolcoll); + convert_set_operation_charset(pstate, op->larg, ltle, col_id, rescolcoll, res_charset); + convert_set_operation_charset(pstate, op->rarg, rtle, col_id, rescolcoll, res_charset); + } + col_id++; + /* emit results */ op->colTypes = lappend_oid(op->colTypes, rescoltype); op->colTypmods = lappend_int(op->colTypmods, rescoltypmod); diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 150b63fcc..a105fb82a 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -841,7 +841,7 @@ static void setDelimiterName(core_yyscan_t yyscanner, char*input, VariableSetStm * DOT_DOT is unused in the core SQL grammar, and so will always provoke * parse errors. It is needed by PL/pgsql. */ -%token IDENT FCONST SCONST BCONST VCONST XCONST Op CmpOp CmpNullOp COMMENTSTRING SET_USER_IDENT SET_IDENT +%token IDENT FCONST SCONST BCONST VCONST XCONST Op CmpOp CmpNullOp COMMENTSTRING SET_USER_IDENT SET_IDENT UNDERSCORE_CHARSET %token ICONST PARAM %token TYPECAST ORA_JOINOP DOT_DOT COLON_EQUALS PARA_EQUALS SET_IDENT_SESSION SET_IDENT_GLOBAL @@ -2464,15 +2464,31 @@ set_rest_more: /* Generic SET syntaxes: */ n->args = list_make1(makeStringConst($2, @2)); $$ = n; } - | NAMES opt_encoding + | NAMES opt_encoding opt_collate { VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_SET_VALUE; - n->name = "client_encoding"; - if ($2 != NULL) - n->args = list_make1(makeStringConst($2, @2)); - else - n->kind = VAR_SET_DEFAULT; + if ($3 != NULL) { + if ($2 == NULL) { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("cannot specify collation without character set"), + parser_errposition(@3))); + } + n->args = list_make2(makeStringConst($2, @2), makeStringConst($3, @3)); + n->name = "set_names"; + } else { + if ($2 != NULL) { + n->args = list_make1(makeStringConst($2, @2)); + } else { + n->kind = VAR_SET_DEFAULT; + } + if (ENABLE_MULTI_CHARSET) { + n->name = "set_names"; + } else { + n->name = "client_encoding"; + } + } $$ = n; } | ROLE ColId_or_Sconst @@ -3082,6 +3098,8 @@ zone_value: opt_encoding: Sconst { $$ = $1; } + | IDENT { $$ = $1; } + | BINARY { $$ = (char*)$1; } | DEFAULT { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; } ; @@ -25277,7 +25295,7 @@ character_set: charset_collate_name: ColId { $$ = $1; } - | BINARY { $$ = pstrdup($1); } + | BINARY { $$ = "binary"; } | Sconst { $$ = $1; } ; @@ -28559,6 +28577,51 @@ AexprConst: Iconst */ $$ = makeBitStringConst($1, @1); } + | UNDERSCORE_CHARSET Sconst + { + const char* encoding_name = $1; + char *original_str = pg_server_to_client($2, strlen($2)); + int encoding = pg_valid_server_encoding(encoding_name); + Assert(encoding >= 0); + + A_Const *con = makeNode(A_Const); + con->val.type = T_String; + con->val.val.str = original_str; + con->location = @2; + + CharsetClause *n = makeNode(CharsetClause); + n->arg = (Node *)con; + n->charset = encoding; + n->is_binary = (strcmp(encoding_name, "binary") == 0); + n->location = @1; + $$ = (Node *) n; + } + | UNDERSCORE_CHARSET BCONST + { + const char* encoding_name = $1; + int encoding = pg_valid_server_encoding(encoding_name); + Assert(encoding >= 0); + + CharsetClause *n = makeNode(CharsetClause); + n->arg = makeBitStringConst($2, @2); + n->charset = encoding; + n->is_binary = (strcmp(encoding_name, "binary") == 0); + n->location = @1; + $$ = (Node *) n; + } + | UNDERSCORE_CHARSET XCONST + { + const char* encoding_name = $1; + int encoding = pg_valid_server_encoding(encoding_name); + Assert(encoding >= 0); + + CharsetClause *n = makeNode(CharsetClause); + n->arg = makeBitStringConst($2, @2); + n->charset = encoding; + n->is_binary = (strcmp(encoding_name, "binary") == 0); + n->location = @1; + $$ = (Node *) n; + } | func_name Sconst { /* generic type 'literal' syntax */ @@ -29670,8 +29733,12 @@ makeStringConst(char *str, int location) else { n->val.type = T_String; - n->val.val.str = str; n->location = location; + if (NULL == str) { + n->val.val.str = str; + } else { + n->val.val.str = pg_server_to_any(str, strlen(str), GetCharsetConnection()); + } } return (Node *)n; diff --git a/src/common/backend/parser/parse_coerce.cpp b/src/common/backend/parser/parse_coerce.cpp index afd29dba4..af255e1db 100644 --- a/src/common/backend/parser/parse_coerce.cpp +++ b/src/common/backend/parser/parse_coerce.cpp @@ -237,14 +237,16 @@ Node* coerce_to_target_type(ParseState* pstate, Node* expr, Oid exprtype, Oid ta * pstate - parse state (can be NULL, see semtc_coerce_type) * expr - input expression tree (already transformed by semtc_expr) * target_charset - desired result character set - * targetTypeId - desired result type + * target_type - desired result type */ -Node* coerce_to_target_charset(Node* expr, int target_charset, Oid targetTypeId) +Node* coerce_to_target_charset(Node* expr, int target_charset, Oid target_type, int32 target_typmod, Oid target_collation) { FuncExpr* fexpr = NULL; + Node* result = NULL; List* args = NIL; Const* cons = NULL; - int exprcharset = PG_INVALID_ENCODING; + int exprcharset; + Oid exprtype; if (target_charset == PG_INVALID_ENCODING) { return expr; @@ -258,20 +260,41 @@ Node* coerce_to_target_charset(Node* expr, int target_charset, Oid targetTypeId) return expr; } + check_type_supports_multi_charset(target_type, false); + exprtype = exprType(expr); + /* datatype have no collation and charset */ + if (exprtype != UNKNOWNOID && !OidIsValid(get_typcollation(exprtype))) { + return expr; + } + /* coerce expression to bytea or text first */ + args = list_make1(coerce_type( + NULL, expr, exprtype, TEXTOID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, exprLocation(expr))); + + /* construct a convert FuncExpr */ const char* expr_charset_name = pg_encoding_to_char(exprcharset); const char* target_charset_name = pg_encoding_to_char(target_charset); - - args = list_make1(expr); - cons = makeConst(NAMEOID, -1, InvalidOid, sizeof(const char*), NameGetDatum(expr_charset_name), false, true); args = lappend(args, cons); - cons = makeConst(NAMEOID, -1, InvalidOid, sizeof(const char*), - NameGetDatum(target_charset_name), false, true); + cons = makeConst(NAMEOID, -1, InvalidOid, sizeof(const char*), NameGetDatum(target_charset_name), false, true); args = lappend(args, cons); - fexpr = makeFuncExpr(CONVERTFUNCOID, targetTypeId, args, InvalidOid, InvalidOid, COERCE_IMPLICIT_CAST); - return (Node*)fexpr; + fexpr = makeFuncExpr(CONVERTFUNCOID, TEXTOID, args, target_collation, InvalidOid, COERCE_IMPLICIT_CAST); + + /* coerce convert expression to original datatype */ + if (target_type == UNKNOWNOID) { + result = (Node*)fexpr; + } else { + result = coerce_type(NULL, (Node*)fexpr, TEXTOID, target_type, target_typmod, + COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, exprLocation(expr)); + } + + /* set collation after coerce_to_target_type */ + exprSetCollation(result, target_collation); + if (IsA(expr, Const) || IsA(expr, RelabelType)) { + result = eval_const_expression_value(NULL, result, NULL); + } + return result; } /* @@ -312,8 +335,15 @@ Node *type_transfer(Node *node, Oid atttypid, bool isSelect) VARBITOID, -1, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1); break; default: - result = isSelect ? node : - coerce_type(NULL, node, con->consttype, TEXTOID, -1, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1); + if (isSelect) { + result = node; + } else { + Oid collid = exprCollation(node); + result = coerce_type(NULL, node, con->consttype, TEXTOID, -1, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1); + if (OidIsValid(collid)) { + exprSetCollation(result, collid); + } + } break; } @@ -339,6 +369,22 @@ Node *const_expression_to_const(Node *node) return eval_const_expression_value(NULL, result, NULL); } +static Datum stringTypeDatum_with_collation(Type tp, char* string, int32 atttypmod, bool can_ignore, Oid collation) +{ + Datum result; + int tmp_encoding = get_valid_charset_by_collation(collation); + int db_encoding = GetDatabaseEncoding(); + + if (tmp_encoding == db_encoding) { + return stringTypeDatum(tp, string, atttypmod, can_ignore); + } + + DB_ENCODING_SWITCH_TO(tmp_encoding); + result = stringTypeDatum(tp, string, atttypmod, can_ignore); + DB_ENCODING_SWITCH_BACK(db_encoding); + return result; +} + /* * coerce_type() * Convert an expression to a different type. @@ -471,7 +517,12 @@ Node* coerce_type(ParseState* pstate, Node* node, Oid inputTypeId, Oid targetTyp newcon->consttype = baseTypeId; newcon->consttypmod = inputTypeMod; - newcon->constcollid = typeTypeCollation(targetType); + if (OidIsValid(GetCollationConnection()) && + IsSupportCharsetType(baseTypeId)) { + newcon->constcollid = GetCollationConnection(); + } else { + newcon->constcollid = typeTypeCollation(targetType); + } newcon->constlen = typeLen(targetType); newcon->constbyval = typeByVal(targetType); newcon->constisnull = con->constisnull; @@ -491,12 +542,12 @@ Node* coerce_type(ParseState* pstate, Node* node, Oid inputTypeId, Oid targetTyp setup_parser_errposition_callback(&pcbstate, pstate, con->location); /* - * We assume here that UNKNOWN's internal representation is the same - * as CSTRING. - */ + * We assume here that UNKNOWN's internal representation is the same + * as CSTRING. + */ if (!con->constisnull) { - newcon->constvalue = stringTypeDatum(targetType, DatumGetCString(con->constvalue), inputTypeMod, - pstate != NULL && pstate->p_has_ignore); + newcon->constvalue = stringTypeDatum_with_collation(targetType, DatumGetCString(con->constvalue), + inputTypeMod, pstate != NULL && pstate->p_has_ignore, con->constcollid); } else { newcon->constvalue = stringTypeDatum(targetType, NULL, inputTypeMod, pstate != NULL && pstate->p_has_ignore); @@ -894,12 +945,17 @@ static Node* coerce_type_typmod(Node* node, Oid targetTypeId, int32 targetTypMod pathtype = find_typmod_coercion_function(targetTypeId, &funcId); if (pathtype != COERCION_PATH_NONE) { + Oid node_collation = exprCollation(node); /* Suppress display of nested coercion steps */ if (hideInputCoercion) { hide_coercion_node(node); } node = build_coercion_expression( node, pathtype, funcId, targetTypeId, targetTypMod, cformat, location, isExplicit); + if (OidIsValid(node_collation)) { + exprSetInputCollation(node, node_collation); + exprSetCollation(node, node_collation); + } } return node; @@ -1253,6 +1309,120 @@ Node* coerce_to_specific_type(ParseState* pstate, Node* node, Oid targetTypeId, return node; } +Node* coerce_to_settype(ParseState* pstate, Node* expr, Oid exprtype, Oid targettype, int32 targettypmod, +CoercionContext ccontext, CoercionForm cformat, int location, Oid collation) +{ + if (!can_coerce_type(1, &exprtype, &targettype, ccontext)) { + return NULL; + } + + if (exprtype == targettype || expr == NULL) { + /* no conversion needed */ + return expr; + } + + Node* result = NULL; + CoercionPathType pathtype; + Oid funcId; + + if (exprtype == UNKNOWNOID && IsA(expr, Const)) { + Const* con = (Const*)expr; + Const* newcon = makeNode(Const); + + int32 baseTypeMod = targettypmod; + Oid baseTypeId = getBaseTypeAndTypmod(targettype, &baseTypeMod); + int32 inputTypeMod = -1; + Type target = typeidType(baseTypeId); + ParseCallbackState pcbstate; + + newcon->consttype = baseTypeId; + newcon->consttypmod = inputTypeMod; + newcon->constcollid = typeTypeCollation(target); + newcon->constlen = typeLen(target); + newcon->constbyval = typeByVal(target); + newcon->constisnull = con->constisnull; + newcon->cursor_data.cur_dno = -1; + newcon->location = con->location; + setup_parser_errposition_callback(&pcbstate, pstate, con->location); + + Form_pg_type typform = (Form_pg_type)GETSTRUCT(target); + Oid typinput = typform->typinput; + Oid typioparam = getTypeIOParam(target); + newcon->constvalue = OidInputFunctionCallColl(typinput, DatumGetCString(con->constvalue), typioparam, inputTypeMod, collation); + + cancel_parser_errposition_callback(&pcbstate); + result = (Node*)newcon; + ReleaseSysCache(target); + + result = coerce_type_typmod(result, + targettype, + targettypmod, + cformat, + location, + (cformat != COERCE_IMPLICIT_CAST), + (result != expr && !IsA(result, Const))); + + return result; + } + + pathtype = find_coercion_pathway(targettype, exprtype, ccontext, &funcId); + if (pathtype != COERCION_PATH_NONE) { + if (pathtype != COERCION_PATH_RELABELTYPE) { + Oid baseTypeId; + int32 baseTypeMod; + + baseTypeMod = targettypmod; + baseTypeId = getBaseTypeAndTypmod(targettype, &baseTypeMod); + + result = build_coercion_expression( + expr, pathtype, funcId, baseTypeId, baseTypeMod, cformat, location, (cformat != COERCE_IMPLICIT_CAST)); + + if (targettype != baseTypeId) + result = coerce_to_domain(result, + baseTypeId, + baseTypeMod, + targettype, + cformat, + location, + true, + exprIsLengthCoercion(result, NULL)); + } else { + result = coerce_to_domain(expr, InvalidOid, -1, targettype, cformat, location, false, false); + if (result == expr) { + RelabelType* r = makeRelabelType((Expr*)result, targettype, -1, InvalidOid, cformat); + + r->location = location; + result = (Node*)r; + } + } + + result = coerce_type_typmod(result, + targettype, + targettypmod, + cformat, + location, + (cformat != COERCE_IMPLICIT_CAST), + (result != expr && !IsA(result, Const))); + + return result; + } + + if (targettype == ANYSETOID && type_is_set(exprtype)) { + return expr; + } + + if (type_is_set(exprtype) && type_is_set(targettype)) { + return expr; + } + + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("failed to find conversion function from %s to %s", + format_type_be(exprtype), + format_type_be(targettype)))); + return NULL; +} + /* * parser_coercion_errposition - report coercion error location, if possible * diff --git a/src/common/backend/parser/parse_collate.cpp b/src/common/backend/parser/parse_collate.cpp index de9b673fe..624fcef3c 100644 --- a/src/common/backend/parser/parse_collate.cpp +++ b/src/common/backend/parser/parse_collate.cpp @@ -43,10 +43,15 @@ #include "catalog/pg_aggregate.h" #include "catalog/pg_collation.h" +#include "catalog/pg_proc.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "parser/parse_collate.h" +#include "parser/parse_utilcmd.h" +#include "parser/parse_coerce.h" +#include "parser/parse_type.h" #include "utils/lsyscache.h" +#include "lib/string.h" /* * Collation strength (the SQL standard calls this "derivation"). Order is @@ -60,6 +65,20 @@ typedef enum { COLLATE_EXPLICIT /* collation was derived explicitly */ } CollateStrength; +/* Derivation of collation for B compatibility. The smaller the value, the higher the priority */ +typedef enum { + DERIVATION_IMPLICIT, + DERIVATION_SYSCONST, + DERIVATION_COERCIBLE, + DERIVATION_IGNORABLE +} CollateDerivation; + +typedef enum { + UNKNONWN_CHARSET, + SINGLE_CHARSET, + MULTI_CHARSET +} CharsetStatus; + typedef struct { ParseState* pstate; /* parse state (for error reporting) */ Oid collation; /* OID of current collation, if any */ @@ -68,15 +87,29 @@ typedef struct { /* Remaining fields are only valid when strength == COLLATE_CONFLICT */ Oid collation2; /* OID of conflicting collation */ int location2; /* location of expr that set collation2 */ + CollateDerivation derivation; /* Collation priority for B compatibility, only used when strength is COLLATE_IMPLICIT. */ + CharsetStatus charset_status; /* for B compatibility */ } assign_collations_context; static bool assign_query_collations_walker(Node* node, ParseState* pstate); static bool assign_collations_walker(Node* node, assign_collations_context* context); -static void merge_collation_state(Oid collation, CollateStrength strength, int location, Oid collation2, int location2, - assign_collations_context* context); +static void merge_collation_state(Oid collation, CollateStrength strength, int location, CollateDerivation derivation, + Oid collation2, int location2, assign_collations_context* context); static void assign_aggregate_collations(Aggref* aggref, assign_collations_context* loccontext); static void assign_ordered_set_collations(Aggref* aggref, assign_collations_context* loccontext); +static void assign_expression_charset(Node* node, Oid target_collation); +static void merge_rowcompareexpr_arg_charsets(RowCompareExpr *rcexpr); +static void update_charset_status(assign_collations_context* context, Oid collation); +static void check_collate_expr_charset(ParseState *pstate, CollateExpr *cexpr, Oid arg_collation); +static void merge_same_charset_collation(Oid collation, CollateStrength strength, int location, + CollateDerivation derivation, assign_collations_context* context); +static void merge_diff_charset_collation(Oid collation, CollateStrength strength, int location, + CollateDerivation derivation, int charset, int context_charset, assign_collations_context* context); +static void deal_expr_collation_b_compatibility( + Node* node, Oid expr_type, assign_collations_context* context, int location); +#define TYPE_IS_COLLATABLE_B_FORMAT(type_oid) \ + (IsSupportCharsetType(type_oid) || (type_oid) == UNKNOWNOID || IsBinaryType(type_oid)) /* * @Description: set appropriate collation, strength and location * according to the type collation. @@ -87,16 +120,30 @@ static void assign_ordered_set_collations(Aggref* aggref, assign_collations_cont * @in collatable: represent if the input is collatable * @in context: collation state */ -FORCE_INLINE static void get_valid_collation(Oid& collation, CollateStrength& strength, int& location, Oid typcollation, - bool collatable, const Node* node, assign_collations_context context) +FORCE_INLINE static void get_valid_collation(Oid& collation, CollateStrength& strength, int& location, CollateDerivation &derivation, + Oid typcollation, bool collatable, const Node* node, assign_collations_context context) { if (OidIsValid(typcollation)) { /* typllation (comes from a node) is collatable; what about its input? */ if (collatable) { - /* Collation state bubbles up from children. */ - collation = context.collation; + if (context.collation == BINARY_COLLATION_OID && typcollation != context.collation) { + collation = OidIsValid(GetCollationConnection()) ? GetCollationConnection() : typcollation; + } else { + /* Collation state bubbles up from children. */ + collation = context.collation; + } strength = context.strength; location = context.location; + derivation = context.derivation; + } else if (ENABLE_MULTI_CHARSET && + context.strength == COLLATE_NONE && + (OidIsValid(GetCollationConnection()) || context.derivation == DERIVATION_SYSCONST)) { + /* collation of version() is UTF8_GENERAL_CI */ + collation = (context.derivation == DERIVATION_SYSCONST) ? + UTF8_GENERAL_CI_COLLATION_OID : GetCollationConnection(); + strength = COLLATE_IMPLICIT; + location = exprCollation(node); + derivation = (context.derivation == DERIVATION_IGNORABLE) ? DERIVATION_COERCIBLE : context.derivation; } else { /* * Collatable output produced without any collatable @@ -107,12 +154,14 @@ FORCE_INLINE static void get_valid_collation(Oid& collation, CollateStrength& st collation = typcollation; strength = COLLATE_IMPLICIT; location = exprCollation(node); + derivation = context.derivation; } } else { /* Node's result type isn't collatable. */ collation = InvalidOid; strength = COLLATE_NONE; location = -1; /* won't be used */ + derivation = context.derivation; } } @@ -203,6 +252,8 @@ void assign_expr_collations(ParseState* pstate, Node* expr) context.collation = InvalidOid; context.strength = COLLATE_NONE; context.location = -1; + context.derivation = DERIVATION_IGNORABLE; + context.charset_status = UNKNONWN_CHARSET; /* and away we go */ (void)assign_collations_walker(expr, &context); @@ -233,6 +284,8 @@ Oid select_common_collation(ParseState* pstate, List* exprs, bool none_ok) context.collation = InvalidOid; context.strength = COLLATE_NONE; context.location = -1; + context.derivation = DERIVATION_IGNORABLE; + context.charset_status = UNKNONWN_CHARSET; /* and away we go */ (void)assign_collations_walker((Node*)exprs, &context); @@ -244,7 +297,8 @@ Oid select_common_collation(ParseState* pstate, List* exprs, bool none_ok) } ereport(ERROR, (errcode(ERRCODE_COLLATION_MISMATCH), - errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"", + errmsg("collation mismatch between%scollations \"%s\" and \"%s\"", + (ENABLE_MULTI_CHARSET ? " " : " implicit "), get_collation_name(context.collation), get_collation_name(context.collation2)), errhint("You can choose the collation by applying the COLLATE clause to one or both expressions."), @@ -273,7 +327,9 @@ Oid select_common_collation(ParseState* pstate, List* exprs, bool none_ok) static bool assign_collations_walker(Node* node, assign_collations_context* context) { Oid collation = InvalidOid; + Oid type_oid = InvalidOid; CollateStrength strength = COLLATE_NONE; + CollateDerivation derivation = DERIVATION_IGNORABLE; int location = -1; /* Need do nothing for empty subexpressions */ @@ -292,6 +348,8 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont loccontext.location = -1; loccontext.collation2 = InvalidOid; loccontext.location2 = -1; + loccontext.derivation = DERIVATION_IGNORABLE; + loccontext.charset_status = UNKNONWN_CHARSET; /* * Recurse if appropriate, then determine the collation for this node. @@ -309,6 +367,9 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont CollateExpr* expr = (CollateExpr*)node; (void)expression_tree_walker(node, (bool (*)())assign_collations_walker, (void*)&loccontext); + if (ENABLE_MULTI_CHARSET) { + check_collate_expr_charset(loccontext.pstate, expr, loccontext.collation); + } collation = expr->collOid; AssertEreport(OidIsValid(collation), MOD_OPT, "The OID of collation is invalid."); @@ -334,12 +395,18 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont collation = expr->resultcollid; strength = COLLATE_IMPLICIT; location = exprLocation(node); + } else if (ENABLE_MULTI_CHARSET && IsBinaryType(expr->resulttype)) { + /* Node's result type isn't collatable. */ + collation = BINARY_COLLATION_OID; + strength = COLLATE_IMPLICIT; + location = exprLocation(node); } else { /* Node's result type isn't collatable. */ collation = InvalidOid; strength = COLLATE_NONE; location = -1; /* won't be used */ } + derivation = loccontext.derivation; } break; case T_RowExpr: { /* @@ -358,6 +425,10 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont */ return false; /* done */ } + case T_SelectIntoVarList: { + SubLink* sublink = ((SelectIntoVarList*)node)->sublink; + return assign_collations_walker((Node *)sublink, context); + } case T_RowCompareExpr: { /* * For RowCompare, we have to find the common collation of @@ -380,7 +451,7 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont colls = lappend_oid(colls, coll); } expr->inputcollids = colls; - + merge_rowcompareexpr_arg_charsets(expr); /* * Since the result is always boolean and therefore never has * a collation, we can just stop here: this node has no impact @@ -399,13 +470,16 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont */ CoerceToDomain* expr = (CoerceToDomain*)node; Oid typcollation = get_typcollation(expr->resulttype); - + if (ENABLE_MULTI_CHARSET && IsBinaryType(expr->resulttype)) { + typcollation = BINARY_COLLATION_OID; + } /* ... but first, recurse */ (void)expression_tree_walker(node, (bool (*)())assign_collations_walker, (void*)&loccontext); get_valid_collation(collation, strength, location, + derivation, typcollation, (typcollation == DEFAULT_COLLATION_OID) ? true : false, node, @@ -417,6 +491,7 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont */ Oid collation_oid = (strength == COLLATE_CONFLICT) ? InvalidOid : collation; exprSetCollation(node, collation_oid); + derivation = loccontext.derivation; } break; case T_TargetEntry: (void)expression_tree_walker(node, (bool (*)())assign_collations_walker, (void*)&loccontext); @@ -429,6 +504,7 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont collation = loccontext.collation; strength = loccontext.strength; location = loccontext.location; + derivation = loccontext.derivation; /* * Throw error if the collation is indeterminate for a TargetEntry @@ -446,7 +522,8 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont if (strength == COLLATE_CONFLICT && ((TargetEntry*)node)->ressortgroupref != 0) { ereport(ERROR, (errcode(ERRCODE_COLLATION_MISMATCH), - errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"", + errmsg("collation mismatch between%scollations \"%s\" and \"%s\"", + (ENABLE_MULTI_CHARSET ? " " : " implicit "), get_collation_name(loccontext.collation), get_collation_name(loccontext.collation2)), errhint( @@ -485,8 +562,13 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont AssertEreport(IsA(tent, TargetEntry), MOD_OPT, "not the target entry"); AssertEreport((!tent->resjunk), MOD_OPT, "the target entry is junk"); collation = exprCollation((Node*)tent->expr); + type_oid = exprType((Node*)tent->expr); + if (ENABLE_MULTI_CHARSET && IsBinaryType(type_oid)) { + collation = BINARY_COLLATION_OID; + } /* collation doesn't change if it's converted to array */ strength = COLLATE_IMPLICIT; + derivation = DERIVATION_COERCIBLE; location = exprLocation((Node*)tent->expr); } break; case T_List: @@ -499,6 +581,8 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont collation = loccontext.collation; strength = loccontext.strength; location = loccontext.location; + derivation = loccontext.derivation; + context->charset_status = Max(context->charset_status, loccontext.charset_status); break; case T_Var: @@ -508,8 +592,8 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont case T_CaseTestExpr: case T_SetToDefault: case T_CurrentOfExpr: - case T_PrefixKey: case T_UserVar: + case T_UserSetElem: case T_SetVariableExpr: /* @@ -533,6 +617,17 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont strength = COLLATE_NONE; } location = exprLocation(node); + /* B compatibility */ + if (ENABLE_MULTI_CHARSET && strength == COLLATE_NONE) { + type_oid = exprType(node); + collation = IsBinaryType(type_oid) ? BINARY_COLLATION_OID : collation; + strength = IsBinaryType(type_oid) ? COLLATE_IMPLICIT : strength; + } + if (IsA(node, Const)) { + derivation = ((Const*)node)->constisnull ? DERIVATION_IGNORABLE : DERIVATION_COERCIBLE; + } else { + derivation = DERIVATION_IMPLICIT; + } break; default: { @@ -601,15 +696,22 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont /* * Now figure out what collation to assign to this node. */ - typcollation = get_typcollation(exprType(node)); + type_oid = exprType(node); + if (ENABLE_MULTI_CHARSET) { + deal_expr_collation_b_compatibility(node, type_oid, &loccontext, location); + typcollation = IsBinaryType(type_oid) ? BINARY_COLLATION_OID : get_typcollation(type_oid); + } else { + typcollation = get_typcollation(type_oid); + } + get_valid_collation(collation, strength, location, + derivation, typcollation, (loccontext.strength > COLLATE_NONE) ? true : false, node, loccontext); - /* * Save the result collation into the expression node. If the * state is COLLATE_CONFLICT, we'll set the collation to @@ -627,13 +729,17 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont } else { exprSetInputCollation(node, loccontext.collation); } + + if (loccontext.charset_status == MULTI_CHARSET) { + assign_expression_charset(node, loccontext.collation); + } } break; } /* * Now, merge my information into my parent's state. */ - merge_collation_state(collation, strength, location, loccontext.collation2, loccontext.location2, context); + merge_collation_state(collation, strength, location, derivation, loccontext.collation2, loccontext.location2, context); return false; } @@ -641,9 +747,12 @@ static bool assign_collations_walker(Node* node, assign_collations_context* cont /* * Merge collation state of a subexpression into the context for its parent. */ -static void merge_collation_state(Oid collation, CollateStrength strength, int location, Oid collation2, int location2, +static void merge_collation_state(Oid collation, CollateStrength strength, int location, CollateDerivation derivation, Oid collation2, int location2, assign_collations_context* context) { + if (DB_IS_CMPT(B_FORMAT)) { + update_charset_status(context, collation); + } /* * If the collation strength for this node is different from what's * already in *context, then this node either dominates or is dominated by @@ -654,6 +763,7 @@ static void merge_collation_state(Oid collation, CollateStrength strength, int l context->collation = collation; context->strength = strength; context->location = location; + context->derivation = derivation; /* Bubble up error info if applicable */ if (strength == COLLATE_CONFLICT) { context->collation2 = collation2; @@ -666,6 +776,35 @@ static void merge_collation_state(Oid collation, CollateStrength strength, int l /* Nothing + nothing is still nothing */ break; case COLLATE_IMPLICIT: + if (ENABLE_MULTI_CHARSET) { + if (context->collation == collation) { + if (derivation < context->derivation) { + context->location = location; + context->derivation = derivation; + } + return; + } + + /* smaller derivation has precedence */ + if (derivation < context->derivation) { + context->collation = collation; + context->strength = strength; + context->location = location; + context->derivation = derivation; + return; + } else if (derivation > context->derivation) { + return; + } + + int charset = get_valid_charset_by_collation(collation); + int context_charset = get_valid_charset_by_collation(context->collation); + if (charset == context_charset) { + return merge_same_charset_collation(collation, strength, location, derivation, context); + } + return merge_diff_charset_collation( + collation, strength, location, derivation, charset, context_charset, context); + } + if (collation != context->collation) { /* * Non-default implicit collation always beats default. @@ -694,6 +833,14 @@ static void merge_collation_state(Oid collation, CollateStrength strength, int l break; case COLLATE_EXPLICIT: if (collation != context->collation) { + if (ENABLE_MULTI_CHARSET && context->collation != BINARY_COLLATION_OID) { + int charset = get_valid_charset_by_collation(collation); + int context_charset = get_valid_charset_by_collation(context->collation); + if (charset != context_charset) { + return merge_diff_charset_collation( + collation, strength, location, derivation, charset, context_charset, context); + } + } /* * Ooops, we have a conflict of explicit COLLATE clauses. * Here we choose to throw error immediately; that is what @@ -714,6 +861,129 @@ static void merge_collation_state(Oid collation, CollateStrength strength, int l } } +static void merge_same_charset_collation(Oid collation, CollateStrength strength, int location, + CollateDerivation derivation, assign_collations_context* context) +{ + bool is_bin_collation = COLLATION_HAS_BIN_SUFFIX(collation); + bool context_is_bin_collation = COLLATION_HAS_BIN_SUFFIX(context->collation); + + /* Conflict if both collation are *_bin */ + if (is_bin_collation && context_is_bin_collation) { + context->strength = COLLATE_CONFLICT; + context->collation2 = collation; + context->location2 = location; + return; + } + + /* *_bin collation has precedence */ + if (is_bin_collation) { + context->collation = collation; + context->strength = strength; + context->location = location; + context->derivation = derivation; + return; + } else if (context_is_bin_collation) { + return; + } + + /* DEFAULT collation last */ + if (context->collation == DEFAULT_COLLATION_OID) { + /* Override previous parent state */ + context->collation = collation; + context->strength = strength; + context->location = location; + context->derivation = derivation; + return; + } else if (collation == DEFAULT_COLLATION_OID) { + return; + } + context->strength = COLLATE_CONFLICT; + context->collation2 = collation; + context->location2 = location; +} + +static void merge_diff_charset_collation(Oid collation, CollateStrength strength, int location, + CollateDerivation derivation, int charset, int context_charset, assign_collations_context* context) +{ + /* binary collation has precedence */ + if (collation == BINARY_COLLATION_OID) { + context->collation = BINARY_COLLATION_OID; + context->strength = strength; + context->location = location; + context->derivation = derivation; + return; + } else if (context->collation == BINARY_COLLATION_OID) { + return; + } + + /* unicode charset has precedence */ + if (IS_UNICODE_ENCODING(charset)){ + context->collation = collation; + context->strength = strength; + context->location = location; + context->derivation = derivation; + return; + } else if (IS_UNICODE_ENCODING(context_charset)) { + return; + } + context->strength = COLLATE_CONFLICT; + context->collation2 = collation; + context->location2 = location; +} + +static void deal_expr_collation_b_compatibility(Node* node, Oid expr_type, + assign_collations_context* context, int location) +{ + int db_charset = GetDatabaseEncoding(); + int arg_charset = get_valid_charset_by_collation(context->collation); + if (arg_charset != db_charset) { + check_type_supports_multi_charset(expr_type, true); + } + + if (IsA(node, FuncExpr)) { + FuncExpr* func = (FuncExpr*)node; + if (IsSystemObjOid(func->funcid)) { + if (func->funcid == VERSIONFUNCOID || + func->funcid == OPENGAUSSVERSIONFUNCOID) { + context->derivation = DERIVATION_SYSCONST; + } else if ((func->funcid == CONVERTTOFUNCOID || + func->funcid == CONVERTTONOCASEFUNCOID) && + arg_charset != GetDatabaseEncoding()) { + /* convert_to argument string encoding must be server_encoding */ + ereport(ERROR, + (errcode(ERRCODE_COLLATION_MISMATCH), + errmsg("the character set of convert_to function arguments must be server_encoding"), + parser_errposition(context->pstate, location))); + } + } else if (PROC_IS_PRO(get_func_prokind(func->funcid))) { + /* the charset for arguments of procedure should be server_encoding in B compatibility */ + context->collation = get_default_collation_by_charset(db_charset); + if (context->charset_status == SINGLE_CHARSET) { + context->charset_status = MULTI_CHARSET; /* try to convert argument charset to server_encoding */ + } + if (context->strength == COLLATE_CONFLICT) { + context->strength = COLLATE_EXPLICIT; /* avoid InvalidOid collation */ + } + } + } + + /* + * When CONFLICT, final collation will be InvalidOid. + * We must ensure that the charset retrieved by the collation is the same as the actual charset. + */ + if (context->strength == COLLATE_CONFLICT) { + if (arg_charset != get_valid_charset_by_collation(context->collation2) || + arg_charset != GetDatabaseEncoding()) { + ereport(ERROR, + (errcode(ERRCODE_COLLATION_MISMATCH), + errmsg("collation mismatch between collations \"%s\" and \"%s\"", + get_collation_name(context->collation), + get_collation_name(context->collation2)), + parser_errposition(context->pstate, context->collation))); + } + } +} + /* * Aggref is a special case because expressions used only for ordering * shouldn't be taken to conflict with each other or with regular args, @@ -790,3 +1060,285 @@ static void assign_ordered_set_collations(Aggref* aggref, assign_collations_cont } } } + +/* In B compatibility, the encoding of expression can be different form server_encoding. */ +static void check_collate_expr_charset(ParseState *pstate, CollateExpr *cexpr, Oid arg_collation) +{ + if (cexpr->collOid == arg_collation) { + return; + } + + if (arg_collation == BINARY_COLLATION_OID) { + const char* coll_name = get_collation_name(cexpr->collOid); + ereport(ERROR, + (errmsg("COLLATION \"%s\" is not valid for CHARACTER SET \"binary\"", coll_name ? coll_name : "NULL"), + parser_errposition(pstate, cexpr->location))); + } + + Oid argtype = exprType((Node*)cexpr->arg); + if (cexpr->collOid == BINARY_COLLATION_OID && + (argtype == BITOID || argtype == VARBITOID || IsBinaryType(argtype))) { + return; + } + + if (!type_is_collatable(argtype) && argtype != UNKNOWNOID) { + return; + } + + int argcharset = get_charset_by_collation(arg_collation); + int newcharset = get_charset_by_collation(cexpr->collOid); + if (newcharset == argcharset) { + return; + } + if (newcharset == PG_INVALID_ENCODING) { + /* + * eg: _utf8mb4 'string' COLLATE "C" or + * 'string' COLLATE 'utf8mb4_unicode_ci' COLLATE "C" or + * 'string' COLLATE "zh_CN.utf8" COLLATE "C" + * Keep the syntax compatible with previous versions. + */ + if (argcharset == GetDatabaseEncoding()) { + return; + } + /* If arg expression has a different encoding, throw error. */ + const char* coll_name = get_collation_name(cexpr->collOid); + const char* encoding_name = pg_encoding_to_char(argcharset); + ereport(ERROR, + (errmsg("COLLATION \"%s\" is not valid for CHARACTER SET \"%s\" which is different from server_encoding", + coll_name ? coll_name : "NULL", encoding_name ? encoding_name : "NULL"), + parser_errposition(pstate, cexpr->location))); + } + + argcharset = (argcharset == PG_INVALID_ENCODING) ? GetDatabaseEncoding() : argcharset; + if (newcharset != argcharset) { + const char* coll_name = get_collation_name(cexpr->collOid); + const char* encoding_name = pg_encoding_to_char(argcharset); + ereport(ERROR, + (errcode(ERRCODE_COLLATION_MISMATCH), + errmsg("COLLATION \"%s\" is not valid for CHARACTER SET \"%s\"", + coll_name ? coll_name : "NULL", encoding_name ? encoding_name : "NULL"), + parser_errposition(pstate, cexpr->location))); + } +} + +static void update_charset_status(assign_collations_context* context, Oid collation) +{ + if (!OidIsValid(collation)) { + return; + } + + if (context->charset_status == MULTI_CHARSET) { + return; + } + + if (context->charset_status == UNKNONWN_CHARSET) { + context->charset_status = SINGLE_CHARSET; + return; + } + + if (collation == BINARY_COLLATION_OID || context->collation == BINARY_COLLATION_OID) { + return; + } + + if (context->strength == COLLATE_NONE && !OidIsValid(context->collation)) { + return; + } + + int charset = get_valid_charset_by_collation(collation); + int context_charset = get_valid_charset_by_collation(context->collation); + + if (charset != context_charset) { + context->charset_status = MULTI_CHARSET; + if (!ENABLE_MULTI_CHARSET) { + ereport(ERROR, (errcode(ERRCODE_COLLATION_MISMATCH), + errmsg("different character set data is not allowed when parameter " + "b_format_behavior_compat_options does not contain 'enable_multi_charset' option"))); + } + } +} + +Node *convert_arg_charset(Node *arg_expr, int target_charset, Oid target_collation) +{ + Oid type_oid = exprType(arg_expr); + if (exprCollation(arg_expr) == BINARY_COLLATION_OID) { + return arg_expr; + } + + return coerce_to_target_charset(arg_expr, target_charset, type_oid, exprTypmod(arg_expr), target_collation); +} + +void merge_arg_charsets(Oid target_collation, List *args) +{ + if (target_collation == BINARY_COLLATION_OID) { + return; + } + + int target_charset = get_valid_charset_by_collation(target_collation); + foreach_cell(item, args) { + Node *arg_expr = (Node*)lfirst(item); + lfirst(item) = (void*)convert_arg_charset(arg_expr, target_charset, target_collation); + } +} + +static void merge_aggregate_charsets(Aggref* aggref, Oid target_collation) +{ + if (target_collation == BINARY_COLLATION_OID) { + return; + } + + int target_charset = get_valid_charset_by_collation(target_collation); + foreach_cell (lc, aggref->args) { + TargetEntry* tle = (TargetEntry*)lfirst(lc); + Assert(IsA(tle, TargetEntry)); + if (!tle->resjunk) { + tle->expr = (Expr*)convert_arg_charset((Node*)tle->expr, target_charset, target_collation); + } + } +} + +static void merge_ordered_set_charsets(Aggref* aggref, Oid target_collation) +{ + if (target_collation == BINARY_COLLATION_OID) { + return; + } + + merge_arg_charsets(target_collation, aggref->aggdirectargs); + + bool merge_sort_collations = (list_length(aggref->args) == 1 && + get_func_variadictype(aggref->aggfnoid) == InvalidOid); + int target_charset = get_valid_charset_by_collation(target_collation); + foreach_cell (lc, aggref->args) { + TargetEntry* tle = (TargetEntry*)lfirst(lc); + Assert(IsA(tle, TargetEntry)); + if (merge_sort_collations) { + tle->expr = (Expr*)convert_arg_charset((Node*)tle->expr, target_charset, target_collation); + } + } +} + +static void merge_aggref_charsets(Aggref* aggref, Oid target_collation) +{ + switch (aggref->aggkind) { + case AGGKIND_NORMAL: + merge_aggregate_charsets(aggref, target_collation); + break; + case AGGKIND_ORDERED_SET: + merge_ordered_set_charsets(aggref, target_collation); + break; + default: + merge_aggregate_charsets(aggref, target_collation); + break; + } +} + +void merge_rowcompareexpr_arg_charsets(RowCompareExpr *rcexpr) +{ + ListCell *left_item = NULL; + ListCell *right_item = NULL; + ListCell *coll_item = NULL; + forthree(left_item, rcexpr->largs, right_item, rcexpr->rargs, coll_item, rcexpr->inputcollids) { + Node *left_expr = (Node*)lfirst(left_item); + Node *right_expr = (Node*)lfirst(right_item); + Oid collation = lfirst_oid(coll_item); + if (collation == BINARY_COLLATION_OID) { + continue; + } + + int charset = get_valid_charset_by_collation(collation); + lfirst(left_item) = (void*)convert_arg_charset(left_expr, charset, collation); + lfirst(right_item) = (void*)convert_arg_charset(right_expr, charset, collation); + } +} + +void merge_caseexpr_arg_charsets(Oid target_collation, CaseExpr *caseexpr) +{ + if (target_collation == BINARY_COLLATION_OID) { + return; + } + + int target_charset = get_valid_charset_by_collation(target_collation); + foreach_cell(item, caseexpr->args) { + CaseWhen* when = (CaseWhen*)lfirst(item); + Assert(IsA(when, CaseWhen)); + when->result = (Expr*)convert_arg_charset((Node*)when->result, target_charset, target_collation); + } + caseexpr->defresult = (Expr*)convert_arg_charset((Node*)caseexpr->defresult, target_charset, target_collation); +} + +void merge_scalararrayopexpr_arg_charsets(Oid target_collation, ScalarArrayOpExpr *sexpr) +{ + if (target_collation == BINARY_COLLATION_OID) { + return; + } + Assert(list_length(sexpr->args) == 2); + + Node *col_expr = (Node*)linitial(sexpr->args); + Node *array_expr = (Node*)lsecond(sexpr->args); + int target_charset = get_valid_charset_by_collation(target_collation); + linitial(sexpr->args) = (void*)convert_arg_charset(col_expr, target_charset, target_collation); + assign_expression_charset(array_expr, target_collation); +} + +static void assign_expression_charset(Node* node, Oid target_collation) +{ + if (!DB_IS_CMPT(B_FORMAT) || node == NULL || target_collation == BINARY_COLLATION_OID) { + return; + } + + check_stack_depth(); + switch (nodeTag(node)) { + case T_Aggref: { + merge_aggref_charsets((Aggref*)node, target_collation); + } break; + case T_WindowFunc: { + merge_arg_charsets(target_collation, ((WindowFunc*)node)->args); + } break; + case T_FuncExpr: { + merge_arg_charsets(target_collation, ((FuncExpr*)node)->args); + } break; + case T_OpExpr: { + merge_arg_charsets(target_collation, ((OpExpr*)node)->args); + } break; + case T_NullIfExpr: { + merge_arg_charsets(target_collation, ((NullIfExpr*)node)->args); + } break; + case T_ScalarArrayOpExpr: { + merge_scalararrayopexpr_arg_charsets(target_collation, (ScalarArrayOpExpr*)node); + } break; + case T_BoolExpr: { + merge_arg_charsets(target_collation, ((BoolExpr*)node)->args); + } break; + case T_CaseExpr: { + merge_caseexpr_arg_charsets(target_collation, (CaseExpr*)node); + } break; + case T_CoalesceExpr: { + merge_arg_charsets(target_collation, ((CoalesceExpr*)node)->args); + } break; + case T_MinMaxExpr: { + merge_arg_charsets(((MinMaxExpr*)node)->inputcollid, ((MinMaxExpr*)node)->args); + } break; + case T_XmlExpr: { + merge_arg_charsets(target_collation, ((XmlExpr*)node)->named_args); + merge_arg_charsets(target_collation, ((XmlExpr*)node)->args); + } break; + case T_ArrayCoerceExpr: { + assign_expression_charset((Node*)((ArrayCoerceExpr*)node)->arg, target_collation); + exprSetCollation(node, target_collation); + } break; + case T_ArrayExpr: { + merge_arg_charsets(target_collation, ((ArrayExpr*)node)->elements); + } break; + case T_RowCompareExpr: + case T_RelabelType: + case T_CoerceViaIO: { + // have been merged in assign_collations_walker + } break; + default: + ereport(ERROR, + (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), + errmsg("unrecognized node type: %d during merge expression charsets", (int)nodeTag(node)))); + break; + } + + return; +} diff --git a/src/common/backend/parser/parse_expr.cpp b/src/common/backend/parser/parse_expr.cpp index 764af9329..4c28146a3 100644 --- a/src/common/backend/parser/parse_expr.cpp +++ b/src/common/backend/parser/parse_expr.cpp @@ -21,7 +21,7 @@ #include "catalog/pg_type.h" #include "catalog/pg_proc.h" #include "catalog/gs_package.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" #include "commands/dbcommands.h" #include "commands/sequence.h" #include "db4ai/predict_by.h" @@ -44,6 +44,7 @@ #include "parser/parse_target.h" #include "parser/parse_type.h" #include "parser/parse_agg.h" +#include "parser/parse_utilcmd.h" #include "rewrite/rewriteManip.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -52,6 +53,7 @@ #include "funcapi.h" #include "utils/guc.h" #include "utils/guc_tables.h" +#include "utils/varbit.h" extern Node* build_column_default(Relation rel, int attrno, bool isInsertCmd = false, bool needOnUpdate = false); extern Node* makeAConst(Value* v, int location); @@ -85,6 +87,7 @@ static Node* transformPredictByFunction(ParseState* pstate, PredictByFunction* c static Node* transformWholeRowRef(ParseState* pstate, RangeTblEntry* rte, int location); static Node* transformIndirection(ParseState* pstate, A_Indirection* ind); static Node* transformTypeCast(ParseState* pstate, TypeCast* tc); +static Node* transformCharsetClause(ParseState* pstate, CharsetClause* c); static Node* transformCollateClause(ParseState* pstate, CollateClause* c); static Node* make_row_comparison_op(ParseState* pstate, List* opname, List* largs, List* rargs, int location); static Node* make_row_distinct_op(ParseState* pstate, List* opname, RowExpr* lrow, RowExpr* rrow, int location); @@ -538,6 +541,9 @@ Node *transformExprRecurse(ParseState *pstate, Node *expr) case T_SetVariableExpr: result = transformSetVariableExpr((SetVariableExpr*)expr); break; + case T_CharsetClause: + result = transformCharsetClause(pstate, (CharsetClause*)expr); + break; /********************************************* * Quietly accept node types that may be presented when we are @@ -1700,6 +1706,7 @@ static Node* transformUserSetElem(ParseState* pstate, UserSetElem *elem) UserSetElem *result = makeNode(UserSetElem); result->name = elem->name; Node *value = transformExprRecurse(pstate, (Node*)elem->val); + assign_expr_collations(pstate, value); if (IsA(elem->val, UserSetElem)) { result->name = list_concat(result->name, ((UserSetElem *)value)->name); @@ -2937,6 +2944,45 @@ static Node* transformTypeCast(ParseState* pstate, TypeCast* tc) return result; } +/* + * Handle an _charset clause. + * + * Transform the argument, and set charset's default collation. + * Only B-compatibility database. + */ +static Node* transformCharsetClause(ParseState* pstate, CharsetClause* c) +{ + Node *result = NULL; + Const *con = NULL; + + Assert(DB_IS_CMPT(B_FORMAT)); + result = transformExprRecurse(pstate, c->arg); + Assert(IsA(result, Const)); + con = (Const*)result; + /* T_BitString */ + if (con->consttype == BITOID) { + /* transform bit to bytea */ + VarBit* vb = DatumGetVarBitP(con->constvalue); + Datum bit_binary = CStringGetByteaDatum((const char*)VARBITS(vb), VARBITBYTES(vb)); + if (c->is_binary) { + result = (Node *)makeConst(BYTEAOID, -1, InvalidOid, -1, bit_binary, false, false); + } else { + /* bytea datum can be a text datum */ + result = (Node *)makeConst(TEXTOID, -1, InvalidOid, -1, bit_binary, false, false); + } + } else { + /* treate string as binary datatype: bytea */ + if (c->is_binary) { + result = coerce_type(pstate, result, exprType(result), BYTEAOID, -1, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, c->location); + } else { + result = coerce_type(pstate, result, exprType(result), TEXTOID, -1, COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, c->location); + } + } + + exprSetCollation(result, get_default_collation_by_charset(c->charset)); + return result; +} + /* * Handle an explicit COLLATE clause. * @@ -2953,10 +2999,13 @@ static Node* transformCollateClause(ParseState* pstate, CollateClause* c) argtype = exprType((Node*)newc->arg); /* - * The unknown type is not collatable, but coerce_type() takes care of it - * separately, so we'll let it go here. - */ - if (!type_is_collatable(argtype) && argtype != UNKNOWNOID) { + * The unknown type is not collatable, but coerce_type() takes care of it + * separately, so we'll let it go here. + */ + if (!type_is_collatable(argtype) && argtype != UNKNOWNOID && + !(DB_IS_CMPT(B_FORMAT) && + (IsBinaryType(argtype) || + (IsA(newc->arg, Const) && (argtype == BITOID || argtype == VARBITOID))))) { ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("collations are not supported by type %s", format_type_be(argtype)), @@ -2964,6 +3013,30 @@ static Node* transformCollateClause(ParseState* pstate, CollateClause* c) } newc->collOid = LookupCollation(pstate, c->collname, c->location); newc->location = c->location; + if (!DB_IS_CMPT(B_FORMAT)) { + return (Node*)newc; + } + + /* + * In B compatibility, binary type expression is collatable. + * The collation of binary type expression can only be "binary". + */ + if (argtype == BITOID || argtype == VARBITOID || IsBinaryType(argtype)) { + if (newc->collOid != BINARY_COLLATION_OID) { + const char* coll_name = get_collation_name(newc->collOid); + ereport(ERROR, + (errcode(ERRCODE_COLLATION_MISMATCH), + errmsg("COLLATION \"%s\" is not valid for binary type", coll_name ? coll_name : "NULL"), + parser_errposition(pstate, c->location))); + } + /* "X'..' COLLATE binary" and "B'..' COLLATE binary" should be treated as binary type. */ + if (IsA(newc->arg, Const) && (argtype == BITOID || argtype == VARBITOID)) { + /* transform bit to bytea */ + VarBit* vb = DatumGetVarBitP(((Const*)newc->arg)->constvalue); + Datum bit_binary = CStringGetByteaDatum((const char*)VARBITS(vb), VARBITBYTES(vb)); + newc->arg = (Expr*)makeConst(BYTEAOID, -1, InvalidOid, -1, bit_binary, false, false); + } + } return (Node*)newc; } diff --git a/src/common/backend/parser/parse_node.cpp b/src/common/backend/parser/parse_node.cpp index 88ed12930..6643328a1 100644 --- a/src/common/backend/parser/parse_node.cpp +++ b/src/common/backend/parser/parse_node.cpp @@ -459,6 +459,7 @@ Const* make_const(ParseState* pstate, Value* value, int location) Datum val; int64 val64; Oid typid; + Oid collid = InvalidOid; int typelen; bool typebyval = false; ParseCallbackState pcbstate; @@ -518,6 +519,9 @@ Const* make_const(ParseState* pstate, Value* value, int location) typid = UNKNOWNOID; /* will be coerced later */ typelen = -2; /* cstring-style varwidth type */ typebyval = false; + if (OidIsValid(GetCollationConnection())) { + collid = GetCollationConnection(); + } break; case T_BitString: @@ -545,7 +549,7 @@ Const* make_const(ParseState* pstate, Value* value, int location) con = makeConst(typid, -1, /* typmod -1 is OK for all cases */ - InvalidOid, /* all cases are uncollatable types */ + collid, /* all cases are uncollatable types */ typelen, val, false, diff --git a/src/common/backend/parser/parse_param.cpp b/src/common/backend/parser/parse_param.cpp index 92d141d2e..6cf7a288b 100644 --- a/src/common/backend/parser/parse_param.cpp +++ b/src/common/backend/parser/parse_param.cpp @@ -164,7 +164,11 @@ static Node* variable_paramref_hook(ParseState* pstate, ParamRef* pref) param->paramid = paramno; param->paramtype = *pptype; param->paramtypmod = -1; - param->paramcollid = get_typcollation(param->paramtype); + if (OidIsValid(GetCollationConnection()) && IsSupportCharsetType(param->paramtype)) { + param->paramcollid = GetCollationConnection(); + } else { + param->paramcollid = get_typcollation(param->paramtype); + } param->location = pref->location; param->tableOfIndexTypeList = NULL; diff --git a/src/common/backend/parser/parse_target.cpp b/src/common/backend/parser/parse_target.cpp index b271a8275..4371d5244 100644 --- a/src/common/backend/parser/parse_target.cpp +++ b/src/common/backend/parser/parse_target.cpp @@ -28,6 +28,7 @@ #include "parser/parse_relation.h" #include "parser/parse_target.h" #include "parser/parse_type.h" +#include "parser/parse_collate.h" #include "nodes/parsenodes_common.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -404,8 +405,8 @@ Expr* transformAssignedExpr(ParseState* pstate, Expr* expr, ParseExprKind exprKi attrtype = attnumTypeId(rd, attrno); attrtypmod = rd->rd_att->attrs[attrno - 1].atttypmod; attrcollation = rd->rd_att->attrs[attrno - 1].attcollation; - if (DB_IS_CMPT(B_FORMAT)) { - attrcharset = get_charset_by_collation(attrcollation); + if (DB_IS_CMPT(B_FORMAT) && OidIsValid(attrcollation)) { + attrcharset = get_valid_charset_by_collation(attrcollation); } /* @@ -501,7 +502,12 @@ Expr* transformAssignedExpr(ParseState* pstate, Expr* expr, ParseExprKind exprKi bool is_all_satisfied = pstate->p_is_td_compatible_truncation && (attrtype == BPCHAROID || attrtype == VARCHAROID) && ((type_mod > 0 && attrtypmod < type_mod) || type_mod < 0); - if (is_all_satisfied) { + + if (type_is_set(attrtype)) { + Node* orig_expr = (Node*)expr; + expr = (Expr*)coerce_to_settype( + pstate, orig_expr, type_id, attrtype, attrtypmod, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1, attrcollation); + } else if (is_all_satisfied) { expr = (Expr*)coerce_to_target_type( pstate, orig_expr, type_id, attrtype, attrtypmod, COERCION_ASSIGNMENT, COERCE_EXPLICIT_CAST, -1); pstate->tdTruncCastStatus = TRUNC_CAST_QUERY; @@ -551,7 +557,10 @@ Expr* transformAssignedExpr(ParseState* pstate, Expr* expr, ParseExprKind exprKi } } #ifndef ENABLE_MULTIPLE_NODES - expr = (Expr*)coerce_to_target_charset((Node*)expr, attrcharset, attrtype); + if (attrcharset != PG_INVALID_ENCODING) { + assign_expr_collations(pstate, (Node*)expr); + expr = (Expr*)coerce_to_target_charset((Node*)expr, attrcharset, attrtype, attrtypmod, attrcollation); + } #endif ELOG_FIELD_NAME_END; diff --git a/src/common/backend/parser/parse_type.cpp b/src/common/backend/parser/parse_type.cpp index e06b081ed..cd9673a34 100644 --- a/src/common/backend/parser/parse_type.cpp +++ b/src/common/backend/parser/parse_type.cpp @@ -37,7 +37,7 @@ #include "utils/timestamp.h" #include "utils/syscache.h" #include "utils/pl_package.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" #include "parser/parse_utilcmd.h" static int32 typenameTypeMod(ParseState* pstate, const TypeName* typname, Type typ); @@ -657,16 +657,16 @@ Oid LookupCollation(ParseState* pstate, List* collnames, int location) return colloid; } -static Oid get_column_def_collation_b_format(ColumnDef* coldef, Oid typeOid, Oid typcollation, +Oid get_column_def_collation_b_format(ColumnDef* coldef, Oid typeOid, Oid typcollation, bool is_bin_type, Oid rel_coll_oid) { - if (coldef->typname->charset != PG_INVALID_ENCODING && !IsSupportCharsetType(typeOid) && !type_is_enum(typeOid)) { + if (coldef->typname->charset != PG_INVALID_ENCODING && !IsSupportCharsetType(typeOid) && !type_is_enum(typeOid) && !type_is_set(typeOid)) { ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("type %s not support set charset", format_type_be(typeOid)))); } Oid result = InvalidOid; - if (!OidIsValid(typcollation) && !is_bin_type) { + if (!OidIsValid(typcollation) && !is_bin_type && !type_is_set(typeOid)) { return InvalidOid; } else if (OidIsValid(coldef->collOid)) { /* Precooked collation spec, use that */ @@ -732,7 +732,7 @@ Oid GetColumnDefCollation(ParseState* pstate, ColumnDef* coldef, Oid typeOid, Oi check_binary_collation(result, typeOid); } /* Complain if COLLATE is applied to an uncollatable type */ - if (OidIsValid(result) && !OidIsValid(typcollation) && !is_bin_type) { + if (OidIsValid(result) && !OidIsValid(typcollation) && !is_bin_type && !type_is_set(typeOid)) { ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("collations are not supported by type %s", format_type_be(typeOid)), @@ -1612,5 +1612,30 @@ Oid LookupTypeInPackage(List* typeNames, const char* typeName, Oid pkgOid, Oid n bool IsBinaryType(Oid typid) { - return (typid == BLOBOID) ? true : false; -} \ No newline at end of file + return ((typid) == BLOBOID || + (typid) == BYTEAOID); +} + +void check_type_supports_multi_charset(Oid typid, bool allow_array) +{ + switch (typid) { + case XMLOID: + case JSONOID: + case TSVECTOROID: + case GTSVECTOROID: + case TSQUERYOID: + case RECORDOID: + case HLL_OID: + case HLL_HASHVAL_OID: + case HLL_TRANS_OID: + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("multi character set for datatype '%s' is not supported", get_typename(typid)))); + default: + break; + } + + if (!allow_array && type_is_array(typid)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("multi character set for datatype '%s' is not supported", get_typename(typid)))); + } +} diff --git a/src/common/backend/parser/parse_utilcmd.cpp b/src/common/backend/parser/parse_utilcmd.cpp index e79c5cb9e..3747f843b 100644 --- a/src/common/backend/parser/parse_utilcmd.cpp +++ b/src/common/backend/parser/parse_utilcmd.cpp @@ -94,8 +94,8 @@ #include "client_logic/client_logic.h" #include "client_logic/client_logic_enums.h" #include "storage/checksum_impl.h" +#include "catalog/gs_collation.h" -#include "catalog/gs_utf8_collation.h" /* State shared by transformCreateSchemaStmt and its subroutines */ typedef struct { const char* stmtType; /* "CREATE SCHEMA" or "ALTER SCHEMA" */ @@ -232,60 +232,7 @@ static void checkPartitionConstraintWithExpr(Constraint* con) } } -int get_charset_by_collation(Oid coll_oid) -{ - HeapTuple tp = NULL; - int result = PG_INVALID_ENCODING; - - /* The collation OID in B format has a rule, through which we can quickly get the charset from the OID. */ - if (COLLATION_IN_B_FORMAT(coll_oid)) { - return FAST_GET_CHARSET_BY_COLL(coll_oid); - } - - if (COLLATION_HAS_INVALID_ENCODING(coll_oid)) { - return result; - } - - tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid)); - if (!HeapTupleIsValid(tp)) { - return result; - } - Form_pg_collation coll_tup = (Form_pg_collation)GETSTRUCT(tp); - result = coll_tup->collencoding; - ReleaseSysCache(tp); - return result; -} - -Oid get_default_collation_by_charset(int charset) -{ - Oid coll_oid = InvalidOid; - Relation rel; - ScanKeyData key[2]; - SysScanDesc scan = NULL; - HeapTuple tup = NULL; - - rel = heap_open(CollationRelationId, AccessShareLock); - ScanKeyInit(&key[0], Anum_pg_collation_collencoding, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(charset)); - ScanKeyInit(&key[1], Anum_pg_collation_collisdef, BTEqualStrategyNumber, F_BOOLEQ, BoolGetDatum(true)); - - scan = systable_beginscan(rel, CollationEncDefIndexId, true, NULL, 2, key); - - while (HeapTupleIsValid(tup = systable_getnext(scan))) { - coll_oid = HeapTupleGetOid(tup); - break; - } - systable_endscan(scan); - heap_close(rel, AccessShareLock); - - if (coll_oid == InvalidOid) { - ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("default collation for encoding \"%s\" does not exist", - pg_encoding_to_char(charset)))); - } - return coll_oid; -} - -static Oid check_collation_by_charset(const char* collate, int charset) +Oid check_collation_by_charset(const char* collate, int charset) { Oid coll_oid = InvalidOid; coll_oid = GetSysCacheOid3(COLLNAMEENCNSP, PointerGetDatum(collate), @@ -356,7 +303,8 @@ Oid transform_default_collation(const char* collate, int charset, Oid def_coll_o ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("this collation only cannot be specified here"))); } - if (charset != PG_INVALID_ENCODING && charset != PG_SQL_ASCII && charset != GetDatabaseEncoding()) { + if ((!ENABLE_MULTI_CHARSET || t_thrd.proc->workingVersionNum < MULTI_CHARSET_VERSION_NUM) && + charset != PG_INVALID_ENCODING && charset != PG_SQL_ASCII && charset != GetDatabaseEncoding()) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("difference between the charset and the database encoding has not supported"))); } @@ -607,6 +555,16 @@ Oid *namespaceid, bool isFirstNode) break; } } + + Oid rel_coll_oid = DEFAULT_COLLATION_OID; + if (DB_CMPT_B) { + Oid nspdefcoll = get_nsp_default_collation(*namespaceid); + if (stmt->collate || stmt->charset != PG_INVALID_ENCODING || nspdefcoll != InvalidOid) { + rel_coll_oid = transform_default_collation(stmt->collate, stmt->charset, nspdefcoll); + } + } + cxt.rel_coll_id = rel_coll_oid; + /* * Run through each primary element in the table creation clause. Separate * column defs from constraints, and do preliminary analysis. @@ -926,6 +884,16 @@ static List* GetAutoIncSeqOptions(CreateStmtContext* cxt) return list_make1(option); } +inline Oid get_rel_colaltion(Relation rel) +{ + if (rel == NULL || rel->rd_options == NULL) { + return InvalidOid; + } + + StdRdOptions *opt = (StdRdOptions*)(rel->rd_options); + return opt->collate; +} + /* * createSetOwnedByTable - * create a set owned by table, need to add record to pg_depend. @@ -969,6 +937,12 @@ static void CreateSetOwnedByTable(CreateStmtContext* cxt, ColumnDef* column, cha setstmt = makeNode(CreateSetStmt); setstmt->typname = column->typname; + /* get collation oid in alter table syntax */ + Oid rel_coll_oid = cxt->rel_coll_id; + Oid coll_oid = get_rel_colaltion(cxt->rel); + coll_oid = (coll_oid == InvalidOid) ? rel_coll_oid : coll_oid; + setstmt->set_collation = get_column_def_collation_b_format(column, ANYSETOID, 100, false, coll_oid); + cxt->blist = lappend(cxt->blist, setstmt); /* replace the set column type namespace and name for CreateStmt */ @@ -4801,6 +4775,7 @@ List* transformAlterTableStmt(Oid relid, AlterTableStmt* stmt, const char* query cxt.alist = NIL; cxt.pkey = NULL; cxt.ispartitioned = RelationIsPartitioned(rel); + cxt.rel_coll_id = InvalidOid; #ifdef PGXC cxt.fallback_dist_col = NULL; @@ -8412,6 +8387,7 @@ static void TransformModifyColumnDatatype(CreateStmtContext* cxt, AlterTableCmd* PrecheckColumnTypeForSet(cxt, def->typname); new_set = true; def->typname->typeOid = InvalidOid; // pg_attribute.atttypid + cxt->rel_coll_id = InvalidOid; CreateSetOwnedByTable(cxt, def, def->colname); } } else if (strcmp(tname, "smallserial") == 0 || strcmp(tname, "serial2") == 0 || strcmp(tname, "serial") == 0 || diff --git a/src/common/backend/parser/scan.l b/src/common/backend/parser/scan.l index 94813de5c..a61f6e4aa 100755 --- a/src/common/backend/parser/scan.l +++ b/src/common/backend/parser/scan.l @@ -1178,6 +1178,15 @@ other . * if necessary. */ ident = downcase_truncate_identifier(yytext, yyleng, yyextra->warnOnTruncateIdent); + /* Is it _charset? */ + if (ident[0] == '_' && + ENABLE_MULTI_CHARSET && + pg_valid_server_encoding(ident + 1) >= 0) { + yylval->str = pstrdup(ident + 1); + yyextra->is_hint_str = false; + yyextra->ident_quoted = false; + return UNDERSCORE_CHARSET; + } yylval->str = ident; yyextra->ident_quoted = false; set_is_delimiter_name(yytext,yyscanner); diff --git a/src/common/backend/pgxc_single/copy/copyops.cpp b/src/common/backend/pgxc_single/copy/copyops.cpp index 9946536a4..7b9ebae84 100644 --- a/src/common/backend/pgxc_single/copy/copyops.cpp +++ b/src/common/backend/pgxc_single/copy/copyops.cpp @@ -37,7 +37,7 @@ } while (0) static int get_decimal_from_hex(char hex); -static void attribute_out_text(StringInfo buf, char* string); +static void attribute_out_text(StringInfo buf, char* string, int str_encoding, FmgrInfo *convert_finfo); /* * Return decimal value for a hexadecimal digit @@ -54,7 +54,7 @@ static int get_decimal_from_hex(char hex) * Output an attribute to text * This takes portions of the code of CopyAttributeOutText */ -static void attribute_out_text(StringInfo buf, char* string) +static void attribute_out_text(StringInfo buf, char* string, int str_encoding, FmgrInfo *convert_finfo) { char* ptr = NULL; char c; @@ -63,11 +63,15 @@ static void attribute_out_text(StringInfo buf, char* string) bool need_transcoding, encoding_embeds_ascii; int file_encoding = pg_get_client_encoding(); - need_transcoding = (file_encoding != GetDatabaseEncoding() || pg_database_encoding_max_length() > 1); + need_transcoding = (file_encoding != str_encoding || pg_encoding_max_length(str_encoding) > 1); encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY(file_encoding); if (need_transcoding) { - ptr = pg_server_to_any(string, strlen(string), file_encoding); + if (str_encoding != GetDatabaseEncoding()) { + ptr = try_fast_encoding_conversion(string, strlen(string), str_encoding, file_encoding, (void*)convert_finfo); + } else { + ptr = pg_server_to_any(string, strlen(string), file_encoding, (void*)convert_finfo); + } } else { ptr = string; } @@ -356,11 +360,15 @@ char* CopyOps_BuildOneRowTo(TupleDesc tupdesc, Datum* values, const bool* nulls, char* res = NULL; int i; FmgrInfo* out_functions = NULL; + FmgrInfo* out_convert_funcs = NULL; FormData_pg_attribute* attr = tupdesc->attrs; + int *attr_encodings = NULL; StringInfo buf; /* Get info about the columns we need to process. */ out_functions = (FmgrInfo*)palloc(tupdesc->natts * sizeof(FmgrInfo)); + out_convert_funcs = (FmgrInfo*)palloc(tupdesc->natts * sizeof(FmgrInfo)); + attr_encodings = (int*)palloc(tupdesc->natts * sizeof(int)); for (i = 0; i < tupdesc->natts; i++) { Oid out_func_oid; bool isvarlena = false; @@ -371,6 +379,8 @@ char* CopyOps_BuildOneRowTo(TupleDesc tupdesc, Datum* values, const bool* nulls, getTypeOutputInfo(attr[i].atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &out_functions[i]); + attr_encodings[i] = get_valid_charset_by_collation(attr[i].attcollation); + construct_conversion_fmgr_info(attr_encodings[i], pg_get_client_encoding(), (void*)&out_convert_funcs[i]); } /* Initialize output buffer */ @@ -394,7 +404,7 @@ char* CopyOps_BuildOneRowTo(TupleDesc tupdesc, Datum* values, const bool* nulls, } else { char* string = NULL; string = OutputFunctionCall(&out_functions[i], value); - attribute_out_text(buf, string); + attribute_out_text(buf, string, attr_encodings[i], &out_convert_funcs[i]); pfree(string); } } @@ -402,6 +412,8 @@ char* CopyOps_BuildOneRowTo(TupleDesc tupdesc, Datum* values, const bool* nulls, /* Record length of message */ *len = buf->len; res = pstrdup(buf->data); + pfree(attr_encodings); + pfree(out_convert_funcs); pfree(out_functions); pfree(buf->data); pfree(buf); diff --git a/src/common/backend/utils/adt/like.cpp b/src/common/backend/utils/adt/like.cpp index fb374915f..ddb9e07a2 100644 --- a/src/common/backend/utils/adt/like.cpp +++ b/src/common/backend/utils/adt/like.cpp @@ -25,7 +25,7 @@ #include "miscadmin.h" #include "utils/builtins.h" #include "utils/pg_locale.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" static int SB_MatchText(char* t, int tlen, char* p, int plen, pg_locale_t locale, bool locale_is_c); static text* SB_do_like_escape(text*, text*); @@ -156,8 +156,8 @@ int GenericMatchText(char* s, int slen, char* p, int plen) int generic_match_text_with_collation(char* s, int slen, char* p, int plen, Oid collation) { - if (IS_UTF8_GENERAL_COLLATION(collation)) { - return matchtext_utf8mb4((unsigned char*)s, slen, (unsigned char*)p, plen); + if (is_b_format_collation(collation)) { + return match_text_by_builtin_collations((unsigned char*)s, slen, (unsigned char*)p, plen, collation); } return GenericMatchText(s, slen, p, plen); diff --git a/src/common/backend/utils/adt/ruleutils.cpp b/src/common/backend/utils/adt/ruleutils.cpp index 4c8ff9ec4..425e9f061 100644 --- a/src/common/backend/utils/adt/ruleutils.cpp +++ b/src/common/backend/utils/adt/ruleutils.cpp @@ -10921,6 +10921,7 @@ static void get_const_expr(Const* constval, deparse_context* context, int showty char* extval = NULL; bool isfloat = false; bool needlabel = false; + bool skip_collation = false; if (constval->constisnull || constval->ismaxvalue) { /* @@ -11048,7 +11049,16 @@ static void get_const_expr(Const* constval, deparse_context* context, int showty break; default: - simple_quote_literal(buf, extval); + int src_encoding = get_valid_charset_by_collation(constval->constcollid); + char* converted_str = (src_encoding != GetDatabaseEncoding()) ? + pg_any_to_server(extval, strlen(extval), src_encoding) : extval; + skip_collation = (src_encoding != GetCharsetConnection() || GetCollationConnection() == constval->constcollid); + if (converted_str != extval) { + simple_quote_literal(buf, converted_str); + pfree_ext(converted_str); + } else { + simple_quote_literal(buf, extval); + } break; } @@ -11086,6 +11096,9 @@ static void get_const_expr(Const* constval, deparse_context* context, int showty if (needlabel || showtype > 0) appendStringInfo(buf, "::%s", format_type_with_typemod(constval->consttype, constval->consttypmod)); + if (skip_collation) { + return; + } get_const_collation(constval, context); } diff --git a/src/common/backend/utils/adt/selfuncs.cpp b/src/common/backend/utils/adt/selfuncs.cpp index 497816b95..f232bc7ce 100755 --- a/src/common/backend/utils/adt/selfuncs.cpp +++ b/src/common/backend/utils/adt/selfuncs.cpp @@ -5744,7 +5744,7 @@ static Pattern_Prefix_Status like_fixed_prefix( *prefix_const = string_to_const(match, typeId); else *prefix_const = string_to_bytea_const(match, match_pos); - + (*prefix_const)->constcollid = patt_const->constcollid; if (rest_selec != NULL) *rest_selec = like_selectivity(&patt[pos], pattlen - pos, case_insensitive); @@ -5795,6 +5795,7 @@ static Pattern_Prefix_Status regex_fixed_prefix( } *prefix_const = string_to_const(prefix, typeId); + (*prefix_const)->constcollid = patt_const->constcollid; if (rest_selec != NULL) { if (exact) { @@ -5816,6 +5817,38 @@ static Pattern_Prefix_Status regex_fixed_prefix( return Pattern_Prefix_Partial; } +static Pattern_Prefix_Status like_fixed_prefix_with_encoding( + Const* patt_const, bool case_insensitive, Oid collation, Const** prefix_const, Selectivity* rest_selec) +{ + Pattern_Prefix_Status result; + int tmp_encoding = get_valid_charset_by_collation(patt_const->constcollid); + int db_encoding = GetDatabaseEncoding(); + if (db_encoding == tmp_encoding) { + return like_fixed_prefix(patt_const, case_insensitive, collation, prefix_const, rest_selec); + } + + DB_ENCODING_SWITCH_TO(tmp_encoding); + result = like_fixed_prefix(patt_const, case_insensitive, collation, prefix_const, rest_selec); + DB_ENCODING_SWITCH_BACK(db_encoding); + return result; +} + +static Pattern_Prefix_Status regex_fixed_prefix_with_encoding( + Const* patt_const, bool case_insensitive, Oid collation, Const** prefix_const, Selectivity* rest_selec) +{ + Pattern_Prefix_Status result; + int tmp_encoding = get_valid_charset_by_collation(patt_const->constcollid); + int db_encoding = GetDatabaseEncoding(); + if (db_encoding == tmp_encoding) { + return regex_fixed_prefix(patt_const, case_insensitive, collation, prefix_const, rest_selec); + } + + DB_ENCODING_SWITCH_TO(tmp_encoding); + result = regex_fixed_prefix(patt_const, case_insensitive, collation, prefix_const, rest_selec); + DB_ENCODING_SWITCH_BACK(db_encoding); + return result; +} + Pattern_Prefix_Status pattern_fixed_prefix( Const* patt, Pattern_Type ptype, Oid collation, Const** prefix, Selectivity* rest_selec) { @@ -5823,16 +5856,16 @@ Pattern_Prefix_Status pattern_fixed_prefix( switch (ptype) { case Pattern_Type_Like: - result = like_fixed_prefix(patt, false, collation, prefix, rest_selec); + result = like_fixed_prefix_with_encoding(patt, false, collation, prefix, rest_selec); break; case Pattern_Type_Like_IC: - result = like_fixed_prefix(patt, true, collation, prefix, rest_selec); + result = like_fixed_prefix_with_encoding(patt, true, collation, prefix, rest_selec); break; case Pattern_Type_Regex: - result = regex_fixed_prefix(patt, false, collation, prefix, rest_selec); + result = regex_fixed_prefix_with_encoding(patt, false, collation, prefix, rest_selec); break; case Pattern_Type_Regex_IC: - result = regex_fixed_prefix(patt, true, collation, prefix, rest_selec); + result = regex_fixed_prefix_with_encoding(patt, true, collation, prefix, rest_selec); break; default: ereport(ERROR, @@ -5841,6 +5874,7 @@ Pattern_Prefix_Status pattern_fixed_prefix( result = Pattern_Prefix_None; /* keep compiler quiet */ break; } + return result; } diff --git a/src/common/backend/utils/adt/set.cpp b/src/common/backend/utils/adt/set.cpp index f36f44130..ad6d04c67 100644 --- a/src/common/backend/utils/adt/set.cpp +++ b/src/common/backend/utils/adt/set.cpp @@ -42,10 +42,11 @@ #include "utils/int8.h" #include "utils/sortsupport.h" #include "fmgr.h" +#include "catalog/gs_collation.h" #define KEY_NUM (2) -static VarBit* get_set_in_result(Oid settypoid, char *setlabels); +static VarBit* get_set_in_result(Oid settypoid, char *setlabels, Oid collation); /* Basic I/O support */ @@ -54,7 +55,7 @@ Datum set_in(PG_FUNCTION_ARGS) char *setlabels = PG_GETARG_CSTRING(0); Oid settypoid = PG_GETARG_OID(1); - PG_RETURN_VARBIT_P(get_set_in_result(settypoid, setlabels)); + PG_RETURN_VARBIT_P(get_set_in_result(settypoid, setlabels, PG_GET_COLLATION())); } Datum set_out(PG_FUNCTION_ARGS) @@ -138,7 +139,7 @@ Datum set_recv(PG_FUNCTION_ARGS) int nbytes; char* setlabels = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); - PG_RETURN_VARBIT_P(get_set_in_result(settypoid, setlabels)); + PG_RETURN_VARBIT_P(get_set_in_result(settypoid, setlabels, PG_GET_COLLATION())); } Datum set_send(PG_FUNCTION_ARGS) @@ -285,6 +286,12 @@ Datum hashsetint(PG_FUNCTION_ARGS) Datum hashsettext(PG_FUNCTION_ARGS) { char *setlabels = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + if (is_b_format_collation(PG_GET_COLLATION())) { + Datum result = hash_text_by_builtin_collations((GS_UCHAR*)setlabels, strlen(setlabels), PG_GET_COLLATION()); + pfree_ext(setlabels); + return result; + } + return DirectFunctionCall1(hashtext, PointerGetDatum(cstring_to_text(setlabels))); } @@ -354,6 +361,13 @@ Datum btsetint8cmp(PG_FUNCTION_ARGS) /* compare (>,>=,<,<=,=,!=) functions */ Datum seteq(PG_FUNCTION_ARGS) { + if (is_b_format_collation(PG_GET_COLLATION())) { + const char *a = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(1))); + bool result = (varstr_cmp_by_builtin_collations(a, strlen(a), b, strlen(b), PG_GET_COLLATION()) == 0); + PG_RETURN_BOOL(result); + } + VarBit *d1 = PG_GETARG_VARBIT_P(0); Oid settypid1 = *(Oid *)VARBITS(d1); VarBit *d2 = PG_GETARG_VARBIT_P(1); @@ -377,6 +391,13 @@ Datum seteq(PG_FUNCTION_ARGS) Datum setne(PG_FUNCTION_ARGS) { + if (is_b_format_collation(PG_GET_COLLATION())) { + const char *a = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(1))); + bool result = (varstr_cmp_by_builtin_collations(a, strlen(a), b, strlen(b), PG_GET_COLLATION()) != 0); + PG_RETURN_BOOL(result); + } + VarBit *d1 = PG_GETARG_VARBIT_P(0); Oid settypid1 = *(Oid *)VARBITS(d1); VarBit *d2 = PG_GETARG_VARBIT_P(1); @@ -400,6 +421,13 @@ Datum setne(PG_FUNCTION_ARGS) Datum setge(PG_FUNCTION_ARGS) { + if (is_b_format_collation(PG_GET_COLLATION())) { + const char *a = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(1))); + bool result = (varstr_cmp_by_builtin_collations(a, strlen(a), b, strlen(b), PG_GET_COLLATION()) >= 0); + PG_RETURN_BOOL(result); + } + VarBit *d1 = PG_GETARG_VARBIT_P(0); Oid settypid1 = *(Oid *)VARBITS(d1); VarBit *d2 = PG_GETARG_VARBIT_P(1); @@ -423,6 +451,13 @@ Datum setge(PG_FUNCTION_ARGS) Datum setgt(PG_FUNCTION_ARGS) { + if (is_b_format_collation(PG_GET_COLLATION())) { + const char *a = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(1))); + bool result = (varstr_cmp_by_builtin_collations(a, strlen(a), b, strlen(b), PG_GET_COLLATION()) > 0); + PG_RETURN_BOOL(result); + } + VarBit *d1 = PG_GETARG_VARBIT_P(0); Oid settypid1 = *(Oid *)VARBITS(d1); @@ -447,6 +482,13 @@ Datum setgt(PG_FUNCTION_ARGS) Datum setlt(PG_FUNCTION_ARGS) { + if (is_b_format_collation(PG_GET_COLLATION())) { + const char *a = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(1))); + bool result = (varstr_cmp_by_builtin_collations(a, strlen(a), b, strlen(b), PG_GET_COLLATION()) < 0); + PG_RETURN_BOOL(result); + } + VarBit *d1 = PG_GETARG_VARBIT_P(0); Oid settypid1 = *(Oid *)VARBITS(d1); VarBit *d2 = PG_GETARG_VARBIT_P(1); @@ -470,6 +512,13 @@ Datum setlt(PG_FUNCTION_ARGS) Datum setle(PG_FUNCTION_ARGS) { + if (is_b_format_collation(PG_GET_COLLATION())) { + const char *a = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(0))); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, PG_GETARG_DATUM(1))); + bool result = (varstr_cmp_by_builtin_collations(a, strlen(a), b, strlen(b), PG_GET_COLLATION()) <= 0); + PG_RETURN_BOOL(result); + } + VarBit *d1 = PG_GETARG_VARBIT_P(0); Oid settypid1 = *(Oid *)VARBITS(d1); VarBit *d2 = PG_GETARG_VARBIT_P(1); @@ -753,13 +802,13 @@ Datum setint8le(PG_FUNCTION_ARGS) Datum settexteq(PG_FUNCTION_ARGS) { Datum set = DirectFunctionCall1(settotext, PG_GETARG_DATUM(0)); - return DirectFunctionCall2(texteq, PointerGetDatum(set), PG_GETARG_DATUM(1)); + return DirectFunctionCall2Coll(texteq, PG_GET_COLLATION(), PointerGetDatum(set), PG_GETARG_DATUM(1)); } Datum settextne(PG_FUNCTION_ARGS) { Datum set = DirectFunctionCall1(settotext, PG_GETARG_DATUM(0)); - return DirectFunctionCall2(textne, PointerGetDatum(set), PG_GETARG_DATUM(1)); + return DirectFunctionCall2Coll(textne, PG_GET_COLLATION(), PointerGetDatum(set), PG_GETARG_DATUM(1)); } Datum settextgt(PG_FUNCTION_ARGS) @@ -776,7 +825,7 @@ Datum settextge(PG_FUNCTION_ARGS) Datum settextlt(PG_FUNCTION_ARGS) { - Datum set = DirectFunctionCall1(settotext, PG_GETARG_DATUM(0)); + Datum set = DirectFunctionCall1(settotext, PG_GETARG_DATUM(0));\ return DirectFunctionCall2Coll(text_lt, PG_GET_COLLATION(), PointerGetDatum(set), PG_GETARG_DATUM(1)); } @@ -790,13 +839,13 @@ Datum settextle(PG_FUNCTION_ARGS) Datum textseteq(PG_FUNCTION_ARGS) { Datum set = DirectFunctionCall1(settotext, PG_GETARG_DATUM(1)); - return DirectFunctionCall2(texteq, PG_GETARG_DATUM(0), PointerGetDatum(set)); + return DirectFunctionCall2Coll(texteq, PG_GET_COLLATION(), PG_GETARG_DATUM(0), PointerGetDatum(set)); } Datum textsetne(PG_FUNCTION_ARGS) { Datum set = DirectFunctionCall1(settotext, PG_GETARG_DATUM(1)); - return DirectFunctionCall2(textne, PG_GETARG_DATUM(0), PointerGetDatum(set)); + return DirectFunctionCall2Coll(textne, PG_GET_COLLATION(), PG_GETARG_DATUM(0), PointerGetDatum(set)); } Datum textsetgt(PG_FUNCTION_ARGS) @@ -927,7 +976,7 @@ Datum bpchartoset(PG_FUNCTION_ARGS) Datum txt = PG_GETARG_DATUM(0); text* trimtxt = (text*)DirectFunctionCall1(rtrim1, txt); char* setlabels = TextDatumGetCString(trimtxt); - Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels); + Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels, PG_GET_COLLATION()); pfree_ext(trimtxt); pfree_ext(setlabels); PG_RETURN_VARBIT_P(result); @@ -938,7 +987,7 @@ Datum varchartoset(PG_FUNCTION_ARGS) Datum txt = PG_GETARG_DATUM(0); char* setlabels = DatumGetCString(DirectFunctionCall1(varcharout, txt)); - Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels); + Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels, PG_GET_COLLATION()); pfree_ext(setlabels); PG_RETURN_VARBIT_P(result); } @@ -948,7 +997,7 @@ Datum texttoset(PG_FUNCTION_ARGS) Datum txt = PG_GETARG_DATUM(0); char *setlabels = DatumGetCString(DirectFunctionCall1(textout, txt)); - Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels); + Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels, PG_GET_COLLATION()); pfree_ext(setlabels); PG_RETURN_VARBIT_P(result); } @@ -958,7 +1007,7 @@ Datum nvarchar2toset(PG_FUNCTION_ARGS) Datum txt = PG_GETARG_DATUM(0); char *setlabels = DatumGetCString(DirectFunctionCall1(nvarchar2out, txt)); - Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels); + Datum result = (Datum)get_set_in_result(PG_GETARG_OID(1), setlabels, PG_GET_COLLATION()); pfree_ext(setlabels); PG_RETURN_VARBIT_P(result); } @@ -970,6 +1019,15 @@ static int btsetfastcmp(Datum x, Datum y, SortSupport ssup) VarBit *d2 = DatumGetVarBitP(y); Oid settypid2 = *(Oid *)VARBITS(d2); + + if (is_b_format_collation(ssup->ssup_collation)) { + int result; + const char *a = DatumGetCString(DirectFunctionCall1(set_out, x)); + const char *b = DatumGetCString(DirectFunctionCall1(set_out, y)); + result = varstr_cmp_by_builtin_collations((char*)a, strlen(a), (char*)b, strlen(b), ssup->ssup_collation); + return result; + } + /* compare by its value if arguments are the same set, otherwise by character order */ if (settypid1 == settypid2) { int64 a = settoint64(d1); @@ -1062,38 +1120,9 @@ Datum findinset(PG_FUNCTION_ARGS) PG_RETURN_INT32(0); } -static void process_set_label(const char *label, Oid settypoid, VarBit **result) +static void get_set_result(Oid settypoid, VarBit **result, Form_pg_set settup) { Oid *oid = NULL; - Relation pg_set = NULL; - ScanKeyData key[2]; - SysScanDesc scan = NULL; - HeapTuple tup = NULL; - - text *s = cstring_to_text(label); - if (text_length(PointerGetDatum(s)) > SETNAMELEN) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input value for set %s: \"%s\"", format_type_be(settypoid), label))); - } - - pg_set = heap_open(SetRelationId, AccessShareLock); - ScanKeyInit(&key[0], Anum_pg_set_settypid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(settypoid)); - ScanKeyInit(&key[1], Anum_pg_set_setlabel, BTEqualStrategyNumber, F_TEXTEQ, PointerGetDatum(s)); - - scan = systable_beginscan(pg_set, SetTypIdLabelIndexId, true, NULL, KEY_NUM, key); - tup = systable_getnext(scan); - pfree_ext(s); - - if (!HeapTupleIsValid(tup)) { - systable_endscan(scan); - heap_close(pg_set, AccessShareLock); - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input value for set %s: '%s'", format_type_be(settypoid), label))); - } - - Form_pg_set settup = (Form_pg_set)GETSTRUCT(tup); if (*result == NULL) { int typmod = settup->setnum + sizeof(Oid) * BITS_PER_BYTE; @@ -1109,11 +1138,87 @@ static void process_set_label(const char *label, Oid settypoid, VarBit **result) bits8 *bitmap = (bits8 *)((char*)oid + sizeof(Oid) + (settup->setsortorder / BITS_PER_BYTE)); (*bitmap) |= (1 << (settup->setsortorder % BITS_PER_BYTE)); - systable_endscan(scan); - heap_close(pg_set, AccessShareLock); } -static void preprocess_set_value(char *value, Oid settypoid, VarBit **result) +static void process_set_label_by_collation(char *label, Oid settypoid, VarBit **result, Oid collation) +{ + Relation pg_set = NULL; + HeapTuple tup = NULL; + + ScanKeyData key[1]; + SysScanDesc scan = NULL; + int res = 0; + bool find = false; + bool isnull = true; + + pg_set = heap_open(SetRelationId, AccessShareLock); + ScanKeyInit(&key[0], Anum_pg_set_settypid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(settypoid)); + + scan = systable_beginscan(pg_set, SetTypIdLabelIndexId, true, NULL, 1, key); + while (HeapTupleIsValid(tup = systable_getnext(scan))) { + Form_pg_set settup = (Form_pg_set)GETSTRUCT(tup); + text* setlabel = (text*)heap_getattr(tup, Anum_pg_set_setlabel, pg_set->rd_att, &isnull); + + res = varstr_cmp_by_builtin_collations((char*)VARDATA_ANY(setlabel), VARSIZE_ANY_EXHDR(setlabel), + label, strlen(label), collation); + if (res == 0) { + get_set_result(settypoid, result, settup); + + find = true; + break; + } + } + systable_endscan(scan); + heap_close(pg_set, AccessShareLock); + if (!find) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input value for set %s: '%s'", format_type_be(settypoid), label))); + } +} + +static void process_set_label(char *label, Oid settypoid, VarBit **result, Oid collation) +{ + Relation pg_set = NULL; + HeapTuple tup = NULL; + text *s = cstring_to_text(label); + + if (is_b_format_collation(collation)) { + process_set_label_by_collation(label, settypoid, result, collation); + } else { + if (text_length(PointerGetDatum(s)) > SETNAMELEN) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input value for set %s: \"%s\"", format_type_be(settypoid), label))); + } + ScanKeyData key[2]; + SysScanDesc scan = NULL; + pg_set = heap_open(SetRelationId, AccessShareLock); + ScanKeyInit(&key[0], Anum_pg_set_settypid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(settypoid)); + ScanKeyInit(&key[1], Anum_pg_set_setlabel, BTEqualStrategyNumber, F_TEXTEQ, PointerGetDatum(s)); + + scan = systable_beginscan(pg_set, SetTypIdLabelIndexId, true, NULL, KEY_NUM, key); + + tup = systable_getnext(scan); + pfree_ext(s); + + if (!HeapTupleIsValid(tup)) { + systable_endscan(scan); + heap_close(pg_set, AccessShareLock); + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input value for set %s: '%s'", format_type_be(settypoid), label))); + } + + Form_pg_set settup = (Form_pg_set)GETSTRUCT(tup); + get_set_result(settypoid, result, settup); + + systable_endscan(scan); + heap_close(pg_set, AccessShareLock); + } +} + +static void preprocess_set_value(char *value, Oid settypoid, VarBit **result, Oid collation) { bool hasEmpty = false; @@ -1131,21 +1236,21 @@ static void preprocess_set_value(char *value, Oid settypoid, VarBit **result) } if (hasEmpty) { - process_set_label("", settypoid, result); + process_set_label("", settypoid, result, collation); } } -static VarBit* get_set_in_result(Oid settypoid, char *setlabels) +static VarBit* get_set_in_result(Oid settypoid, char *setlabels, Oid collation) { VarBit *result = NULL; char* next_token = NULL; char* labels = pstrdup(setlabels); - preprocess_set_value(setlabels, settypoid, &result); + preprocess_set_value(setlabels, settypoid, &result, collation); char* token = strtok_s(labels, SETLABELDELIMIT, &next_token); while (token != NULL) { - process_set_label(token, settypoid, &result); + process_set_label(token, settypoid, &result, collation); token = strtok_s(NULL, SETLABELDELIMIT, &next_token); } diff --git a/src/common/backend/utils/adt/varchar.cpp b/src/common/backend/utils/adt/varchar.cpp index 82aff9842..4188e7a60 100644 --- a/src/common/backend/utils/adt/varchar.cpp +++ b/src/common/backend/utils/adt/varchar.cpp @@ -25,7 +25,7 @@ #include "utils/sortsupport.h" #include "vecexecutor/vectorbatch.h" #include "utils/pg_locale.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" #include "miscadmin.h" @@ -1036,10 +1036,10 @@ Datum hashbpchar(PG_FUNCTION_ARGS) keydata = VARDATA_ANY(key); keylen = bcTruelen(key); - if (!is_b_format_collation(collid)) { - result = hash_any((unsigned char*)keydata, keylen); + if (is_b_format_collation(collid)) { + result = hash_text_by_builtin_collations((unsigned char *)VARDATA_ANY(key), keylen, collid); } else { - result = hash_text_by_builtin_colltions((unsigned char *)VARDATA_ANY(key), keylen, collid); + result = hash_any((unsigned char*)keydata, keylen); } /* Avoid leaking memory for toasted inputs */ diff --git a/src/common/backend/utils/adt/varlena.cpp b/src/common/backend/utils/adt/varlena.cpp index 6da8f8ab8..0b929a3ab 100644 --- a/src/common/backend/utils/adt/varlena.cpp +++ b/src/common/backend/utils/adt/varlena.cpp @@ -42,7 +42,7 @@ #include "executor/node/nodeSort.h" #include "pgxc/groupmgr.h" #include "openssl/evp.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" #include "catalog/pg_collation_fn.h" #define SUBSTR_WITH_LEN_OFFSET 2 @@ -675,6 +675,7 @@ Oid binary_need_transform_typeid(Oid typeoid, Oid* collation) switch (typeoid) { /* binary type no need to transform */ case BLOBOID: + case BYTEAOID: break; /* string type need to transform to binary type */ case TEXTOID: @@ -864,6 +865,25 @@ int32 text_length(Datum str) } } +int32 text_length_with_encoding(Datum str, int encoding) +{ + Assert(PG_VALID_ENCODING(encoding)); + + /* fastpath when max encoding length is one */ + if (pg_encoding_max_length(encoding) == 1) + PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ); + else { + text* t = DatumGetTextPP(str); + int32 result = 0; + + result = pg_encoding_mbstrlen_with_len(VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t), encoding); + if ((Pointer)(t) != (Pointer)(str)) + pfree_ext(t); + + PG_RETURN_INT32(result); + } +} + /* * textoctetlen - * returns the physical length of a text* @@ -1342,6 +1362,22 @@ text* text_substring(Datum str, int32 start, int32 length, bool length_not_speci return NULL; } +text* text_substring_with_encoding(Datum str, int32 start, int32 length, bool length_not_specified, int encoding) +{ + Assert(encoding != PG_INVALID_ENCODING); + + int db_encoding = GetDatabaseEncoding(); + if (encoding == db_encoding) { + return text_substring(str, start, length, length_not_specified); + } + + text* result = NULL; + DB_ENCODING_SWITCH_TO(encoding); + result = text_substring(str, start, length, length_not_specified); + DB_ENCODING_SWITCH_BACK(db_encoding); + return result; +} + // adapt A db's substr(text str,integer start,integer length) // when start<0, amend the sartPosition to abs(start) from last char, // then search backward @@ -1974,18 +2010,17 @@ Datum texteq(PG_FUNCTION_ARGS) Datum arg2 = PG_GETARG_DATUM(1); bool result = false; - Oid collid = PG_GET_COLLATION(); - if (is_b_format_collation(collid)) { - result = texteq_with_collation(fcinfo); - PG_RETURN_BOOL(result); - } - if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) || VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("texteq could not support more than 1GB clob/blob data"))); } Size len1, len2; + if (is_b_format_collation(PG_GET_COLLATION())) { + result = texteq_with_collation(fcinfo); + PG_RETURN_BOOL(result); + } + /* * Since we only care about equality or not-equality, we can avoid all the * expense of strcoll() here, and just do bitwise comparison. In fact, we @@ -2164,7 +2199,6 @@ Datum text_gt(PG_FUNCTION_ARGS) FUNC_CHECK_HUGE_POINTER(false, arg1, "text_gt()"); bool result = false; - result = (text_cmp(arg1, arg2, PG_GET_COLLATION()) > 0); PG_FREE_IF_COPY(arg1, 0); @@ -2180,7 +2214,6 @@ Datum text_ge(PG_FUNCTION_ARGS) FUNC_CHECK_HUGE_POINTER(false, arg1, "text_ge()"); bool result = false; - result = (text_cmp(arg1, arg2, PG_GET_COLLATION()) >= 0); PG_FREE_IF_COPY(arg1, 0); diff --git a/src/common/backend/utils/fmgr/fmgr.cpp b/src/common/backend/utils/fmgr/fmgr.cpp index 902481271..bd3538496 100755 --- a/src/common/backend/utils/fmgr/fmgr.cpp +++ b/src/common/backend/utils/fmgr/fmgr.cpp @@ -2136,7 +2136,7 @@ void CheckNullResult(Oid oid, bool isnull, char* str) * With param can_ignore == true, truncation or transformation may be cast * if function failed for ignorable errors like overflowing or out of range. */ -Datum InputFunctionCall(FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, bool can_ignore) +Datum InputFunctionCall(FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, bool can_ignore, Oid collation) { FunctionCallInfoData fcinfo; Datum result; @@ -2158,7 +2158,7 @@ Datum InputFunctionCall(FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmo fcinfo.argnull[1] = false; fcinfo.argnull[2] = false; fcinfo.can_ignore = can_ignore; - + fcinfo.fncollation = collation; result = FunctionCallInvoke(&fcinfo); /* Should get null result if and only if str is NULL */ @@ -2356,6 +2356,13 @@ bytea* OidSendFunctionCall(Oid functionId, Datum val) return SendFunctionCall(&flinfo, val); } +Datum OidInputFunctionCallColl(Oid functionId, char* str, Oid typioparam, int32 typmod, Oid collation) +{ + FmgrInfo flinfo; + + fmgr_info(functionId, &flinfo); + return InputFunctionCall(&flinfo, str, typioparam, typmod, false, collation); +} /* * !!! OLD INTERFACE !!! * diff --git a/src/common/backend/utils/init/globals.cpp b/src/common/backend/utils/init/globals.cpp index 8662565fd..abe024ecf 100644 --- a/src/common/backend/utils/init/globals.cpp +++ b/src/common/backend/utils/init/globals.cpp @@ -75,16 +75,16 @@ bool will_shutdown = false; * NEXT | 92899 | ? | ? * ********************************************/ -const uint32 GRAND_VERSION_NUM = 92902; +const uint32 GRAND_VERSION_NUM = 92903; /******************************************** * 2.VERSION NUM FOR EACH FEATURE * Please write indescending order. ********************************************/ +const uint32 MULTI_CHARSET_VERSION_NUM = 92903; const uint32 NBTREE_INSERT_OPTIMIZATION_VERSION_NUM = 92902; const uint32 NBTREE_DEDUPLICATION_VERSION_NUM = 92902; const uint32 ONDEMAND_REDO_VERSION_NUM = 92901; - const uint32 SRF_FUSION_VERSION_NUM = 92847; const uint32 INDEX_HINT_VERSION_NUM = 92845; const uint32 INNER_UNIQUE_VERSION_NUM = 92845; diff --git a/src/common/backend/utils/init/postinit.cpp b/src/common/backend/utils/init/postinit.cpp index 4ffde0d73..4c8782aa4 100644 --- a/src/common/backend/utils/init/postinit.cpp +++ b/src/common/backend/utils/init/postinit.cpp @@ -394,6 +394,7 @@ static void SetEncordingInfo(Form_pg_database dbform, char* collate, char* ctype SetConfigOption("server_encoding", GetDatabaseEncodingName(), PGC_INTERNAL, PGC_S_OVERRIDE); /* If we have no other source of client_encoding, use server encoding */ SetConfigOption("client_encoding", GetDatabaseEncodingName(), PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); + SetConfigOption("character_set_connection", GetDatabaseEncodingName(), PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); // if we are identical no bother to set that in thread pool settings. if (!IS_THREAD_POOL_WORKER || strcmp(NameStr(dbform->datcollate), NameStr(t_thrd.port_cxt.cur_datcollate)) != 0 || @@ -436,6 +437,17 @@ static void SetEncordingInfo(Form_pg_database dbform, char* collate, char* ctype } SetConfigOption("sql_compatibility", NameStr(dbform->datcompatibility), PGC_INTERNAL, PGC_S_OVERRIDE); + + if (ENABLE_MULTI_CHARSET) { + Oid collid = get_default_collation_by_charset(GetDatabaseEncoding(), false); + SetConfigOption( + "collation_connection", + OidIsValid(collid) ? get_collation_name(collid) : "", + PGC_BACKEND, + PGC_S_DYNAMIC_DEFAULT); + } else { + SetConfigOption("collation_connection", "", PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); + } return; } diff --git a/src/common/backend/utils/mb/encnames.cpp b/src/common/backend/utils/mb/encnames.cpp index 1a950cf47..9481606e6 100644 --- a/src/common/backend/utils/mb/encnames.cpp +++ b/src/common/backend/utils/mb/encnames.cpp @@ -130,9 +130,9 @@ unsigned int pg_encname_tbl_sz = sizeof(pg_encname_tbl) / sizeof(pg_encname_tbl[ */ pg_enc pg_enc_coll_map_b[] = { PG_SQL_ASCII, /* SQL/ASCII */ - PG_GBK, /* GBK (Windows-936) */ + PG_GBK, /* GBK (Windows-936), collation oid range(1280 - 1535) */ PG_UTF8, /* Unicode UTF8 */ - PG_GB18030 /* GB18030 */ + PG_GB18030 /* GB18030, collation oid range(1768 - 2024) */ }; /* ---------- diff --git a/src/common/backend/utils/mb/mbutils.cpp b/src/common/backend/utils/mb/mbutils.cpp index 20132d97e..ab9943568 100644 --- a/src/common/backend/utils/mb/mbutils.cpp +++ b/src/common/backend/utils/mb/mbutils.cpp @@ -223,6 +223,12 @@ void InitializeClientEncoding(void) pg_enc2name_tbl[u_sess->mb_cxt.pending_client_encoding].name, GetDatabaseEncodingName()))); } + u_sess->mb_cxt.character_set_connection = &pg_enc2name_tbl[GetDatabaseEncoding()]; + if (ENABLE_MULTI_CHARSET) { + u_sess->mb_cxt.collation_connection = get_default_collation_by_charset(GetDatabaseEncoding(), false); + } else { + u_sess->mb_cxt.collation_connection = InvalidOid; + } } /* @@ -320,6 +326,69 @@ unsigned char* pg_do_encoding_conversion(unsigned char* src, int len, int src_en return result; } +void construct_conversion_fmgr_info(int src_encoding, int dst_encoding, void* finfo) +{ + Assert(finfo != NULL); + + FmgrInfo* convert_finfo = (FmgrInfo*)finfo; + if (src_encoding == dst_encoding) { + convert_finfo->fn_oid = InvalidOid; + return; + } + + if (src_encoding == PG_SQL_ASCII || dst_encoding == PG_SQL_ASCII) { + convert_finfo->fn_oid = InvalidOid; + return; + } + + Oid convert_func = FindDefaultConversionProc(src_encoding, dst_encoding); + if (OidIsValid(convert_func)) { + fmgr_info(convert_func, convert_finfo); + } else { + convert_finfo->fn_oid = InvalidOid; + } +} + + +static char* fast_encoding_conversion(char* src, int len, int src_encoding, int dest_encoding, FmgrInfo* convert_finfo) +{ + if (len <= 0) { + return src; + } + + char* result = NULL; + Assert(convert_finfo != NULL); + Assert(OidIsValid(convert_finfo->fn_oid)); + + /* + * Allocate space for conversion result, being wary of integer overflow + */ + if ((Size)len >= (MaxAllocSize / (Size)MAX_CONVERSION_GROWTH)) { + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("out of memory"), + errdetail("String of %d bytes is too long for encoding conversion.", len))); + } + result = (char*)palloc(len * MAX_CONVERSION_GROWTH + 1); + + FunctionCall5(convert_finfo, + Int32GetDatum(src_encoding), + Int32GetDatum(dest_encoding), + CStringGetDatum(src), + CStringGetDatum(result), + Int32GetDatum(len)); + return result; +} + +char* try_fast_encoding_conversion(char* src, int len, int src_encoding, int dest_encoding, void* convert_finfo) +{ + if (unlikely(!OidIsValid(((FmgrInfo*)convert_finfo)->fn_oid))) { + return (char*)pg_do_encoding_conversion((unsigned char*)src, len, src_encoding, dest_encoding); + } + + return fast_encoding_conversion(src, len, src_encoding, dest_encoding, (FmgrInfo*)convert_finfo); +} + /* * Convert string using encoding_name. The source * encoding is the DB encoding. @@ -618,6 +687,35 @@ char* pg_any_to_server(const char* s, int len, int encoding) } } +/* + * convert any encoding to client encoding. + */ +char* pg_any_to_client(const char* s, int len, int encoding, void* convert_finfo) +{ + Assert(u_sess->mb_cxt.ClientEncoding); + + if (len <= 0) { + return (char*)s; + } + + if (encoding == u_sess->mb_cxt.ClientEncoding->encoding || encoding == PG_SQL_ASCII) { + /* + * No conversion is needed, but we must still validate the data. + */ + return (char*)s; + } + + if (u_sess->mb_cxt.DatabaseEncoding->encoding == encoding) { + return perform_default_encoding_conversion(s, len, false); + } else if (convert_finfo != NULL) { + return try_fast_encoding_conversion( + (char*)s, len, encoding, u_sess->mb_cxt.ClientEncoding->encoding, convert_finfo); + } else { + return (char*)pg_do_encoding_conversion( + (unsigned char*)s, len, encoding, u_sess->mb_cxt.ClientEncoding->encoding); + } +} + /* * convert server encoding to client encoding. */ @@ -648,7 +746,7 @@ bool WillTranscodingBePerformed(int encoding) /* * convert server encoding to any encoding. */ -char* pg_server_to_any(const char* s, int len, int encoding) +char* pg_server_to_any(const char* s, int len, int encoding, void *convert_finfo) { Assert(u_sess->mb_cxt.DatabaseEncoding); Assert(u_sess->mb_cxt.ClientEncoding); @@ -666,6 +764,9 @@ char* pg_server_to_any(const char* s, int len, int encoding) } if (u_sess->mb_cxt.ClientEncoding->encoding == encoding) { return perform_default_encoding_conversion(s, len, false); + } else if (convert_finfo != NULL) { + return try_fast_encoding_conversion( + (char*)s, len, u_sess->mb_cxt.DatabaseEncoding->encoding, encoding, convert_finfo); } else { return (char*)pg_do_encoding_conversion( (unsigned char*)s, len, u_sess->mb_cxt.DatabaseEncoding->encoding, encoding); @@ -806,6 +907,27 @@ int pg_mbstrlen_with_len(const char* mbstr, int limit) return len; } +/* returns the length (counted in wchars) of a multibyte string + * (not necessarily NULL terminated) + */ +int pg_encoding_mbstrlen_with_len(const char* mbstr, int limit, int encoding) +{ + int len = 0; + + /* optimization for single byte encoding */ + if (pg_encoding_max_length(encoding) == 1) { + return limit; + } + while (limit > 0 && *mbstr) { + int l = pg_encoding_mblen(encoding, mbstr); + + limit -= l; + mbstr += l; + len++; + } + return len; +} + /* returns the length (counted in wchars) of a multibyte string * with fixed encoding. */ @@ -1015,6 +1137,26 @@ const char* GetDatabaseEncodingName(void) return u_sess->mb_cxt.DatabaseEncoding->name; } +int GetCharsetConnection(void) +{ + Assert(u_sess->mb_cxt.character_set_connection); + return u_sess->mb_cxt.character_set_connection->encoding; +} + +const char* GetCharsetConnectionName(void) +{ + Assert(u_sess->mb_cxt.character_set_connection); + return u_sess->mb_cxt.character_set_connection->name; +} + +Oid GetCollationConnection(void) +{ + if (!ENABLE_MULTI_CHARSET) { + return InvalidOid; + } + return u_sess->mb_cxt.collation_connection; +} + Datum getdatabaseencoding(PG_FUNCTION_ARGS) { Assert(u_sess->mb_cxt.DatabaseEncoding); diff --git a/src/common/backend/utils/misc/guc.cpp b/src/common/backend/utils/misc/guc.cpp index ed699ac72..d0fb7b6c4 100755 --- a/src/common/backend/utils/misc/guc.cpp +++ b/src/common/backend/utils/misc/guc.cpp @@ -80,6 +80,7 @@ #include "parser/parse_type.h" #include "parser/parser.h" #include "parser/parse_coerce.h" +#include "parser/parse_utilcmd.h" #include "parser/scansup.h" #include "pgstat.h" #include "pgxc/route.h" @@ -462,6 +463,7 @@ static bool check_default_transaction_isolation(int* newval, void** extra, GucSo static bool check_enable_stmt_track(bool* newval, void** extra, GucSource source); static bool check_debug_assertions(bool* newval, void** extra, GucSource source); static void process_set_global_transation(Oid databaseid, Oid roleid, VariableSetStmt* setstmt); +static void process_set_names_collate(VariableSetStmt* setstmt, GucAction action); static VariableSetStmt* process_set_global_trans_args(ListCell* lcell); #ifdef USE_BONJOUR static bool check_bonjour(bool* newval, void** extra, GucSource source); @@ -3160,6 +3162,30 @@ static void InitConfigureNamesString() check_client_encoding, assign_client_encoding, NULL}, + {{"character_set_connection", + PGC_USERSET, + NODE_ALL, + CLIENT_CONN_LOCALE, + gettext_noop("Set character_set_connection."), + NULL, + GUC_IS_NAME | GUC_REPORT}, + &u_sess->attr.attr_common.character_set_connection, + "", + check_charset_connection, + assign_charset_connection, + show_charset_connection}, + {{"collation_connection", + PGC_USERSET, + NODE_ALL, + CLIENT_CONN_LOCALE, + gettext_noop("Set collation_connection."), + NULL, + GUC_IS_NAME | GUC_REPORT}, + &u_sess->attr.attr_common.collation_connection, + "", + check_collation_connection, + assign_collation_connection, + show_collation_connection}, {{"safe_data_path", PGC_SIGHUP, NODE_ALL, @@ -8898,7 +8924,10 @@ void ExecSetVariableStmt(VariableSetStmt* stmt, ParamListInfo paramInfo) switch (stmt->kind) { case VAR_SET_VALUE: case VAR_SET_CURRENT: - + if (strcmp(stmt->name, "set_names") == 0) { + process_set_names_collate(stmt, action); + break; + } (void)set_config_option(stmt->name, ExtractSetVariableArgs(stmt), ((superuser() || (isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) ? @@ -9112,6 +9141,14 @@ void ExecSetVariableStmt(VariableSetStmt* stmt, ParamListInfo paramInfo) case VAR_SET_DEFAULT: case VAR_RESET: + if (strcmp(stmt->name, "set_names") == 0) { + GucContext context = (superuser() || (isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) ? + PGC_SUSET : PGC_USERSET; + (void)set_config_option("client_encoding", NULL, context, PGC_S_SESSION, action, true, 0); + (void)set_config_option("character_set_connection", NULL, context, PGC_S_SESSION, action, true, 0); + (void)set_config_option("collation_connection", NULL, context, PGC_S_SESSION, action, true, 0); + break; + } (void)set_config_option(stmt->name, NULL, ((superuser() || (isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION, action, true, 0); @@ -11561,6 +11598,32 @@ static VariableSetStmt* process_set_global_trans_args(ListCell* lcell) return vss; } +static void process_set_names_collate(VariableSetStmt* setstmt, GucAction action) +{ + ListCell* stmtarg = list_head(setstmt->args); + A_Const* item = (A_Const*)lfirst(stmtarg); + char* charset = strVal(&item->val); + char* collation = NULL; + int encoding = pg_char_to_encoding(charset); + if (!PG_VALID_ENCODING(encoding)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid encoding \"%s\" does not exist", charset))); + } + if ((stmtarg = lnext(stmtarg)) != NULL) { + item = (A_Const*)lfirst(stmtarg); + collation = strVal(&item->val); + (void)check_collation_by_charset(collation, encoding); + } else { + Oid collid = get_default_collation_by_charset(encoding); + collation = get_collation_name(collid); + } + GucContext context = (superuser() || (isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) ? + PGC_SUSET : PGC_USERSET; + (void)set_config_option("client_encoding", charset, context, PGC_S_SESSION, action, true, 0); + (void)set_config_option("character_set_connection", charset, context, PGC_S_SESSION, action, true, 0); + (void)set_config_option("collation_connection", collation, context, PGC_S_SESSION, action, true, 0); +} + static bool check_gpc_syscache_threshold(bool* newval, void** extra, GucSource source) { if (*newval) { diff --git a/src/common/backend/utils/misc/guc/guc_sql.cpp b/src/common/backend/utils/misc/guc/guc_sql.cpp index 08d27dd07..eea75db5a 100755 --- a/src/common/backend/utils/misc/guc/guc_sql.cpp +++ b/src/common/backend/utils/misc/guc/guc_sql.cpp @@ -347,7 +347,8 @@ static const struct b_format_behavior_compat_entry b_format_behavior_compat_opti {"enable_modify_column", B_FORMAT_OPT_ENABLE_MODIFY_COLUMN}, {"default_collation", B_FORMAT_OPT_DEFAULT_COLLATION}, {"fetch", B_FORMAT_OPT_FETCH}, - {"diagnostics", B_FORMAT_OPT_DIAGNOSTICS} + {"diagnostics", B_FORMAT_OPT_DIAGNOSTICS}, + {"enable_multi_charset", B_FORMAT_OPT_ENABLE_MULTI_CHARSET} }; typedef struct behavior_compat_entry { @@ -3382,7 +3383,8 @@ static bool b_format_forbid_distribute_parameter(const char *elem) "set_session_transaction", "enable_set_variables", "enable_modify_column", - "fetch" + "fetch", + "enable_multi_charset" }; for (int i = 0; i < B_FORMAT_FORBID_GUC_NUM; i++) { if (strcmp(forbidList[i], elem) == 0) { @@ -3397,6 +3399,10 @@ static bool b_format_forbid_distribute_parameter(const char *elem) */ static bool check_b_format_behavior_compat_options(char **newval, void **extra, GucSource source) { + if (strcasecmp(*newval, "ALL") == 0) { + return true; + } + char *rawstring = NULL; List *elemlist = NULL; ListCell *cell = NULL; @@ -3454,11 +3460,17 @@ static bool check_b_format_behavior_compat_options(char **newval, void **extra, */ static void assign_b_format_behavior_compat_options(const char *newval, void *extra) { + int start = 0; + int result = 0; + + if (strcasecmp(newval, "ALL") == 0) { + u_sess->utils_cxt.b_format_behavior_compat_flags = 0xFFFFFFFF; + return; + } + char *rawstring = NULL; List *elemlist = NULL; ListCell *cell = NULL; - int start = 0; - int result = 0; rawstring = pstrdup(newval); (void)SplitIdentifierString(rawstring, ',', &elemlist); diff --git a/src/common/interfaces/libpq/frontend_parser/gram.y b/src/common/interfaces/libpq/frontend_parser/gram.y index 59bd9dfac..ebe4ad7a7 100755 --- a/src/common/interfaces/libpq/frontend_parser/gram.y +++ b/src/common/interfaces/libpq/frontend_parser/gram.y @@ -495,7 +495,7 @@ extern THR_LOCAL bool stmt_contains_operator_plus; * DOT_DOT is unused in the core SQL grammar, and so will always provoke * parse errors. It is needed by PL/pgsql. */ -%token IDENT FCONST SCONST BCONST XCONST Op CmpOp COMMENTSTRING SET_USER_IDENT SET_IDENT +%token IDENT FCONST SCONST BCONST XCONST Op CmpOp COMMENTSTRING SET_USER_IDENT SET_IDENT UNDERSCORE_CHARSET %token ICONST PARAM %token TYPECAST ORA_JOINOP DOT_DOT COLON_EQUALS PARA_EQUALS SET_IDENT_SESSION SET_IDENT_GLOBAL diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index 866e537c7..fe3217956 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -425,7 +425,7 @@ static void processFunctionRecordOutParam(int varno, Oid funcoid, int* outparam) * Some of these are not directly referenced in this file, but they must be * here anyway. */ -%token IDENT FCONST SCONST BCONST VCONST XCONST Op CmpOp CmpNullOp COMMENTSTRING SET_USER_IDENT SET_IDENT +%token IDENT FCONST SCONST BCONST VCONST XCONST Op CmpOp CmpNullOp COMMENTSTRING SET_USER_IDENT SET_IDENT UNDERSCORE_CHARSET %token ICONST PARAM %token TYPECAST ORA_JOINOP DOT_DOT COLON_EQUALS PARA_EQUALS SET_IDENT_SESSION SET_IDENT_GLOBAL diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index 82a93bf7c..09c891a78 100644 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -37,6 +37,7 @@ #include "nodes/primnodes.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" +#include "parser/parse_type.h" #include "parser/scansup.h" #include "pgaudit.h" #include "pgstat.h" @@ -281,7 +282,10 @@ static List* invalid_depend_func_and_packgae(Oid pkgOid); static void ReportCompileConcurrentError(const char* objName, bool isPackage); static Datum CopyFcinfoArgValue(Oid typOid, Datum value, bool isNull); static bool InOutParaIsSup(char prokind, Oid funcOid); - +static bool plsql_convert_value_charset(PLpgSQL_execstate* estate, Datum *val, bool isnull, Oid val_type, + Oid val_collation, PLpgSQL_datum* target); +static bool plsql_convert_expr_value_charset(PLpgSQL_execstate* estate, Datum *val, bool isnull, Oid val_type, + PLpgSQL_expr* val_expr, PLpgSQL_datum* target); /* ---------- * plpgsql_check_line_validity Called by the debugger plugin for * validating a given linenumber @@ -3522,7 +3526,11 @@ static int expand_stmt_case(PLpgSQL_execstate* estate, PLpgSQL_stmt_case* stmt, } /* now we can assign to the variable */ - exec_assign_value(estate, (PLpgSQL_datum*)t_var, t_val, t_oid, &isnull, NULL, NULL); + if (plsql_convert_expr_value_charset(estate, &t_val, isnull, t_oid, stmt->t_expr, (PLpgSQL_datum*)t_var)) { + exec_assign_value(estate, (PLpgSQL_datum*)t_var, t_val, CSTRINGOID, &isnull, NULL, NULL); + } else { + exec_assign_value(estate, (PLpgSQL_datum*)t_var, t_val, t_oid, &isnull, NULL, NULL); + } exec_eval_cleanup(estate); } @@ -4655,7 +4663,11 @@ static int exec_stmt_case(PLpgSQL_execstate* estate, PLpgSQL_stmt_case* stmt, bo } /* now we can assign to the variable */ - exec_assign_value(estate, (PLpgSQL_datum*)t_var, t_val, t_oid, &isnull); + if (plsql_convert_expr_value_charset(estate, &t_val, isnull, t_oid, stmt->t_expr, (PLpgSQL_datum*)t_var)) { + exec_assign_value(estate, (PLpgSQL_datum*)t_var, t_val, CSTRINGOID, &isnull); + } else { + exec_assign_value(estate, (PLpgSQL_datum*)t_var, t_val, t_oid, &isnull); + } exec_eval_cleanup(estate); } @@ -8519,7 +8531,11 @@ void exec_assign_expr(PLpgSQL_execstate* estate, PLpgSQL_datum* target, PLpgSQL_ ExecCopyDataToDatum(estate->datums, target_dno, estate->cursor_return_data); } } - exec_assign_value(estate, target, value, valtype, &isnull, tableOfIndex, &TableOfIndexInfo); + if (plsql_convert_expr_value_charset(estate, &value, isnull, valtype, expr, target)) { + exec_assign_value(estate, target, value, CSTRINGOID, &isnull, tableOfIndex, &TableOfIndexInfo); + } else { + exec_assign_value(estate, target, value, valtype, &isnull, tableOfIndex, &TableOfIndexInfo); + } if (saved_cursor_data != estate->cursor_return_data) { pfree_ext(estate->cursor_return_data); estate->cursor_return_data = saved_cursor_data; @@ -12202,6 +12218,7 @@ static void exec_move_row(PLpgSQL_execstate* estate, Datum value; bool isnull = false; Oid valtype; + Oid val_collation; if (row->varnos[fnum] < 0) { continue; /* skip dropped column in row struct */ @@ -12228,6 +12245,7 @@ static void exec_move_row(PLpgSQL_execstate* estate, isnull = true; } valtype = SPI_gettypeid(tupdesc, anum + 1); + val_collation = SPI_getcollation(tupdesc, anum + 1); anum++; } else { value = (Datum)0; @@ -12238,6 +12256,7 @@ static void exec_move_row(PLpgSQL_execstate* estate, * about the type of a source NULL */ valtype = InvalidOid; + val_collation = InvalidOid; } /* accept function's return value for cursor */ @@ -12256,7 +12275,12 @@ static void exec_move_row(PLpgSQL_execstate* estate, } } } - exec_assign_value(estate, (PLpgSQL_datum*)var, value, valtype, &isnull, tableOfIndex); + + if (plsql_convert_value_charset(estate, &value, isnull, valtype, val_collation, (PLpgSQL_datum*)var)) { + exec_assign_value(estate, (PLpgSQL_datum*)var, value, CSTRINGOID, &isnull, tableOfIndex); + } else { + exec_assign_value(estate, (PLpgSQL_datum*)var, value, valtype, &isnull, tableOfIndex); + } } if (fromExecSql) { free_func_tableof_index(); @@ -12270,6 +12294,7 @@ static void exec_move_row(PLpgSQL_execstate* estate, Datum value; bool isnull = false; Oid valtype; + Oid val_collation; var = (PLpgSQL_var*)(row->intodatums[fnum]); @@ -12285,6 +12310,7 @@ static void exec_move_row(PLpgSQL_execstate* estate, isnull = true; } valtype = SPI_gettypeid(tupdesc, anum + 1); + val_collation = SPI_getcollation(tupdesc, anum + 1); anum++; } else { value = (Datum)0; @@ -12295,9 +12321,14 @@ static void exec_move_row(PLpgSQL_execstate* estate, * about the type of a source NULL */ valtype = InvalidOid; + val_collation = InvalidOid; } - exec_assign_value(estate, (PLpgSQL_datum*)var, value, valtype, &isnull); + if (plsql_convert_value_charset(estate, &value, isnull, valtype, val_collation, (PLpgSQL_datum*)var)) { + exec_assign_value(estate, (PLpgSQL_datum*)var, value, CSTRINGOID, &isnull); + } else { + exec_assign_value(estate, (PLpgSQL_datum*)var, value, valtype, &isnull); + } } } @@ -15051,4 +15082,68 @@ static void CheckAssignTarget(PLpgSQL_execstate* estate, int dno) { CheckAutoRefCursor(estate, dno); CheckNestedTableofVar(estate, dno); } + +static bool plsql_convert_value_charset_internal(PLpgSQL_execstate* estate, Datum *val, bool isnull, Oid val_type, + Oid val_collation, Oid target_collation) +{ + check_type_supports_multi_charset(val_type, false); + if (val_type != UNKNOWNOID && !OidIsValid(get_typcollation(val_type))) { + return false; + } + + int val_charset = get_valid_charset_by_collation(val_collation); + int target_charset = get_valid_charset_by_collation(target_collation); + if (target_charset == val_charset) { + return false; + } + + Datum value = *val; + Datum str_datum = exec_simple_cast_value(estate, value, val_type, CSTRINGOID, -1, false); + char* src_str = DatumGetCString(str_datum); + MemoryContext oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory); + char* dest_str = (char*)pg_do_encoding_conversion((unsigned char*)src_str, strlen(src_str), val_charset, target_charset); + MemoryContextSwitchTo(oldcontext); + + if (dest_str != src_str && str_datum != value) { + pfree_ext(src_str); + } + + *val = CStringGetDatum(dest_str); + return true; +} + +static bool plsql_convert_value_charset(PLpgSQL_execstate* estate, Datum *val, bool isnull, Oid val_type, + Oid val_collation, PLpgSQL_datum* target) +{ + if (!ENABLE_MODIFY_COLUMN || isnull || target->dtype != PLPGSQL_DTYPE_VAR) { + return false; + } + + PLpgSQL_var* target_var = (PLpgSQL_var*)target; + Oid target_collation = target_var->datatype->collation; + if (!OidIsValid(target_collation) || val_collation == target_collation) { + return false; + } + + return plsql_convert_value_charset_internal(estate, val, isnull, val_type, val_collation, target_collation); +} + +static bool plsql_convert_expr_value_charset(PLpgSQL_execstate* estate, Datum *val, bool isnull, Oid val_type, + PLpgSQL_expr* val_expr, PLpgSQL_datum* target) +{ + if (!ENABLE_MODIFY_COLUMN || isnull || target->dtype != PLPGSQL_DTYPE_VAR || + val_expr == NULL || val_expr->expr_simple_expr == NULL) { + return false; + } + + PLpgSQL_var* target_var = (PLpgSQL_var*)target; + Oid target_collation = target_var->datatype->collation; + Oid val_collation = exprCollation((Node*)val_expr->expr_simple_expr); + if (!OidIsValid(target_collation) || val_collation == target_collation) { + return false; + } + + return plsql_convert_value_charset_internal(estate, val, isnull, val_type, val_collation, target_collation); +} + #endif diff --git a/src/gausskernel/cbb/utils/partition/partitionmap.cpp b/src/gausskernel/cbb/utils/partition/partitionmap.cpp index 309e1d43e..df9ec6cb7 100755 --- a/src/gausskernel/cbb/utils/partition/partitionmap.cpp +++ b/src/gausskernel/cbb/utils/partition/partitionmap.cpp @@ -40,6 +40,7 @@ #include "parser/parse_node.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" +#include "parser/parse_collate.h" #include "utils/catcache.h" #include "utils/syscache.h" #include "utils/array.h" @@ -2788,11 +2789,13 @@ int constCompare_constType(Const* value1, Const* value2) eqExpr = (Expr*)makeSimpleA_Expr(AEXPR_OP, "=", (Node*)value1, (Node*)value2, -1); eqExpr = (Expr*)transformExpr(pstate, (Node*)eqExpr, EXPR_KIND_PARTITION_EXPRESSION); + assign_expr_collations(pstate, (Node*)eqExpr); gtExpr = (Expr*)makeSimpleA_Expr(AEXPR_OP, ">", (Node*)value1, (Node*)value2, -1); gtExpr = (Expr*)transformExpr(pstate, (Node*)gtExpr, EXPR_KIND_PARTITION_EXPRESSION); ((OpExpr*)gtExpr)->inputcollid = value1->constcollid; + assign_expr_collations(pstate, (Node*)gtExpr); estate = CreateExecutorState(); econtext = GetPerTupleExprContext(estate); diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index c0ee882d3..0b8376fa8 100755 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -746,6 +746,9 @@ void receive(TupleTableSlot *slot, DestReceiver *self) if (result->isnulls == NULL) { result->isnulls = (bool *)pg_malloc(natts * sizeof(bool)); } + if (result->collids == NULL) { + result->collids = (Oid *)pg_malloc(natts * sizeof(Oid)); + } if (result->atttypids == NULL) { result->atttypids = (Oid *)pg_malloc(natts * sizeof(Oid)); } @@ -756,6 +759,7 @@ void receive(TupleTableSlot *slot, DestReceiver *self) origattr = tableam_tslot_getattr(slot, i + 1, &isnull); if (isnull) { result->isnulls[i] = true; + result->collids[i] = typeinfo->attrs[i].attcollation; continue; } @@ -771,6 +775,7 @@ void receive(TupleTableSlot *slot, DestReceiver *self) value = OidOutputFunctionCall(typoutput, attr); values = lappend(values, value); result->atttypids[i] = typeinfo->attrs[i].atttypid; + result->collids[i] = typeinfo->attrs[i].attcollation; /* Clean up detoasted copy, if any */ if (DatumGetPointer(attr) != DatumGetPointer(origattr)) { @@ -803,6 +808,7 @@ void destroy(DestReceiver *self) list_free(tuples); pfree_ext(result->isnulls); + pfree_ext(result->collids); pfree_ext(result->atttypids); pfree_ext(self); } diff --git a/src/gausskernel/optimizer/commands/copy.cpp b/src/gausskernel/optimizer/commands/copy.cpp index aeb1fe572..7f13439da 100644 --- a/src/gausskernel/optimizer/commands/copy.cpp +++ b/src/gausskernel/optimizer/commands/copy.cpp @@ -269,8 +269,9 @@ static void bulkload_set_readattrs_func(CopyState cstate); static void bulkload_init_time_format(CopyState cstate); static Datum CopyReadBinaryAttribute( CopyState cstate, int column_no, FmgrInfo* flinfo, Oid typioparam, int32 typmod, bool* isnull); -static void CopyAttributeOutText(CopyState cstate, char* string); -static void CopyAttributeOutCSV(CopyState cstate, char* string, bool use_quote, bool single_attr); +static void CopyAttributeOutText(CopyState cstate, char* string, int str_encoding, FmgrInfo *convert_finfo); +static void CopyAttributeOutCSV( + CopyState cstate, char* string, bool use_quote, bool single_attr, int str_encoding, FmgrInfo *convert_finfo); static void SelectAttributeIntoOutfile(CopyState cstate, char* string, bool is_optionally, Oid fn_oid); static void ProcessEnclosedChar(CopyState cstate, char* cur_char, char enclosedc, char escapedc); static void CopyNonEncodingAttributeOut(CopyState cstate, char* string, bool use_quote); @@ -1283,7 +1284,7 @@ static void PrintDelimHeader(CopyState cstate) CopySendString(cstate, cstate->delim); hdr_delim = true; colname = NameStr(attr[attnum - 1].attname); - CopyAttributeOutCSV(cstate, colname, false, list_length(cstate->attnumlist) == 1); + CopyAttributeOutCSV(cstate, colname, false, list_length(cstate->attnumlist) == 1, GetDatabaseEncoding(), NULL); } } @@ -3091,6 +3092,8 @@ static uint64 CopyTo(CopyState cstate, bool isFirst, bool isLast) } /* Get info about the columns we need to process. */ cstate->out_functions = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + cstate->out_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + cstate->attr_encodings = (int*)palloc(num_phys_attrs * sizeof(int)); foreach (cur, cstate->attnumlist) { int attnum = lfirst_int(cur); Oid out_func_oid; @@ -3101,6 +3104,13 @@ static uint64 CopyTo(CopyState cstate, bool isFirst, bool isLast) else getTypeOutputInfo(attr[attnum - 1].atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); + /* set conversion functions */ + cstate->attr_encodings[attnum - 1] = get_valid_charset_by_collation(attr[attnum - 1].attcollation); + construct_conversion_fmgr_info(cstate->attr_encodings[attnum - 1], cstate->file_encoding, + (void*)&cstate->out_convert_funcs[attnum - 1]); + if (cstate->attr_encodings[attnum - 1] != cstate->file_encoding) { + cstate->need_transcoding = true; + } } /* @@ -3411,10 +3421,13 @@ void CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum* values, const bool* nul CopyAttributeOutCSV(cstate, string, use_quote, - list_length(cstate->attnumlist) == 1); + list_length(cstate->attnumlist) == 1, + cstate->attr_encodings[attnum - 1], + &cstate->out_convert_funcs[attnum - 1]); break; case FORMAT_TEXT: - CopyAttributeOutText(cstate, string); + CopyAttributeOutText(cstate, string, cstate->attr_encodings[attnum - 1], + &cstate->out_convert_funcs[attnum - 1]); break; default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Invalid file format"))); @@ -5748,6 +5761,8 @@ CopyState BeginCopyFrom(Relation rel, const char* filename, List* attnamelist, MemoryContext oldcontext; AdaptMem* memUsage = (AdaptMem*)mem_info; bool volatile_defexprs = false; + int* attr_encodings = NULL; + FmgrInfo* in_convert_funcs = NULL; cstate = BeginCopy(true, rel, NULL, queryString, attnamelist, options); oldcontext = MemoryContextSwitchTo(cstate->copycontext); @@ -5772,10 +5787,12 @@ CopyState BeginCopyFrom(Relation rel, const char* filename, List* attnamelist, * input function we use depends on text/binary format choice.) */ in_functions = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + in_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); typioparams = (Oid*)palloc(num_phys_attrs * sizeof(Oid)); accept_empty_str = (bool*)palloc(num_phys_attrs * sizeof(bool)); defmap = (int*)palloc(num_phys_attrs * sizeof(int)); defexprs = (ExprState**)palloc(num_phys_attrs * sizeof(ExprState*)); + attr_encodings = (int*)palloc(num_phys_attrs * sizeof(int)); if (cstate->trans_expr_list != NULL) { cstate->as_typemods = (AssignTypmod *)palloc0(num_phys_attrs * sizeof(AssignTypmod)); cstate->transexprs = (ExprState **)palloc0(num_phys_attrs * sizeof(ExprState*)); @@ -5796,7 +5813,7 @@ CopyState BeginCopyFrom(Relation rel, const char* filename, List* attnamelist, /* Output functions are required to convert default values to output form */ cstate->out_functions = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); - + cstate->out_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); for (attnum = 1; attnum <= num_phys_attrs; attnum++) { /* We don't need info for dropped attributes */ if (attr[attnum - 1].attisdropped) @@ -5809,6 +5826,9 @@ CopyState BeginCopyFrom(Relation rel, const char* filename, List* attnamelist, else getTypeInputInfo(attr[attnum - 1].atttypid, &in_func_oid, &typioparams[attnum - 1]); fmgr_info(in_func_oid, &in_functions[attnum - 1]); + attr_encodings[attnum - 1] = get_valid_charset_by_collation(attr[attnum - 1].attcollation); + construct_conversion_fmgr_info( + GetDatabaseEncoding(), attr_encodings[attnum - 1], (void*)&in_convert_funcs[attnum - 1]); /* Get default info if needed */ if (!list_member_int(cstate->attnumlist, attnum) && !ISGENERATEDCOL(tupDesc, attnum - 1)) { @@ -5843,6 +5863,11 @@ CopyState BeginCopyFrom(Relation rel, const char* filename, List* attnamelist, else getTypeOutputInfo(attr[attnum - 1].atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); + construct_conversion_fmgr_info(attr_encodings[attnum - 1], cstate->file_encoding, + (void*)&cstate->out_convert_funcs[attnum - 1]); + if (attr_encodings[attnum - 1] != cstate->file_encoding) { + cstate->need_transcoding = true; + } } } else { #endif /* PGXC */ @@ -5872,6 +5897,8 @@ CopyState BeginCopyFrom(Relation rel, const char* filename, List* attnamelist, cstate->defexprs = defexprs; cstate->volatile_defexprs = volatile_defexprs; cstate->num_defaults = num_defaults; + cstate->attr_encodings = attr_encodings; + cstate->in_convert_funcs = in_convert_funcs; if (func) { cstate->copyGetDataFunc = func; @@ -6159,13 +6186,16 @@ extern void SPI_pop_conditional(bool pushed); * @in typmod: some datatype mode * @return: the datatype value outputed from built-in datatype input function */ -Datum InputFunctionCallForBulkload(CopyState cstate, FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod) +Datum InputFunctionCallForBulkload(CopyState cstate, FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, + int encoding, FmgrInfo* convert_finfo) { FunctionCallInfoData fcinfo; Datum result; bool pushed = false; short nargs = 3; char* date_time_fmt = NULL; + char* converted_str = NULL; + int db_encoding = GetDatabaseEncoding(); if (str == NULL && flinfo->fn_strict) return (Datum)0; /* just return null result */ @@ -6206,12 +6236,17 @@ Datum InputFunctionCallForBulkload(CopyState cstate, FmgrInfo* flinfo, char* str } InitFunctionCallInfoData(fcinfo, flinfo, nargs, InvalidOid, NULL, NULL); + if (str != NULL && db_encoding != encoding) { + converted_str = try_fast_encoding_conversion(str, strlen(str), db_encoding, encoding, (void*)convert_finfo); + } else { + converted_str = str; + } - fcinfo.arg[0] = CStringGetDatum(str); + fcinfo.arg[0] = CStringGetDatum(converted_str); fcinfo.arg[1] = ObjectIdGetDatum(typioparam); fcinfo.arg[2] = Int32GetDatum(typmod); - fcinfo.argnull[0] = (str == NULL); + fcinfo.argnull[0] = (converted_str == NULL); fcinfo.argnull[1] = false; fcinfo.argnull[2] = false; @@ -6223,8 +6258,17 @@ Datum InputFunctionCallForBulkload(CopyState cstate, FmgrInfo* flinfo, char* str fcinfo.argnull[3] = false; } - result = FunctionCallInvoke(&fcinfo); + if (encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(encoding); + result = FunctionCallInvoke(&fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + result = FunctionCallInvoke(&fcinfo); + } + if (converted_str != str) { + pfree_ext(converted_str); + } /* Should get null result if and only if str is NULL */ if (str == NULL) { if (!fcinfo.isnull) @@ -6419,8 +6463,8 @@ bool NextCopyFrom(CopyState cstate, ExprContext* econtext, Datum* values, bool* cstate->cur_attname = NameStr(attr[m].attname); cstate->cur_attval = string; atttypmod = (asTypemods != NULL && asTypemods[m].assign) ? asTypemods[m].typemod : attr[m].atttypmod; - values[m] = - InputFunctionCallForBulkload(cstate, &in_functions[m], string, typioparams[m], atttypmod); + values[m] = InputFunctionCallForBulkload(cstate, &in_functions[m], string, typioparams[m], atttypmod, + cstate->attr_encodings[m], &cstate->in_convert_funcs[m]); if (string != NULL) nulls[m] = false; cstate->cur_attname = NULL; @@ -6660,9 +6704,12 @@ static void append_defvals(Datum* values, CopyState cstate) CopyAttributeOutCSV(&new_cstate, string, false /* don't force quote */, - false /* there's at least one user-supplied attribute */); + false /* there's at least one user-supplied attribute */, + cstate->attr_encodings[attindex], + &cstate->out_convert_funcs[attindex]); else - CopyAttributeOutText(&new_cstate, string); + CopyAttributeOutText(&new_cstate, string, cstate->attr_encodings[attindex], + &cstate->out_convert_funcs[attindex]); CopySendString(&new_cstate, new_cstate.delim); } } @@ -7928,7 +7975,7 @@ static Datum CopyReadBinaryAttribute( } while (0) template -static void CopyAttributeOutTextT(CopyState cstate, char* string) +static void CopyAttributeOutTextT(CopyState cstate, char* string, int str_encoding, FmgrInfo *convert_finfo) { char* ptr = NULL; char* start = NULL; @@ -7938,7 +7985,12 @@ static void CopyAttributeOutTextT(CopyState cstate, char* string) int delimLen = cstate->delim_len; if (cstate->need_transcoding) - ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding); + if (str_encoding == GetDatabaseEncoding()) { + ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding, (void*)convert_finfo); + } else { + ptr = try_fast_encoding_conversion( + string, strlen(string), str_encoding, cstate->file_encoding, (void*)convert_finfo); + } else ptr = string; @@ -8083,19 +8135,20 @@ static void CopyAttributeOutTextT(CopyState cstate, char* string) DUMPSOFAR(); } -static void CopyAttributeOutText(CopyState cstate, char* string) +static void CopyAttributeOutText(CopyState cstate, char* string, int str_encoding, FmgrInfo *convert_finfo) { switch (cstate->delim_len) { case 1: - CopyAttributeOutTextT(cstate, string); + CopyAttributeOutTextT(cstate, string, str_encoding, convert_finfo); break; default: - CopyAttributeOutTextT(cstate, string); + CopyAttributeOutTextT(cstate, string, str_encoding, convert_finfo); } } template -static void CopyAttributeOutCSVT(CopyState cstate, char* string, bool use_quote, bool single_attr) +static void CopyAttributeOutCSVT(CopyState cstate, char* string, bool use_quote, bool single_attr, + int str_encoding, FmgrInfo *convert_finfo) { char* ptr = NULL; char* start = NULL; @@ -8110,7 +8163,12 @@ static void CopyAttributeOutCSVT(CopyState cstate, char* string, bool use_quote, use_quote = true; if (cstate->need_transcoding) - ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding); + if (str_encoding == GetDatabaseEncoding()) { + ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding, (void*)convert_finfo); + } else { + ptr = try_fast_encoding_conversion( + string, strlen(string), str_encoding, cstate->file_encoding, (void*)convert_finfo); + } else ptr = string; @@ -8172,14 +8230,15 @@ static void CopyAttributeOutCSVT(CopyState cstate, char* string, bool use_quote, * Send text representation of one attribute, with conversion and * CSV-style escaping */ -static void CopyAttributeOutCSV(CopyState cstate, char* string, bool use_quote, bool single_attr) +static void CopyAttributeOutCSV(CopyState cstate, char* string, bool use_quote, bool single_attr, + int str_encoding, FmgrInfo *convert_finfo) { switch (cstate->delim_len) { case 1: - CopyAttributeOutCSVT(cstate, string, use_quote, single_attr); + CopyAttributeOutCSVT(cstate, string, use_quote, single_attr, str_encoding, convert_finfo); break; default: - CopyAttributeOutCSVT(cstate, string, use_quote, single_attr); + CopyAttributeOutCSVT(cstate, string, use_quote, single_attr, str_encoding, convert_finfo); } } @@ -9596,6 +9655,8 @@ CopyState beginExport( } /* Get info about the columns we need to process. */ cstate->out_functions = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + cstate->out_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + cstate->attr_encodings = (int*)palloc(num_phys_attrs * sizeof(int)); ListCell* cur = NULL; foreach (cur, cstate->attnumlist) { int attnum = lfirst_int(cur); @@ -9607,6 +9668,12 @@ CopyState beginExport( else getTypeOutputInfo(attr[attnum - 1].atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); + cstate->attr_encodings[attnum - 1] = get_valid_charset_by_collation(attr[attnum - 1].attcollation); + construct_conversion_fmgr_info(cstate->attr_encodings[attnum - 1], cstate->file_encoding, + (void*)&cstate->out_convert_funcs[attnum - 1]); + if (cstate->attr_encodings[attnum - 1] != cstate->file_encoding) { + cstate->need_transcoding = true; + } } /* diff --git a/src/gausskernel/optimizer/commands/formatter.cpp b/src/gausskernel/optimizer/commands/formatter.cpp index a6c812eec..d166262a6 100644 --- a/src/gausskernel/optimizer/commands/formatter.cpp +++ b/src/gausskernel/optimizer/commands/formatter.cpp @@ -246,14 +246,20 @@ static void MbCutString(int encoding, char* str, int limitLen) } template -static void AttributeOutFixed(CopyState cstate, char* string, FieldDesc* desc) +static void AttributeOutFixed(CopyState cstate, char* string, FieldDesc* desc, + int str_encoding, FmgrInfo *convert_finfo) { char* ptr = NULL; int len; StringInfo outbuf = cstate->fe_msgbuf; if (cstate->need_transcoding) - ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding); + if (str_encoding == GetDatabaseEncoding()) { + ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding, (void*)convert_finfo); + } else { + ptr = try_fast_encoding_conversion( + string, strlen(string), str_encoding, cstate->file_encoding, (void*)convert_finfo); + } else ptr = string; @@ -325,11 +331,12 @@ void FixedRowOut(CopyState cstate, Datum* values, const bool* nulls) bool isnull = nulls[attnum - 1]; if (isnull) { - AttributeOutFixed(cstate, descs[i].nullString, descs + i); + AttributeOutFixed(cstate, descs[i].nullString, descs + i, GetDatabaseEncoding(), NULL); } else { string = OutputFunctionCall(&out_functions[attnum - 1], value); Assert(string != NULL); - AttributeOutFixed(cstate, string, descs + i); + AttributeOutFixed(cstate, string, descs + i, + cstate->attr_encodings[attnum - 1], &cstate->out_convert_funcs[attnum - 1]); } } } @@ -353,7 +360,7 @@ void PrintFixedHeader(CopyState cstate) int attnum = formatter->fieldDesc[i].attnum; colname = pstrdup(NameStr(attr[attnum - 1].attname)); - AttributeOutFixed(cstate, colname, descs + i); + AttributeOutFixed(cstate, colname, descs + i, GetDatabaseEncoding(), NULL); pfree_ext(colname); } } diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index a4f42e9d5..67e08d521 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -174,7 +174,7 @@ #include "fmgr.h" #include "pgstat.h" #include "postmaster/rbcleaner.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" #ifdef ENABLE_MULTIPLE_NODES #include "tsdb/utils/ts_relcache.h" #include "tsdb/common/ts_tablecmds.h" @@ -779,6 +779,7 @@ static void ATAlterCheckModifiyColumnRepeatedly(const AlterTableCmd* cmd, const static int128 EvaluateAutoIncrement(Relation rel, TupleDesc desc, AttrNumber attnum, Datum* value, bool* is_null); static void SetRelAutoIncrement(Relation rel, TupleDesc desc, int128 autoinc); static Node* RecookAutoincAttrDefault(Relation rel, int attrno, Oid targettype, int targettypmod); +static void check_unsupported_charset_for_column(Oid collation, const char* col_name); inline static bool CStoreSupportATCmd(AlterTableType cmdtype) { @@ -1924,6 +1925,15 @@ static void CheckPartitionKeyForCreateTable(PartitionState *partTableState, List else if (partTableState->partitionStrategy == PART_STRATEGY_LIST) CompareListValue(pos, descriptor->attrs, partTableState->partitionList, partkeyIsFunc); + /* charset of partkey columns cannot be different from server_encoding */ + if (DB_IS_CMPT(B_FORMAT)) { + foreach_cell (cell, pos) { + int attidx = lfirst_int(cell); + check_unsupported_charset_for_column( + descriptor->attrs[attidx].attcollation, NameStr(descriptor->attrs[attidx].attname)); + } + } + list_free_ext(pos); } @@ -2616,6 +2626,15 @@ ObjectAddress DefineRelation(CreateStmt* stmt, char relkind, Oid ownerId, Object ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("must have at least one column"))); } + /* check column charset */ + if (DB_IS_CMPT(B_FORMAT) && + (0 == pg_strcasecmp(storeChar, ORIENTATION_COLUMN) || 0 == pg_strcasecmp(storeChar, ORIENTATION_TIMESERIES))) { + for (int attidx = 0; attidx < descriptor->natts; attidx++) { + check_unsupported_charset_for_column( + descriptor->attrs[attidx].attcollation, NameStr(descriptor->attrs[attidx].attname)); + } + } + if (stmt->partTableState) { CheckPartitionKeyForCreateTable(stmt->partTableState, schema, descriptor); if (stmt->partTableState->subPartitionState != NULL) { @@ -8641,7 +8660,7 @@ static void sqlcmd_alter_prep_convert_charset(AlteredTableInfo* tab, Relation re format_type_be(targettypid)))); } - transform = coerce_to_target_charset(transform, cc->charset, targettypid); + transform = coerce_to_target_charset(transform, cc->charset, targettypid, attTup->atttypmod, targetcollid); exprSetCollation(transform, targetcollid); @@ -11987,6 +12006,9 @@ static ObjectAddress ATExecAddColumn(List** wqueue, AlteredTableInfo* tab, Relat collOid = GetColumnDefCollation(NULL, colDef, typeOid, rel_coll_oid); if (DB_IS_CMPT(B_FORMAT)) { typeOid = binary_need_transform_typeid(typeOid, &collOid); + if (RelationIsColStore(rel) || RelationIsTsStore(rel)) { + check_unsupported_charset_for_column(collOid, colDef->colname); + } } aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE); @@ -15604,7 +15626,7 @@ static void ATPrepAlterColumnType(List** wqueue, AlteredTableInfo* tab, Relation "column \"%s\" cannot be cast automatically to type %s", colName, format_type_be(targettype)), errhint("Specify a USING expression to perform the conversion."))); #ifndef ENABLE_MULTIPLE_NODES - transform = coerce_to_target_charset(transform, target_charset, attTup->atttypid); + transform = coerce_to_target_charset(transform, target_charset, attTup->atttypid, attTup->atttypmod, targetcollid); #endif /* Fix collations after all else */ assign_expr_collations(pstate, transform); @@ -16247,6 +16269,9 @@ static ObjectAddress ATExecAlterColumnType(AlteredTableInfo* tab, Relation rel, targetcollid = GetColumnDefCollation(NULL, def, targettype, rel_coll_oid); if (DB_IS_CMPT(B_FORMAT)) { targettype = binary_need_transform_typeid(targettype, &targetcollid); + if (RelationIsColStore(rel) || RelationIsTsStore(rel)) { + check_unsupported_charset_for_column(targetcollid, colName); + } } if (attnum == RelAutoIncAttrNum(rel)) { CheckAutoIncrementDatatype(targettype, colName); @@ -16592,8 +16617,8 @@ static ObjectAddress ATExecAlterColumnType(AlteredTableInfo* tab, Relation rel, RangeTblEntry* rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true); addRTEtoQuery(pstate, rte, true, true, true); pstate->p_rawdefaultlist = NULL; - update_expr = cookDefault(pstate, update_expr, attTup->atttypid, attTup->atttypmod, NameStr(attTup->attname), - def->generatedCol); + update_expr = cookDefault(pstate, update_expr, attTup->atttypid, attTup->atttypmod, + attTup->attcollation, NameStr(attTup->attname), def->generatedCol); } StoreAttrDefault(rel, attnum, defaultexpr, generatedCol, update_expr); @@ -31739,7 +31764,7 @@ static Node* RebuildGeneratedColumnExpr(Relation rel, AttrNumber gen_attnum) { ParseState* pstate = NULL; RangeTblEntry *rte = NULL; - FormData_pg_attribute pgattr = rel->rd_att->attrs[gen_attnum - 1]; + Form_pg_attribute pgattr = &rel->rd_att->attrs[gen_attnum - 1]; Node* gen_expr = build_column_default(rel, gen_attnum); Assert(gen_expr); @@ -31749,8 +31774,8 @@ static Node* RebuildGeneratedColumnExpr(Relation rel, AttrNumber gen_attnum) pstate = make_parsestate(NULL); rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true); addRTEtoQuery(pstate, rte, false, true, true); - gen_expr = cookDefault( - pstate, gen_expr, pgattr.atttypid, pgattr.atttypmod, NameStr(pgattr.attname), ATTRIBUTE_GENERATED_STORED); + gen_expr = cookDefault(pstate, gen_expr, pgattr->atttypid, pgattr->atttypmod, pgattr->attcollation, + NameStr(pgattr->attname), ATTRIBUTE_GENERATED_STORED); /* readd pg_attrdef */ RemoveAttrDefault(RelationGetRelid(rel), gen_attnum, DROP_RESTRICT, true, true); StoreAttrDefault(rel, gen_attnum, gen_expr, ATTRIBUTE_GENERATED_STORED, NULL, true); @@ -32511,3 +32536,17 @@ void RebuildDependViewForProc(Oid proc_oid) } list_free_ext(oid_list); } + +static void check_unsupported_charset_for_column(Oid collation, const char* col_name) +{ + if (!OidIsValid(collation)) { + return; + } + + int attcharset = get_valid_charset_by_collation(collation); + if (attcharset != PG_SQL_ASCII && attcharset != GetDatabaseEncoding()) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("difference between the charset of column %s and the database encoding has not supported", + col_name))); + } +} diff --git a/src/gausskernel/optimizer/commands/typecmds.cpp b/src/gausskernel/optimizer/commands/typecmds.cpp index 59aa3a891..c562d2a11 100644 --- a/src/gausskernel/optimizer/commands/typecmds.cpp +++ b/src/gausskernel/optimizer/commands/typecmds.cpp @@ -878,7 +878,8 @@ ObjectAddress DefineDomain(CreateDomainStmt* stmt) * Cook the constr->raw_expr into an expression. Note: * name is strictly for error message */ - defaultExpr = cookDefault(pstate, constr->raw_expr, basetypeoid, basetypeMod, domainName, 0); + defaultExpr = cookDefault(pstate, constr->raw_expr, basetypeoid, basetypeMod, + baseType->typcollation, domainName, 0); /* * If the expression is just a NULL constant, we treat it @@ -1318,11 +1319,11 @@ ObjectAddress DefineSet(CreateSetStmt *stmt) -1, /* typMod (Domains only) */ 0, /* Array dimensions of typbasetype */ false, /* Type NOT NULL */ - InvalidOid); /* type's collation */ + 100); /* type's collation */ /* Enter the set's values into pg_set */ setTypeOid=address.objectId; - SetValuesCreate(setTypeOid, stmt->typname->typmods); + SetValuesCreate(setTypeOid, stmt->typname->typmods, stmt->set_collation); stmt->typname->typeOid = setTypeOid; stmt->typname->typmods = NIL; return address; @@ -2278,8 +2279,8 @@ ObjectAddress AlterDomainDefault(List* names, Node* defaultRaw) * Cook the colDef->raw_expr into an expression. Note: Name is * strictly for error message */ - defaultExpr = - cookDefault(pstate, defaultRaw, typTup->typbasetype, typTup->typtypmod, NameStr(typTup->typname), 0); + defaultExpr = cookDefault(pstate, defaultRaw, typTup->typbasetype, typTup->typtypmod, + typTup->typcollation, NameStr(typTup->typname), 0); /* * If the expression is just a NULL constant, we treat the command * like ALTER ... DROP DEFAULT. (But see note for same test in diff --git a/src/gausskernel/optimizer/commands/variable.cpp b/src/gausskernel/optimizer/commands/variable.cpp index e622da2c3..a2a19503c 100644 --- a/src/gausskernel/optimizer/commands/variable.cpp +++ b/src/gausskernel/optimizer/commands/variable.cpp @@ -26,10 +26,12 @@ #include "miscadmin.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" #include "utils/snapmgr.h" #include "utils/timestamp.h" #include "mb/pg_wchar.h" +#include "parser/parse_utilcmd.h" /* * DATESTYLE */ @@ -824,6 +826,79 @@ bool check_client_encoding(char** newval, void** extra, GucSource source) return true; } +bool check_charset_connection(char** newval, void** extra, GucSource source) +{ + if (strcmp(*newval, "") == 0) { + return true; + } + + int charset = pg_valid_client_encoding(*newval); + if (!PG_VALID_ENCODING(charset)) { + return false; + } + /* Get the canonical name (no aliases, uniform case) */ + const char* canonical_name = pg_encoding_to_char(charset); + + if (strcmp(*newval, canonical_name) != 0 && strcmp(*newval, "UNICODE") != 0) { + pfree(*newval); + *newval = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER), canonical_name); + if (!*newval) { + return false; + } + } + + /* + * Save the charset's ID in *extra, for use by assign_charset_connection. + */ + *extra = MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER), sizeof(int)); + if (!*extra) { + return false; + } + *((int*)*extra) = charset; + + return true; +} + +bool check_collation_connection(char** newval, void** extra, GucSource source) +{ + if (strcmp(*newval, "") == 0) { + return true; + } + + if (!u_sess->mb_cxt.backend_startup_complete) { + *extra = (void*)MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER), *newval); + if (!*extra) { + return false; + } + return true; + } + + Oid collid = get_collation_oid_with_lower_name(*newval, PG_INVALID_ENCODING); + if (!OidIsValid(collid)) { + return false; + } + + char* coll_name = get_collation_name(collid); + if (strcmp(*newval, coll_name) != 0) { + pfree(*newval); + *newval = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER), coll_name); + if (!*newval) { + pfree_ext(coll_name); + return false; + } + } + /* + * Save the collate's ID in *extra, for use by assign_collation_connection. + */ + *extra = (void*)MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER), coll_name); + if (!*extra) { + pfree_ext(coll_name); + return false; + } + pfree_ext(coll_name); + return true; +} + void assign_client_encoding(const char* newval, void* extra) { if (extra == NULL) { @@ -836,6 +911,48 @@ void assign_client_encoding(const char* newval, void* extra) elog(LOG, "SetClientEncoding(%d) failed", encoding); } +void assign_charset_connection(const char* newval, void* extra) +{ + if (extra == NULL) { + return; + } + + if (!u_sess->mb_cxt.backend_startup_complete) { + return; + } + + if (!ENABLE_MULTI_CHARSET) { + ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED), + errmsg("character_set_connection can be changed when b_format_behavior_compat_options contains enable_multi_charset option"))); + } + int charset = *((int*)extra); + u_sess->mb_cxt.character_set_connection = &pg_enc2name_tbl[charset]; + + Oid collid = get_default_collation_by_charset(charset); + u_sess->mb_cxt.collation_connection = collid; +} + +void assign_collation_connection(const char* newval, void* extra) +{ + if (extra == NULL) { + return; + } + + if (!u_sess->mb_cxt.backend_startup_complete) { + return; + } + + if (!ENABLE_MULTI_CHARSET) { + ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED), + errmsg("collation_connection can be changed when b_format_behavior_compat_options contains enable_multi_charset option"))); + } + Oid collid = get_collation_oid_with_lower_name((char*)extra, PG_INVALID_ENCODING); + u_sess->mb_cxt.collation_connection = collid; + + int charset = get_charset_by_collation(collid); + u_sess->mb_cxt.character_set_connection = &pg_enc2name_tbl[charset]; +} + /* * SET SESSION AUTHORIZATION */ @@ -1019,3 +1136,23 @@ const char* show_role(void) return u_sess->attr.attr_common.role_string ? u_sess->attr.attr_common.role_string : "none"; } +const char* show_charset_connection(void) +{ + return GetCharsetConnectionName(); +} + +const char* show_collation_connection(void) +{ + Oid collid = GetCollationConnection(); + if (OidIsValid(collid)) { + HeapTuple tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); + if (HeapTupleIsValid(tp)) { + Form_pg_collation colltup = (Form_pg_collation)GETSTRUCT(tp); + char* result = MemoryContextStrdup( + SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), NameStr(colltup->collname)); + ReleaseSysCache(tp); + return result; + } + } + return ""; +} \ No newline at end of file diff --git a/src/gausskernel/optimizer/path/indxpath.cpp b/src/gausskernel/optimizer/path/indxpath.cpp index d20089d3b..11a11de5a 100755 --- a/src/gausskernel/optimizer/path/indxpath.cpp +++ b/src/gausskernel/optimizer/path/indxpath.cpp @@ -149,6 +149,8 @@ static List* expand_indexqual_opclause(IndexOptInfo* index, RestrictInfo* rinfo, static RestrictInfo* expand_indexqual_rowcompare(RestrictInfo* rinfo, IndexOptInfo* index, int indexcol); static List* prefix_quals(Node* leftop, Oid opfamily, Oid collation, Const* prefix, Pattern_Prefix_Status pstatus, int prefixkey_len); +static List* prefix_quals_with_encdoing(Node* leftop, Oid opfamily, Oid collation, Const* prefix, + Pattern_Prefix_Status pstatus, int prefixkey_len); static List* network_prefix_quals(Node* leftop, Oid expr_op, Oid opfamily, Datum rightop); static Datum string_to_datum(const char* str, Oid datatype); static Const* string_to_const(const char* str, Oid datatype); @@ -3558,7 +3560,7 @@ static List* expand_indexqual_opclause(IndexOptInfo* index, RestrictInfo* rinfo, case OID_BYTEA_LIKE_OP: if (!op_in_opfamily(expr_op, opfamily)) { pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll, &prefix, NULL); - return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); + return prefix_quals_with_encdoing(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); } break; @@ -3568,7 +3570,7 @@ static List* expand_indexqual_opclause(IndexOptInfo* index, RestrictInfo* rinfo, if (!op_in_opfamily(expr_op, opfamily)) { /* the right-hand const is type text for all of these */ pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, expr_coll, &prefix, NULL); - return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); + return prefix_quals_with_encdoing(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); } break; @@ -3578,7 +3580,7 @@ static List* expand_indexqual_opclause(IndexOptInfo* index, RestrictInfo* rinfo, if (!op_in_opfamily(expr_op, opfamily)) { /* the right-hand const is type text for all of these */ pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex, expr_coll, &prefix, NULL); - return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); + return prefix_quals_with_encdoing(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); } break; @@ -3588,7 +3590,7 @@ static List* expand_indexqual_opclause(IndexOptInfo* index, RestrictInfo* rinfo, if (!op_in_opfamily(expr_op, opfamily)) { /* the right-hand const is type text for all of these */ pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, expr_coll, &prefix, NULL); - return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); + return prefix_quals_with_encdoing(leftop, opfamily, idxcollation, prefix, pstatus, prefixkey_len); } break; @@ -4008,6 +4010,23 @@ static List* prefix_quals(Node* leftop, Oid opfamily, Oid collation, Const* pref return result; } +static List* prefix_quals_with_encdoing(Node* leftop, Oid opfamily, Oid collation, Const* prefix_const, + Pattern_Prefix_Status pstatus, int prefixkey_len) +{ + List* result = NULL; + int tmp_encoding = get_valid_charset_by_collation(prefix_const->constcollid); + int db_encoding = GetDatabaseEncoding(); + + if (tmp_encoding == db_encoding) { + return prefix_quals(leftop, opfamily, collation, prefix_const, pstatus, prefixkey_len); + } + + DB_ENCODING_SWITCH_TO(tmp_encoding); + result = prefix_quals(leftop, opfamily, collation, prefix_const, pstatus, prefixkey_len); + DB_ENCODING_SWITCH_BACK(db_encoding); + return result; +} + /* * Given a leftop and a rightop, and a inet-family sup/sub operator, * generate suitable indexqual condition(s). expr_op is the original @@ -4231,10 +4250,11 @@ static Const* prefix_const_node(Const* con, int prefix_len, Oid datatype) return makeConst(datatype, -1, con->constcollid, con->constlen, prefix_value, false, false); } } else { + int charset = get_valid_charset_by_collation(con->constcollid); /* length of characters */ - prefix_const_len = text_length(con->constvalue); + prefix_const_len = text_length_with_encoding(con->constvalue, charset); if (prefix_len < prefix_const_len) { - prefix_value = PointerGetDatum(text_substring(con->constvalue, 1, prefix_len, false)); + prefix_value = PointerGetDatum(text_substring_with_encoding(con->constvalue, 1, prefix_len, false, charset)); return makeConst(datatype, -1, con->constcollid, con->constlen, prefix_value, false, false); } } diff --git a/src/gausskernel/optimizer/plan/planner.cpp b/src/gausskernel/optimizer/plan/planner.cpp index 71c0c0f41..a0d4f193f 100755 --- a/src/gausskernel/optimizer/plan/planner.cpp +++ b/src/gausskernel/optimizer/plan/planner.cpp @@ -89,6 +89,7 @@ #include "executor/node/nodeModifyTable.h" #include "optimizer/gplanmgr.h" #include "instruments/instr_statement.h" +#include "catalog/gs_collation.h" #include "replication/libpqsw.h" /* Hook for plugins to get control in planner() */ @@ -9066,6 +9067,28 @@ static bool IsTypeUnSupportedByVectorEngine(Oid typeOid) } return false; } + +static bool IsCollationUnSupportedByVectorEngine(Oid collation) +{ + if (!DB_IS_CMPT(B_FORMAT)) { + return false; + } + + if (is_b_format_collation(collation)) { + ereport(DEBUG2, (errmodule(MOD_OPT_PLANNER), + errmsg("Vectorize plan failed due to has unsupport collation: %u", collation))); + return true; + } + + int charset = get_valid_charset_by_collation(collation); + if (charset != GetDatabaseEncoding()) { + ereport(DEBUG2, (errmodule(MOD_OPT_PLANNER), + errmsg("Vectorize plan failed due to has charset: %d different from server_encoding", charset))); + return true; + } + return false; +} + /* * @Description: Check if it has unsupport expression in vector engine * @@ -9103,17 +9126,20 @@ bool vector_engine_unsupport_expression_walker(Node* node, VectorPlanContext* pl errmsg("Vectorize plan failed due to has system column"))); return true; } else { - return IsTypeUnSupportedByVectorEngine(var->vartype); + return (IsTypeUnSupportedByVectorEngine(var->vartype) || + IsCollationUnSupportedByVectorEngine(var->varcollid)); } break; } case T_Const: { Const* c = (Const *)node; - return IsTypeUnSupportedByVectorEngine(c->consttype); + return (IsTypeUnSupportedByVectorEngine(c->consttype) || + IsCollationUnSupportedByVectorEngine(c->constcollid)); } case T_Param: { Param *par = (Param *)node; - return IsTypeUnSupportedByVectorEngine(par->paramtype); + return (IsTypeUnSupportedByVectorEngine(par->paramtype) || + IsCollationUnSupportedByVectorEngine(par->paramcollid)); } case T_SubPlan: { SubPlan* subplan = (SubPlan*)node; @@ -9121,6 +9147,11 @@ bool vector_engine_unsupport_expression_walker(Node* node, VectorPlanContext* pl if (!IsTypeSupportedByVectorEngine(subplan->firstColType)) { return true; } + + Oid collation = exprCollation(node); + if (IsCollationUnSupportedByVectorEngine(collation)) { + return true; + } break; } /* count the number of complex expression, for vectorized plan of row tables */ @@ -9137,6 +9168,15 @@ bool vector_engine_unsupport_expression_walker(Node* node, VectorPlanContext* pl && !IsTypeSupportedByVectorEngine(exprType(node))) { return true; } + + Oid collation = exprInputCollation(node); + if (IsCollationUnSupportedByVectorEngine(collation)) { + return true; + } + collation = exprCollation(node); + if (IsCollationUnSupportedByVectorEngine(collation)) { + return true; + } break; } default: diff --git a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp index 651793834..4efc0ffe3 100644 --- a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp +++ b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp @@ -4421,7 +4421,7 @@ List* QueryRewrite(Query* parsetree) return results; } -Const* processResToConst(char* value, Oid atttypid) +Const* processResToConst(char* value, Oid atttypid, Oid collid) { Const *con = NULL; uint len = strlen(value); @@ -4439,7 +4439,7 @@ Const* processResToConst(char* value, Oid atttypid) con = makeConst(BOOLOID, -1, InvalidOid, sizeof(bool), BoolGetDatum(false), false, true); } } else { - con = makeConst(UNKNOWNOID, -1, InvalidOid, -2, str_datum, false, false); + con = makeConst(UNKNOWNOID, -1, collid, -2, str_datum, false, false); } return con; } @@ -5216,8 +5216,9 @@ Node* QueryRewriteNonConstant(Node *node) bool isnull = result->isnulls[0]; if (isnull) { + Oid collid = exprCollation(node); /* return a null const */ - con = makeConst(UNKNOWNOID, -1, InvalidOid, -2, (Datum)0, true, false); + con = makeConst(UNKNOWNOID, -1, collid, -2, (Datum)0, true, false); (*result->pub.rDestroy)((DestReceiver *)result); return (Node *)con; } @@ -5225,7 +5226,7 @@ Node* QueryRewriteNonConstant(Node *node) char* value = (char *)linitial((List *)linitial(result->tuples)); Oid atttypid = result->atttypids[0]; /* convert value to const expression. */ - con = processResToConst(value, atttypid); + con = processResToConst(value, atttypid, result->collids[0]); res = atttypid == BOOLOID ? (Node *)con : type_transfer((Node *)con, atttypid, true); (*result->pub.rDestroy)((DestReceiver *)result); @@ -5245,8 +5246,10 @@ List* QueryRewriteSelectIntoVarList(Node *node, int res_len) DestroyStringInfo(select_sql); if (result->tuples == NULL) { - for (int i = 0; i < res_len; i++) { - Const *con = makeConst(UNKNOWNOID, -1, InvalidOid, -2, (Datum)0, true, false); + ListCell *target_cell = list_head(parsetree->targetList); + for (int i = 0; i < res_len; i++, target_cell = lnext(target_cell)) { + Oid collid = exprCollation((Node*)((TargetEntry*)lfirst(target_cell))->expr); + Const *con = makeConst(UNKNOWNOID, -1, collid, -2, (Datum)0, true, false); resList = lappend(resList, con); } @@ -5263,14 +5266,15 @@ List* QueryRewriteSelectIntoVarList(Node *node, int res_len) ListCell *stmt_res_cur = list_head((List *)linitial(result->tuples)); for (int idx = 0; idx < res_len; idx++) { + Oid collid = result->collids[idx]; if (result->isnulls[idx]) { - Const *con = makeConst(UNKNOWNOID, -1, InvalidOid, -2, (Datum)0, true, false); + Const *con = makeConst(UNKNOWNOID, -1, collid, -2, (Datum)0, true, false); resList = lappend(resList, con); } else { char *value = (char *)lfirst(stmt_res_cur); Oid atttypid = result->atttypids[idx]; /* convert value to const expression. */ - Const *con = processResToConst(value, atttypid); + Const *con = processResToConst(value, atttypid, collid); Node* rnode = atttypid == BOOLOID ? (Node*)con : type_transfer((Node *)con, atttypid, true); resList = lappend(resList, rnode); stmt_res_cur = lnext(stmt_res_cur); diff --git a/src/gausskernel/optimizer/util/plancat.cpp b/src/gausskernel/optimizer/util/plancat.cpp index 8be9507dc..900c01264 100755 --- a/src/gausskernel/optimizer/util/plancat.cpp +++ b/src/gausskernel/optimizer/util/plancat.cpp @@ -1786,7 +1786,8 @@ static bool InstrAsPatternMatch(Oid* operatorid, List** args) Selectivity restriction_selectivity(PlannerInfo* root, Oid operatorid, List* args, Oid inputcollid, int varRelid) { float8 result; - + int tmp_encoding = PG_INVALID_ENCODING; + int db_encoding = PG_INVALID_ENCODING; bool useInstrOpt = false; if (ENABLE_SQL_BETA_FEATURE(SEL_EXPR_INSTR)) { useInstrOpt = InstrAsPatternMatch(&operatorid, &args); @@ -1807,6 +1808,28 @@ Selectivity restriction_selectivity(PlannerInfo* root, Oid operatorid, List* arg Int32GetDatum(varRelid))); } + if (DB_IS_CMPT(B_FORMAT)) { + tmp_encoding = get_valid_charset_by_collation(inputcollid); + db_encoding = GetDatabaseEncoding(); + } + + if (tmp_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(tmp_encoding); + result = DatumGetFloat8(OidFunctionCall4Coll(oprrest, + inputcollid, + PointerGetDatum(root), + ObjectIdGetDatum(operatorid), + PointerGetDatum(args), + Int32GetDatum(varRelid))); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + result = DatumGetFloat8(OidFunctionCall4Coll(oprrest, + inputcollid, + PointerGetDatum(root), + ObjectIdGetDatum(operatorid), + PointerGetDatum(args), + Int32GetDatum(varRelid))); + } if (useInstrOpt) { list_free_ext(args); diff --git a/src/gausskernel/process/tcop/utility.cpp b/src/gausskernel/process/tcop/utility.cpp index 09a2ced20..ee87bc303 100755 --- a/src/gausskernel/process/tcop/utility.cpp +++ b/src/gausskernel/process/tcop/utility.cpp @@ -10730,7 +10730,9 @@ static void drop_stmt_pre_treatment( } #endif -char* VariableBlackList[] = {"client_encoding"}; +char* VariableBlackList[] = { + "client_encoding" +}; bool IsVariableinBlackList(const char* name) { diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index e3c98a558..487acd36d 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -505,6 +505,8 @@ static void knl_u_mb_init(knl_u_mb_context* mb_cxt) mb_cxt->ToClientConvProc = NULL; mb_cxt->ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; mb_cxt->DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; + mb_cxt->character_set_connection = &pg_enc2name_tbl[PG_SQL_ASCII]; + mb_cxt->collation_connection = InvalidOid; mb_cxt->PlatformEncoding = NULL; mb_cxt->backend_startup_complete = false; mb_cxt->pending_client_encoding = PG_SQL_ASCII; diff --git a/src/gausskernel/runtime/executor/execExpr.cpp b/src/gausskernel/runtime/executor/execExpr.cpp index 7ee7d54d6..872e68f84 100644 --- a/src/gausskernel/runtime/executor/execExpr.cpp +++ b/src/gausskernel/runtime/executor/execExpr.cpp @@ -1996,7 +1996,10 @@ ExecInitExprRec(Expr *node, ExprState *state, Oid argtype = exprType((Node*)pkey->arg); if (argtype == BYTEAOID || argtype == RAWOID || argtype == BLOBOID) { scratch.opcode = EEOP_PREFIX_BTYEA; + scratch.d.prefix_key.encoding = PG_INVALID_ENCODING; } else { + Oid collation = exprCollation((Node*)pkey->arg); + scratch.d.prefix_key.encoding = get_valid_charset_by_collation(collation); scratch.opcode = EEOP_PREFIX_TEXT; } ExecInitExprRec(pkey->arg, state, resv, resnull, node); diff --git a/src/gausskernel/runtime/executor/execExprInterp.cpp b/src/gausskernel/runtime/executor/execExprInterp.cpp index cd5270c69..94d901509 100644 --- a/src/gausskernel/runtime/executor/execExprInterp.cpp +++ b/src/gausskernel/runtime/executor/execExprInterp.cpp @@ -304,6 +304,8 @@ ExecMakeFunctionResultNoSets(ExprState *state, ExprEvalStep *op,ExprContext *eco bool savedProConfigIsSet = u_sess->SPI_cxt.is_proconfig_set; bool is_have_huge_clob = false; bool needResetErrMsg = op->d.func.needResetErrMsg; + int func_encoding = PG_INVALID_ENCODING; + int db_encoding = PG_INVALID_ENCODING; if(!u_sess->SPI_cxt.is_allow_commit_rollback){ if(fcinfo->context){ @@ -332,6 +334,11 @@ ExecMakeFunctionResultNoSets(ExprState *state, ExprEvalStep *op,ExprContext *eco fcinfo->swinfo.sw_is_flt_frame = true; } + if (DB_IS_CMPT(B_FORMAT)) { + func_encoding = get_valid_charset_by_collation(fcinfo->fncollation); + db_encoding = GetDatabaseEncoding(); + } + i = 0; econtext->is_cursor = false; u_sess->plsql_cxt.func_tableof_index = NIL; @@ -407,7 +414,13 @@ ExecMakeFunctionResultNoSets(ExprState *state, ExprEvalStep *op,ExprContext *eco if (u_sess->instr_cxt.global_instr != NULL && fcinfo->flinfo->fn_addr == plpgsql_call_handler) { StreamInstrumentation* save_global_instr = u_sess->instr_cxt.global_instr; u_sess->instr_cxt.global_instr = NULL; - *op->resvalue = op->d.func.fn_addr(fcinfo); + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + *op->resvalue = op->d.func.fn_addr(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + *op->resvalue = op->d.func.fn_addr(fcinfo); + } u_sess->instr_cxt.global_instr = save_global_instr; } else { if (fcinfo->argTypes[0] == CLOBOID && fcinfo->argTypes[1] == CLOBOID && fcinfo->flinfo->fn_addr == textcat) { @@ -420,8 +433,14 @@ ExecMakeFunctionResultNoSets(ExprState *state, ExprEvalStep *op,ExprContext *eco struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(fcinfo->arg[1])); fcinfo->arg[1] = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null); } - } - *op->resvalue = op->d.func.fn_addr(fcinfo); + } + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + *op->resvalue = op->d.func.fn_addr(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + *op->resvalue = op->d.func.fn_addr(fcinfo); + } } *op->resnull = fcinfo->isnull; @@ -871,12 +890,26 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull, ExprDoneCo FunctionCallInfo fcinfo = op->d.func.fcinfo_data; Datum d; + int func_encoding = PG_INVALID_ENCODING; + int db_encoding = PG_INVALID_ENCODING; + + if (DB_IS_CMPT(B_FORMAT)) { + func_encoding = get_valid_charset_by_collation(fcinfo->fncollation); + db_encoding = GetDatabaseEncoding(); + } + if (econtext) { fcinfo->can_ignore = econtext->can_ignore; } fcinfo->isnull = false; - d = op->d.func.fn_addr(fcinfo); + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + d = op->d.func.fn_addr(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + d = op->d.func.fn_addr(fcinfo); + } *op->resvalue = d; *op->resnull = fcinfo->isnull; @@ -889,6 +922,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull, ExprDoneCo int nargs = op->d.func.nargs; Datum d; + int func_encoding = PG_INVALID_ENCODING; + int db_encoding = PG_INVALID_ENCODING; + + if (DB_IS_CMPT(B_FORMAT)) { + func_encoding = get_valid_charset_by_collation(fcinfo->fncollation); + db_encoding = GetDatabaseEncoding(); + } + if (econtext) { fcinfo->can_ignore = econtext->can_ignore; } @@ -901,7 +942,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull, ExprDoneCo } } fcinfo->isnull = false; - d = op->d.func.fn_addr(fcinfo); + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + d = op->d.func.fn_addr(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + d = op->d.func.fn_addr(fcinfo); + } *op->resvalue = d; *op->resnull = fcinfo->isnull; @@ -2095,7 +2142,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull, ExprDoneCo *op->resvalue = (Datum)0; *op->resnull = true; } else { - *op->resvalue = PointerGetDatum(text_substring(*op->resvalue, 1, op->d.prefix_key.pkey->length, false)); + *op->resvalue = PointerGetDatum(text_substring_with_encoding( + *op->resvalue, 1, op->d.prefix_key.pkey->length, false, op->d.prefix_key.encoding)); *op->resnull = false; } diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index 4efe98b5e..1eebc4074 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -1271,6 +1271,7 @@ static Datum ExecEvalUserSetElm(ExprState* exprstate, ExprContext* econtext, boo UserSetElemState* usestate = (UserSetElemState*)exprstate; UserSetElem* elem = usestate->use; UserSetElem elemcopy; + Oid collid = exprCollation((Node*)elem->val); elemcopy.xpr = elem->xpr; elemcopy.name = elem->name; @@ -1292,7 +1293,7 @@ static Datum ExecEvalUserSetElm(ExprState* exprstate, ExprContext* econtext, boo Datum result = ExecEvalExpr(usestate->instate, econtext, isNull, isDone); if (*isNull) { - con = makeConst(UNKNOWNOID, -1, InvalidOid, -2, result, true, false); + con = makeConst(UNKNOWNOID, -1, collid, -2, result, true, false); res = (Node*)con; elemcopy.val = (Expr*)const_expression_to_const(res); } else { @@ -1319,7 +1320,7 @@ static Datum ExecEvalUserSetElm(ExprState* exprstate, ExprContext* econtext, boo Oid atttypid = exprType((Node*)elem->val); value = CStringFromDatum(atttypid, result); - con = processResToConst(value, atttypid); + con = processResToConst(value, atttypid, collid); if (atttypid == BOOLOID) res = (Node*)con; else @@ -2216,6 +2217,8 @@ static Datum ExecMakeFunctionResult(FuncExprState* fcache, ExprContext* econtext bool hasSetArg = false; int i; int* var_dno = NULL; + int func_encoding = PG_INVALID_ENCODING; + int db_encoding = PG_INVALID_ENCODING; econtext->plpgsql_estate = plpgsql_estate; plpgsql_estate = NULL; @@ -2342,6 +2345,11 @@ restart: fcache->setArgsValid = false; } + if (DB_IS_CMPT(B_FORMAT)) { + func_encoding = get_valid_charset_by_collation(fcinfo->fncollation); + db_encoding = GetDatabaseEncoding(); + } + /* * Now call the function, passing the evaluated parameter values. */ @@ -2400,7 +2408,14 @@ restart: fcinfo->isnull = false; rsinfo.isDone = ExprSingleResult; - result = FunctionCallInvoke(fcinfo); + + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + result = FunctionCallInvoke(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + result = FunctionCallInvoke(fcinfo); + } if (AUDIT_SYSTEM_EXEC_ENABLED) { audit_system_function(fcinfo, AUDIT_OK); } @@ -2574,7 +2589,13 @@ restart: pgstat_init_function_usage(fcinfo, &fcusage); fcinfo->isnull = false; - result = FunctionCallInvoke(fcinfo); + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + result = FunctionCallInvoke(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + result = FunctionCallInvoke(fcinfo); + } *isNull = fcinfo->isnull; pgstat_end_function_usage(&fcusage, true); @@ -2622,6 +2643,8 @@ static Datum ExecMakeFunctionResultNoSets( bool proIsProcedure = false; bool supportTranaction = false; bool is_have_huge_clob = false; + int func_encoding = PG_INVALID_ENCODING; + int db_encoding = PG_INVALID_ENCODING; #ifdef ENABLE_MULTIPLE_NODES if (IS_PGXC_COORDINATOR && (t_thrd.proc->workingVersionNum >= STP_SUPPORT_COMMIT_ROLLBACK)) { @@ -2805,6 +2828,11 @@ static Datum ExecMakeFunctionResultNoSets( } } + if (DB_IS_CMPT(B_FORMAT)) { + func_encoding = get_valid_charset_by_collation(fcinfo->fncollation); + db_encoding = GetDatabaseEncoding(); + } + pgstat_init_function_usage(fcinfo, &fcusage); fcinfo->isnull = false; @@ -2812,7 +2840,13 @@ static Datum ExecMakeFunctionResultNoSets( if (u_sess->instr_cxt.global_instr != NULL && fcinfo->flinfo->fn_addr == plpgsql_call_handler) { StreamInstrumentation* save_global_instr = u_sess->instr_cxt.global_instr; u_sess->instr_cxt.global_instr = NULL; - result = FunctionCallInvoke(fcinfo); // node will be free at here or else; + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + result = FunctionCallInvoke(fcinfo); // node will be free at here or else; + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + result = FunctionCallInvoke(fcinfo); // node will be free at here or else; + } u_sess->instr_cxt.global_instr = save_global_instr; } else { if (fcinfo->argTypes[0] == CLOBOID && fcinfo->argTypes[1] == CLOBOID && fcinfo->flinfo->fn_addr == textcat) { @@ -2826,7 +2860,13 @@ static Datum ExecMakeFunctionResultNoSets( fcinfo->arg[1] = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null); } } - result = FunctionCallInvoke(fcinfo); + if (func_encoding != db_encoding) { + DB_ENCODING_SWITCH_TO(func_encoding); + result = FunctionCallInvoke(fcinfo); + DB_ENCODING_SWITCH_BACK(db_encoding); + } else { + result = FunctionCallInvoke(fcinfo); + } } *isNull = fcinfo->isnull; if (AUDIT_SYSTEM_EXEC_ENABLED) { @@ -5539,7 +5579,7 @@ static Datum ExecEvalCurrentOfExpr(ExprState* exprstate, ExprContext* econtext, * ExecEvalPrefixText * ---------------------------------------------------------------- */ -static Datum ExecEvalPrefixText(GenericExprState* state, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone) +static Datum ExecEvalPrefixText(PrefixKeyState* state, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone) { PrefixKey* pkey = (PrefixKey*)state->xprstate.expr; Datum result = ExecEvalExpr(state->arg, econtext, isNull, isDone); @@ -5548,13 +5588,13 @@ static Datum ExecEvalPrefixText(GenericExprState* state, ExprContext* econtext, return (Datum)0; } - return PointerGetDatum(text_substring(result, 1, pkey->length, false)); + return PointerGetDatum(text_substring_with_encoding(result, 1, pkey->length, false, state->encoding)); } /* ---------------------------------------------------------------- * ExecEvalPrefixBytea * ---------------------------------------------------------------- */ -static Datum ExecEvalPrefixBytea(GenericExprState* state, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone) +static Datum ExecEvalPrefixBytea(PrefixKeyState* state, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone) { PrefixKey* pkey = (PrefixKey*)state->xprstate.expr; Datum result = ExecEvalExpr(state->arg, econtext, isNull, isDone); @@ -6314,16 +6354,20 @@ ExprState* ExecInitExprByRecursion(Expr* node, PlanState* parent) } break; case T_PrefixKey: { PrefixKey* pkey = (PrefixKey*)node; - GenericExprState* gstate = makeNode(GenericExprState); + PrefixKeyState* pstate = makeNode(PrefixKeyState); Oid argtype = exprType((Node*)pkey->arg); if (argtype == BYTEAOID || argtype == RAWOID || argtype == BLOBOID) { - gstate->xprstate.evalfunc = (ExprStateEvalFunc)ExecEvalPrefixBytea; + pstate->xprstate.evalfunc = (ExprStateEvalFunc)ExecEvalPrefixBytea; + pstate->encoding = PG_INVALID_ENCODING; } else { - gstate->xprstate.evalfunc = (ExprStateEvalFunc)ExecEvalPrefixText; + Oid argcollation = exprCollation((Node*)pkey->arg); + pstate->xprstate.evalfunc = (ExprStateEvalFunc)ExecEvalPrefixText; + pstate->encoding = get_valid_charset_by_collation(argcollation); } - gstate->arg = ExecInitExpr(pkey->arg, parent); - state = (ExprState*)gstate; + pstate->arg = ExecInitExpr(pkey->arg, parent); + + state = (ExprState*)pstate; } break; case T_UserSetElem: { UserSetElem* useexpr = (UserSetElem*)node; diff --git a/src/gausskernel/runtime/executor/spi.cpp b/src/gausskernel/runtime/executor/spi.cpp index cb5af345e..68e7bd010 100644 --- a/src/gausskernel/runtime/executor/spi.cpp +++ b/src/gausskernel/runtime/executor/spi.cpp @@ -1424,6 +1424,22 @@ Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber) } } +Oid SPI_getcollation(TupleDesc tupdesc, int fnumber) +{ + SPI_result = 0; + + if (fnumber > tupdesc->natts || fnumber == 0 || fnumber <= FirstLowInvalidHeapAttributeNumber) { + SPI_result = SPI_ERROR_NOATTRIBUTE; + return InvalidOid; + } + + if (fnumber > 0) { + return tupdesc->attrs[fnumber - 1].attcollation; + } else { + return (SystemAttributeDefinition(fnumber, true, false, false))->attcollation; + } +} + char *SPI_getrelname(Relation rel) { return pstrdup(RelationGetRelationName(rel)); diff --git a/src/gausskernel/security/gs_ledger/ledger_archive.cpp b/src/gausskernel/security/gs_ledger/ledger_archive.cpp index 95037edf5..9d5048fbc 100644 --- a/src/gausskernel/security/gs_ledger/ledger_archive.cpp +++ b/src/gausskernel/security/gs_ledger/ledger_archive.cpp @@ -102,12 +102,21 @@ static uint64 ledger_copytable(CopyState cstate) /* For each column type, get its out function. */ cstate->out_functions = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + cstate->out_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); + cstate->attr_encodings = (int*)palloc(num_phys_attrs * sizeof(int)); foreach (cur, cstate->attnumlist) { int attnum = lfirst_int(cur); Oid out_func_oid; bool isvarlena = false; getTypeOutputInfo(attr[attnum - 1].atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); + /* set conversion functions */ + cstate->attr_encodings[attnum - 1] = get_valid_charset_by_collation(attr[attnum - 1].attcollation); + construct_conversion_fmgr_info(cstate->attr_encodings[attnum - 1], cstate->file_encoding, + (void*)&cstate->out_convert_funcs[attnum - 1]); + if (cstate->attr_encodings[attnum - 1] != cstate->file_encoding) { + cstate->need_transcoding = true; + } } /* diff --git a/src/gausskernel/storage/access/common/printtup.cpp b/src/gausskernel/storage/access/common/printtup.cpp index ace173dbb..d47d0434c 100644 --- a/src/gausskernel/storage/access/common/printtup.cpp +++ b/src/gausskernel/storage/access/common/printtup.cpp @@ -768,9 +768,14 @@ static void printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int if (format == 0) { getTypeOutputInfo(typeinfo->attrs[i].atttypid, &thisState->typoutput, &thisState->typisvarlena); fmgr_info(thisState->typoutput, &thisState->finfo); + thisState->encoding = get_valid_charset_by_collation(typeinfo->attrs[i].attcollation); + construct_conversion_fmgr_info( + thisState->encoding, u_sess->mb_cxt.ClientEncoding->encoding, (void*)&thisState->convert_finfo); } else if (format == 1) { getTypeBinaryOutputInfo(typeinfo->attrs[i].atttypid, &thisState->typsend, &thisState->typisvarlena); fmgr_info(thisState->typsend, &thisState->finfo); + thisState->encoding = PG_INVALID_ENCODING; // just initialize, should not be used + thisState->convert_finfo.fn_oid = InvalidOid; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unsupported format code: %d", format))); } @@ -805,6 +810,9 @@ static void printtup_prepare_info_for_stream(DR_printtup *myState, TupleDesc typ thisState->format = 0; getTypeOutputInfo(typeinfo->attrs[i].atttypid, &thisState->typoutput, &thisState->typisvarlena); fmgr_info(thisState->typoutput, &thisState->finfo); + thisState->encoding = get_valid_charset_by_collation(typeinfo->attrs[i].attcollation); + construct_conversion_fmgr_info( + thisState->encoding, u_sess->mb_cxt.ClientEncoding->encoding, (void*)&thisState->convert_finfo); } } @@ -1106,7 +1114,7 @@ void printtup(TupleTableSlot *slot, DestReceiver *self) * attr had been converted to CSTRING type previously by using anyarray_out. * just send over the DataRow message as we received it. */ - pq_sendcountedtext_printtup(buf, (char *)attr, strlen((char *)attr)); + pq_sendcountedtext_printtup(buf, (char *)attr, strlen((char *)attr), thisState->encoding, (void*)&thisState->convert_finfo); } else { if (thisState->format == 0) { /* Text output */ @@ -1190,7 +1198,7 @@ void printtup(TupleTableSlot *slot, DestReceiver *self) #ifndef ENABLE_MULTIPLE_NODES t_thrd.xact_cxt.callPrint = false; #endif - pq_sendcountedtext_printtup(buf, outputstr, strlen(outputstr)); + pq_sendcountedtext_printtup(buf, outputstr, strlen(outputstr), thisState->encoding, (void*)&thisState->convert_finfo); if (need_free) { pfree(outputstr); } diff --git a/src/gausskernel/storage/access/common/scankey.cpp b/src/gausskernel/storage/access/common/scankey.cpp index 8d70a68ef..8dac692f3 100644 --- a/src/gausskernel/storage/access/common/scankey.cpp +++ b/src/gausskernel/storage/access/common/scankey.cpp @@ -18,6 +18,7 @@ #include "access/skey.h" #include "catalog/pg_collation.h" +#include "utils/builtins.h" /* * ScanKeyEntryInitialize diff --git a/src/gausskernel/storage/access/common/tupdesc.cpp b/src/gausskernel/storage/access/common/tupdesc.cpp index 668a56423..29a5347a8 100644 --- a/src/gausskernel/storage/access/common/tupdesc.cpp +++ b/src/gausskernel/storage/access/common/tupdesc.cpp @@ -36,7 +36,7 @@ #include "utils/lsyscache.h" #include "mb/pg_wchar.h" #include "parser/parse_utilcmd.h" -#include "catalog/gs_utf8_collation.h" +#include "catalog/gs_collation.h" /* * CreateTemplateTupleDesc diff --git a/src/gausskernel/storage/access/hash/hashfunc.cpp b/src/gausskernel/storage/access/hash/hashfunc.cpp index fd07f72c0..fd99b4f20 100644 --- a/src/gausskernel/storage/access/hash/hashfunc.cpp +++ b/src/gausskernel/storage/access/hash/hashfunc.cpp @@ -29,8 +29,8 @@ #include "knl/knl_variable.h" #include "access/hash.h" +#include "catalog/gs_collation.h" -#include "catalog/gs_utf8_collation.h" #ifdef PGXC #include "catalog/pg_type.h" #include "utils/builtins.h" @@ -170,10 +170,11 @@ Datum hashtext(PG_FUNCTION_ARGS) FUNC_CHECK_HUGE_POINTER(false, key, "hashtext()"); if (is_b_format_collation(collid)) { - result = hash_text_by_builtin_colltions((unsigned char *)VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key), collid); + result = hash_text_by_builtin_collations((unsigned char *)VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key), collid); PG_FREE_IF_COPY(key, 0); return result; } + #ifdef PGXC if (g_instance.attr.attr_sql.string_hash_compatible) { result = hash_any((unsigned char *)VARDATA_ANY(key), bcTruelen(key)); diff --git a/src/gausskernel/storage/bulkload/dist_fdw.cpp b/src/gausskernel/storage/bulkload/dist_fdw.cpp index 7017a40ef..216f31233 100644 --- a/src/gausskernel/storage/bulkload/dist_fdw.cpp +++ b/src/gausskernel/storage/bulkload/dist_fdw.cpp @@ -1484,6 +1484,8 @@ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const c ExprState **defexprs; MemoryContext oldcontext; bool volatile_defexprs = false; + FmgrInfo *in_convert_funcs = NULL; + int *attr_encodings = NULL; DistBegin((CopyState)importstate, true, rel, NULL, NULL, attnamelist, options); oldcontext = MemoryContextSwitchTo(importstate->copycontext); @@ -1524,6 +1526,8 @@ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const c accept_empty_str = (bool *)palloc(num_phys_attrs * sizeof(bool)); defmap = (int *)palloc(num_phys_attrs * sizeof(int)); defexprs = (ExprState **)palloc(num_phys_attrs * sizeof(ExprState *)); + attr_encodings = (int*)palloc(num_phys_attrs * sizeof(int)); + in_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); #ifdef PGXC /* We don't currently allow COPY with non-shippable ROW triggers */ @@ -1536,6 +1540,7 @@ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const c /* Output functions are required to convert default values to output form */ importstate->out_functions = (FmgrInfo *)palloc(num_phys_attrs * sizeof(FmgrInfo)); + importstate->out_convert_funcs = (FmgrInfo*)palloc(num_phys_attrs * sizeof(FmgrInfo)); #endif for (attnum = 1; attnum <= num_phys_attrs; attnum++) { @@ -1550,7 +1555,9 @@ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const c else getTypeInputInfo(attr[attnum - 1].atttypid, &in_func_oid, &typioparams[attnum - 1]); fmgr_info(in_func_oid, &in_functions[attnum - 1]); - + attr_encodings[attnum - 1] = get_valid_charset_by_collation(attr[attnum - 1].attcollation); + construct_conversion_fmgr_info( + GetDatabaseEncoding(), attr_encodings[attnum - 1], (void*)&in_convert_funcs[attnum - 1]); /* Get default info if needed */ if (!list_member_int(importstate->attnumlist, attnum)) { /* attribute is NOT to be copied from input */ @@ -1583,6 +1590,12 @@ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const c else getTypeOutputInfo(attr[attnum - 1].atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &importstate->out_functions[attnum - 1]); + /* set conversion functions */ + construct_conversion_fmgr_info(attr_encodings[attnum - 1], importstate->file_encoding, + (void*)&importstate->out_convert_funcs[attnum - 1]); + if (attr_encodings[attnum - 1] != importstate->file_encoding) { + importstate->need_transcoding = true; + } } } else { #endif /* PGXC */ @@ -1608,6 +1621,8 @@ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const c importstate->defexprs = defexprs; importstate->volatile_defexprs = volatile_defexprs; importstate->num_defaults = num_defaults; + importstate->attr_encodings = attr_encodings; + importstate->in_convert_funcs = in_convert_funcs; importstate->filename = pstrdup(filename); diff --git a/src/include/access/printtup.h b/src/include/access/printtup.h index ffca29d68..f6e97254d 100644 --- a/src/include/access/printtup.h +++ b/src/include/access/printtup.h @@ -44,6 +44,8 @@ typedef struct { /* Per-attribute information */ bool typisvarlena; /* is it varlena (ie possibly toastable)? */ int16 format; /* format code for this column */ FmgrInfo finfo; /* Precomputed call info for output fn */ + int encoding; /* The character set of the text type attribute, valid when different from server_encoding */ + FmgrInfo convert_finfo; /* Precomputed call info for encoding conversion fn */ } PrinttupAttrInfo; typedef struct { diff --git a/src/include/catalog/gs_collation.h b/src/include/catalog/gs_collation.h new file mode 100644 index 000000000..ea556b023 --- /dev/null +++ b/src/include/catalog/gs_collation.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * + * gs_collation.h + * + * IDENTIFICATION + * src/include/catalog/gs_collation.h + * + * --------------------------------------------------------------------------------------- + */ +#ifndef GS_COLLATION_H +#define GS_COLLATION_H +#include "postgres.h" +#include "mb/pg_wchar.h" + +#define NEXT_WORD_POS(p, p_word_bytes) ((p) += (p_word_bytes)) + +extern int compare_tail_space(const unsigned char* str_value, int end_space_num, int res); +extern Datum hash_mb_bin_pad_space(const unsigned char *key, size_t len); + +/* utf8 */ +extern int matchtext_utf8mb4(unsigned char* t, int tlen, unsigned char* p, int plen); +extern int strnncoll_utf8mb4_general_pad_space(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2); +extern Datum hash_utf8mb4_general_pad_space(const unsigned char *key, size_t len); +extern int strnncoll_binary(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2); + +/* gbk */ +extern int strnncoll_mb_bin_pad_space(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2); +extern int strnncoll_gbk_chinese_ci_pad_space(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2); +extern Datum hash_gbk_chinese_pad_space(const unsigned char *key, size_t len); +extern int matchtext_gbk_chinese(unsigned char* s, int slen, unsigned char* p, int plen); + +/* gb18030 */ +extern int strnncoll_gb18030_chinese_ci_pad_space(const unsigned char* arg1, size_t len1, + const unsigned char* arg2, size_t len2); +extern Datum hash_gb18030_chinese_pad_space(const unsigned char *key, size_t len); +extern int matchtext_gb18030(unsigned char* t, int tlen, unsigned char* p, int plen); + +/* common */ +extern int varstr_cmp_by_builtin_collations(const char* arg1, int len1,const char* arg2, int len2, Oid collid); +extern Datum hash_text_by_builtin_collations(const unsigned char *key, int len, Oid collid); +extern int match_text_by_builtin_collations(unsigned char* t, int tlen, unsigned char* p, int plen, Oid collation); +extern void check_binary_collation(Oid collation, Oid type_oid); +extern bool is_support_b_format_collation(Oid collation); +extern bool is_b_format_collation(Oid collation); +extern int matchtext_general(unsigned char* s, int slen, unsigned char* p, int plen); + +#endif /* GS_COLLATION_H */ \ No newline at end of file diff --git a/src/include/catalog/gs_utf8_collation.h b/src/include/catalog/gs_utf8_collation.h deleted file mode 100644 index 6aa774a48..000000000 --- a/src/include/catalog/gs_utf8_collation.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. - * - * openGauss is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * --------------------------------------------------------------------------------------- - * - * gs_utf8_collation.h - * - * IDENTIFICATION - * src/include/catalog/gs_utf8_collation.h - * - * --------------------------------------------------------------------------------------- - */ -#ifndef GS_UTF8_COLLATION_H -#define GS_UTF8_COLLATION_H - -int varstr_cmp_by_builtin_collations(char* arg1, int len1, char* arg2, int len2, Oid collid); -Datum hash_text_by_builtin_colltions(const unsigned char *key, size_t len, Oid collid); -void check_binary_collation(Oid collation, Oid type_oid); -bool is_support_b_format_collation(Oid collation); -Oid binary_need_transform_typeid(Oid typeoid, Oid* collation); -int matchtext_utf8mb4(unsigned char* t, int tlen, unsigned char* p, int plen); -bool is_b_format_collation(Oid collation); - -#define IS_UTF8_GENERAL_COLLATION(colloid) \ - ((colloid == UTF8MB4_GENERAL_CI_COLLATION_OID) || \ - (colloid == UTF8MB4_UNICODE_CI_COLLATION_OID) || \ - (colloid == UTF8_GENERAL_CI_COLLATION_OID) || \ - (colloid == UTF8_UNICODE_CI_COLLATION_OID)) -#endif /* GS_UTF8_COLLATION_H */ \ No newline at end of file diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index bae80534d..f2bd42173 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -192,7 +192,7 @@ extern List *AddRelationNewConstraints(Relation rel, List *newColDefaults, List extern List *AddRelClusterConstraints(Relation rel, List *clusterKeys); extern Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, char generatedCol, Node* update_expr, bool skip_dep = false); -extern Node *cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, char *attname, +extern Node *cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, Oid attcollation, char *attname, char generatedCol); extern void DeleteRelationTuple(Oid relid); extern void DeleteAttributeTuples(Oid relid); diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h index f6ca591cf..fc3633379 100644 --- a/src/include/catalog/pg_collation.h +++ b/src/include/catalog/pg_collation.h @@ -88,7 +88,15 @@ DESCR("standard POSIX collation"); DATA(insert OID = 1026 (binary PGNSP PGUID 0 "binary" "binary" "NO PAD" t)); DESCR("binary collation"); #define BINARY_COLLATION_OID 1026 + /* GBK's start with 1280 */ +DATA(insert OID = 1327 (gbk_chinese_ci PGNSP PGUID 6 "gbk_chinese_ci" "gbk_chinese_ci" "PAD SPACE" t)); +DESCR("gbk_chinese_ci collation"); +#define GBK_CHINESE_CI_COLLATION_OID 1327 +DATA(insert OID = 1328 (gbk_bin PGNSP PGUID 6 "gbk_bin" "gbk_bin" "PAD SPACE" _null_)); +DESCR("gbk_bin collation"); +#define GBK_BIN_COLLATION_OID 1328 + /* UTF8's start with 1536 */ DATA(insert OID = 1537 (utf8mb4_general_ci PGNSP PGUID 7 "utf8mb4_general_ci" "utf8mb4_general_ci" "PAD SPACE" t)); DESCR("utf8mb4_general_ci collation"); @@ -109,7 +117,14 @@ DESCR("utf8_unicode_ci collation"); DATA(insert OID = 1553 (utf8_bin PGNSP PGUID 7 "utf8_bin" "utf8_bin" "PAD SPACE" _null_)); DESCR("utf8_bin collation"); #define UTF8_BIN_COLLATION_OID 1553 -/* GB10830's start with 1792 */ + +/* GB18030's start with 1792 */ +DATA(insert OID = 1800 (gb18030_chinese_ci PGNSP PGUID 36 "gb18030_chinese_ci" "gb18030_chinese_ci" "PAD SPACE" t)); +DESCR("gb18030_chinese_ci collation"); +#define GB18030_CHINESE_CI_COLLATION_OID 1800 +DATA(insert OID = 1801 (gb18030_bin PGNSP PGUID 36 "gb18030_bin" "gb18030_bin" "PAD SPACE" _null_)); +DESCR("gb18030_bin collation"); +#define GB18030_BIN_COLLATION_OID 1801 #define B_FORMAT_COLLATION_OID_MAX 10000 #define B_FORMAT_COLLATION_STR_LEN 4 @@ -120,4 +135,13 @@ DESCR("utf8_bin collation"); #define COLLATION_HAS_INVALID_ENCODING(colloid) \ ((colloid) < B_FORMAT_COLLATION_OID_MIN) +extern int get_charset_by_collation(Oid colloid); +extern int get_valid_charset_by_collation(Oid colloid); +extern Oid get_default_collation_by_charset(int charset, bool report_error = true); +#define COLLATION_HAS_BIN_SUFFIX(colloid) \ + ((colloid) == UTF8_BIN_COLLATION_OID || \ + (colloid) == UTF8MB4_BIN_COLLATION_OID || \ + (colloid) == GBK_BIN_COLLATION_OID || \ + (colloid) == GB18030_BIN_COLLATION_OID) + #endif /* PG_COLLATION_H */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 2f90776ee..303ff921b 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -174,6 +174,8 @@ typedef FormData_pg_proc *Form_pg_proc; /* keep the following ordered by OID so that later changes can be made easier */ /* OIDS 1 - 99 */ +#define VERSIONFUNCOID 89 +#define OPENGAUSSVERSIONFUNCOID 90 #define TEXTLENOID 1257 #define EQSELRETURNOID 101 #define NEQSELRETURNOID 102 @@ -305,6 +307,7 @@ typedef FormData_pg_proc *Form_pg_proc; #define INTERVALTOCHARFUNCOID 1768 #define CONCATFUNCOID 3058 #define CONCATWSFUNCOID 3059 +#define CONVERTTONOCASEFUNCOID 3198 #define ANYTOTEXTFORMATFUNCOID 3539 #define DEFAULTFORMATFUNCOID 3540 #define INTERVALACCUMFUNCOID 1843 diff --git a/src/include/catalog/pg_set.h b/src/include/catalog/pg_set.h index db0c55a4d..9c5177b2c 100644 --- a/src/include/catalog/pg_set.h +++ b/src/include/catalog/pg_set.h @@ -81,7 +81,7 @@ typedef FormData_pg_set *Form_pg_set; #define SETNAMELEN (255) #define SETLABELDELIMIT "," -extern void SetValuesCreate(Oid setTypeOid, List *vals); +extern void SetValuesCreate(Oid setTypeOid, List *vals, Oid collation); extern void SetValuesDelete(Oid setTypeOid); extern Datum GetSetDefineStr(Oid settypid); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 2409238f3..c14a37c6b 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -775,6 +775,7 @@ DESCR("hypper log log hashval array"); #define HLL_HASHVAL_ARRAYOID 4304 DATA(insert OID = 4370 ( hll_trans_type PGNSP PGUID -1 f p P f t \054 0 0 4371 hll_trans_in hll_trans_out hll_trans_recv hll_trans_send - - - i e f 0 -1 0 0 _null_ _null_ _null_ )); DESCR("hypper log log internal type"); +#define HLL_TRANS_OID 4370 DATA(insert OID = 4371 ( _hll_trans_type PGNSP PGUID -1 f p P f t \054 0 4370 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DESCR("hypper log log internal type"); @@ -864,6 +865,7 @@ DATA(insert OID = 3272 ( anyset PGNSP PGUID -1 f s H t t \054 0 0 0 anyset_in (((typid) == TEXTOID) || \ ((typid) == VARCHAROID) || \ ((typid) == BPCHAROID) || \ - ((typid) == NVARCHAR2OID)) + ((typid) == NVARCHAR2OID) || \ + (type_is_set(typid))) #endif /* PG_TYPE_H */ diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_903.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_903.sql new file mode 100644 index 000000000..9ac0945f7 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_903.sql @@ -0,0 +1,20 @@ +-------------------------------------------------------------- +-- delete pg_catalog.pg_collation +-------------------------------------------------------------- +CREATE OR REPLACE FUNCTION pg_catalog.Delete_pg_collation_temp() +RETURNS void +AS $$ +DECLARE +row_name record; +query_str_nodes text; +BEGIN + query_str_nodes := 'select * from dbe_perf.node_name'; + FOR row_name IN EXECUTE(query_str_nodes) LOOP + delete from pg_catalog.pg_collation where collname in ('gbk_chinese_ci', 'gbk_bin', 'gb18030_chinese_ci', 'gb18030_bin'); + END LOOP; +return; +END; +$$ LANGUAGE 'plpgsql'; + +SELECT pg_catalog.Delete_pg_collation_temp(); +DROP FUNCTION pg_catalog.Delete_pg_collation_temp(); \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_903.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_903.sql new file mode 100644 index 000000000..9ac0945f7 --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_903.sql @@ -0,0 +1,20 @@ +-------------------------------------------------------------- +-- delete pg_catalog.pg_collation +-------------------------------------------------------------- +CREATE OR REPLACE FUNCTION pg_catalog.Delete_pg_collation_temp() +RETURNS void +AS $$ +DECLARE +row_name record; +query_str_nodes text; +BEGIN + query_str_nodes := 'select * from dbe_perf.node_name'; + FOR row_name IN EXECUTE(query_str_nodes) LOOP + delete from pg_catalog.pg_collation where collname in ('gbk_chinese_ci', 'gbk_bin', 'gb18030_chinese_ci', 'gb18030_bin'); + END LOOP; +return; +END; +$$ LANGUAGE 'plpgsql'; + +SELECT pg_catalog.Delete_pg_collation_temp(); +DROP FUNCTION pg_catalog.Delete_pg_collation_temp(); \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_903.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_903.sql new file mode 100644 index 000000000..ad1162249 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_903.sql @@ -0,0 +1,37 @@ +-- ---------------------------------------------------------------- +-- upgrade pg_catalog.pg_collation +-- ---------------------------------------------------------------- +CREATE OR REPLACE FUNCTION pg_catalog.Insert_pg_collation_temp( +IN collname text, +IN collnamespace integer, +IN collowner integer, +IN collencoding integer, +IN collcollate text, +IN collctype text, +IN collpadattr text, +IN collisdef bool +) +RETURNS void +AS $$ +DECLARE + row_name record; + query_str_nodes text; +BEGIN + query_str_nodes := 'select * from dbe_perf.node_name'; + FOR row_name IN EXECUTE(query_str_nodes) LOOP + insert into pg_catalog.pg_collation values (collname, collnamespace, collowner, collencoding, collcollate, collctype, collpadattr, collisdef); + END LOOP; + return; +END; $$ +LANGUAGE 'plpgsql'; + +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1327; +select pg_catalog.Insert_pg_collation_temp('gbk_chinese_ci', 11, 10, 6, 'gbk_chinese_ci', 'gbk_chinese_ci', 'PAD SPACE', true); +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1328; +select pg_catalog.Insert_pg_collation_temp('gbk_bin', 11, 10, 6, 'gbk_bin', 'gbk_bin', 'PAD SPACE', null); +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1800; +select pg_catalog.Insert_pg_collation_temp('gb18030_chinese_ci', 11, 10, 36, 'gb18030_chinese_ci', 'gb18030_chinese_ci', 'PAD SPACE', true); +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1801; +select pg_catalog.Insert_pg_collation_temp('gb18030_bin', 11, 10, 36, 'gb18030_bin', 'gb18030_bin', 'PAD SPACE', null); + +DROP FUNCTION pg_catalog.Insert_pg_collation_temp; \ No newline at end of file diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_903.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_903.sql new file mode 100644 index 000000000..ad1162249 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_903.sql @@ -0,0 +1,37 @@ +-- ---------------------------------------------------------------- +-- upgrade pg_catalog.pg_collation +-- ---------------------------------------------------------------- +CREATE OR REPLACE FUNCTION pg_catalog.Insert_pg_collation_temp( +IN collname text, +IN collnamespace integer, +IN collowner integer, +IN collencoding integer, +IN collcollate text, +IN collctype text, +IN collpadattr text, +IN collisdef bool +) +RETURNS void +AS $$ +DECLARE + row_name record; + query_str_nodes text; +BEGIN + query_str_nodes := 'select * from dbe_perf.node_name'; + FOR row_name IN EXECUTE(query_str_nodes) LOOP + insert into pg_catalog.pg_collation values (collname, collnamespace, collowner, collencoding, collcollate, collctype, collpadattr, collisdef); + END LOOP; + return; +END; $$ +LANGUAGE 'plpgsql'; + +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1327; +select pg_catalog.Insert_pg_collation_temp('gbk_chinese_ci', 11, 10, 6, 'gbk_chinese_ci', 'gbk_chinese_ci', 'PAD SPACE', true); +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1328; +select pg_catalog.Insert_pg_collation_temp('gbk_bin', 11, 10, 6, 'gbk_bin', 'gbk_bin', 'PAD SPACE', null); +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1800; +select pg_catalog.Insert_pg_collation_temp('gb18030_chinese_ci', 11, 10, 36, 'gb18030_chinese_ci', 'gb18030_chinese_ci', 'PAD SPACE', true); +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_GENERAL, 1801; +select pg_catalog.Insert_pg_collation_temp('gb18030_bin', 11, 10, 36, 'gb18030_bin', 'gb18030_bin', 'PAD SPACE', null); + +DROP FUNCTION pg_catalog.Insert_pg_collation_temp; \ No newline at end of file diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h index 727404127..c9436f62f 100644 --- a/src/include/commands/copy.h +++ b/src/include/commands/copy.h @@ -213,11 +213,13 @@ typedef struct CopyStateData { * Working state for COPY TO/FROM */ MemoryContext copycontext; /* per-copy execution context */ + int* attr_encodings; /* for B compatibility multi charsets */ /* * Working state for COPY TO */ FmgrInfo* out_functions; /* lookup info for output functions */ + FmgrInfo* out_convert_funcs; /* lookup info for encoding conversion */ MemoryContext rowcontext; /* per-row evaluation context */ /* @@ -244,6 +246,7 @@ typedef struct CopyStateData { FmgrInfo* err_out_functions; /* lookup info for output functions of copy_error_log*/ AssignTypmod *as_typemods; /* array of typmod for each transformed column */ ExprState** transexprs; /* array of expr for each transformed column */ + FmgrInfo* in_convert_funcs; /* lookup info for encoding conversion */ Relation summary_table; /* opened copy_summary table */ int64 skiprows; diff --git a/src/include/commands/sqladvisor.h b/src/include/commands/sqladvisor.h index 0bc67bb32..0f1aa4a11 100644 --- a/src/include/commands/sqladvisor.h +++ b/src/include/commands/sqladvisor.h @@ -198,6 +198,7 @@ typedef struct { MemoryContext mxct; List *tuples; Oid *atttypids; /* for sublink in user-defined variables */ + Oid *collids; /* for variables collation ids*/ bool *isnulls; /* for sublink in user-defined variables */ } StmtResult; diff --git a/src/include/commands/variable.h b/src/include/commands/variable.h index 9661a1c6d..51c82d292 100644 --- a/src/include/commands/variable.h +++ b/src/include/commands/variable.h @@ -30,8 +30,14 @@ extern bool check_random_seed(double* newval, void** extra, GucSource source); extern void assign_random_seed(double newval, void* extra); extern const char* show_random_seed(void); extern bool check_client_encoding(char** newval, void** extra, GucSource source); +extern bool check_charset_connection(char** newval, void** extra, GucSource source); +extern const char* show_charset_connection(void); +extern const char* show_collation_connection(void); +extern bool check_collation_connection(char** newval, void** extra, GucSource source); extern bool check_security_path(char** newval, void** extra, GucSource source); extern void assign_client_encoding(const char* newval, void* extra); +extern void assign_charset_connection(const char* newval, void* extra); +extern void assign_collation_connection(const char* newval, void* extra); extern bool check_mix_replication_param(bool* newval, void** extra, GucSource source); extern bool check_session_authorization(char** newval, void** extra, GucSource source); extern void assign_session_authorization(const char* newval, void* extra); diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index e37bc65b6..d1fa9e8c4 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -132,6 +132,7 @@ extern char* SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber); extern Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool* isnull); extern char* SPI_gettype(TupleDesc tupdesc, int fnumber); extern Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber); +extern Oid SPI_getcollation(TupleDesc tupdesc, int fnumber); extern char* SPI_getrelname(Relation rel); extern char* SPI_getnspname(Relation rel); extern void* SPI_palloc(Size size); diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 1d8f64621..a6fd7a5c4 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -565,7 +565,7 @@ typedef struct { } CFunInfo; /* Special cases for convenient invocation of datatype I/O functions. */ -extern Datum InputFunctionCall(FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, bool can_ignore = false); +extern Datum InputFunctionCall(FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, bool can_ignore = false, Oid collation = InvalidOid); extern Datum InputFunctionCallForDateType( FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, char* date_time_fmt); extern Datum OidInputFunctionCall(Oid functionId, char* str, Oid typioparam, int32 typmod, bool can_ignore = false); @@ -575,6 +575,7 @@ extern Datum ReceiveFunctionCall(FmgrInfo* flinfo, fmStringInfo buf, Oid typiopa extern Datum OidReceiveFunctionCall(Oid functionId, fmStringInfo buf, Oid typioparam, int32 typmod); extern bytea* SendFunctionCall(FmgrInfo* flinfo, Datum val); extern bytea* OidSendFunctionCall(Oid functionId, Datum val); +extern Datum OidInputFunctionCallColl(Oid functionId, char* str, Oid typioparam, int32 typmod, Oid collation); /* * Routines in fmgr.c diff --git a/src/include/knl/knl_guc/knl_session_attr_common.h b/src/include/knl/knl_guc/knl_session_attr_common.h index 3d11fe68e..a7e03fe6e 100644 --- a/src/include/knl/knl_guc/knl_session_attr_common.h +++ b/src/include/knl/knl_guc/knl_session_attr_common.h @@ -112,6 +112,8 @@ typedef struct knl_session_attr_common { int64 group_concat_max_len; double ConnectionAlarmRate; char* client_encoding_string; + char* character_set_connection; + char* collation_connection; char* Log_line_prefix; char* safe_data_path; char* log_timezone_string; diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index 429d58d9b..7faf02a5e 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -931,6 +931,8 @@ typedef struct knl_u_mb_context { struct pg_enc2name* PlatformEncoding; + struct pg_enc2name* character_set_connection; + Oid collation_connection; /* * During backend startup we can't set client encoding because we (a) * can't look up the conversion functions, and (b) may not know the database diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h index 6d3aabf85..287c065ef 100644 --- a/src/include/libpq/pqformat.h +++ b/src/include/libpq/pqformat.h @@ -21,7 +21,7 @@ extern void pq_beginmessage(StringInfo buf, char msgtype); extern void pq_beginmessage_reuse(StringInfo buf, char msgtype); extern void pq_sendbytes(StringInfo buf, const char* data, int datalen); extern void pq_sendcountedtext(StringInfo buf, const char* str, int slen, bool countincludesself); -extern void pq_sendcountedtext_printtup(StringInfo buf, const char* str, int slen); +extern void pq_sendcountedtext_printtup(StringInfo buf, const char* str, int slen, int src_encoding, void* convert_finfo); extern void pq_sendtext(StringInfo buf, const char* str, int slen); extern void pq_sendstring(StringInfo buf, const char* str); extern void pq_send_ascii_string(StringInfo buf, const char* str); diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h index 03c9987da..fe36248c5 100644 --- a/src/include/mb/pg_wchar.h +++ b/src/include/mb/pg_wchar.h @@ -250,6 +250,8 @@ typedef enum pg_enc { /* On FE are possible all encodings */ #define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc) +#define IS_UNICODE_ENCODING(_enc) ((_enc) == PG_UTF8) + /* * When converting strings between different encodings, we assume that space * for converted result is 4-to-1 growth in the worst case. The rate for @@ -448,6 +450,7 @@ extern int pg_mbstrlen(const char* mbstr); extern int pg_mbstrlen_with_len(const char* mbstr, int len); extern int pg_mbstrlen_with_len_eml(const char* mbstr, int len, int eml); extern int pg_mbstrlen_with_len_toast(const char* mbstr, int* limit); +extern int pg_encoding_mbstrlen_with_len(const char* mbstr, int limit, int encoding); extern int pg_mbcliplen(const char* mbstr, int len, int limit); extern int pg_encoding_mbcliplen(int encoding, const char* mbstr, int len, int limit); extern int pg_mbcharcliplen(const char* mbstr, int len, int imit); @@ -465,6 +468,9 @@ extern const char* pg_get_client_encoding_name(void); extern void SetDatabaseEncoding(int encoding); extern int GetDatabaseEncoding(void); extern const char* GetDatabaseEncodingName(void); +extern int GetCharsetConnection(void); +extern const char* GetCharsetConnectionName(void); +extern Oid GetCollationConnection(void); extern int GetPlatformEncoding(void); extern void pg_bind_textdomain_codeset(const char* domainname); @@ -475,11 +481,15 @@ extern unsigned char* unicode_to_utf8(pg_wchar c, unsigned char* utf8string); extern pg_wchar utf8_to_unicode(const unsigned char* c); extern int pg_utf_mblen(const unsigned char*); extern unsigned char* pg_do_encoding_conversion(unsigned char* src, int len, int src_encoding, int dest_encoding); +extern void construct_conversion_fmgr_info(int src_encoding, int dst_encoding, void* finfo); +extern char* try_fast_encoding_conversion( + char* src, int len, int src_encoding, int dest_encoding, void* convert_finfo); extern char* pg_client_to_server(const char* s, int len); extern char* pg_server_to_client(const char* s, int len); extern char* pg_any_to_server(const char* s, int len, int encoding); -extern char* pg_server_to_any(const char* s, int len, int encoding); +extern char* pg_server_to_any(const char* s, int len, int encoding, void* convert_finfo = NULL); +extern char* pg_any_to_client(const char* s, int len, int encoding, void* convert_finfo = NULL); extern bool WillTranscodingBePerformed(int encoding); extern unsigned short BIG5toCNS(unsigned short big5, unsigned char* lc); @@ -524,4 +534,23 @@ extern char* gs_nl_langinfo_r(const char* ctype); extern WCHAR* pgwin32_toUTF16(const char* str, int len, int* utf16len); #endif +#define DB_ENCODING_SWITCH_TO(tmp_encoding) \ + do { \ + SetDatabaseEncoding(tmp_encoding); \ + uint32 save_count = t_thrd.int_cxt.InterruptHoldoffCount; \ + PG_TRY(); \ + { \ + +#define DB_ENCODING_SWITCH_BACK(db_encoding) \ + } \ + PG_CATCH(); \ + { \ + t_thrd.int_cxt.InterruptHoldoffCount = save_count; \ + SetDatabaseEncoding(db_encoding); \ + PG_RE_THROW(); \ + } \ + PG_END_TRY(); \ + SetDatabaseEncoding(db_encoding); \ + } while (0) \ + #endif /* PG_WCHAR_H */ diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 4d67d5b56..b8db51629 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -40,6 +40,7 @@ extern const uint32 NBTREE_INSERT_OPTIMIZATION_VERSION_NUM; extern const uint32 NBTREE_DEDUPLICATION_VERSION_NUM; extern const uint32 ONDEMAND_REDO_VERSION_NUM; +extern const uint32 MULTI_CHARSET_VERSION_NUM; extern const uint32 SRF_FUSION_VERSION_NUM; extern const uint32 INNER_UNIQUE_VERSION_NUM; extern const uint32 PARTITION_ENHANCE_VERSION_NUM; @@ -145,7 +146,8 @@ extern void SSUpgradeFileBeforeCommit(); #define B_FORMAT_OPT_DEFAULT_COLLATION 8 #define B_FORMAT_OPT_FETCH 16 #define B_FORMAT_OPT_DIAGNOSTICS 32 -#define B_FORMAT_OPT_MAX 6 +#define B_FORMAT_OPT_ENABLE_MULTI_CHARSET 64 +#define B_FORMAT_OPT_MAX 7 #define ENABLE_SET_SESSION_TRANSACTION \ ((u_sess->utils_cxt.b_format_behavior_compat_flags & B_FORMAT_OPT_ENABLE_SET_SESSION_TRANSACTION) && \ @@ -158,6 +160,9 @@ extern void SSUpgradeFileBeforeCommit(); u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) #define B_FETCH ((u_sess->utils_cxt.b_format_behavior_compat_flags & B_FORMAT_OPT_FETCH) && \ u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) +#define ENABLE_MULTI_CHARSET \ + ((u_sess->utils_cxt.b_format_behavior_compat_flags & B_FORMAT_OPT_ENABLE_MULTI_CHARSET) && \ + u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) #define B_DIAGNOSTICS ((u_sess->utils_cxt.b_format_behavior_compat_flags & B_FORMAT_OPT_DIAGNOSTICS) && \ u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) diff --git a/src/include/nodes/execExpr.h b/src/include/nodes/execExpr.h index 45bbbd680..70d73ae2f 100644 --- a/src/include/nodes/execExpr.h +++ b/src/include/nodes/execExpr.h @@ -622,6 +622,7 @@ typedef struct ExprEvalStep struct { PrefixKey* pkey; + int encoding; } prefix_key; /* for EEOP_GROUPING_ID* */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 18b049a0e..f3add6928 100755 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -2731,6 +2731,13 @@ typedef struct UserSetElemState { UserSetElem* use; ExprState* instate; } UserSetElemState; + +typedef struct PrefixKeyState { + ExprState xprstate; + ExprState* arg; /* state of my child node */ + int encoding; +} PrefixKeyState; + /* ---------------- * GroupingFuncExprState node * diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index d84777b03..4ee1de6e0 100755 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -307,6 +307,7 @@ typedef enum NodeTag { T_UserSetElemState, T_ListPartitionDefState, T_HashPartitionDefState, + T_PrefixKeyState, /* * TAGS FOR PLANNER NODES (relation.h) @@ -837,7 +838,8 @@ typedef enum NodeTag { T_CondInfo, T_GetDiagStmt, T_DolphinCallStmt, - T_CallContext + T_CallContext, + T_CharsetClause } NodeTag; /* if you add to NodeTag also need to add nodeTagToString */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index f7180f8ad..fe7e86ae9 100755 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2348,6 +2348,7 @@ typedef struct DolphinCallStmt typedef struct CreateSetStmt { NodeTag type; TypeName *typname; /* type of column */ + Oid set_collation; } CreateSetStmt; /* ---------------------- diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index aa9c45dd6..0d90e9f78 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -752,6 +752,17 @@ typedef struct CharsetCollateOptions { char* collate; } CharsetCollateOptions; +/* + * CharsetClause - a expression + */ +typedef struct CharsetClause { + NodeTag type; + Node *arg; /* string const */ + int charset; /* encoding id */ + bool is_binary; + int location; +} CharsetClause; + /* ---------------------- * Create Schema Statement * diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index a4733f7bd..1d54ae299 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -64,6 +64,9 @@ extern Oid select_common_type(ParseState* pstate, List* exprs, const char* conte extern bool check_all_in_whitelist(List* resultexprs); extern Node* coerce_to_common_type(ParseState* pstate, Node* node, Oid targetTypeId, const char* context); +extern Node* coerce_to_settype(ParseState* pstate, Node* expr, Oid exprtype, Oid targettype, int32 targettypmod, + CoercionContext ccontext, CoercionForm cformat, int location, Oid collation); + extern bool check_generic_type_consistency(Oid* actual_arg_types, Oid* declared_arg_types, int nargs); extern Oid enforce_generic_type_consistency( Oid* actual_arg_types, Oid* declared_arg_types, int nargs, Oid rettype, bool allow_poly); @@ -74,7 +77,8 @@ extern CoercionPathType find_coercion_pathway( extern CoercionPathType find_typmod_coercion_function(Oid typeId, Oid* funcid); extern void expression_error_callback(void* arg); -extern Node* coerce_to_target_charset(Node* expr, int target_charset, Oid targetTypeId); +extern Node* coerce_to_target_charset( + Node* expr, int target_charset, Oid target_type, int32 target_typmod, Oid target_collation); extern Node *transferConstToAconst(Node *node); diff --git a/src/include/parser/parse_collate.h b/src/include/parser/parse_collate.h index d99f2ae3f..be382db89 100644 --- a/src/include/parser/parse_collate.h +++ b/src/include/parser/parse_collate.h @@ -24,4 +24,6 @@ extern void assign_expr_collations(ParseState* pstate, Node* expr); extern Oid select_common_collation(ParseState* pstate, List* exprs, bool none_ok); +extern Node *convert_arg_charset(Node *arg_expr, int target_charset, Oid target_collation); + #endif /* PARSE_COLLATE_H */ diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h index 0280ee644..848981993 100644 --- a/src/include/parser/parse_type.h +++ b/src/include/parser/parse_type.h @@ -34,6 +34,8 @@ extern char* TypeNameListToString(List* typenames); extern Oid LookupCollation(ParseState* pstate, List* collnames, int location); extern Oid GetColumnDefCollation(ParseState* pstate, ColumnDef* coldef, Oid typeOid, Oid rel_coll_oid = InvalidOid); +extern Oid get_column_def_collation_b_format(ColumnDef* coldef, Oid typeOid, Oid typcollation, + bool is_bin_type = false, Oid rel_coll_oid = InvalidOid); extern Type typeidType(Oid id); @@ -57,7 +59,7 @@ extern void parseTypeString(const char* str, Oid* typeid_p, int32* typmod_p); extern bool IsTypeTableInInstallationGroup(const Type type_tup); extern HeapTuple FindPkgVariableType(ParseState* pstate, const TypeName* typname, int32* typmod_p); extern char* CastPackageTypeName(const char* typName, Oid pkgOid, bool isPackage, bool isPublic = true); -#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid) extern bool IsBinaryType(Oid typid); - +#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid) +extern void check_type_supports_multi_charset(Oid typid, bool allow_array); #endif /* PARSE_TYPE_H */ diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h index 10c2e1323..5595c4eb7 100644 --- a/src/include/parser/parse_utilcmd.h +++ b/src/include/parser/parse_utilcmd.h @@ -52,6 +52,7 @@ typedef struct { List* uuids; /* used for create sequence */ bool isResizing; /* true if the table is resizing */ bool ofType; /* true if statement contains OF typename */ + Oid rel_coll_id; /* relation collation oid */ } CreateStmtContext; typedef enum TransformTableType { TRANSFORM_INVALID = 0, TRANSFORM_TO_HASHBUCKET, TRANSFORM_TO_NONHASHBUCKET} TransformTableType; @@ -95,9 +96,8 @@ extern char* getTmptableIndexName(const char* srcSchema, const char* srcIndex); extern IndexStmt* generateClonedIndexStmt( CreateStmtContext* cxt, Relation source_idx, const AttrNumber* attmap, int attmap_length, Relation rel, TransformTableType transformType); -extern int get_charset_by_collation(Oid colloid); -extern Oid get_default_collation_by_charset(int charset); extern Oid transform_default_collation(const char* collate, int charset, Oid def_coll_oid = InvalidOid, bool is_attr = false); +extern Oid check_collation_by_charset(const char* collate, int charset); #endif /* PARSE_UTILCMD_H */ diff --git a/src/include/rewrite/rewriteHandler.h b/src/include/rewrite/rewriteHandler.h index b21f3db15..cc2d136fa 100644 --- a/src/include/rewrite/rewriteHandler.h +++ b/src/include/rewrite/rewriteHandler.h @@ -36,6 +36,6 @@ extern List* QueryRewriteRefresh(Query *parsetree); extern List* QueryRewritePrepareStmt(Query *parsetree); extern Node* QueryRewriteNonConstant(Node *node); extern List* QueryRewriteSelectIntoVarList(Node *node, int res_len); -extern Const* processResToConst(char* value, Oid atttypid); +extern Const* processResToConst(char* value, Oid atttypid, Oid collid); #endif /* REWRITEHANDLER_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index a73108092..553049adb 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1011,8 +1011,11 @@ extern void text_to_cstring_buffer(const text* src, char* dst, size_t dst_len); extern int text_instr_3args(text* textStr, text* textStrToSearch, int32 beginIndex); extern int text_instr_4args(text* textStr, text* textStrToSearch, int32 beginIndex, int occurTimes); extern int32 text_length(Datum str); +extern int32 text_length_with_encoding(Datum str, int encoding); extern int text_cmp(text* arg1, text* arg2, Oid collid); extern text* text_substring(Datum str, int32 start, int32 length, bool length_not_specified); +extern text* text_substring_with_encoding( + Datum str, int32 start, int32 length, bool length_not_specified, int encoding); extern Datum instr_3args(PG_FUNCTION_ARGS); extern Datum instr_4args(PG_FUNCTION_ARGS); extern Datum byteain(PG_FUNCTION_ARGS); @@ -1105,6 +1108,7 @@ extern Datum bytea_string_agg_finalfn(PG_FUNCTION_ARGS); extern Datum string_agg_transfn(PG_FUNCTION_ARGS); extern Datum string_agg_finalfn(PG_FUNCTION_ARGS); extern Datum checksumtext_agg_transfn(PG_FUNCTION_ARGS); +extern Oid binary_need_transform_typeid(Oid tyeoid, Oid* collation); extern Datum group_concat_transfn(PG_FUNCTION_ARGS); extern Datum group_concat_finalfn(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/charset_gbk_b_db.out b/src/test/regress/expected/charset_gbk_b_db.out new file mode 100644 index 000000000..6fddbd39c --- /dev/null +++ b/src/test/regress/expected/charset_gbk_b_db.out @@ -0,0 +1,3616 @@ +CREATE DATABASE c_gbk_b_db WITH ENCODING 'gbk' LC_COLLATE='C' LC_CTYPE='C' DBCOMPATIBILITY 'B'; +\c c_gbk_b_db +SET b_format_behavior_compat_options = 'all'; +SHOW b_format_behavior_compat_options; + b_format_behavior_compat_options +---------------------------------- + all +(1 row) + +-- ------------------------------------------ +SET NAMES 'gbk'; +SHOW client_encoding; + client_encoding +----------------- + GBK +(1 row) + +SHOW server_encoding; + server_encoding +----------------- + GBK +(1 row) + +SHOW character_set_connection; + character_set_connection +-------------------------- + GBK +(1 row) + +SHOW collation_connection; + collation_connection +---------------------- + gbk_chinese_ci +(1 row) + +set enable_expr_fusion = ON; +-- -- CONST charset and collation +SELECT _utf8mb4'高斯' COLLATE gbk_chinese_ci; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT _utf8mb4'高斯' COLLATE gbk_chinese_ci; + ^ +SELECT _utf8mb4'高斯' COLLATE 'binary'; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT _utf8mb4'高斯' COLLATE 'binary'; + ^ +SELECT _utf8mb4'高斯' COLLATE "zh_CN.utf8"; + ?column? +---------- + ¸ß˹ +(1 row) + +SELECT _utf8mb4'高斯' COLLATE "C"; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "UTF8" which is different from server_encoding +LINE 1: SELECT _utf8mb4'高斯' COLLATE "C"; + ^ +SELECT _gbk'高斯' COLLATE gbk_chinese_ci; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk'高斯' COLLATE 'binary'; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT _gbk'高斯' COLLATE 'binary'; + ^ +SELECT _gbk'高斯' COLLATE "zh_CN.gbk"; -- support origin collation + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk'高斯' COLLATE "C"; -- support origin collation + ?column? +---------- + 高斯 +(1 row) + +-- -- CONST collation only +SELECT X'E9AB98E696AF' COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: SELECT X'E9AB98E696AF' COLLATE "utf8mb4_unicode_ci"; + ^ +SELECT X'E9AB98E696AF' COLLATE "binary"; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: ...111010011010101110011000111001101001011010101111' COLLATE "u... + ^ +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "binary"; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT 1 COLLATE "utf8mb4_unicode_ci"; -- not support yet +ERROR: collations are not supported by type integer +LINE 1: SELECT 1 COLLATE "utf8mb4_unicode_ci"; + ^ +SELECT 1 COLLATE "binary"; -- not support yet +ERROR: collations are not supported by type integer +LINE 1: SELECT 1 COLLATE "binary"; + ^ +SELECT CAST('高斯' AS bytea) COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: SELECT CAST('高斯' AS bytea) COLLATE "utf8mb4_unicode_ci"; + ^ +CONTEXT: referenced column: bytea +SELECT CAST('高斯' AS bytea) COLLATE "binary"; + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: SELECT CAST('E9AB98E696AF' AS blob) COLLATE "utf8mb4_unicode... + ^ +CONTEXT: referenced column: blob +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "binary"; + blob +-------------- + E9AB98E696AF +(1 row) + +SELECT '高斯' COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT '高斯' COLLATE "utf8mb4_unicode_ci"; + ^ +SELECT '高斯' COLLATE "gbk_chinese_ci"; + ?column? +---------- + 高斯 +(1 row) + +SELECT '高斯' COLLATE "gb18030_chinese_ci"; -- ERROR +ERROR: COLLATION "gb18030_chinese_ci" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT '高斯' COLLATE "gb18030_chinese_ci"; + ^ +SELECT '高斯' COLLATE "binary"; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT '高斯' COLLATE "binary"; + ^ +-- 中文 const charset +SELECT CAST('高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_binary'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_utf8mb4'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_gbk'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT _binary'高斯'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4'高斯'; + ?column? +---------- + ¸ß˹ +(1 row) + +SELECT _gbk'高斯'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gb18030'高斯'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk X'e9ab98e696af'; + ?column? +---------- + 高斯 +(1 row) + +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); -- ERROR +ERROR: the character set of convert_to function arguments must be server_encoding +SELECT COLLATION FOR(CAST('高斯' AS bytea)::text); + pg_collation_for +------------------ + gbk_chinese_ci +(1 row) + +-- -- 中文 const compare +-- -- -- same charset & explicit collation +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "utf8mb4_unicode_ci" +LINE 1: ...˜æ–¯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE ut... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_general_ci = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...' COLLATE utf8mb4_general_ci = _utf8mb4'高斯DB' COLLATE ut... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "C"; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "UTF8" which is different from server_encoding +LINE 1: ...˜æ–¯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "C... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "zh_CN.utf8"; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "zh_CN.utf8" +LINE 1: ...˜æ–¯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "z... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "DEFAULT"; -- ERROR +ERROR: COLLATION "default" is not valid for CHARACTER SET "UTF8" which is different from server_encoding +LINE 1: ...˜æ–¯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "D... + ^ +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: ...ELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB' COLLATE ut... + ^ +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB' COLLATE utf8mb4_bin; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GBK" +LINE 1: ...ELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB' COLLATE ut... + ^ +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB' COLLATE "C"; -- ERROR +ERROR: collation mismatch between explicit collations "gbk_chinese_ci" and "C" +LINE 1: ...gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB' COLLATE "C... + ^ +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB' COLLATE "zh_CN.gbk"; -- ERROR +ERROR: collation mismatch between explicit collations "gbk_chinese_ci" and "zh_CN.gbk" +LINE 1: ...gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB' COLLATE "z... + ^ +SELECT _gbk'高斯db' COLLATE gbk_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +ERROR: collation mismatch between explicit collations "gbk_bin" and "gbk_chinese_ci" +LINE 1: ...T _gbk'高斯db' COLLATE gbk_bin = _gbk'高斯DB' COLLATE gb... + ^ +SELECT _gb18030'高斯db' COLLATE gb18030_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_chinese_ci" +LINE 1: ...COLLATE gb18030_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; + ^ +-- -- -- same charset & implicit collation +SELECT _gbk'高斯DB' = '高斯DB'; + ?column? +---------- + t +(1 row) + +-- -- -- diff charset & explicit collation +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB' COLLATE 'binary'; -- not support yet +ERROR: operator does not exist: text = bytea +LINE 1: ...ECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯db' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ..._chinese_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; + ^ +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 1: ...ATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_bin; + ^ +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...ATE gbk_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ^ +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...B' COLLATE gbk_bin = _gb18030'高斯DB' COLLATE gb18030_bin; + ^ +-- -- -- diff charset & implicit collation +SELECT _utf8mb4'高斯DB' = _binary'高斯DB'; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _utf8mb4'高斯DB' = _binary'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = _utf8mb4'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = _binary'高斯DB'; -- not support yet +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _gbk'高斯DB' = _binary'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _gbk'高斯DB' = _gb18030'高斯DB'; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: SELECT _gbk'高斯DB' = _gb18030'高斯DB'; + ^ +SELECT _gb18030'高斯DB' = _utf8mb4'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gb18030'高斯DB' = _binary'高斯DB'; -- not support yet +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _gb18030'高斯DB' = _binary'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT '高斯DB' = _utf8mb4'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT '高斯DB' = _gb18030'高斯DB'; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: SELECT '高斯DB' = _gb18030'高斯DB'; + ^ +SELECT _binary'高斯DB' = _utf8mb4'高斯DB'; -- not support yet +ERROR: operator does not exist: bytea = text +LINE 1: SELECT _binary'高斯DB' = _utf8mb4'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _binary'高斯DB' = _gbk'高斯DB'; -- not support yet +ERROR: operator does not exist: bytea = text +LINE 1: SELECT _binary'高斯DB' = _gbk'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _binary'高斯DB' = _gb18030'高斯DB'; -- not support yet +ERROR: operator does not exist: bytea = text +LINE 1: SELECT _binary'高斯DB' = _gb18030'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +-- -- -- explicit & implicit +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "C"; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "zh_CN.gbk"; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'楂樻柉DB' = _gbk'高斯db' COLLATE gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'楂樻柉DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB'; +ERROR: operator does not exist: text = bytea +LINE 1: ...ECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _binary'高斯DB'; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _binary'高æ... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB'; + ?column? +---------- + t +(1 row) + +-- -- 中文 const concat +-- -- -- same charset & explicit collation +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE "C"); -- ERROR +ERROR: collation mismatch between explicit collations "gbk_chinese_ci" and "C" +LINE 1: ...gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE "C... + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE "zh_CN.gbk"); -- ERROR +ERROR: collation mismatch between explicit collations "gbk_chinese_ci" and "zh_CN.gbk" +LINE 1: ...gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE "z... + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE gbk_chinese_ci); + concat +------------------ + 高斯DB高斯DB +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE gbk_bin); -- ERROR +ERROR: collation mismatch between explicit collations "gbk_chinese_ci" and "gbk_bin" +LINE 1: ...gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE gb... + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB' COLLATE gbk_chinese_ci); -- ERROR +ERROR: collation mismatch between explicit collations "gbk_bin" and "gbk_chinese_ci" +LINE 1: ...ONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB' COLLATE gb... + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB' COLLATE gbk_bin); + concat +------------------ + 高斯DB高斯DB +(1 row) + +-- -- -- same charset & implicit collation +SELECT CONCAT(_gbk'高斯DB' , '高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_chinese_ci +(1 row) + +-- -- -- diff charset & explicit collation +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...' COLLATE gb18030_chinese_ci) result, collation for(result); + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 1: ...˜æ–¯DB' COLLATE gb18030_bin) result, collation for(result); + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...' COLLATE gb18030_chinese_ci) result, collation for(result); + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...˜æ–¯DB' COLLATE gb18030_bin) result, collation for(result); + ^ +-- -- -- diff charset & implicit collation +SELECT CONCAT(_utf8mb4'高斯DB' , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------+------------------ + 高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------+------------------ + 高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...˜æ–¯DB' , _gb18030'高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB' , '高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...18030'高斯DB' , '高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB' , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------+------------------ + 高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT( _binary'高斯DB', _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------+------------------ + \xe9ab98e696af4442高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT( _binary'高斯DB', '高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------+------------------ + \xe9ab98e696af4442高斯DB | gbk_chinese_ci +(1 row) + +-- -- -- explicit & implicit +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "C") result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | "C" +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "zh_CN.gbk") result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | "zh_CN.gbk" +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gbk'高斯db' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gb18030'高斯db' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 高斯DB高斯db | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | gb18030_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + ¸ß˹DB\xe9ab98e696af4442 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + ¸ß˹DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+------------------ + ¸ß˹DB\xe9ab98e696af4442 | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 高斯DB高斯DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gb18030_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(_binary'高斯DB', _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci) result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + \xe9ab98e696af4442¸ß˹DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_binary'高斯DB' COLLATE 'binary', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------+------------------ + \xe9ab98e696af4442高斯DB | gbk_chinese_ci +(1 row) + +-- -- -- concat 3 args +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------------------+------------------ + \xe9ab98e696af4442高斯DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------------------------+------------------ + \xe9ab98e696af4442高斯DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------+-------------------- + ¸ß˹DB高斯DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------------+------------------ + ¸ß˹DB高斯DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _binary'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------------------+------------------ + 高斯DB高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci, _binary'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------------+-------------------- + ¸ß˹DB高斯DB\xe9ab98e696af4442 | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...˜æ–¯DB', _utf8mb4'高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _binary'高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...高斯DB', _binary'高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB' COLLATE gb18030_chinese_ci, _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------+-------------------- + 高斯DB高斯DB¸ß˹DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci, _binary'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------------------+------------------ + 高斯DB高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +-- -- -- const compare CONCAT +SELECT _utf8mb4'楂樻柉DB' = CONCAT(_gbk'高斯DB'); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB'); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...B楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB'); + ^ +-- -- -- const CONCAT CONCAT +SELECT CONCAT(_utf8mb4'楂樻柉DB', CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 高斯DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB', CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); + result | pg_collation_for +----------------------------------+-------------------- + 高斯DB高斯DB高斯DB高斯DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); + result | pg_collation_for +----------------------------------+------------------ + 高斯DB高斯DB高斯DB高斯DB | utf8mb4_bin +(1 row) + +-- -- -- const CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT('高斯DB', opengauss_version()) result, collation for(result); + result | pg_collation_for +---------------+------------------ + 高斯DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), '高斯DB') result, collation for(result); + result | pg_collation_for +---------------+------------------ + 5.1.0高斯DB | utf8_general_ci +(1 row) + +SELECT CONCAT('高斯DB', 123) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 高斯DB123 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(123, '高斯DB') result, collation for(result); + result | pg_collation_for +-------------+------------------ + 123高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT('高斯DB', DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 高斯DB05-01-2023 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', '高斯DB') result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 05-01-2023高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT('高斯DB', NULL) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, '高斯DB') result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +-- -- -- -- diff charset +SELECT CONCAT(_utf8mb4'高斯DB', opengauss_version()) result, collation for(result); + result | pg_collation_for +-------------+------------------ + ¸ß˹DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +-------------+------------------ + 5.1.0¸ß˹DB | utf8_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', 123) result, collation for(result); + result | pg_collation_for +-----------+-------------------- + ¸ß˹DB123 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(123, _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +-----------+-------------------- + 123¸ß˹DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +------------------+-------------------- + ¸ß˹DB05-01-2023 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 05-01-2023¸ß˹DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', NULL) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(NULL, _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +-- -- -- CONCAT CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT(CONCAT('高斯DB'), opengauss_version()) result, collation for(result); + result | pg_collation_for +---------------+------------------ + 高斯DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +---------------+------------------ + 5.1.0高斯DB | utf8_general_ci +(1 row) + +SELECT CONCAT(CONCAT('高斯DB'), 123) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 高斯DB123 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(123, CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 123高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT('高斯DB'), DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 高斯DB05-01-2023 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 05-01-2023高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT('高斯DB'), NULL) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +-- -- -- -- diff charset +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), opengauss_version()) result, collation for(result); + result | pg_collation_for +-------------+------------------ + ¸ß˹DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), CONCAT(_utf8mb4'高斯DB')) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 5.1.0¸ß˹DB | utf8_general_ci +(1 row) + +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), 123) result, collation for(result); + result | pg_collation_for +-----------+-------------------- + ¸ß˹DB123 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(123, CONCAT(_utf8mb4'高斯DB')) result, collation for(result); + result | pg_collation_for +-----------+-------------------- + 123¸ß˹DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +------------------+-------------------- + ¸ß˹DB05-01-2023 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', CONCAT(_utf8mb4'高斯DB')) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 05-01-2023¸ß˹DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), NULL) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(NULL, CONCAT(_utf8mb4'高斯DB')) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +-- -- -- CONCAT NUMBERS +SELECT CONCAT('100', 200) result, collation for(result); + result | pg_collation_for +--------+------------------ + 100200 | gbk_chinese_ci +(1 row) + +SELECT CONCAT('100', date'2021-01-01') result, collation for(result); + result | pg_collation_for +---------------+------------------ + 10001-01-2021 | gbk_chinese_ci +(1 row) + +SELECT CONCAT('100', NULL) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT('100', NULL::bytea) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT('100', NULL::text) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(100, 200) result, collation for(result); + result | pg_collation_for +--------+------------------ + 100200 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(100, date'2021-01-01') result, collation for(result); + result | pg_collation_for +---------------+------------------ + 10001-01-2021 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(100, NULL) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(100, NULL::bytea) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(100, NULL::text) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, NULL::bytea) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, NULL::text) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL), '100') result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::bytea), '100') result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::text), '100') result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL), 100) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::bytea), 100) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::text), 100) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +-- -- 中文 with column charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea +-----------+-----------+----------+----------+--------------+--------------+-------------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 +(1 row) + +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + length | length | length | length | length | length | length +--------+--------+--------+--------+--------+--------+-------- + 5 | 5 | 5 | 5 | 5 | 5 | 8 +(1 row) + +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + lengthb | lengthb | lengthb | lengthb | lengthb | lengthb | length +---------+---------+---------+---------+---------+---------+-------- + 11 | 11 | 8 | 8 | 8 | 8 | 8 +(1 row) + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高æ'::text) + Filter: ((futf8_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + futf8_bin +----------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高æ'::text) + Filter: ((futf8_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + futf8_bin +----------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高æ'::text) + Filter: ((fgbk_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高æ'::text) + Filter: ((fgbk_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + fgbk_bin +---------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高æ'::text) + Filter: ((fgb18030_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高æ'::text) + Filter: ((fgb18030_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +reset enable_seqscan; +-- -- COLUMN collation only +SELECT futf8_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT futf8_bin COLLATE gbk_chinese_ci FROM t_diff_charset_... + ^ +SELECT futf8_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT futf8_bin COLLATE 'binary' FROM t_diff_charset_column... + ^ +SELECT futf8_bin COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "UTF8" which is different from server_encoding +LINE 1: SELECT futf8_bin COLLATE "C" FROM t_diff_charset_columns; + ^ +SELECT fgbk_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT fgbk_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT fgbk_bin COLLATE 'binary' FROM t_diff_charset_columns... + ^ +SELECT fgbk_bin COLLATE "zh_CN.gbk" FROM t_diff_charset_columns; -- support origin collation + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT fgbk_bin COLLATE "C" FROM t_diff_charset_columns; -- support origin collation + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT fgb18030_bin COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +SELECT fgb18030_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "GB18030" +LINE 1: SELECT fgb18030_bin COLLATE gbk_chinese_ci FROM t_diff_chars... + ^ +SELECT fgb18030_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GB18030" +LINE 1: SELECT fgb18030_bin COLLATE 'binary' FROM t_diff_charset_col... + ^ +SELECT fgb18030_bin COLLATE "zh_CN.gb18030" FROM t_diff_charset_columns; -- ERROR + fgb18030_bin +-------------- + 高斯DB +(1 row) + +SELECT fgb18030_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GB18030" which is different from server_encoding +LINE 1: SELECT fgb18030_bin COLLATE "C" FROM t_diff_charset_columns; + ^ +SELECT fbytea COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for binary type +LINE 1: SELECT fbytea COLLATE gbk_chinese_ci FROM t_diff_charset_col... + ^ +CONTEXT: referenced column: fbytea +SELECT fbytea COLLATE 'binary' FROM t_diff_charset_columns; + fbytea +-------------------- + \xe9ab98e696af4442 +(1 row) + +SELECT fbytea COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "zh_CN.utf8" is not valid for binary type +LINE 1: SELECT fbytea COLLATE "zh_CN.utf8" FROM t_diff_charset_colum... + ^ +CONTEXT: referenced column: fbytea +SELECT fbytea COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for binary type +LINE 1: SELECT fbytea COLLATE "C" FROM t_diff_charset_columns; + ^ +CONTEXT: referenced column: fbytea +SELECT fblob COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for binary type +LINE 1: SELECT fblob COLLATE gbk_chinese_ci FROM t_diff_charset_colu... + ^ +CONTEXT: referenced column: fblob +SELECT fblob COLLATE 'binary' FROM t_diff_charset_columns; + fblob +-------------- + E9AB98E696AF +(1 row) + +SELECT fblob COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "zh_CN.utf8" is not valid for binary type +LINE 1: SELECT fblob COLLATE "zh_CN.utf8" FROM t_diff_charset_column... + ^ +CONTEXT: referenced column: fblob +SELECT fblob COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for binary type +LINE 1: SELECT fblob COLLATE "C" FROM t_diff_charset_columns; + ^ +CONTEXT: referenced column: fblob +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE gbk_chinese_c... + ^ +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE 'binary' FROM... + ^ +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR + futf8_uni +----------- + 高斯db +(1 row) + +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "UTF8" which is different from server_encoding +LINE 1: SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "C" FROM t_di... + ^ +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE utf8mb4_unicode_ci FROM t_diff_charset_columns; + futf8_uni +----------- + 高斯db +(1 row) + +SELECT (fgbk_chi COLLATE "C") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT (fgbk_chi COLLATE "C") COLLATE utf8mb4_bin FROM t_dif... + ^ +SELECT (fgbk_chi COLLATE "C") COLLATE gbk_chinese_ci FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db +(1 row) + +SELECT (fblob COLLATE "binary") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "utf8mb4_bin" is not valid for binary type +LINE 1: SELECT (fblob COLLATE "binary") COLLATE utf8mb4_bin FROM t_d... + ^ +CONTEXT: referenced column: fblob +SELECT fbit COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: collations are not supported by type bit varying +LINE 1: SELECT fbit COLLATE 'binary' FROM t_diff_charset_columns; + ^ +CONTEXT: referenced column: fbit +-- -- COLUMN compare COLUMN +-- -- -- same charset & implicit collation +SELECT futf8_bin = futf8_uni, futf8_uni = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT fgbk_bin = fgbk_chi, fgbk_chi = fgbk_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT fgb18030_bin = fgb18030_chi, fgb18030_chi = fgb18030_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT futf8_gen = futf8_uni, futf8_uni = futf8_gen FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...utf8_uni, futf8_uni = futf8_gen FROM t_diff_charset_columns; + ^ +SELECT futf8_gen > futf8_uni, futf8_uni > futf8_gen FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...utf8_uni, futf8_uni > futf8_gen FROM t_diff_charset_columns; + ^ +-- -- -- diff charset & implicit collation +SELECT futf8_bin = fgbk_bin, fgbk_bin = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_bin = fgbk_chi, fgbk_chi = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT futf8_bin = fgb18030_bin, fgb18030_bin = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_bin = fgb18030_chi, fgb18030_chi = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT futf8_uni = fgbk_bin, fgbk_bin = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_uni = fgbk_chi, fgbk_chi = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_uni = fgb18030_bin, fgb18030_bin = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_uni = fgb18030_chi, fgb18030_chi = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT fgbk_bin = fgb18030_bin, fgb18030_bin = fgbk_bin FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...30_bin, fgb18030_bin = fgbk_bin FROM t_diff_charset_columns; + ^ +SELECT fgbk_bin = fgb18030_chi, fgb18030_chi = fgbk_bin FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...30_chi, fgb18030_chi = fgbk_bin FROM t_diff_charset_columns; + ^ +SELECT fgbk_chi = fgb18030_chi, fgb18030_chi = fgbk_chi FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...30_chi, fgb18030_chi = fgbk_chi FROM t_diff_charset_columns; + ^ +-- -- -- with binary & implicit collation +SELECT futf8_bin = fbytea, fbytea = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT futf8_bin = fbytea, fbytea = futf8_bin FROM t_diff_ch... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT futf8_bin = fblob, fblob = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "æ" +SELECT futf8_uni = fbytea, fbytea = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT futf8_uni = fbytea, fbytea = futf8_uni FROM t_diff_ch... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT futf8_uni = fblob, fblob = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "æ" +SELECT fgbk_bin = fbytea, fbytea = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT fgbk_bin = fbytea, fbytea = fgbk_bin FROM t_diff_char... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT fgbk_bin = fblob, fblob = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "é" +SELECT fgb18030_bin = fbytea, fbytea = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT fgb18030_bin = fbytea, fbytea = fgb18030_bin FROM t_d... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT fgb18030_bin = fblob, fblob = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "é" +SELECT fbytea = fblob, fblob = fbytea FROM t_diff_charset_columns; +ERROR: operator does not exist: bytea = blob +LINE 1: SELECT fbytea = fblob, fblob = fbytea FROM t_diff_charset_co... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +-- -- COLUMN concat COLUMN +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(fgbk_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | gbk_bin +(1 row) + +SELECT CONCAT(fgb18030_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | gb18030_bin +(1 row) + +SELECT CONCAT(futf8_gen, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- result is _bin +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_uni, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯db高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯db高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(fgbk_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- with binary & implicit collation +SELECT CONCAT(futf8_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-------------------------------+------------------ + 楂樻柉DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(futf8_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-------------------------+------------------ + 楂樻柉DBE9AB98E696AF | gbk_chinese_ci +(1 row) + +SELECT CONCAT(futf8_uni, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-------------------------------+------------------ + 楂樻柉db\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(futf8_uni, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-------------------------+------------------ + 楂樻柉dbE9AB98E696AF | gbk_chinese_ci +(1 row) + +SELECT CONCAT(fgbk_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +----------------------------+------------------ + 高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(fgbk_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +----------------------+------------------ + 高斯DBE9AB98E696AF | gbk_chinese_ci +(1 row) + +SELECT CONCAT(fgb18030_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +----------------------------+------------------ + 高斯DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(fgb18030_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +----------------------+------------------ + 高斯DBE9AB98E696AF | gbk_chinese_ci +(1 row) + +SELECT CONCAT(fbytea, fblob) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------------------------+------------------ + \xe9ab98e696af4442E9AB98E696AF | gbk_chinese_ci +(1 row) + +-- -- concat column and @uservar +set enable_set_variable_b_format=on; +-- -- -- string var utf8mb4_general_ci +set @var_utf8_gen = _utf8mb4'高斯DB' COLLATE utf8mb4_general_ci; -- should support +SELECT collation for(@var_utf8_gen); + pg_collation_for +-------------------- + utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_uni, @var_utf8_gen) result, collation for(result) FROM t_diff_charset_columns; -- null collation +ERROR: collation mismatch between collations "utf8mb4_unicode_ci" and "utf8mb4_general_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_bin, @var_utf8_gen) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_general_ci + result | pg_collation_for +----------------+-------------------- + 高斯DB¸ß˹DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(@var_utf8_gen, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- _bin + result | pg_collation_for +----------------+------------------ + ¸ß˹DB高斯DB | utf8mb4_bin +(1 row) + +-- -- -- string var gbk_chinese_ci +set @var_gbk_chi = '高斯DB' COLLATE gbk_chinese_ci; -- should support +SELECT collation for(@var_gbk_chi); + pg_collation_for +------------------ + gbk_chinese_ci +(1 row) + +SELECT CONCAT(futf8_uni, @var_gbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- futf8_uni + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(@var_gbk_chi, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_bin +(1 row) + +-- -- -- number var +set @var_num = 5.0; +SELECT CONCAT(futf8_bin, @var_num) result, collation for(result) FROM t_diff_charset_columns; -- futf8_bin + result | pg_collation_for +-----------+------------------ + 高斯DB5 | utf8mb4_bin +(1 row) + +SELECT CONCAT(@var_num, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin + result | pg_collation_for +-----------+------------------ + 5高斯DB | gbk_bin +(1 row) + +-- -- -- bytea var +set @var_binary = _binary'高斯DB'; -- not support yet +ERROR: failed to find conversion function from bytea to text +SELECT CONCAT(futf8_bin, @var_binary) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | utf8mb4_bin +(1 row) + +SELECT CONCAT(@var_binary, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | gbk_bin +(1 row) + +-- -- concat column and bind parameter +-- -- -- -- PBE with implicit collation +PREPARE test_merge_collation(text) AS +SELECT CONCAT(futf8_uni, $1) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- $1 use collation_connection, futf8_uni + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate utf8mb4_unicode_ci); -- explicit noneffective, futf8_uni + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +EXECUTE test_merge_collation(_gbk'高斯DB'); -- _gbk noneffective, futf8_uni + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with implicit collation +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; -- $1 use collation_connection, ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 2: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +DEALLOCATE test_merge_collation; +ERROR: prepared statement "test_merge_collation" does not exist +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate utf8mb4_unicode_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- $1 use collation_connection, ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 2: SELECT CONCAT($1 collate utf8mb4_unicode_ci, futf8_bin) resu... + ^ +DEALLOCATE test_merge_collation; +ERROR: prepared statement "test_merge_collation" does not exist +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate gbk_chinese_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- gbk_chinese_ci + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_chinese_ci +(1 row) + +EXECUTE test_merge_collation(_gbk'高斯DB'); -- gbk_chinese_ci + result | pg_collation_for +------------------+------------------ + 高斯DB高斯DB | gbk_chinese_ci +(1 row) + +DEALLOCATE test_merge_collation; +-- -- concat for DERIVATION +-- -- -- same charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(futf8_bin, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin collate utf8mb4_unicode_ci) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(futf8_bin collate utf8mb4_unicode_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(futf8_gen), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- conflict +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(futf8_uni, CONCAT(futf8_gen)) result, collation for(result) FROM t_diff_charset_columns; -- conflict +ERROR: collation mismatch between collations "utf8mb4_unicode_ci" and "utf8mb4_general_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(futf8_uni, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +---------------+-------------------- + 高斯db5.1.0 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(opengauss_version(), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +---------------+-------------------- + 5.1.0高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(fgbk_chi, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯db高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT('高斯DB', fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯DB高斯db | gbk_chinese_ci +(1 row) + +SELECT CONCAT(futf8_uni, 123) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+-------------------- + 高斯db123 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(123, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+-------------------- + 123高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------------+-------------------- + 高斯db05-01-2023 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------------+-------------------- + 05-01-2023高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, NULL) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(NULL, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + | utf8mb4_unicode_ci +(1 row) + +-- -- -- diff charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), CONCAT(fgbk_chi, fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(fgbk_chi, fgb18030_chi), CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi COLLATE gbk_chinese_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi, CONCAT(fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(fgb18030_bin), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_bin" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +---------------+------------------ + 高斯db5.1.0 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(opengauss_version(), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +---------------+------------------ + 5.1.0高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(futf8_uni, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT('高斯DB', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯DB高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(fgbk_chi, 123) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+------------------ + 高斯db123 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(123, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+------------------ + 123高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(fgbk_chi, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------------+------------------ + 高斯db05-01-2023 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------------+------------------ + 05-01-2023高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(fgbk_chi, NULL) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | gbk_bin +(1 row) + +-- -- test explicit collate on concat +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯DB高斯db | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_bin, futf8_uni) COLLATE gbk_chinese_ci r... + ^ +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE gbk_chinese_ci re... + ^ +-- -- -- with binary & implicit collation +SELECT CONCAT(fbytea, futf8_uni) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT CONCAT(fbytea, futf8_uni) COLLATE "binary" result, co... + ^ +SELECT CONCAT(fbytea, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text +ERROR: COLLATION "utf8mb4_general_ci" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT CONCAT(fbytea, futf8_uni) COLLATE utf8mb4_general_ci ... + ^ +-- -- test explicit collate on blob result +SELECT CAST('DEADBEEF' AS blob) COLLATE utf8mb4_general_ci result; -- ERROR +ERROR: COLLATION "utf8mb4_general_ci" is not valid for binary type +LINE 1: SELECT CAST('DEADBEEF' AS blob) COLLATE utf8mb4_general_ci r... + ^ +CONTEXT: referenced column: result +SELECT CAST('DEADBEEF' AS blob) COLLATE "binary" result; + result +---------- + DEADBEEF +(1 row) + +-- -- case when +-- -- -- condition same charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | gbk_bin +(1 row) + +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CASE WHEN (futf8_gen = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT CASE futf8_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | gbk_bin +(1 row) + +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CASE futf8_gen WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- condition same charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+-------------------- + 高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+-------------------- + 高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT CASE futf8_bin WHEN futf8_uni THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+-------------------- + 高斯DB | utf8mb4_unicode_ci +(1 row) + +-- -- -- condition diff charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | gbk_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE fgbk_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | gbk_bin +(1 row) + +SELECT CASE fgbk_bin WHEN fgb18030_bin THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- condition diff charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgb18030_chi) ELSE (fgbk_chi) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE fgbk_bin WHEN futf8_uni THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE fgb18030_chi WHEN fgbk_chi THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- in +-- -- -- column utf8 +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 2: ...mns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); + ^ +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...mns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); + ^ +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); + QUERY PLAN +--------------------------------------------------------------------- + Seq Scan on t_diff_charset_columns + Filter: ((futf8_bin)::text = ANY ('{高斯DB,高斯DB}'::text[])) +(2 rows) + +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); + futf8_bin +----------- + 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 2: ...WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); + ^ +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); + ^ +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.futf8_gen FROM t_diff_charset_columns t2); + futf8_bin +----------- +(0 rows) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.futf8_uni FROM t_diff_charset_columns t2); +ERROR: collation mismatch between collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...gen in (SELECT t2.futf8_uni FROM t_diff_charset_columns t2); + ^ +-- -- -- column gbk +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 2: ..._columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB'); + ^ +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE gbk_bin); + QUERY PLAN +------------------------------------------------------------------------------------ + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ('{高斯DB,高斯DB}'::text[] COLLATE gbk_bin)) +(2 rows) + +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE gbk_bin); + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); + QUERY PLAN +---------------------------------------------------------------------------------- + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ('{¸ß˹DB,高斯DB}'::text[] COLLATE gbk_bin)) +(2 rows) + +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ((ARRAY['高斯DB'::character varying, (concat('高斯DB'::text))::character varying])::text[])) +(2 rows) + +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.fgbk_chi FROM t_diff_charset_columns t2); + futf8_bin +----------- +(0 rows) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.futf8_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- +(0 rows) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgb18030_bin FROM t_diff_charset_columns t2); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 1: ... in (SELECT t2.fgb18030_bin FROM t_diff_charset_columns t2); + ^ +-- -- COALESCE +SELECT COALESCE(fgbk_chi, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT COALESCE(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT COALESCE(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +ERROR: collation mismatch between collations "utf8mb4_unicode_ci" and "utf8mb4_general_ci" +LINE 1: ... result, collation for (result) FROM t_diff_charset_columns; + ^ +SELECT COALESCE(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ... result, collation for (result) FROM t_diff_charset_columns; + ^ +-- -- GREATEST +SELECT GREATEST(fgbk_chi, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT GREATEST(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; + result | pg_collation_for +----------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT GREATEST(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +ERROR: collation mismatch between collations "utf8mb4_unicode_ci" and "utf8mb4_general_ci" +LINE 1: ... result, collation for (result) FROM t_diff_charset_columns; + ^ +SELECT GREATEST(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ... result, collation for (result) FROM t_diff_charset_columns; + ^ +-- -- XMLEXPR +SELECT xmlelement(NAME a, fgbk_chi, futf8_bin) result FROM t_diff_charset_columns; +ERROR: multi character set for datatype 'xml' is not supported +SELECT xmlelement(NAME a, futf8_gen, futf8_bin) result FROM t_diff_charset_columns; +ERROR: multi character set for datatype 'xml' is not supported +SELECT xmlelement(NAME a, futf8_uni, futf8_gen) result FROM t_diff_charset_columns; -- conflict +ERROR: multi character set for datatype 'xml' is not supported +SELECT xmlelement(NAME a, fgbk_chi, fgb18030_chi) result FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ... fgbk_chi, fgb18030_chi) result FROM t_diff_charset_columns; + ^ +SELECT xmlconcat(xmlelement(NAME a, fgbk_chi, futf8_bin), xmlelement(NAME b, fgb18030_chi)) result FROM t_diff_charset_columns; +ERROR: multi character set for datatype 'xml' is not supported +-- -- rowcompare +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db'); + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi +-----------+-----------+----------+----------+--------------+-------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db +(1 row) + +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB'); + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi +-----------+-----------+----------+----------+--------------+-------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db +(1 row) + +-- -- aggregate +SELECT count(futf8_bin), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin; + count | futf8_bin +-------+----------- + 1 | 高斯DB +(1 row) + +SELECT count(fgbk_bin), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin; + count | fgbk_bin +-------+---------- + 1 | 高斯DB +(1 row) + +SELECT count(fgb18030_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + count | fgb18030_bin +-------+-------------- + 1 | 高斯DB +(1 row) + +SELECT group_concat(futf8_bin, fgbk_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + group_concat | fgb18030_bin +------------------+-------------- + 高斯DB高斯db | 高斯DB +(1 row) + +SELECT group_concat(fgbk_bin, fgbk_chi order by futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + group_concat | fgb18030_bin +------------------+-------------- + 高斯DB高斯db | 高斯DB +(1 row) + +SELECT group_concat(DISTINCT fgbk_bin, futf8_bin order by fgbk_bin, futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + group_concat | fgb18030_bin +------------------+-------------- + 高斯DB高斯DB | 高斯DB +(1 row) + +-- -- UNION +-- -- -- const +select _utf8mb4'高斯' union select _gbk'高斯'; + ?column? +---------- + 高斯 + ¸ß˹ +(2 rows) + +select _gb18030'高斯' union select _gbk'高斯'; -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: select _gb18030'高斯' union select _gbk'高斯'; + ^ +HINT: You can choose the collation by applying the COLLATE clause to one or both expressions. +-- -- -- column +select futf8_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; + futf8_bin +----------- + 高斯DB +(1 row) + +select fgb18030_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_bin" +LINE 3: select fgbk_bin FROM t_diff_charset_columns; + ^ +HINT: You can choose the collation by applying the COLLATE clause to one or both expressions. +-- -- -- explicit +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db +(1 row) + +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union all + select fgbk_bin FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db + 高斯DB +(2 rows) + +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + INTERSECT + select fgbk_bin FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db +(1 row) + +-- -- -- mixed +select _utf8mb4'高斯', futf8_bin FROM t_diff_charset_columns + union + select _gbk'高斯', fgbk_bin FROM t_diff_charset_columns; + ?column? | futf8_bin +----------+----------- + 高斯 | 高斯DB + ¸ß˹ | 高斯DB +(2 rows) + +select _utf8mb4'GS', futf8_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_bin FROM t_diff_charset_columns; + ?column? | futf8_bin +----------+----------- + GS | 高斯DB +(1 row) + +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_chi FROM t_diff_charset_columns; + ?column? | fgbk_bin +----------+---------- + GS | 高斯DB + GS | 高斯db +(2 rows) + +-- -- -- 3 select +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_bin FROM t_diff_charset_columns; + ?column? | fgbk_bin +----------+---------- + GS | 高斯DB +(1 row) + +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; + ?column? | fgbk_bin +----------+---------- + GS | 高斯DB +(1 row) + +-- -- -- complex select +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + ?column? | group_concat | fgbk_bin +----------+------------------+---------- + GS | 高斯DB高斯db | 高斯DB +(1 row) + +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi COLLATE gb18030_chinese_ci), fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns GROUP BY fgb18030_chi; + ?column? | group_concat | fgbk_bin +----------+------------------+---------- + GS | 高斯DB高斯db | 高斯DB +(1 row) + +DROP TABLE t_diff_charset_columns; +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +NOTICE: table "t_charset_utf8mb4" does not exist, skipping +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_utf8mb4_id_seq" for serial column "t_charset_utf8mb4.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_utf8mb4_pkey" for table "t_charset_utf8mb4" +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB'; + QUERY PLAN +---------------------------------- + Seq Scan on t_charset_utf8mb4 + Filter: (a = '高斯DB'::text) +(2 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; + QUERY PLAN +------------------------------------------ + Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '高斯db'::text) +(2 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db'; + QUERY PLAN +------------------------------------------ + Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '高斯db'::text) +(2 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '¸ß˹DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '¸ß˹db'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: ...harset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_un... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯' ORDER BY id; + id | a | b +----+--------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 2 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' OR... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+----------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(5 rows) + +DELETE FROM t_charset_utf8mb4 WHERE a='高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a='高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +DROP TABLE IF EXISTS t_charset_utf8mb4; +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +NOTICE: table "t_charset_gbk" does not exist, skipping +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_gbk_id_seq" for serial column "t_charset_gbk.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_gbk_pkey" for table "t_charset_gbk" +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +INSERT INTO t_charset_gbk SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB'; + QUERY PLAN +---------------------------------- + Seq Scan on t_charset_gbk + Filter: (a = '高斯DB'::text) +(2 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; + QUERY PLAN +---------------------------------- + Seq Scan on t_charset_gbk + Filter: (a = '高斯db'::text) +(2 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +------------------------------------------------------ + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '¸ß˹DB'::text COLLATE gbk_bin) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +---------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '¸ß˹db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: ...rset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; + QUERY PLAN +---------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '¸ß˹db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; + id | a | b +----+--------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 2 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER ... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+----------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(5 rows) + +DELETE FROM t_charset_gbk WHERE a='高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea= _binary'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +DROP TABLE IF EXISTS t_charset_gbk; +set enable_expr_fusion = OFF; +-- ------------------------------------------ +-- SET NAMES utf8mb4; +SET NAMES utf8mb4; +SHOW client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +SHOW server_encoding; + server_encoding +----------------- + GBK +(1 row) + +SHOW character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +SHOW collation_connection; + collation_connection +---------------------- + utf8mb4_general_ci +(1 row) + +-- 中文 +SELECT CAST('高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_binary'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_utf8mb4'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_gbk'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT _binary'高斯'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4'高斯'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk'高斯'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _binary X'E9AB98E696AF'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4 X'E9AB98E696AF'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk X'E9AB98E696AF'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT '楂樻柉'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); -- ERROR +ERROR: the character set of convert_to function arguments must be server_encoding +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); -- ERROR +ERROR: the character set of convert_to function arguments must be server_encoding +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +NOTICE: table "t_charset_utf8mb4" does not exist, skipping +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_utf8mb4_id_seq" for serial column "t_charset_utf8mb4.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_utf8mb4_pkey" for table "t_charset_utf8mb4" +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1; + QUERY PLAN +----------------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '楂樻柉DB'::text COLLATE pg_catalog.utf8mb4_bin) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 4 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; + QUERY PLAN +------------------------------------------------ + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '楂樻柉db'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: ..._utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 4 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1; + QUERY PLAN +-------------------------------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '楂樻柉db'::text COLLATE pg_catalog.utf8mb4_unicode_ci) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 4 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '高斯DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '高斯db'::text COLLATE pg_catalog.utf8mb4_unicode_ci) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | 高斯DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; + id | a | b +----+--------+---------------------- + 2 | 楂樻柉 | \xe6a582e6a8bbe69f89 +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯' ORDER BY id; + id | a | b +----+------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDE... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' ORDER BY id; + id | a | b +----+----------+-------------------- + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 5 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 5 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_utf8mb4 SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+--------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 5 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(6 rows) + +DELETE FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a::bytea=_binary'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +DROP TABLE IF EXISTS t_charset_utf8mb4; +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +NOTICE: table "t_charset_gbk" does not exist, skipping +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_gbk_id_seq" for serial column "t_charset_gbk.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_gbk_pkey" for table "t_charset_gbk" +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_gbk SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1; + QUERY PLAN +---------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '楂樻柉DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 3 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; + QUERY PLAN +---------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '楂樻柉db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: ... t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci L... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 3 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '高斯DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '高斯db'::text COLLATE pg_catalog.utf8mb4_unicode_ci) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; + QUERY PLAN +---------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '高斯db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 2 | 高斯DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; + id | a | b +----+------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 2 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯DB' ORDER BY id; + id | a | b +----+----------+-------------------- + 3 | 楂樻柉DB | \xe9ab98e696af4442 + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 3 | 楂樻柉DB | \xe9ab98e696af4442 + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; + id | a | b +----+--------+---------------------- + 5 | 楂樻柉 | \xe6a582e6a8bbe69f89 +(1 row) + +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; + id | a | b +----+--------+---------------------- + 5 | 楂樻柉 | \xe6a582e6a8bbe69f89 +(1 row) + +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_gbk SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+--------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 5 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(6 rows) + +DELETE FROM t_charset_gbk WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea=_binary'高斯DB'; -- DELETE 0 +DELETE FROM t_charset_gbk WHERE a::bytea= E'\\xB8DFCBB94442'::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +DROP TABLE IF EXISTS t_charset_gbk; +-- test multi charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea +-----------+-----------+----------+----------+--------------+--------------+-------------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 +(1 row) + +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; -- 5 + length | length | length | length | length | length | length +--------+--------+--------+--------+--------+--------+-------- + 4 | 4 | 4 | 4 | 4 | 4 | 8 +(1 row) + +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + lengthb | lengthb | lengthb | lengthb | lengthb | lengthb | length +---------+---------+---------+---------+---------+---------+-------- + 8 | 8 | 6 | 6 | 6 | 6 | 8 +(1 row) + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高斯'::text) + Filter: ((futf8_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + futf8_bin +----------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高斯'::text) + Filter: ((futf8_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + futf8_bin +----------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高斯'::text) + Filter: ((fgbk_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高斯'::text) + Filter: ((fgbk_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + fgbk_bin +---------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高斯'::text) + Filter: ((fgb18030_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高斯'::text) + Filter: ((fgb18030_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +reset enable_seqscan; +DROP TABLE t_diff_charset_columns; +\c regression diff --git a/src/test/regress/expected/charset_utf8mb4_b_db.out b/src/test/regress/expected/charset_utf8mb4_b_db.out new file mode 100644 index 000000000..8fdc86aae --- /dev/null +++ b/src/test/regress/expected/charset_utf8mb4_b_db.out @@ -0,0 +1,4775 @@ +CREATE DATABASE c_utf8mb4_b_db WITH ENCODING 'utf8mb4' LC_COLLATE='C' LC_CTYPE='C' DBCOMPATIBILITY 'B'; +\c c_utf8mb4_b_db +-- test _charset syntax +-- -- test _charset COMPATIBILITY +SET b_format_behavior_compat_options = ''; +SHOW b_format_behavior_compat_options; + b_format_behavior_compat_options +---------------------------------- + +(1 row) + +SELECT _gbk'ABCD' = _utf8mb4'ABCD'; -- ERROR +ERROR: type "_gbk" does not exist +LINE 1: SELECT _gbk'ABCD' = _utf8mb4'ABCD'; + ^ +CREATE TABLE test_charset_syntax(_utf8 text); +DROP TABLE test_charset_syntax; +SET b_format_behavior_compat_options = 'all'; +SHOW b_format_behavior_compat_options; + b_format_behavior_compat_options +---------------------------------- + all +(1 row) + +SELECT _gbk'ABCD' = _utf8mb4'ABCD'; + ?column? +---------- + t +(1 row) + +CREATE TABLE test_charset_syntax(_utf8 text); -- ERROR +ERROR: syntax error at or near "_utf8" +LINE 1: CREATE TABLE test_charset_syntax(_utf8 text); + ^ +CREATE TABLE test_charset_syntax(_column text); +DROP TABLE test_charset_syntax; +-- -- test _charset + expression +SELECT _utf8mb4 10; -- ERROR +ERROR: syntax error at or near "10" +LINE 1: SELECT _utf8mb4 10; + ^ +SELECT _utf8mb4 CONCAT('高斯', 'DB'); -- ERROR +ERROR: syntax error at or near "CONCAT" +LINE 1: SELECT _utf8mb4 CONCAT('高斯', 'DB'); + ^ +SELECT _utf8_mb4'ABCD' = _Utf-8mB4'ABCD'; -- ERROR +ERROR: syntax error at or near "'ABCD'" +LINE 1: SELECT _utf8_mb4'ABCD' = _Utf-8mB4'ABCD'; + ^ +SELECT __utf8mb4'ABCD' = __Utf8mB4'ABCD'; -- special + ?column? +---------- + t +(1 row) + +SELECT _gbk'ABCD' = _GbK'ABCD'; + ?column? +---------- + t +(1 row) + +SELECT _binary E'', _binary E'' IS NULL; + ?column? | ?column? +----------+---------- + \x | f +(1 row) + +SELECT _binary E'\\xe9ab98e696af'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4 E'\\xe9ab98e696af'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _gbk E'\\xe9ab98e696af'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4 X'\\xe9ab98e696af'; -- ERROR, X'string' equal 'string' +ERROR: "\" is not a valid hexadecimal digit +LINE 1: SELECT _utf8mb4 X'\\xe9ab98e696af'; + ^ +SELECT _binary X'', _binary X'' IS NULL; + ?column? | ?column? +----------+---------- + \x | f +(1 row) + +SELECT _binary X'E9AB98E696AF'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4 X'E9AB98E696AF'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk X'E9AB98E696AF'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _binary B'', _binary B'' IS NULL; + ?column? | ?column? +----------+---------- + \x | f +(1 row) + +SELECT _binary B'0'; + ?column? +---------- + \x00 +(1 row) + +SELECT _binary B'111010011010101110011000111001101001011010101111'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4 B'111010011010101110011000111001101001011010101111'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk B'111010011010101110011000111001101001011010101111'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _utf8mb4 B'111010011010101110011000111001101001011010101111高斯'; -- ERROR +ERROR: "é" is not a valid binary digit +LINE 1: SELECT _utf8mb4 B'111010011010101110011000111001101001011010... + ^ +SELECT _binary X'000D' | X'0BC0'; -- ERROR not support yet +ERROR: operator does not exist: bytea | bit +LINE 1: SELECT _binary X'000D' | X'0BC0'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +-- ------------------------------------------ +-- SET NAMES utf8mb4; +SET NAMES 'utf8mb4'; +SHOW client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +SHOW server_encoding; + server_encoding +----------------- + UTF8 +(1 row) + +SHOW character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +SHOW collation_connection; + collation_connection +---------------------- + utf8mb4_general_ci +(1 row) + +-- -- CONST charset and collation +SELECT _utf8mb4'高斯' COLLATE gbk_chinese_ci; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT _utf8mb4'高斯' COLLATE gbk_chinese_ci; + ^ +SELECT _utf8mb4'高斯' COLLATE 'binary'; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT _utf8mb4'高斯' COLLATE 'binary'; + ^ +SELECT _utf8mb4'高斯' COLLATE "zh_CN.utf8"; -- support origin collation + ?column? +---------- + 高斯 +(1 row) + +SELECT _utf8mb4'高斯' COLLATE "C"; -- support origin collation + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk'高斯' COLLATE gbk_chinese_ci; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _gbk'高斯' COLLATE 'binary'; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT _gbk'高斯' COLLATE 'binary'; + ^ +SELECT _gbk'高斯' COLLATE "zh_CN.gbk"; -- ERROR + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _gbk'高斯' COLLATE "C"; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GBK" which is different from server_encoding +LINE 1: SELECT _gbk'高斯' COLLATE "C"; + ^ +SELECT _gb18030'高斯' COLLATE gb18030_chinese_ci; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _gb18030'高斯' COLLATE gbk_chinese_ci; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "GB18030" +LINE 1: SELECT _gb18030'高斯' COLLATE gbk_chinese_ci; + ^ +SELECT _gb18030'高斯' COLLATE 'binary'; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GB18030" +LINE 1: SELECT _gb18030'高斯' COLLATE 'binary'; + ^ +SELECT _gb18030'高斯' COLLATE "zh_CN.gb18030"; -- ERROR + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _gb18030'高斯' COLLATE "C"; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GB18030" which is different from server_encoding +LINE 1: SELECT _gb18030'高斯' COLLATE "C"; + ^ +SELECT _binary'高斯' COLLATE gbk_chinese_ci; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for binary type +LINE 1: SELECT _binary'高斯' COLLATE gbk_chinese_ci; + ^ +SELECT _binary'高斯' COLLATE 'binary'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _binary'高斯' COLLATE "zh_CN.utf8"; -- ERROR +ERROR: COLLATION "zh_CN.utf8" is not valid for binary type +LINE 1: SELECT _binary'高斯' COLLATE "zh_CN.utf8"; + ^ +SELECT _binary'高斯' COLLATE "C"; -- ERROR +ERROR: COLLATION "C" is not valid for binary type +LINE 1: SELECT _binary'高斯' COLLATE "C"; + ^ +SELECT _binary'' COLLATE utf8mb4_bin; -- ERROR +ERROR: COLLATION "utf8mb4_bin" is not valid for binary type +LINE 1: SELECT _binary'' COLLATE utf8mb4_bin; + ^ +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE gbk_chinese_ci; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE gbk_chin... + ^ +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE 'binary'; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE 'binary'... + ^ +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE "zh_CN.utf8"; -- support origin collation + ?column? +---------- + 高斯 +(1 row) + +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE "C"; -- support origin collation + ?column? +---------- + 高斯 +(1 row) + +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE utf8mb4_unicode_ci; + ?column? +---------- + 高斯 +(1 row) + +SELECT (_gbk'高斯' COLLATE "C") COLLATE utf8mb4_bin; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GBK" which is different from server_encoding +LINE 1: SELECT (_gbk'高斯' COLLATE "C") COLLATE utf8mb4_bin; + ^ +SELECT (_gbk'高斯' COLLATE "C") COLLATE gbk_chinese_ci; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GBK" which is different from server_encoding +LINE 1: SELECT (_gbk'高斯' COLLATE "C") COLLATE gbk_chinese_ci; + ^ +SELECT (_binary'高斯' COLLATE "binary") COLLATE utf8mb4_bin; -- ERROR +ERROR: COLLATION "utf8mb4_bin" is not valid for binary type +LINE 1: SELECT (_binary'高斯' COLLATE "binary") COLLATE utf8mb4_bin; + ^ +-- -- CONST collation only +SELECT X'E9AB98E696AF' COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: SELECT X'E9AB98E696AF' COLLATE "utf8mb4_unicode_ci"; + ^ +SELECT X'E9AB98E696AF' COLLATE "binary"; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: ...111010011010101110011000111001101001011010101111' COLLATE "u... + ^ +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "binary"; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT 1 COLLATE "utf8mb4_unicode_ci"; -- not support yet +ERROR: collations are not supported by type integer +LINE 1: SELECT 1 COLLATE "utf8mb4_unicode_ci"; + ^ +SELECT 1 COLLATE "binary"; -- not support yet +ERROR: collations are not supported by type integer +LINE 1: SELECT 1 COLLATE "binary"; + ^ +SELECT CAST('高斯' AS bytea) COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: SELECT CAST('高斯' AS bytea) COLLATE "utf8mb4_unicode_ci"; + ^ +CONTEXT: referenced column: bytea +SELECT CAST('高斯' AS bytea) COLLATE "binary"; + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "utf8mb4_unicode_ci"; -- ERROR +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for binary type +LINE 1: SELECT CAST('E9AB98E696AF' AS blob) COLLATE "utf8mb4_unicode... + ^ +CONTEXT: referenced column: blob +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "binary"; + blob +-------------- + E9AB98E696AF +(1 row) + +SELECT '高斯' COLLATE "utf8mb4_unicode_ci"; + ?column? +---------- + 高斯 +(1 row) + +SELECT '高斯' COLLATE "gbk_chinese_ci"; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT '高斯' COLLATE "gbk_chinese_ci"; + ^ +SELECT '高斯' COLLATE "gb18030_chinese_ci"; -- ERROR +ERROR: COLLATION "gb18030_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT '高斯' COLLATE "gb18030_chinese_ci"; + ^ +SELECT '高斯' COLLATE "binary"; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT '高斯' COLLATE "binary"; + ^ +-- 中文 const charset +SELECT CAST('高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_binary'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_utf8mb4'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_gbk'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT _binary'高斯'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4'高斯'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _gbk'高斯'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _gb18030'高斯'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT _gbk X'e9ab98e696af'; + ?column? +---------- + 楂樻柉 +(1 row) + +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); + convert_to +---------------- + \xe9ab98e696af +(1 row) + +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); + convert_to +------------ + \xb8dfcbb9 +(1 row) + +-- test datatype +-- -- ARRAY TEST +SELECT array[_utf8mb4'高斯']; + array +-------- + {高斯} +(1 row) + +SELECT array[_gbk'高斯']; + array +---------- + {楂樻柉} +(1 row) + +create table tarray(a text[]); +insert into tarray values(array[_utf8mb4'高斯']); +insert into tarray values(array[_gbk'高斯']); -- ERROR +ERROR: multi character set for datatype '_text' is not supported +CONTEXT: referenced column: a +insert into tarray values(_utf8mb4'{高斯}'::text[]); +insert into tarray values(_gbk'{高斯}'::text[]); -- ERROR +ERROR: multi character set for datatype '_text' is not supported +CONTEXT: referenced column: a +drop table tarray; +-- -- JSON TEST +SELECT _utf8mb4'"高斯"'::json; + json +-------- + "高斯" +(1 row) + +SELECT _gbk'"高斯"'::json; -- ERROR +ERROR: multi character set for datatype 'json' is not supported +create table tjson(a json); +insert into tjson values(_utf8mb4'"高斯"'::json); +insert into tjson values(_gbk'"高斯"'::json); -- ERROR +ERROR: multi character set for datatype 'json' is not supported +drop table tjson; +-- -- XML +SELECT xmlelement(NAME a, _utf8mb4'高斯'); + xmlelement +------------- + 高斯 +(1 row) + +SELECT xmlelement(NAME a, _gbk'高斯'); -- ERROR +ERROR: multi character set for datatype 'xml' is not supported +create table txml(a xml); +insert into txml values(_utf8mb4'高斯'::xml); +insert into txml values(_gbk'高斯'::xml); -- ERROR +ERROR: multi character set for datatype 'xml' is not supported +drop table txml; +-- -- tsvector +SELECT to_tsvector( _utf8mb4'高斯'); + to_tsvector +------------- + '高斯':1 +(1 row) + +SELECT to_tsvector(_gbk'高斯'); -- ERROR +ERROR: multi character set for datatype 'tsvector' is not supported +create table ttsvector(a tsvector); +insert into ttsvector values(_utf8mb4'高斯'::tsvector); +insert into ttsvector values(_gbk'高斯'::tsvector); -- ERROR +ERROR: multi character set for datatype 'tsvector' is not supported +drop table ttsvector; +-- -- hll +SELECT hll_hash_text( _utf8mb4'高斯'); + hll_hash_text +---------------------- + -1822827932029241973 +(1 row) + +SELECT hll_hash_text(_gbk'高斯'); -- ERROR +ERROR: multi character set for datatype 'hll_hashval' is not supported +-- test implicit type converion +select _gbk'111' collate "gbk_bin" = 111; + ?column? +---------- + t +(1 row) + +-- -- 中文 const compare +-- -- -- same charset & explicit collation +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "utf8mb4_unicode_ci" +LINE 1: ...b4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE ut... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_general_ci = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_general_ci" and "utf8mb4_unicode_ci" +LINE 1: ...DB' COLLATE utf8mb4_general_ci = _utf8mb4'高斯DB' COLLATE ut... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "C"; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "C" +LINE 1: ...b4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "C... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "zh_CN.utf8"; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "zh_CN.utf8" +LINE 1: ...b4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "z... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "DEFAULT"; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "default" +LINE 1: ...b4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "D... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "utf8mb4_unicode_ci" +LINE 1: ...T _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB' COLLATE ut... + ^ +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB' COLLATE utf8mb4_bin; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB' COLLATE "C"; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_unicode_ci" and "C" +LINE 1: ...mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB' COLLATE "C... + ^ +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB' COLLATE "zh_CN.utf8"; -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_unicode_ci" and "zh_CN.utf8" +LINE 1: ...mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB' COLLATE "z... + ^ +SELECT _gbk'高斯db' COLLATE gbk_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +ERROR: collation mismatch between explicit collations "gbk_bin" and "gbk_chinese_ci" +LINE 1: ...ELECT _gbk'高斯db' COLLATE gbk_bin = _gbk'高斯DB' COLLATE gb... + ^ +SELECT _gb18030'高斯db' COLLATE gb18030_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_chinese_ci" +LINE 1: ...' COLLATE gb18030_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; + ^ +-- -- -- same charset & implicit collation +SELECT _utf8mb4'高斯DB' = '高斯DB'; + ?column? +---------- + t +(1 row) + +-- -- -- diff charset & explicit collation +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB' COLLATE 'binary'; -- not support yet +ERROR: operator does not exist: text = bytea +LINE 1: ...ELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯db' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...bk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; + ^ +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 1: ...LLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_bin; + ^ +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...LLATE gbk_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ^ +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...DB' COLLATE gbk_bin = _gb18030'高斯DB' COLLATE gb18030_bin; + ^ +-- -- -- diff charset & implicit collation +SELECT _utf8mb4'高斯DB' = _binary'高斯DB'; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _utf8mb4'高斯DB' = _binary'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = _utf8mb4'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = _binary'高斯DB'; -- not support yet +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _gbk'高斯DB' = _binary'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _gbk'高斯DB' = _gb18030'高斯DB'; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: SELECT _gbk'高斯DB' = _gb18030'高斯DB'; + ^ +SELECT _gb18030'高斯DB' = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gb18030'高斯DB' = _utf8mb4'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gb18030'高斯DB' = _binary'高斯DB'; -- not support yet +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _gb18030'高斯DB' = _binary'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT '高斯DB' = _utf8mb4'高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT '高斯DB' = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT '高斯DB' = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _binary'高斯DB' = _utf8mb4'高斯DB'; -- not support yet +ERROR: operator does not exist: bytea = text +LINE 1: SELECT _binary'高斯DB' = _utf8mb4'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _binary'高斯DB' = _gbk'高斯DB'; -- not support yet +ERROR: operator does not exist: bytea = text +LINE 1: SELECT _binary'高斯DB' = _gbk'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _binary'高斯DB' = _gb18030'高斯DB'; -- not support yet +ERROR: operator does not exist: bytea = text +LINE 1: SELECT _binary'高斯DB' = _gb18030'高斯DB'; + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +-- -- -- explicit & implicit +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE utf8mb4_unicode_ci; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE utf8mb4_bin; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "C"; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "zh_CN.utf8"; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'楂樻柉DB' = _gbk'高斯db' COLLATE gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'楂樻柉DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB'; +ERROR: operator does not exist: text = bytea +LINE 1: ...ELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _binary'高斯DB'; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _binary'高斯DB... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB'; + ?column? +---------- + t +(1 row) + +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB'; + ?column? +---------- + f +(1 row) + +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB'; + ?column? +---------- + t +(1 row) + +-- -- 中文 const concat +-- -- -- same charset & explicit collation +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE "C"); -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_unicode_ci" and "C" +LINE 1: ...mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE "C... + ^ +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE "zh_CN.utf8"); -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_unicode_ci" and "zh_CN.utf8" +LINE 1: ...mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE "z... + ^ +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE utf8mb4_unicode_ci); + concat +-------------- + 高斯DB高斯DB +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE utf8mb4_bin); -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_unicode_ci" and "utf8mb4_bin" +LINE 1: ...mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE ut... + ^ +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB' COLLATE utf8mb4_unicode_ci); -- ERROR +ERROR: collation mismatch between explicit collations "utf8mb4_bin" and "utf8mb4_unicode_ci" +LINE 1: ...T(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB' COLLATE ut... + ^ +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB' COLLATE utf8mb4_bin); + concat +-------------- + 高斯DB高斯DB +(1 row) + +-- -- -- same charset & implicit collation +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB') result, collation for(result); + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_general_ci +(1 row) + +-- -- -- diff charset & explicit collation +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...' COLLATE gb18030_chinese_ci) result, collation for(result); + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 1: ...'高斯DB' COLLATE gb18030_bin) result, collation for(result); + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...' COLLATE gb18030_chinese_ci) result, collation for(result); + ^ +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...'高斯DB' COLLATE gb18030_bin) result, collation for(result); + ^ +-- -- -- diff charset & implicit collation +SELECT CONCAT(_utf8mb4'高斯DB' , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + 高斯DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 楂樻柉DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + 高斯DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...k'高斯DB' , _gb18030'高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB' , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 楂樻柉DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_gb18030'高斯DB' , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + 高斯DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT( _binary'高斯DB', _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + \xe9ab98e696af4442高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT( _binary'高斯DB', '高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + \xe9ab98e696af4442高斯DB | utf8mb4_general_ci +(1 row) + +-- -- -- explicit & implicit +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "C") result, collation for(result); + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | "C" +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "zh_CN.utf8") result, collation for(result); + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | "zh_CN.utf8" +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE utf8mb4_unicode_ci) result, collation for(result); + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE utf8mb4_bin) result, collation for(result); + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gbk'高斯db' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------+------------------ + 楂樻柉DB楂樻柉db | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | gbk_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gb18030'高斯db' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 楂樻柉DB楂樻柉db | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | gb18030_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB') result, collation for(result); + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + 高斯DB\xe9ab98e696af4442 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB') result, collation for(result); + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+------------------ + 高斯DB\xe9ab98e696af4442 | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 楂樻柉DB楂樻柉DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); + result | pg_collation_for +------------------+------------------ + 楂樻柉DB楂樻柉DB | gb18030_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + 楂樻柉DB高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 楂樻柉DB楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB') result, collation for(result); + result | pg_collation_for +----------------+------------------ + 楂樻柉DB高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB') result, collation for(result); + result | pg_collation_for +------------------+------------------ + 楂樻柉DB楂樻柉DB | gbk_bin +(1 row) + +SELECT CONCAT(_binary'高斯DB', _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci) result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + \xe9ab98e696af4442高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(_binary'高斯DB' COLLATE 'binary', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + \xe9ab98e696af4442高斯DB | utf8mb4_general_ci +(1 row) + +-- -- -- concat 3 args +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------------+-------------------- + \xe9ab98e696af4442高斯DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------------------------+------------------ + \xe9ab98e696af4442楂樻柉DB楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------+-------------------- + 高斯DB楂樻柉DB楂樻柉DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); + result | pg_collation_for +------------------------+------------------ + 高斯DB楂樻柉DB楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _binary'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------------------+-------------------- + 高斯DB高斯DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci, _binary'高斯DB') result, collation for(result); + result | pg_collation_for +----------------------------------+-------------------- + 高斯DB楂樻柉DB\xe9ab98e696af4442 | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...bk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _binary'高斯DB') result, collation for(result); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...gbk'高斯DB', _binary'高斯DB') result, collation for(result); + ^ +SELECT CONCAT(_gb18030'高斯DB' COLLATE gb18030_chinese_ci, _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------+-------------------- + 楂樻柉DB楂樻柉DB高斯DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci, _binary'高斯DB') result, collation for(result); + result | pg_collation_for +------------------------------------+------------------ + 楂樻柉DB楂樻柉DB\xe9ab98e696af4442 | gbk_chinese_ci +(1 row) + +-- -- -- const compare CONCAT +SELECT _utf8mb4'楂樻柉DB' = CONCAT(_gbk'高斯DB'); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB'); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); + ?column? +---------- + t +(1 row) + +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB'); + ^ +-- -- -- const CONCAT CONCAT +SELECT CONCAT(_utf8mb4'楂樻柉DB', CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 楂樻柉DB楂樻柉DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB', CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); + result | pg_collation_for +----------------------------------+-------------------- + 楂樻柉DB楂樻柉DB楂樻柉DB楂樻柉DB | gb18030_chinese_ci +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +------------------+------------------ + 楂樻柉DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); + result | pg_collation_for +----------------------------------+------------------ + 楂樻柉DB楂樻柉DB楂樻柉DB楂樻柉DB | utf8mb4_bin +(1 row) + +-- -- -- const CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT('高斯DB', opengauss_version()) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 高斯DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), '高斯DB') result, collation for(result); + result | pg_collation_for +-------------+------------------ + 5.1.0高斯DB | utf8_general_ci +(1 row) + +SELECT CONCAT('高斯DB', 123) result, collation for(result); + result | pg_collation_for +-----------+-------------------- + 高斯DB123 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(123, '高斯DB') result, collation for(result); + result | pg_collation_for +-----------+-------------------- + 123高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT('高斯DB', DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 高斯DB05-01-2023 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', '高斯DB') result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 05-01-2023高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT('高斯DB', NULL) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(NULL, '高斯DB') result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +-- -- -- -- diff charset +SELECT CONCAT(_gbk'高斯DB', opengauss_version()) result, collation for(result); + result | pg_collation_for +---------------+------------------ + 楂樻柉DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +---------------+------------------ + 5.1.0楂樻柉DB | utf8_general_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB', 123) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 楂樻柉DB123 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(123, _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +-------------+------------------ + 123楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB', DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 楂樻柉DB05-01-2023 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 05-01-2023楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(_gbk'高斯DB', NULL) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, _gbk'高斯DB') result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +-- -- -- CONCAT CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT(CONCAT('高斯DB'), opengauss_version()) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 高斯DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 5.1.0高斯DB | utf8_general_ci +(1 row) + +SELECT CONCAT(CONCAT('高斯DB'), 123) result, collation for(result); + result | pg_collation_for +-----------+-------------------- + 高斯DB123 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(123, CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +-----------+-------------------- + 123高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT('高斯DB'), DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 高斯DB05-01-2023 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +------------------+-------------------- + 05-01-2023高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT('高斯DB'), NULL) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(NULL, CONCAT('高斯DB')) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +-- -- -- -- diff charset +SELECT CONCAT(CONCAT(_gbk'高斯DB'), opengauss_version()) result, collation for(result); + result | pg_collation_for +---------------+------------------ + 楂樻柉DB5.1.0 | utf8_general_ci +(1 row) + +SELECT CONCAT(opengauss_version(), CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +---------------+------------------ + 5.1.0楂樻柉DB | utf8_general_ci +(1 row) + +SELECT CONCAT(CONCAT(_gbk'高斯DB'), 123) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 楂樻柉DB123 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(123, CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +-------------+------------------ + 123楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(_gbk'高斯DB'), DATE '2023-05-01') result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 楂樻柉DB05-01-2023 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +--------------------+------------------ + 05-01-2023楂樻柉DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(_gbk'高斯DB'), NULL) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, CONCAT(_gbk'高斯DB')) result, collation for(result); + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +-- -- -- CONCAT NUMBERS +SELECT CONCAT('100', 200) result, collation for(result); + result | pg_collation_for +--------+-------------------- + 100200 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT('100', date'2021-01-01') result, collation for(result); + result | pg_collation_for +---------------+-------------------- + 10001-01-2021 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT('100', NULL) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT('100', NULL::bytea) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT('100', NULL::text) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(100, 200) result, collation for(result); + result | pg_collation_for +--------+-------------------- + 100200 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(100, date'2021-01-01') result, collation for(result); + result | pg_collation_for +---------------+-------------------- + 10001-01-2021 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(100, NULL) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(100, NULL::bytea) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(100, NULL::text) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(NULL, NULL::bytea) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(NULL, NULL::text) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL), '100') result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::bytea), '100') result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::text), '100') result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL), 100) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::bytea), 100) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONCAT(100, NULL::text), 100) result, collation for(result); + result | pg_collation_for +--------+-------------------- + | utf8mb4_general_ci +(1 row) + +-- -- 中文 with column charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea +-----------+-----------+----------+----------+--------------+--------------+-------------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 +(1 row) + +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + length | length | length | length | length | length | length +--------+--------+--------+--------+--------+--------+-------- + 4 | 4 | 4 | 4 | 4 | 4 | 8 +(1 row) + +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + lengthb | lengthb | lengthb | lengthb | lengthb | lengthb | length +---------+---------+---------+---------+---------+---------+-------- + 8 | 8 | 6 | 6 | 6 | 6 | 8 +(1 row) + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高斯'::text) + Filter: ((futf8_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + futf8_bin +----------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高斯'::text) + Filter: ((futf8_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + futf8_bin +----------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高斯'::text) + Filter: ((fgbk_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高斯'::text) + Filter: ((fgbk_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + fgbk_bin +---------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高斯'::text) + Filter: ((fgb18030_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高斯'::text) + Filter: ((fgb18030_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +reset enable_seqscan; +-- -- COLUMN collation only +SELECT futf8_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT futf8_bin COLLATE gbk_chinese_ci FROM t_diff_charset_... + ^ +SELECT futf8_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT futf8_bin COLLATE 'binary' FROM t_diff_charset_column... + ^ +SELECT futf8_bin COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- support origin collation + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin COLLATE "C" FROM t_diff_charset_columns; -- support origin collation + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT fgbk_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT fgbk_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GBK" +LINE 1: SELECT fgbk_bin COLLATE 'binary' FROM t_diff_charset_columns... + ^ +SELECT fgbk_bin COLLATE "zh_CN.gbk" FROM t_diff_charset_columns; -- ERROR + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT fgbk_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GBK" which is different from server_encoding +LINE 1: SELECT fgbk_bin COLLATE "C" FROM t_diff_charset_columns; + ^ +SELECT fgb18030_bin COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +SELECT fgb18030_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "GB18030" +LINE 1: SELECT fgb18030_bin COLLATE gbk_chinese_ci FROM t_diff_chars... + ^ +SELECT fgb18030_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "GB18030" +LINE 1: SELECT fgb18030_bin COLLATE 'binary' FROM t_diff_charset_col... + ^ +SELECT fgb18030_bin COLLATE "zh_CN.gb18030" FROM t_diff_charset_columns; -- ERROR + fgb18030_bin +-------------- + 高斯DB +(1 row) + +SELECT fgb18030_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GB18030" which is different from server_encoding +LINE 1: SELECT fgb18030_bin COLLATE "C" FROM t_diff_charset_columns; + ^ +SELECT fbytea COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for binary type +LINE 1: SELECT fbytea COLLATE gbk_chinese_ci FROM t_diff_charset_col... + ^ +CONTEXT: referenced column: fbytea +SELECT fbytea COLLATE 'binary' FROM t_diff_charset_columns; + fbytea +-------------------- + \xe9ab98e696af4442 +(1 row) + +SELECT fbytea COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "zh_CN.utf8" is not valid for binary type +LINE 1: SELECT fbytea COLLATE "zh_CN.utf8" FROM t_diff_charset_colum... + ^ +CONTEXT: referenced column: fbytea +SELECT fbytea COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for binary type +LINE 1: SELECT fbytea COLLATE "C" FROM t_diff_charset_columns; + ^ +CONTEXT: referenced column: fbytea +SELECT fblob COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for binary type +LINE 1: SELECT fblob COLLATE gbk_chinese_ci FROM t_diff_charset_colu... + ^ +CONTEXT: referenced column: fblob +SELECT fblob COLLATE 'binary' FROM t_diff_charset_columns; + fblob +-------------- + E9AB98E696AF +(1 row) + +SELECT fblob COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "zh_CN.utf8" is not valid for binary type +LINE 1: SELECT fblob COLLATE "zh_CN.utf8" FROM t_diff_charset_column... + ^ +CONTEXT: referenced column: fblob +SELECT fblob COLLATE "C" FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for binary type +LINE 1: SELECT fblob COLLATE "C" FROM t_diff_charset_columns; + ^ +CONTEXT: referenced column: fblob +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE gbk_chinese_c... + ^ +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE 'binary' FROM... + ^ +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- support origin collation + futf8_uni +----------- + 高斯db +(1 row) + +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "C" FROM t_diff_charset_columns; -- support origin collation + futf8_uni +----------- + 高斯db +(1 row) + +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE utf8mb4_unicode_ci FROM t_diff_charset_columns; + futf8_uni +----------- + 高斯db +(1 row) + +SELECT (fgbk_chi COLLATE "C") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GBK" which is different from server_encoding +LINE 1: SELECT (fgbk_chi COLLATE "C") COLLATE utf8mb4_bin FROM t_dif... + ^ +SELECT (fgbk_chi COLLATE "C") COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "C" is not valid for CHARACTER SET "GBK" which is different from server_encoding +LINE 1: SELECT (fgbk_chi COLLATE "C") COLLATE gbk_chinese_ci FROM t_... + ^ +SELECT (fblob COLLATE "binary") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "utf8mb4_bin" is not valid for binary type +LINE 1: SELECT (fblob COLLATE "binary") COLLATE utf8mb4_bin FROM t_d... + ^ +CONTEXT: referenced column: fblob +SELECT fbit COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +ERROR: collations are not supported by type bit varying +LINE 1: SELECT fbit COLLATE 'binary' FROM t_diff_charset_columns; + ^ +CONTEXT: referenced column: fbit +-- -- COLUMN compare COLUMN +-- -- -- same charset & implicit collation +SELECT futf8_bin = futf8_uni, futf8_uni = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT fgbk_bin = fgbk_chi, fgbk_chi = fgbk_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT fgb18030_bin = fgb18030_chi, fgb18030_chi = fgb18030_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT futf8_gen = futf8_uni, futf8_uni = futf8_gen FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_gen > futf8_uni, futf8_uni > futf8_gen FROM t_diff_charset_columns; -- ERROR +ERROR: could not determine which collation to use for string comparison +HINT: Use the COLLATE clause to set the collation explicitly. +-- -- -- diff charset & implicit collation +SELECT futf8_bin = fgbk_bin, fgbk_bin = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_bin = fgbk_chi, fgbk_chi = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT futf8_bin = fgb18030_bin, fgb18030_bin = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_bin = fgb18030_chi, fgb18030_chi = futf8_bin FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + f | f +(1 row) + +SELECT futf8_uni = fgbk_bin, fgbk_bin = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_uni = fgbk_chi, fgbk_chi = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_uni = fgb18030_bin, fgb18030_bin = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT futf8_uni = fgb18030_chi, fgb18030_chi = futf8_uni FROM t_diff_charset_columns; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +SELECT fgbk_bin = fgb18030_bin, fgb18030_bin = fgbk_bin FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...30_bin, fgb18030_bin = fgbk_bin FROM t_diff_charset_columns; + ^ +SELECT fgbk_bin = fgb18030_chi, fgb18030_chi = fgbk_bin FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...30_chi, fgb18030_chi = fgbk_bin FROM t_diff_charset_columns; + ^ +SELECT fgbk_chi = fgb18030_chi, fgb18030_chi = fgbk_chi FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...30_chi, fgb18030_chi = fgbk_chi FROM t_diff_charset_columns; + ^ +-- -- -- with binary & implicit collation +SELECT futf8_bin = fbytea, fbytea = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT futf8_bin = fbytea, fbytea = futf8_bin FROM t_diff_ch... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT futf8_bin = fblob, fblob = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "é" +SELECT futf8_uni = fbytea, fbytea = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT futf8_uni = fbytea, fbytea = futf8_uni FROM t_diff_ch... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT futf8_uni = fblob, fblob = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "é" +SELECT fgbk_bin = fbytea, fbytea = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT fgbk_bin = fbytea, fbytea = fgbk_bin FROM t_diff_char... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT fgbk_bin = fblob, fblob = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "¸" +SELECT fgb18030_bin = fbytea, fbytea = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: operator does not exist: character varying = bytea +LINE 1: SELECT fgb18030_bin = fbytea, fbytea = fgb18030_bin FROM t_d... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT fgb18030_bin = fblob, fblob = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +ERROR: invalid hexadecimal digit: "¸" +SELECT fbytea = fblob, fblob = fbytea FROM t_diff_charset_columns; +ERROR: operator does not exist: bytea = blob +LINE 1: SELECT fbytea = fblob, fblob = fbytea FROM t_diff_charset_co... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +-- -- COLUMN concat COLUMN +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(fgbk_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯db | gbk_bin +(1 row) + +SELECT CONCAT(fgb18030_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯db | gb18030_bin +(1 row) + +SELECT CONCAT(futf8_gen, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- result is _bin + result | pg_collation_for +--------------+------------------ + 高斯db高斯db | +(1 row) + +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_uni, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯db高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯db高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(fgbk_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- with binary & implicit collation +SELECT CONCAT(futf8_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +--------------------------+-------------------- + 高斯DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +--------------------+-------------------- + 高斯DBE9AB98E696AF | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_uni, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +--------------------------+-------------------- + 高斯db\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_uni, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +--------------------+-------------------- + 高斯dbE9AB98E696AF | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(fgbk_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-----------------------+-------------------- + ˹DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(fgbk_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-----------------+-------------------- + ˹DBE9AB98E696AF | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(fgb18030_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-----------------------+-------------------- + ˹DB\xe9ab98e696af4442 | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(fgb18030_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED + result | pg_collation_for +-----------------+-------------------- + ˹DBE9AB98E696AF | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(fbytea, fblob) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------------------------+-------------------- + \xe9ab98e696af4442E9AB98E696AF | utf8mb4_general_ci +(1 row) + +-- -- concat column and @uservar +set enable_set_variable_b_format=on; +-- -- -- string var utf8mb4_general_ci +set @var_utf8_uni = '高斯DB' COLLATE utf8mb4_unicode_ci; -- should support +SELECT collation for(@var_utf8_uni); + pg_collation_for +-------------------- + utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_gen, @var_utf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- null collation + result | pg_collation_for +--------------+------------------ + 高斯db高斯DB | +(1 row) + +SELECT CONCAT(fgbk_bin, @var_utf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_unicode_ci + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(@var_utf8_uni, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- _bin + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | utf8mb4_bin +(1 row) + +-- -- -- string var gbk_chinese_ci +set @var_gbk_chi = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- should support +SELECT collation for(@var_gbk_chi); + pg_collation_for +------------------ + gbk_chinese_ci +(1 row) + +SELECT CONCAT(futf8_uni, @var_gbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- futf8_uni + result | pg_collation_for +----------------+-------------------- + 高斯db楂樻柉DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(@var_gbk_chi, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin + result | pg_collation_for +----------------+------------------ + 楂樻柉DB高斯DB | gbk_bin +(1 row) + +-- -- -- number var +set @var_num = 5.0; +SELECT CONCAT(futf8_bin, @var_num) result, collation for(result) FROM t_diff_charset_columns; -- futf8_bin + result | pg_collation_for +---------+------------------ + 高斯DB5 | utf8mb4_bin +(1 row) + +SELECT CONCAT(@var_num, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin + result | pg_collation_for +---------+------------------ + 5高斯DB | gbk_bin +(1 row) + +-- -- -- bytea var +set @var_binary = _binary'高斯DB'; -- not support yet +ERROR: failed to find conversion function from bytea to text +SELECT CONCAT(futf8_bin, @var_binary) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | utf8mb4_bin +(1 row) + +SELECT CONCAT(@var_binary, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | gbk_bin +(1 row) + +-- -- concat column and bind parameter +-- -- -- -- PBE with implicit collation +PREPARE test_merge_collation(text) AS +SELECT CONCAT(futf8_uni, $1) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- $1 use collation_connection, conflict + result | pg_collation_for +--------------+------------------ + 高斯db高斯DB | +(1 row) + +EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate utf8mb4_unicode_ci); -- explicit noneffective, conflict + result | pg_collation_for +--------------+------------------ + 高斯db高斯DB | +(1 row) + +EXECUTE test_merge_collation(_gbk'高斯DB'); -- _gbk noneffective, conflict + result | pg_collation_for +--------------+------------------ + 高斯db高斯DB | +(1 row) + +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with implicit 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 + result | pg_collation_for +--------------+-------------------- + 高斯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) + +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate utf8mb4_unicode_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- utf8mb4_unicode_ci + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_unicode_ci +(1 row) + +EXECUTE test_merge_collation(_gbk'高斯DB'); -- utf8mb4_unicode_ci + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_unicode_ci +(1 row) + +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate gbk_chinese_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- $1 use collation_connection, ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 2: SELECT CONCAT($1 collate gbk_chinese_ci, futf8_bin) result, ... + ^ +DEALLOCATE test_merge_collation; +ERROR: prepared statement "test_merge_collation" does not exist +-- -- concat column and PROCEDURE parameter with CURSOR +-- -- -- implicit collation && string +create or replace procedure merge_collation_func(p1 text, p2 text) +as +DECLARE + concat_res text; + collation_res text; + concat_res_assign varchar(64); + CURSOR c1 IS + SELECT CONCAT(p1, p2) result, collation for(result); +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + concat_res_assign = concat_res; + set @concat_res = concat_res; + set @collation_res = collation_res; + set @concat_res_assign = concat_res_assign; +end; +/ +CALL merge_collation_func('高斯DB', _gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation,@concat_res_assign; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation | @concat_res_assign +----------------+--------------------+--------------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_general_ci | utf8mb4_general_ci | 高斯DB楂樻柉DB +(1 row) + +CALL merge_collation_func(_gb18030'高斯DB', _gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation,@concat_res_assign; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation | @concat_res_assign +------------------+--------------------+--------------------+-------------------- + 楂樻柉DB楂樻柉DB | utf8mb4_general_ci | utf8mb4_general_ci | 楂樻柉DB楂樻柉DB +(1 row) + +CALL merge_collation_func(_gb18030'高斯DB', _gbk'高斯DB' collate gbk_chinese_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation,@concat_res_assign; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation | @concat_res_assign +------------------+--------------------+--------------------+-------------------- + 楂樻柉DB楂樻柉DB | utf8mb4_general_ci | utf8mb4_general_ci | 楂樻柉DB楂樻柉DB +(1 row) + +DROP procedure merge_collation_func; +-- -- -- implicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(futf8_uni, p1) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict + @concat_res | @collation_res | real_collation +--------------+----------------+-------------------- + 高斯db高斯DB | | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict + @concat_res | @collation_res | real_collation +--------------+----------------+-------------------- + 高斯db高斯DB | | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation;; -- conflict + @concat_res | @collation_res | real_collation +----------------+----------------+-------------------- + 高斯db楂樻柉DB | | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation;; -- conflict + @concat_res | @collation_res | real_collation +----------------+----------------+-------------------- + 高斯db楂樻柉DB | | utf8mb4_general_ci +(1 row) + +DROP procedure merge_collation_func; +-- -- -- implicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(p1, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation +--------------+--------------------+-------------------- + 高斯DB高斯DB | utf8mb4_general_ci | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation +--------------+--------------------+-------------------- + 高斯DB高斯DB | utf8mb4_general_ci | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation +----------------+--------------------+-------------------- + 楂樻柉DB高斯DB | utf8mb4_general_ci | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci + @concat_res | @collation_res | real_collation +----------------+--------------------+-------------------- + 楂樻柉DB高斯DB | utf8mb4_general_ci | utf8mb4_general_ci +(1 row) + +DROP procedure merge_collation_func; +-- -- -- explicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(p1, fgbk_bin collate gbk_bin) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +--------------+----------------+-------------------- + 高斯DB高斯DB | gbk_bin | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +--------------+----------------+-------------------- + 高斯DB高斯DB | gbk_bin | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +----------------+----------------+-------------------- + 楂樻柉DB高斯DB | gbk_bin | utf8mb4_general_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +----------------+----------------+-------------------- + 楂樻柉DB高斯DB | gbk_bin | utf8mb4_general_ci +(1 row) + +DROP procedure merge_collation_func; +-- -- -- implicit collation && int +create or replace procedure merge_collation_func(p1 int) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(fgbk_bin, p1) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ +CALL merge_collation_func(100); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +-------------+----------------+-------------------- + 高斯DB100 | gbk_bin | utf8mb4_general_ci +(1 row) + +DROP procedure merge_collation_func; +-- -- -- explicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci)result, c... + ^ +QUERY: SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci)result, collation for(result)FROM t_diff_charset_columns +CONTEXT: PL/pgSQL function merge_collation_func(text) line 7 at OPEN +DROP procedure merge_collation_func; +-- -- concat column and PROCEDURE parameter with select into +-- -- -- implicit collation +create or replace procedure merge_collation_func(p1 text) +as +begin + SELECT CONCAT(futf8_uni, p1) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict + @concat_res | @collation_res | real_collation +--------------+--------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci | utf8mb4_unicode_ci +(1 row) + +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict + @concat_res | @collation_res | real_collation +--------------+--------------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci | utf8mb4_unicode_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_unicode_ci + @concat_res | @collation_res | real_collation +----------------+--------------------+-------------------- + 高斯db楂樻柉DB | utf8mb4_unicode_ci | utf8mb4_unicode_ci +(1 row) + +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_unicode_ci + @concat_res | @collation_res | real_collation +----------------+--------------------+-------------------- + 高斯db楂樻柉DB | utf8mb4_unicode_ci | utf8mb4_unicode_ci +(1 row) + +DROP procedure merge_collation_func; +-- -- -- implicit collation +create or replace procedure merge_collation_func(p1 text) +as +begin + SELECT CONCAT(p1, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +--------------+----------------+---------------- + 高斯DB高斯DB | gbk_bin | gbk_bin +(1 row) + +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +--------------+----------------+---------------- + 高斯DB高斯DB | gbk_bin | gbk_bin +(1 row) + +CALL merge_collation_func(_gbk'高斯DB'); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +----------------+----------------+---------------- + 楂樻柉DB高斯DB | gbk_bin | gbk_bin +(1 row) + +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); + merge_collation_func +---------------------- + +(1 row) + +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin + @concat_res | @collation_res | real_collation +----------------+----------------+---------------- + 楂樻柉DB高斯DB | gbk_bin | gbk_bin +(1 row) + +DROP procedure merge_collation_func; +-- -- -- explicit collation +create or replace procedure merge_collation_func(p1 text) +as +begin + SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res; +end; +/ +CALL merge_collation_func('高斯DB'); -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci) result, ... + ^ +QUERY: SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res +CONTEXT: PL/pgSQL function merge_collation_func(text) line 2 at SQL statement +DROP procedure merge_collation_func; +-- -- concat for DERIVATION +-- -- -- same charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯DB | +(1 row) + +SELECT CONCAT(futf8_bin, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside + result | pg_collation_for +--------------------+------------------ + 高斯DB高斯db高斯db | +(1 row) + +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin collate utf8mb4_unicode_ci) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_unicode_ci + result | pg_collation_for +--------------------+-------------------- + 高斯db高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_bin collate utf8mb4_unicode_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_unicode_ci + result | pg_collation_for +--------------------+-------------------- + 高斯DB高斯db高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(CONCAT(futf8_gen), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- conflict + result | pg_collation_for +--------------+------------------ + 高斯db高斯db | +(1 row) + +SELECT CONCAT(futf8_uni, CONCAT(futf8_gen)) result, collation for(result) FROM t_diff_charset_columns; -- conflict + result | pg_collation_for +--------------+------------------ + 高斯db高斯db | +(1 row) + +SELECT CONCAT(futf8_uni, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+-------------------- + 高斯db5.1.0 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(opengauss_version(), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+-------------------- + 5.1.0高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯db高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT('高斯DB', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, 123) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-----------+-------------------- + 高斯db123 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(123, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-----------+-------------------- + 123高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 高斯db05-01-2023 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+-------------------- + 05-01-2023高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, NULL) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(NULL, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + | utf8mb4_unicode_ci +(1 row) + +-- -- -- diff charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), CONCAT(fgbk_chi, fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(fgbk_chi, fgb18030_chi), CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯db | +(1 row) + +SELECT CONCAT(fgbk_chi, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯db | +(1 row) + +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns; -- gbk_chinese_ci + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯db | gbk_chinese_ci +(1 row) + +SELECT CONCAT(fgbk_chi COLLATE gbk_chinese_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- gbk_chinese_ci + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯db | gbk_chinese_ci +(1 row) + +SELECT CONCAT(CONCAT(futf8_gen, fgbk_chi), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- conflict + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯db | +(1 row) + +SELECT CONCAT(futf8_uni, CONCAT(futf8_gen, fgbk_chi)) result, collation for(result) FROM t_diff_charset_columns; -- conflict + result | pg_collation_for +--------------------+------------------ + 高斯db高斯db高斯db | +(1 row) + +SELECT CONCAT(fgbk_chi, CONCAT(fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(CONCAT(fgb18030_bin), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_bin" +LINE 1: ...) result, collation for(result) FROM t_diff_charset_columns; + ^ +SELECT CONCAT(fgbk_chi, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+------------------ + 高斯db5.1.0 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(opengauss_version(), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-------------+------------------ + 5.1.0高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(fgbk_chi, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯db高斯DB | gbk_chinese_ci +(1 row) + +SELECT CONCAT('高斯DB', fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯DB高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(fgbk_chi, 123) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-----------+------------------ + 高斯db123 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(123, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +-----------+------------------ + 123高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(fgbk_chi, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 高斯db05-01-2023 | gbk_chinese_ci +(1 row) + +SELECT CONCAT(DATE '2023-05-01', fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +------------------+------------------ + 05-01-2023高斯DB | gbk_bin +(1 row) + +SELECT CONCAT(fgbk_chi, NULL) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | gbk_chinese_ci +(1 row) + +SELECT CONCAT(NULL, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + | gbk_bin +(1 row) + +-- -- test explicit collate on concat +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯db | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_bin, futf8_uni) COLLATE gbk_chinese_ci r... + ^ +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+-------------------- + 高斯DB高斯DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE gbk_chinese_ci re... + ^ +-- -- -- with binary & implicit collation +SELECT CONCAT(fbytea, futf8_uni) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(fbytea, futf8_uni) COLLATE "binary" result, co... + ^ +SELECT CONCAT(fbytea, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text + result | pg_collation_for +--------------------------+-------------------- + \xe9ab98e696af4442高斯db | utf8mb4_general_ci +(1 row) + +-- -- test explicit collate on blob result +SELECT CAST('DEADBEEF' AS blob) COLLATE utf8mb4_general_ci result; -- ERROR +ERROR: COLLATION "utf8mb4_general_ci" is not valid for binary type +LINE 1: SELECT CAST('DEADBEEF' AS blob) COLLATE utf8mb4_general_ci r... + ^ +CONTEXT: referenced column: result +SELECT CAST('DEADBEEF' AS blob) COLLATE "binary" result; + result +---------- + DEADBEEF +(1 row) + +-- -- case when +-- -- -- condition same charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | gbk_bin +(1 row) + +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation + result | pg_collation_for +--------+------------------ + 高斯db | +(1 row) + +SELECT CASE WHEN (futf8_gen = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR + result | pg_collation_for +--------+------------------ + 高斯db | gbk_bin +(1 row) + +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT CASE futf8_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | gbk_bin +(1 row) + +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation + result | pg_collation_for +--------+------------------ + 高斯db | +(1 row) + +SELECT CASE futf8_gen WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR + result | pg_collation_for +--------+------------------ + 高斯db | gbk_bin +(1 row) + +-- -- -- condition same charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + 高斯db | utf8mb4_unicode_ci +(1 row) + +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + 高斯DB | utf8mb4_unicode_ci +(1 row) + +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT CASE futf8_bin WHEN futf8_uni THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+-------------------- + 高斯DB | utf8mb4_unicode_ci +(1 row) + +-- -- -- condition diff charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | gbk_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE fgbk_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | gbk_bin +(1 row) + +SELECT CASE fgbk_bin WHEN fgb18030_bin THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- condition diff charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgb18030_chi) ELSE (fgbk_chi) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_bin" and "gb18030_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE fgbk_bin WHEN futf8_uni THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯DB | utf8mb4_bin +(1 row) + +SELECT CASE fgb18030_chi WHEN fgbk_chi THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- -- -- conflict +SELECT CASE _gb18030'高斯' WHEN fgbk_bin THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_bin" +LINE 1: ...D result, collation for(result) FROM t_diff_charset_columns; + ^ +-- -- in +-- -- -- column utf8 +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 2: ...columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); + ^ +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: ...columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); + ^ +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); + QUERY PLAN +------------------------------------------------------------------- + Seq Scan on t_diff_charset_columns + Filter: ((futf8_bin)::text = ANY ('{楂樻柉DB,高斯DB}'::text[])) +(2 rows) + +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); + futf8_bin +----------- + 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Seq Scan on t_diff_charset_columns + Filter: ((futf8_bin)::text = ANY ((ARRAY['楂樻柉DB'::character varying, (concat('高斯DB'))::character varying])::text[])) +(2 rows) + +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.futf8_gen FROM t_diff_charset_columns t2); + futf8_bin +----------- +(0 rows) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.futf8_uni FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +-- -- -- column gbk +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB'); + QUERY PLAN +------------------------------------------------------------------ + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ('{楂樻柉DB,高斯DB}'::text[])) +(2 rows) + +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE utf8mb4_bin); + QUERY PLAN +-------------------------------------------------------------------------------------- + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ('{楂樻柉DB,高斯DB}'::text[] COLLATE utf8mb4_bin)) +(2 rows) + +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE utf8mb4_bin); + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); + QUERY PLAN +------------------------------------------------------------------ + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ('{高斯DB,楂樻柉DB}'::text[])) +(2 rows) + +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Seq Scan on t_diff_charset_columns + Filter: ((fgbk_bin)::text = ANY ((ARRAY['高斯DB'::character varying, (concat('楂樻柉DB'::text))::character varying])::text[])) +(2 rows) + +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); + fgbk_bin +---------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.fgbk_chi FROM t_diff_charset_columns t2); + futf8_bin +----------- +(0 rows) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.futf8_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- + 高斯DB +(1 row) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); + futf8_bin +----------- +(0 rows) + +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgb18030_bin FROM t_diff_charset_columns t2); -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_bin" +LINE 1: ... in (SELECT t2.fgb18030_bin FROM t_diff_charset_columns t2); + ^ +-- -- COALESCE +SELECT COALESCE(fgbk_chi, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT COALESCE(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT COALESCE(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict + result | pg_collation_for +--------+------------------ + 高斯db | +(1 row) + +SELECT COALESCE(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ... result, collation for (result) FROM t_diff_charset_columns; + ^ +-- -- GREATEST +SELECT GREATEST(fgbk_chi, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT GREATEST(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; + result | pg_collation_for +--------+------------------ + 高斯db | utf8mb4_bin +(1 row) + +SELECT GREATEST(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +ERROR: could not determine which collation to use for string comparison +HINT: Use the COLLATE clause to set the collation explicitly. +CONTEXT: referenced column: result +SELECT GREATEST(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gbk_chinese_ci" and "gb18030_chinese_ci" +LINE 1: ... result, collation for (result) FROM t_diff_charset_columns; + ^ +-- -- rowcompare +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db'); + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi +-----------+-----------+----------+----------+--------------+-------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db +(1 row) + +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB'); + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi +-----------+-----------+----------+----------+--------------+-------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db +(1 row) + +-- -- aggregate +SELECT count(futf8_bin), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin; + count | futf8_bin +-------+----------- + 1 | 高斯DB +(1 row) + +SELECT count(fgbk_bin), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin; + count | fgbk_bin +-------+---------- + 1 | 高斯DB +(1 row) + +SELECT count(fgb18030_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + count | fgb18030_bin +-------+-------------- + 1 | 高斯DB +(1 row) + +SELECT group_concat(futf8_bin, fgbk_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + group_concat | fgb18030_bin +--------------+-------------- + 高斯DB高斯db | 高斯DB +(1 row) + +SELECT group_concat(fgbk_bin, fgbk_chi order by futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + group_concat | fgb18030_bin +--------------+-------------- + 高斯DB高斯db | 高斯DB +(1 row) + +SELECT group_concat(DISTINCT fgbk_bin, futf8_bin order by fgbk_bin, futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + group_concat | fgb18030_bin +--------------+-------------- + 高斯DB高斯DB | 高斯DB +(1 row) + +-- -- UNION +-- -- -- const +select _utf8mb4'高斯' union select _gbk'高斯'; + ?column? +---------- + 楂樻柉 + 高斯 +(2 rows) + +select _gb18030'高斯' union select _gbk'高斯'; -- ERROR +ERROR: collation mismatch between collations "gb18030_chinese_ci" and "gbk_chinese_ci" +LINE 1: select _gb18030'高斯' union select _gbk'高斯'; + ^ +HINT: You can choose the collation by applying the COLLATE clause to one or both expressions. +-- -- -- column +select futf8_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; + futf8_bin +----------- + 高斯DB +(1 row) + +select fgb18030_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; -- ERROR +ERROR: collation mismatch between collations "gb18030_bin" and "gbk_bin" +LINE 3: select fgbk_bin FROM t_diff_charset_columns; + ^ +HINT: You can choose the collation by applying the COLLATE clause to one or both expressions. +-- -- -- explicit +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db +(1 row) + +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union all + select fgbk_bin FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db + 高斯DB +(2 rows) + +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + INTERSECT + select fgbk_bin FROM t_diff_charset_columns; + fgbk_chi +---------- + 高斯db +(1 row) + +-- -- -- mixed +select _utf8mb4'高斯', futf8_bin FROM t_diff_charset_columns + union + select _gbk'高斯', fgbk_bin FROM t_diff_charset_columns; + ?column? | futf8_bin +----------+----------- + 楂樻柉 | 高斯DB + 高斯 | 高斯DB +(2 rows) + +select _utf8mb4'GS', futf8_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_bin FROM t_diff_charset_columns; + ?column? | futf8_bin +----------+----------- + GS | 高斯DB +(1 row) + +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_chi FROM t_diff_charset_columns; + ?column? | fgbk_bin +----------+---------- + GS | 高斯DB + GS | 高斯db +(2 rows) + +-- -- -- 3 select +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_bin FROM t_diff_charset_columns; + ?column? | fgbk_bin +----------+---------- + GS | 高斯DB +(1 row) + +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; + ?column? | fgbk_bin +----------+---------- + GS | 高斯DB +(1 row) + +-- -- -- complex select +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + ?column? | group_concat | fgbk_bin +----------+--------------+---------- + GS | 高斯DB高斯db | 高斯DB +(1 row) + +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi COLLATE gb18030_chinese_ci), fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns GROUP BY fgb18030_chi; + ?column? | group_concat | fgbk_bin +----------+--------------+---------- + GS | 高斯DB高斯db | 高斯DB +(1 row) + +-- -- test COLLATE for function +-- -- -- for string function +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) COLLATE utf8mb4_general_ci result, collation for(result); + result | pg_collation_for +----------------+-------------------- + 高斯DB楂樻柉DB | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) COLLATE gbk_chinese_ci result, collation for(result); -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: ...unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) COLLATE gb... + ^ +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE utf8mb4_bin result, collation for(result); + result | pg_collation_for +----------------+------------------ + 高斯DB楂樻柉DB | utf8mb4_bin +(1 row) + +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE gbk_chinese_ci result, collation for(result); -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE gbk_c... + ^ +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE "binary" result, collation for(result); -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE "bina... + ^ +SELECT CONCAT(futf8_uni , futf8_gen) COLLATE utf8mb4_bin result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +--------------+------------------ + 高斯db高斯db | utf8mb4_bin +(1 row) + +SELECT CONCAT(futf8_uni , futf8_gen) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_uni , futf8_gen) COLLATE gbk_chinese_ci ... + ^ +-- -- -- for binary argument string function +SELECT CONCAT(_utf8mb4'高斯DB', _binary'高斯DB') COLLATE "binary" result, collation for(result); -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(_utf8mb4'高斯DB', _binary'高斯DB') COLLATE "bi... + ^ +SELECT CONCAT(_utf8mb4'高斯DB', _binary'高斯DB') COLLATE utf8mb4_unicode_ci result, collation for(result); + result | pg_collation_for +--------------------------+-------------------- + 高斯DB\xe9ab98e696af4442 | utf8mb4_unicode_ci +(1 row) + +SELECT CONCAT(futf8_uni, fbytea) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_uni, fbytea) COLLATE "binary" result, co... + ^ +SELECT CONCAT(futf8_uni, fbytea) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: SELECT CONCAT(futf8_uni, fbytea) COLLATE gbk_chinese_ci resu... + ^ +-- -- -- for binary function +SELECT CONVERT(fbytea, 'UTF8', 'GBK') COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- pg_collation_for binary type ERROR +ERROR: collations are not supported by type bytea +CONTEXT: referenced column: pg_collation_for +SELECT CONVERT(fbytea, 'UTF8', 'GBK') COLLATE "binary" result FROM t_diff_charset_columns; + result +---------------- + \xb8dfcbb94442 +(1 row) + +SELECT CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------------------+-------------------- + \xb8dfcbb94442高斯db | utf8mb4_general_ci +(1 row) + +SELECT CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- ERROR +ERROR: COLLATION "binary" is not valid for CHARACTER SET "UTF8" +LINE 1: ...CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) COLLATE "b... + ^ +SELECT CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) COLLATE utf8mb4_unicode_ci result, collation for(result) FROM t_diff_charset_columns; + result | pg_collation_for +----------------------+-------------------- + \xb8dfcbb94442高斯db | utf8mb4_unicode_ci +(1 row) + +DROP TABLE t_diff_charset_columns; +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +NOTICE: table "t_charset_utf8mb4" does not exist, skipping +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_utf8mb4_id_seq" for serial column "t_charset_utf8mb4.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_utf8mb4_pkey" for table "t_charset_utf8mb4" +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1; + QUERY PLAN +------------------------------------------------------------ + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '楂樻柉DB'::text COLLATE utf8mb4_bin) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 4 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; + QUERY PLAN +------------------------------------------------ + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '楂樻柉db'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: ..._utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 4 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1; + QUERY PLAN +--------------------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '楂樻柉db'::text COLLATE utf8mb4_unicode_ci) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 4 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '高斯DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +----------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '高斯db'::text COLLATE utf8mb4_unicode_ci) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | 高斯DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; + id | a | b +----+--------+---------------------- + 2 | 楂樻柉 | \xe6a582e6a8bbe69f89 +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯' ORDER BY id; + id | a | b +----+------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDE... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' ORDER BY id; + id | a | b +----+----------+-------------------- + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 5 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 5 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_utf8mb4 SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+--------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 5 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(6 rows) + +DELETE FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a::bytea=_binary'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +-- -- -- -- test assign expr +INSERT INTO t_charset_utf8mb4(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+--------+-------------------- + 7 | 高斯DB | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +INSERT INTO t_charset_utf8mb4(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+--------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +UPDATE t_charset_utf8mb4 SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+--------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | DB高斯 | \x4442e9ab98e696af +(2 rows) + +DROP TABLE IF EXISTS t_charset_utf8mb4; +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +NOTICE: table "t_charset_gbk" does not exist, skipping +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_gbk_id_seq" for serial column "t_charset_gbk.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_gbk_pkey" for table "t_charset_gbk" +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_gbk SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1; + QUERY PLAN +---------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '楂樻柉DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 3 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; + QUERY PLAN +---------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '楂樻柉db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: ... t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci L... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 3 | 楂樻柉DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '高斯DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '高斯db'::text COLLATE utf8mb4_unicode_ci) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; + QUERY PLAN +---------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '高斯db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 2 | 高斯DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; + id | a | b +----+------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 2 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯DB' ORDER BY id; + id | a | b +----+----------+-------------------- + 3 | 楂樻柉DB | \xe9ab98e696af4442 + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 3 | 楂樻柉DB | \xe9ab98e696af4442 + 4 | 楂樻柉DB | \xe9ab98e696af4442 + 6 | 楂樻柉DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; + id | a | b +----+--------+---------------------- + 5 | 楂樻柉 | \xe6a582e6a8bbe69f89 +(1 row) + +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; + id | a | b +----+--------+---------------------- + 5 | 楂樻柉 | \xe6a582e6a8bbe69f89 +(1 row) + +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_gbk SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+--------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 5 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(6 rows) + +DELETE FROM t_charset_gbk WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea=_binary'高斯DB'; -- DELETE 0 +DELETE FROM t_charset_gbk WHERE a::bytea= E'\\xB8DFCBB94442'::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +-- -- -- -- test assign expr +INSERT INTO t_charset_gbk(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_gbk SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+--------+-------------------- + 7 | 高斯DB | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +INSERT INTO t_charset_gbk(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+--------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +UPDATE t_charset_gbk SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+--------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | DB高斯 | \x4442e9ab98e696af +(2 rows) + +DROP TABLE IF EXISTS t_charset_gbk; +-- -- test partkey +CREATE TABLE t_multi_charset_partkey (part varchar(32) collate utf8mb4_general_ci, a int) + PARTITION BY RANGE(part) ( + partition p1 values less than('高斯DB'), + partition p2 values less than('高斯db'), + partition p3 values less than(MAXVALUE) +); -- ERROR +ERROR: partition bound of partition "p2" is too low +-- -- -- utf8mb4 +CREATE TABLE t_multi_charset_partkey (part varchar(32) collate utf8mb4_bin, a int) + PARTITION BY RANGE(part) ( + partition p1 values less than('楂樻柉DB'), + partition p2 values less than('楂樻柉db'), + partition p3 values less than('高斯DB'), + partition p4 values less than('高斯db'), + partition p5 values less than(MAXVALUE) +); +-- -- -- insert +INSERT INTO t_multi_charset_partkey VALUES(_gbk'高斯DB', 1); +INSERT INTO t_multi_charset_partkey VALUES(_gbk'高斯db', 2); +INSERT INTO t_multi_charset_partkey VALUES(_utf8mb4'高斯DB', 3); +INSERT INTO t_multi_charset_partkey VALUES(_utf8mb4'高斯db', 4); +-- -- -- select +SELECT * FROM t_multi_charset_partkey PARTITION(p1) order by 1,2; + part | a +------+--- +(0 rows) + +SELECT * FROM t_multi_charset_partkey PARTITION(p2) order by 1,2; + part | a +----------+--- + 楂樻柉DB | 1 +(1 row) + +SELECT * FROM t_multi_charset_partkey PARTITION(p3) order by 1,2; + part | a +----------+--- + 楂樻柉db | 2 +(1 row) + +SELECT * FROM t_multi_charset_partkey PARTITION(p4) order by 1,2; + part | a +--------+--- + 高斯DB | 3 +(1 row) + +SELECT * FROM t_multi_charset_partkey PARTITION(p5) order by 1,2; + part | a +--------+--- + 高斯db | 4 +(1 row) + +-- -- -- partition pruning +EXPLAIN (costs off) +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' order by 1,2; + QUERY PLAN +----------------------------------------------------------------------- + Sort + Sort Key: a + -> Partitioned Seq Scan on t_multi_charset_partkey + Filter: ((part)::text = '楂樻柉DB'::text COLLATE utf8mb4_bin) + Selected Partitions: 2 +(5 rows) + +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' order by 1,2; + part | a +----------+--- + 楂樻柉DB | 1 +(1 row) + +EXPLAIN (costs off) +SELECT * FROM t_multi_charset_partkey WHERE part=_utf8mb4'高斯db' order by 1,2; + QUERY PLAN +------------------------------------------------------- + Sort + Sort Key: a + -> Partitioned Seq Scan on t_multi_charset_partkey + Filter: ((part)::text = '高斯db'::text) + Selected Partitions: 5 +(5 rows) + +SELECT * FROM t_multi_charset_partkey WHERE part=_utf8mb4'高斯db' order by 1,2; + part | a +--------+--- + 高斯db | 4 +(1 row) + +EXPLAIN (costs off) +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' collate gbk_chinese_ci order by 1,2; -- ALL PARTS + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: part COLLATE utf8mb4_bin, a + -> Partition Iterator + Iterations: 5 + -> Partitioned Seq Scan on t_multi_charset_partkey + Filter: ((part)::text = '楂樻柉DB'::text) + Selected Partitions: 1..5 +(7 rows) + +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' collate gbk_chinese_ci order by 1,2; + part | a +----------+--- + 楂樻柉DB | 1 + 楂樻柉db | 2 +(2 rows) + +DROP TABLE t_multi_charset_partkey; +-- -- -- gbk +CREATE TABLE t_multi_charset_partkey (part varchar(32) CHARACTER set gbk collate gbk_bin, a int) + PARTITION BY RANGE(part) ( + partition p1 values less than('高斯DB'), + partition p2 values less than(MAXVALUE) +); -- error +ERROR: difference between the charset of column part and the database encoding has not supported +-- -- test column default value +CREATE TABLE t_default_charset( + a varchar(32) character set gbk collate gbk_bin DEFAULT '高斯DB', + b varchar(32) character set utf8mb4 collate utf8mb4_unicode_ci GENERATED ALWAYS AS (a) STORED, + c varchar(32) character set utf8mb4 collate utf8mb4_unicode_ci GENERATED ALWAYS AS (a||_utf8mb4'高斯DB') STORED); +INSERT INTO t_default_charset VALUES(DEFAULT, DEFAULT, DEFAULT); +select * from t_default_charset; + a | b | c +--------+--------+-------------- + 高斯DB | 高斯DB | 高斯DB高斯DB +(1 row) + +DROP TABLE t_default_charset; +-- ------------------------------------------ +-- SET NAMES GBK; +SET NAMES 'GBK'; +SHOW client_encoding; + client_encoding +----------------- + GBK +(1 row) + +SHOW server_encoding; + server_encoding +----------------- + UTF8 +(1 row) + +SHOW character_set_connection; + character_set_connection +-------------------------- + GBK +(1 row) + +SHOW collation_connection; + collation_connection +---------------------- + gbk_chinese_ci +(1 row) + +-- 中文 +SELECT CAST('高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_binary'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_utf8mb4'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT CAST(_gbk'高斯' AS bytea); + bytea +---------------- + \xe9ab98e696af +(1 row) + +SELECT _binary'高斯'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4'高斯'; + ?column? +---------- + ¸ß˹ +(1 row) + +SELECT _gbk'高斯'; + ?column? +---------- + 高斯 +(1 row) + +SELECT _binary X'E9AB98E696AF'; + ?column? +---------------- + \xe9ab98e696af +(1 row) + +SELECT _utf8mb4 X'E9AB98E696AF'; + ?column? +---------- + ¸ß˹ +(1 row) + +SELECT _gbk X'E9AB98E696AF'; + ?column? +---------- + 高斯 +(1 row) + +SELECT '楂樻柉'; -- ERROR '楂樻柉'(\xe6a582e6a8bbe69f89) will be converted to utf8 first +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); -- ERROR '楂樻柉'(\xe6a582e6a8bbe69f89) will be converted to utf8 first +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); + convert_to +------------ + \xb8dfcbb9 +(1 row) + +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +NOTICE: table "t_charset_utf8mb4" does not exist, skipping +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_utf8mb4_id_seq" for serial column "t_charset_utf8mb4.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_utf8mb4_pkey" for table "t_charset_utf8mb4" +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB'; + QUERY PLAN +---------------------------------- + Seq Scan on t_charset_utf8mb4 + Filter: (a = '高斯DB'::text) +(2 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; + QUERY PLAN +------------------------------------------ + Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '高斯db'::text) +(2 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db'; + QUERY PLAN +------------------------------------------ + Seq Scan on t_charset_utf8mb4 + Filter: ((a)::text = '高斯db'::text) +(2 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '¸ß˹DB'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +-------------------------------------- + Limit + -> Seq Scan on t_charset_utf8mb4 + Filter: (a = '¸ß˹db'::text) +(3 rows) + +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: ...harset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_un... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯' ORDER BY id; + id | a | b +----+--------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 2 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' OR... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+----------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(5 rows) + +DELETE FROM t_charset_utf8mb4 WHERE a='高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a='高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +-- -- -- -- test assign expr +INSERT INTO t_charset_utf8mb4(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+----------+-------------------- + 7 | 高斯DB | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +INSERT INTO t_charset_utf8mb4(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+----------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +UPDATE t_charset_utf8mb4 SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + id | a | b +----+----------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | DB高斯 | \x4442e9ab98e696af +(2 rows) + +DROP TABLE IF EXISTS t_charset_utf8mb4; +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +NOTICE: table "t_charset_gbk" does not exist, skipping +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); +NOTICE: CREATE TABLE will create implicit sequence "t_charset_gbk_id_seq" for serial column "t_charset_gbk.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_charset_gbk_pkey" for table "t_charset_gbk" +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +INSERT INTO t_charset_gbk SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB'; + QUERY PLAN +---------------------------------- + Seq Scan on t_charset_gbk + Filter: (a = '高斯DB'::text) +(2 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; + QUERY PLAN +---------------------------------- + Seq Scan on t_charset_gbk + Filter: (a = '高斯db'::text) +(2 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+---------- + 2 | 高斯DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; + QUERY PLAN +----------------------------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: (a = '¸ß˹DB'::text COLLATE pg_catalog.gbk_bin) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; + QUERY PLAN +---------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '¸ß˹db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: ...rset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_... + ^ +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; + QUERY PLAN +---------------------------------------------- + Limit + -> Seq Scan on t_charset_gbk + Filter: ((a)::text = '¸ß˹db'::text) +(3 rows) + +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; + @id_res | @a_res +---------+-------- + 3 | ¸ß˹DB +(1 row) + +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; + id | a | b +----+--------+---------------- + 1 | 高斯 | \xe9ab98e696af +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + id | a | b +----+----------+-------------------- + 2 | 高斯DB | \xe9ab98e696af4442 +(1 row) + +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +ERROR: operator does not exist: text = bytea +LINE 1: SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER ... + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + id | a | b +----+--------+-------------------- + 3 | ¸ß˹DB | \xe9ab98e696af4442 + 4 | ¸ß˹DB | \xe9ab98e696af4442 + 6 | ¸ß˹DB | \xe9ab98e696af4442 +(3 rows) + +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0x89 0x27 +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+----------+-------------------- + 1 | 高斯 | \xe9ab98e696af + 2 | 高斯DB | \xe9ab98e696af4442 + 3 | 高斯DB | \xe9ab98e696af4442 + 4 | 高斯DB | \xe9ab98e696af4442 + 6 | 高斯DB | \xe9ab98e696af4442 +(5 rows) + +DELETE FROM t_charset_gbk WHERE a='高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea= _binary'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+---+--- +(0 rows) + +-- -- -- -- test assign expr +INSERT INTO t_charset_gbk(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_gbk SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+----------+-------------------- + 7 | 高斯DB | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +INSERT INTO t_charset_gbk(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+----------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | 高斯DB | \xe9ab98e696af4442 +(2 rows) + +UPDATE t_charset_gbk SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_gbk ORDER BY id; + id | a | b +----+----------+-------------------- + 7 | 高斯db | \xe9ab98e696af4442 + 8 | DB高斯 | \x4442e9ab98e696af +(2 rows) + +DROP TABLE IF EXISTS t_charset_gbk; +-- test multi charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; + futf8_bin | futf8_uni | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea +-----------+-----------+----------+----------+--------------+--------------+-------------------- + 高斯DB | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 +(1 row) + +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; -- 5 + length | length | length | length | length | length | length +--------+--------+--------+--------+--------+--------+-------- + 5 | 5 | 5 | 5 | 5 | 5 | 8 +(1 row) + +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + lengthb | lengthb | lengthb | lengthb | lengthb | lengthb | length +---------+---------+---------+---------+---------+---------+-------- + 11 | 11 | 8 | 8 | 8 | 8 | 8 +(1 row) + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高æ'::text) + Filter: ((futf8_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; + futf8_bin +----------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using idx_prefixkey_futf8_bin on t_diff_charset_columns + Index Cond: ((futf8_bin)::text = '高æ'::text) + Filter: ((futf8_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; + futf8_bin +----------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高æ'::text) + Filter: ((fgbk_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; + fgbk_bin +---------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + QUERY PLAN +------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgbk_bin on t_diff_charset_columns + Index Cond: ((fgbk_bin)::text = '高æ'::text) + Filter: ((fgbk_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; + fgbk_bin +---------- + 高斯DB +(1 row) + +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高æ'::text) + Filter: ((fgb18030_bin)::text ~~ '高斯%'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + QUERY PLAN +----------------------------------------------------------------------- + Index Scan using idx_prefixkey_fgb18030_bin on t_diff_charset_columns + Index Cond: ((fgb18030_bin)::text = '高æ'::text) + Filter: ((fgb18030_bin)::text = '高斯DB'::text) +(3 rows) + +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; + fgb18030_bin +-------------- + 高斯DB +(1 row) + +reset enable_seqscan; +DROP TABLE t_diff_charset_columns; +\c regression diff --git a/src/test/regress/expected/hw_datatype_set.out b/src/test/regress/expected/hw_datatype_set.out index 04129cf0a..e0c60328d 100644 --- a/src/test/regress/expected/hw_datatype_set.out +++ b/src/test/regress/expected/hw_datatype_set.out @@ -19,6 +19,7 @@ ERROR: invalid input value for set anyset: 1 CONTEXT: referenced column: find_in_set create database test dbcompatibility = 'B'; \c test +SET b_format_behavior_compat_options = 'enable_multi_charset'; drop table if exists tab; NOTICE: table "tab" does not exist, skipping drop table if exists dual; @@ -4150,3 +4151,1194 @@ select c1, c1+0 from t2 order by 2; drop table t1; drop table t2; +-- test check duplicate set scenes +-- 1. column charset/collate +drop table if exists test_set_key1; +NOTICE: table "test_set_key1" does not exist, skipping +create table test_set_key1(a set('', ' ')); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: duplicate key value violates unique constraint "pg_set_typid_label_index" +--?.* +create table test_set_key1(a set('', ' ') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "" = " " +create table test_set_key1(a set('a', 'a ')); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: duplicate key value violates unique constraint "pg_set_typid_label_index" +--?.* +create table test_set_key1(a set('a', 'a ') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "a" = "a " +create table test_set_key1(a set('aaa', 'AAA ') collate utf8_general_ci); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "AAA " +create table test_set_key1(a set('高斯sS', '高斯ŠŠ ') collate utf8_general_ci); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "高斯sS" = "高斯ŠŠ " +create table test_set_key1(a set('aaa', 'aaA ') charset 'utf8'); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +create table test_set_key1(a set('aaa', 'aaA ') charset 'gbk'); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +create table test_set_key1(a set('aaa', 'aaA ') charset 'gb18030'); +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +--succeed scenes +create table t_column_collation1(a set('a', 'b', 'A','B') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "t_column_collation1_a_set" for column "t_column_collation1.a" +create table t_column_collation2(a set('a', 'b', 'A','B') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "t_column_collation2_a_set" for column "t_column_collation2.a" +create table t_column_collation3(a set('aaa', 'bbb') charset 'utf8'); +NOTICE: CREATE TABLE will create implicit set "t_column_collation3_a_set" for column "t_column_collation3.a" +create table t_column_collation4(a set('a', 'b', 'A','B') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "t_column_collation4_a_set" for column "t_column_collation4.a" +create table t_column_collation5(a set('高斯DB','1') character set utf8mb4 collate utf8mb4_general_ci default '高斯db'); +NOTICE: CREATE TABLE will create implicit set "t_column_collation5_a_set" for column "t_column_collation5.a" +drop table t_column_collation1; +drop table t_column_collation2; +drop table t_column_collation3; +drop table t_column_collation4; +drop table t_column_collation5; +-- 2. table charset/collate +create table test_set_key1(a set('aaa', 'aaA ')) charset 'utf8'; +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +create table test_set_key1(a set('aaa', 'aaA ')) collate 'utf8_general_ci'; +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +create table test_set_key1(a set('aaa', 'aaA ')) charset 'gbk'; +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +create table test_set_key1(a set('aaa', 'aaa ')) charset 'gbk' collate gbk_bin; +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaa " +create table test_set_key1(a set('aaa', 'aaA ')) charset 'gb18030'; +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaA " +create table test_set_key1(a set('aaa', 'aaa ')) charset 'gb18030' collate gb18030_bin; +NOTICE: CREATE TABLE will create implicit set "test_set_key1_a_set" for column "test_set_key1.a" +ERROR: set has duplicate key value "aaa" = "aaa " +--succeed scenes +create table t_table_collation1(a set('aaa', 'bbb')) charset 'utf8'; +NOTICE: CREATE TABLE will create implicit set "t_table_collation1_a_set" for column "t_table_collation1.a" +create table t_table_collation2(a set('aaa', 'aaA ') collate 'utf8_bin')charset 'utf8'; +NOTICE: CREATE TABLE will create implicit set "t_table_collation2_a_set" for column "t_table_collation2.a" +drop table t_table_collation1; +drop table t_table_collation2; +-- 3. schema charset/collate +create schema set_test_schema1 charset = utf8; +set current_schema='set_test_schema1'; +create table t(a set('a', 'A')); --fail +NOTICE: CREATE TABLE will create implicit set "t_a_set" for column "t.a" +ERROR: set has duplicate key value "a" = "A" +create table t(a set('a', 'b')); -- succeed +NOTICE: CREATE TABLE will create implicit set "t_a_set" for column "t.a" +alter table t add column b set('a', 'A', 'b'); -- fail +NOTICE: ALTER TABLE will create implicit set "t_b_set" for column "t.b" +ERROR: set has duplicate key value "a" = "A" +alter table t add column b set('a', 'A', 'b') collate utf8_bin; --succeed +NOTICE: ALTER TABLE will create implicit set "t_b_set" for column "t.b" +insert into t values('a ', 'a '); +insert into t values('a ', 'A '); +insert into t values('B ', 'A '); +insert into t values('a ', 'B '); --fail +ERROR: invalid input value for set t_b_set: 'B ' +LINE 1: insert into t values('a ', 'B '); + ^ +CONTEXT: referenced column: b +drop table t; +create schema set_test_schema2 charset = utf8mb4 collate = utf8mb4_bin; +set current_schema='set_test_schema2'; +create table t(a set('a', 'A')); -- succeed +NOTICE: CREATE TABLE will create implicit set "t_a_set" for column "t.a" +alter table t add column b set('a', 'A', 'b') collate utf8_general_ci; --fail +NOTICE: ALTER TABLE will create implicit set "t_b_set" for column "t.b" +ERROR: set has duplicate key value "a" = "A" +alter table t add column b set('a', 'A', 'b'); -- succeed +NOTICE: ALTER TABLE will create implicit set "t_b_set" for column "t.b" +insert into t values ('a ', 'b '); +insert into t values ('a ', 'B '); -- fail +ERROR: invalid input value for set t_b_set: 'B ' +LINE 1: insert into t values ('a ', 'B '); + ^ +CONTEXT: referenced column: b +drop table t; +drop schema set_test_schema1; +drop schema set_test_schema2; +\c test +SET b_format_behavior_compat_options = 'enable_multi_charset'; +-- test insert value with collation +-- 1. insert value length ignore end space +create table test_set_len (col SET('ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "test_set_len_col_set" for column "test_set_len.col" +insert into test_set_len values ('ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd '); +drop table test_set_len; +-- 2. insert value while collate is binary +-- 3. insert value while collate like _bin +create table test_collation2(a set('aaa', 'AAA','高斯SS', '高斯ss') collate utf8_bin); +NOTICE: CREATE TABLE will create implicit set "test_collation2_a_set" for column "test_collation2.a" +insert into test_collation2 values('aaa '); +insert into test_collation2 values('aaa'); +insert into test_collation2 values('AAA'); +insert into test_collation2 values('AAA '); +insert into test_collation2 values('高斯ss '); +insert into test_collation2 values('高斯SS '); +insert into test_collation2 values('高斯sS '); --failed +ERROR: invalid input value for set test_collation2_a_set: '高斯sS ' +LINE 1: insert into test_collation2 values('高斯sS '); + ^ +CONTEXT: referenced column: a +insert into test_collation2 values('高斯ss,高斯ss '); +-- 4. insert value while collate like _ci +create table test_collation3(a set('高斯sS', '汉字sS', 'aaa', 'bbb')) charset utf8; +NOTICE: CREATE TABLE will create implicit set "test_collation3_a_set" for column "test_collation3.a" +select pg_get_tabledef('test_collation3'); + pg_get_tabledef +--------------------------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE test_collation3 ( + + a SET('高斯sS', '汉字sS', 'aaa', 'bbb') CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci+ + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, compression=no); +(1 row) + +insert into test_collation3 values('高斯sS '); +insert into test_collation3 values('高斯ss,高斯ss '); +insert into test_collation3 values('高斯ŠŠ'); +insert into test_collation3 values('汉字sS '); +insert into test_collation3 values('汉字ss,汉字ss '); +insert into test_collation3 values('汉字ŠŠ'); +insert into test_collation3 values('aaa '); +insert into test_collation3 values('aaa'); +insert into test_collation3 values('AAA '); +-- test update with colalte +create table test_update(a set('a', 'A', 'b'))collate utf8_bin; +NOTICE: CREATE TABLE will create implicit set "test_update_a_set" for column "test_update.a" +insert into test_update values('a'),('A'); +update test_update set a = 'b' where a = 'a'; +update test_update set a = 'b' where a = 'a' collate utf8_general_ci; +select * from test_update; + a +--- + b + b +(2 rows) + +update test_update set a = 'a' where a = 'B' collate utf8_general_ci; +select * from test_update; + a +--- + a + a +(2 rows) + +drop table test_update; +-- test operator +create table test_collation_op(a set('a', 'A', 'b', 'B'), b set('a', 'A', 'b', 'B')) collate utf8_bin; +NOTICE: CREATE TABLE will create implicit set "test_collation_op_a_set" for column "test_collation_op.a" +NOTICE: CREATE TABLE will create implicit set "test_collation_op_b_set" for column "test_collation_op.b" +insert into test_collation_op values('a', 'A'),('A','a'),('b','B'),('B','b'); +-- test '=' +select a from test_collation2 where a = 'aaa'; + a +----- + aaa + aaa +(2 rows) + +select a from test_collation2 where a = '高斯ss' collate utf8_bin; + a +-------- + 高斯ss + 高斯ss +(2 rows) + +select a from test_collation2 where a = 'aaa' collate "utf8_general_ci"; -- set = text + a +----- + aaa + aaa + AAA + AAA +(4 rows) + +select a from test_collation2 where a = '高斯ss' collate utf8_general_ci; + a +-------- + 高斯ss + 高斯SS + 高斯ss +(3 rows) + +select a from test_collation3 where a = '高斯ss'; + a +-------- + 高斯sS + 高斯sS + 高斯sS +(3 rows) + +select a from test_collation3 where a = '高斯ss' collate utf8_bin; + a +--- +(0 rows) + +select a from test_collation3 where a = 'aaa' collate "utf8_general_ci"; + a +----- + aaa + aaa + aaa +(3 rows) + +select a from test_collation2 where 'aaa' = a collate "utf8_general_ci"; -- text = set + a +----- + aaa + aaa + AAA + AAA +(4 rows) + +select + distinct t2.a, t3.a +from + test_collation2 as t2, + test_collation2 as t3 +where t2.a = t3.a collate "utf8_general_ci"; -- set = set + a | a +--------+-------- + 高斯SS | 高斯SS + aaa | AAA + aaa | aaa + 高斯ss | 高斯ss + AAA | AAA + 高斯ss | 高斯SS + AAA | aaa + 高斯SS | 高斯ss +(8 rows) + +select + distinct t2.a, t3.a +from + test_collation2 as t2, + test_collation2 as t3 +where t2.a = t3.a; + a | a +--------+-------- + aaa | aaa + 高斯ss | 高斯ss + 高斯SS | 高斯SS + AAA | AAA +(4 rows) + +-- '<>' +select a, b from test_collation_op where a <> b; -- set <> other set + a | b +---+--- + a | A + A | a + b | B + B | b +(4 rows) + +select a, b from test_collation_op where a <> b collate 'utf8_general_ci'; + a | b +---+--- +(0 rows) + +select a, b from test_collation_op where a <> 'a'; -- set <> text + a | b +---+--- + A | a + b | B + B | b +(3 rows) + +select a, b from test_collation_op where a <> 'a' collate 'utf8_general_ci'; + a | b +---+--- + b | B + B | b +(2 rows) + +select a, b from test_collation_op where 'a' <> a; + a | b +---+--- + A | a + b | B + B | b +(3 rows) + +select a, b from test_collation_op where 'a' <> a collate 'utf8_general_ci'; -- text <> set + a | b +---+--- + b | B + B | b +(2 rows) + +-- '<' +select a, b from test_collation_op where a < b; -- set < other set + a | b +---+--- + A | a + B | b +(2 rows) + +select a from test_collation_op where a < b collate 'utf8_general_ci'; + a +--- +(0 rows) + +select a from test_collation_op where a < 'C'; -- set < text + a +--- + A + B +(2 rows) + +select a from test_collation_op where a < 'C' collate 'utf8_general_ci'; + a +--- + a + A + b + B +(4 rows) + +select a from test_collation_op where 'B' < a; + a +--- + a + b +(2 rows) + +select a from test_collation_op where 'B' < a collate 'utf8_general_ci'; + a +--- +(0 rows) + +-- '<=' +select a, b from test_collation_op where a <= b; -- set <= other set + a | b +---+--- + A | a + B | b +(2 rows) + +select a from test_collation_op where a <= b collate 'utf8_general_ci'; + a +--- + a + A + b + B +(4 rows) + +select a from test_collation_op where a <= 'A'; -- set <= text + a +--- + A +(1 row) + +select a from test_collation_op where a <= 'A' collate 'utf8_general_ci'; + a +--- + a + A +(2 rows) + +select a from test_collation_op where 'B' <= a; -- text <= set + a +--- + a + b + B +(3 rows) + +select a from test_collation_op where 'B' <= a collate 'utf8_general_ci'; + a +--- + b + B +(2 rows) + +-- '>' +select a, b from test_collation_op where a > b; -- set > other set + a | b +---+--- + a | A + b | B +(2 rows) + +select a from test_collation_op where a > b collate 'utf8_general_ci'; + a +--- +(0 rows) + +select a from test_collation_op where a > 'B'; -- set > text + a +--- + a + b +(2 rows) + +select a from test_collation_op where a > 'B' collate 'utf8_general_ci'; + a +--- +(0 rows) + +select a from test_collation_op where 'C' > a; + a +--- + A + B +(2 rows) + +select a from test_collation_op where 'C' > a collate 'utf8_general_ci'; + a +--- + a + A + b + B +(4 rows) + +-- '>=' +select a, b from test_collation_op where a >= b; -- set >= other set + a | b +---+--- + a | A + b | B +(2 rows) + +select a from test_collation_op where a >= b collate 'utf8_general_ci'; + a +--- + a + A + b + B +(4 rows) + +select a from test_collation_op where a >= 'B'; -- set >= text + a +--- + a + b + B +(3 rows) + +select a from test_collation_op where a >= 'B' collate 'utf8_general_ci'; + a +--- + b + B +(2 rows) + +select a from test_collation_op where 'C' >= a; + a +--- + A + B +(2 rows) + +select a from test_collation_op where 'C' >= a collate 'utf8_general_ci'; + a +--- + a + A + b + B +(4 rows) + +-- test order by +select a from test_collation2 order by a; + a +-------- + AAA + AAA + aaa + aaa + 高斯SS + 高斯ss + 高斯ss +(7 rows) + +select a from test_collation2 order by a collate 'utf8_general_ci'; + a +-------- + aaa + aaa + AAA + AAA + 高斯ss + 高斯SS + 高斯ss +(7 rows) + +select a from test_collation2 order by a collate 'utf8_bin'; + a +-------- + AAA + AAA + aaa + aaa + 高斯SS + 高斯ss + 高斯ss +(7 rows) + +select a from test_collation3 order by a; + a +-------- + aaa + aaa + aaa + 汉字sS + 汉字sS + 汉字sS + 高斯sS + 高斯sS + 高斯sS +(9 rows) + +select a from test_collation3 order by a collate 'utf8_general_ci'; + a +-------- + aaa + aaa + aaa + 汉字sS + 汉字sS + 汉字sS + 高斯sS + 高斯sS + 高斯sS +(9 rows) + +select a from test_collation3 order by a collate 'utf8_bin'; + a +-------- + aaa + aaa + aaa + 汉字sS + 汉字sS + 汉字sS + 高斯sS + 高斯sS + 高斯sS +(9 rows) + +-- test distinct +select distinct a from test_collation2; + a +-------- + 高斯SS + 高斯ss + aaa + AAA +(4 rows) + +select distinct a collate 'utf8_bin' from test_collation2; + a +-------- + 高斯SS + 高斯ss + aaa + AAA +(4 rows) + +select distinct a collate 'utf8_general_ci' from test_collation2; + a +-------- + aaa + 高斯ss +(2 rows) + +select distinct a from test_collation3; + a +-------- + 汉字sS + aaa + 高斯sS +(3 rows) + +select distinct a collate 'utf8_bin' from test_collation3; + a +-------- + 高斯sS + aaa + 汉字sS +(3 rows) + +select distinct a collate 'utf8_general_ci' from test_collation3; + a +-------- + 汉字sS + aaa + 高斯sS +(3 rows) + +-- test like +select a from test_collation2 where a like 'aa%'; + a +----- + aaa + aaa +(2 rows) + +select a from test_collation2 where a like 'aa%' collate 'utf8_general_ci'; + a +----- + aaa + aaa + AAA + AAA +(4 rows) + +select a from test_collation3 where a like 'aa%'; + a +----- + aaa + aaa + aaa +(3 rows) + +select a from test_collation3 where a like 'aa%' collate 'utf8_general_ci'; + a +----- + aaa + aaa + aaa +(3 rows) + +-- test alter table modify/add +alter table test_collation3 modify a char(10) collate utf8_bin; +select a from test_collation3 where a = '高斯ss'; + a +--- +(0 rows) + +select a from test_collation3 where a = '高斯sS' collate utf8_bin; + a +---------- + 高斯sS + 高斯sS + 高斯sS +(3 rows) + +alter table test_collation3 modify a set('高斯sS', '汉字sS', 'aaa', 'bbb'); +NOTICE: ALTER TABLE will create implicit set "test_collation3_a_set" for column "test_collation3.a" +select pg_get_tabledef('test_collation3'); + pg_get_tabledef +--------------------------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE test_collation3 ( + + a SET('高斯sS', '汉字sS', 'aaa', 'bbb') CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci+ + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, compression=no); +(1 row) + +insert into test_collation3 values('高斯ŠŠ '); +alter table test_collation3 add b set('a','b', 'c'); +NOTICE: ALTER TABLE will create implicit set "test_collation3_b_set" for column "test_collation3.b" +insert into test_collation3(b) values('A'), ('b '), (3); +-- test unique/primary key +create table t_collation_set5(a set('aaa', 'bbb') collate utf8_general_ci unique); +NOTICE: CREATE TABLE will create implicit set "t_collation_set5_a_set" for column "t_collation_set5.a" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_collation_set5_a_key" for table "t_collation_set5" +insert into t_collation_set5 values('aaa'); +insert into t_collation_set5 values('aaa '); +ERROR: duplicate key value violates unique constraint "t_collation_set5_a_key" +DETAIL: Key (a)=(aaa) already exists. +insert into t_collation_set5 values('AAA '); +ERROR: duplicate key value violates unique constraint "t_collation_set5_a_key" +DETAIL: Key (a)=(aaa) already exists. +create table t_collation_set6(a set('aaa', 'bbb') collate utf8_general_ci primary key); +NOTICE: CREATE TABLE will create implicit set "t_collation_set6_a_set" for column "t_collation_set6.a" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_collation_set6_pkey" for table "t_collation_set6" +insert into t_collation_set6 values('aaa '); +insert into t_collation_set6 values('aaa'); +ERROR: duplicate key value violates unique constraint "t_collation_set6_pkey" +DETAIL: Key (a)=(aaa) already exists. +insert into t_collation_set6 values('AAA '); +ERROR: duplicate key value violates unique constraint "t_collation_set6_pkey" +DETAIL: Key (a)=(aaa) already exists. +drop table t_collation_set5; +drop table t_collation_set6; +-- test join +create table test_join1( + c_char char(10), + c_varchar varchar(10), + c_nvarchar2 nvarchar2(10), + c_text text, + c_set set('a') +) collate utf8_bin; +NOTICE: CREATE TABLE will create implicit set "test_join1_c_set_set" for column "test_join1.c_set" +create table test_join2( + c_set set('A') +) collate utf8_bin; +NOTICE: CREATE TABLE will create implicit set "test_join2_c_set_set" for column "test_join2.c_set" +insert into test_join1 values('a ', 'a ', 'a ', 'a ','a '); +insert into test_join2 values('A'); +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_char; + c_char | c_set +--------+------- +(0 rows) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_char collate 'utf8_general_ci'; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_char; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_char collate 'utf8_general_ci'; + c_char | c_set +--------+------- +(0 rows) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_char > t2.c_set; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_char > t2.c_set collate 'utf8_general_ci'; + c_char | c_set +--------+------- +(0 rows) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_char; + c_char | c_set +--------+------- +(0 rows) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_char collate 'utf8_general_ci'; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_char; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_char collate 'utf8_general_ci'; + c_char | c_set +--------+------- +(0 rows) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_char; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_char collate 'utf8_general_ci'; + c_char | c_set +------------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_varchar; + c_varchar | c_set +-----------+------- +(0 rows) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_varchar collate 'utf8_general_ci'; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_varchar; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_varchar collate 'utf8_general_ci'; + c_varchar | c_set +-----------+------- +(0 rows) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_varchar > t2.c_set; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_varchar > t2.c_set collate 'utf8_general_ci'; + c_varchar | c_set +-----------+------- +(0 rows) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_varchar; + c_varchar | c_set +-----------+------- +(0 rows) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_varchar collate 'utf8_general_ci'; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_varchar; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_varchar collate 'utf8_general_ci'; + c_varchar | c_set +-----------+------- +(0 rows) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_varchar; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_varchar collate 'utf8_general_ci'; + c_varchar | c_set +-----------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_nvarchar2; + c_nvarchar2 | c_set +-------------+------- +(0 rows) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_nvarchar2 collate 'utf8_general_ci'; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_nvarchar2; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_nvarchar2 collate 'utf8_general_ci'; + c_nvarchar2 | c_set +-------------+------- +(0 rows) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_nvarchar2 > t2.c_set; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_nvarchar2 > t2.c_set collate 'utf8_general_ci'; + c_nvarchar2 | c_set +-------------+------- +(0 rows) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_nvarchar2; + c_nvarchar2 | c_set +-------------+------- +(0 rows) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_nvarchar2 collate 'utf8_general_ci'; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_nvarchar2; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_nvarchar2 collate 'utf8_general_ci'; + c_nvarchar2 | c_set +-------------+------- +(0 rows) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_nvarchar2; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_nvarchar2 collate 'utf8_general_ci'; + c_nvarchar2 | c_set +-------------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_text; + c_text | c_set +--------+------- +(0 rows) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_text collate 'utf8_general_ci'; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_text; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_text collate 'utf8_general_ci'; + c_text | c_set +--------+------- +(0 rows) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_text > t2.c_set; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_text > t2.c_set collate 'utf8_general_ci'; + c_text | c_set +--------+------- +(0 rows) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_text; + c_text | c_set +--------+------- +(0 rows) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_text collate 'utf8_general_ci'; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_text; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_text collate 'utf8_general_ci'; + c_text | c_set +--------+------- +(0 rows) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_text; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_text collate 'utf8_general_ci'; + c_text | c_set +--------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_set; + c_set | c_set +-------+------- +(0 rows) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_set collate 'utf8_general_ci'; + c_set | c_set +-------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_set; + c_set | c_set +-------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_set collate 'utf8_general_ci'; + c_set | c_set +-------+------- +(0 rows) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_set > t2.c_set; + c_set | c_set +-------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_set > t2.c_set collate 'utf8_general_ci'; + c_set | c_set +-------+------- +(0 rows) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_set; + c_set | c_set +-------+------- +(0 rows) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_set collate 'utf8_general_ci'; + c_set | c_set +-------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_set; + c_set | c_set +-------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_set collate 'utf8_general_ci'; + c_set | c_set +-------+------- +(0 rows) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_set; + c_set | c_set +-------+------- + a | A +(1 row) + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_set collate 'utf8_general_ci'; + c_set | c_set +-------+------- + a | A +(1 row) + +drop table test_join1; +drop table test_join2; +-- test partition table with collate +create table test_part_tab1(c1 int, c2 set('a', 'b', 'A', 'B'))charset utf8 partition by range(c1) --fail +( + partition test_set_tab_p1 values less than (5), + partition test_set_tab_p2 values less than (10) +); +NOTICE: CREATE TABLE will create implicit set "test_part_tab1_c2_set" for column "test_part_tab1.c2" +ERROR: set has duplicate key value "a" = "A" +create table test_part_tab1(c1 int, c2 set('a', 'b', 'A', 'B'))charset utf8 collate utf8_bin partition by range(c1) -- success +( + partition test_set_tab_p1 values less than (5), + partition test_set_tab_p2 values less than (10) +); +NOTICE: CREATE TABLE will create implicit set "test_part_tab1_c2_set" for column "test_part_tab1.c2" +select pg_get_tabledef('test_part_tab1'); + pg_get_tabledef +--------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE test_part_tab1 ( + + c1 integer, + + c2 SET('a', 'b', 'A', 'B') CHARACTER SET "UTF8" COLLATE utf8_bin + + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8_bin" + + WITH (orientation=row, compression=no) + + PARTITION BY RANGE (c1) + + ( + + PARTITION test_set_tab_p1 VALUES LESS THAN (5) TABLESPACE pg_default,+ + PARTITION test_set_tab_p2 VALUES LESS THAN (10) TABLESPACE pg_default+ + ) + + ENABLE ROW MOVEMENT; +(1 row) + +insert into test_part_tab1 values(1, 'a '); +insert into test_part_tab1 values(6, 'A '); +insert into test_part_tab1 values(2, 'b '); +insert into test_part_tab1 values(7, 'B '); +create table test_part_tab2(c1 int, c2 set('a', 'b', 'c', 'd'))charset utf8 partition by range(c1) -- success +( + partition test_set_tab_p1 values less than (5), + partition test_set_tab_p2 values less than (10) +); +NOTICE: CREATE TABLE will create implicit set "test_part_tab2_c2_set" for column "test_part_tab2.c2" +insert into test_part_tab2 values(1, 'a '); +insert into test_part_tab2 values(6, 'A '); +insert into test_part_tab2 values(2, 'b '); +insert into test_part_tab2 values(7, 'B '); +drop table test_part_tab1; +drop table test_part_tab2; +-- test local/global temp table with collate +create local temp table test_temp_tab1 (c1 set('a', 'b')) charset utf8; +NOTICE: CREATE TABLE will create implicit set "test_temp_tab1_c1_set" for column "test_temp_tab1.c1" +insert into test_temp_tab1 values('a '); +insert into test_temp_tab1 values('A '); +create global temp table test_temp_tab2 (c1 set('a', 'b')) charset utf8 collate utf8_bin; +NOTICE: CREATE TABLE will create implicit set "test_temp_tab2_c1_set" for column "test_temp_tab2.c1" +insert into test_temp_tab2 values('a '); +insert into test_temp_tab2 values('A '); --fail +ERROR: invalid input value for set test_temp_tab2_c1_set: 'A ' +LINE 1: insert into test_temp_tab2 values('A '); + ^ +CONTEXT: referenced column: c1 +drop table test_temp_tab1; +drop table test_temp_tab2; +-- test ustore +create table test_ustore1( + c1 set('a', 'b', 'c', 'd'), + c2 set('a', 'b','A', 'B') collate 'gbk_bin' +) charset utf8 with (STORAGE_TYPE = ustore); +NOTICE: CREATE TABLE will create implicit set "test_ustore1_c1_set" for column "test_ustore1.c1" +NOTICE: CREATE TABLE will create implicit set "test_ustore1_c2_set" for column "test_ustore1.c2" +select pg_get_tabledef('test_ustore1'); + pg_get_tabledef +--------------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE test_ustore1 ( + + c1 SET('a', 'b', 'c', 'd') CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci,+ + c2 SET('a', 'b', 'A', 'B') CHARACTER SET "GBK" COLLATE gbk_bin + + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, storage_type=ustore, compression=no); +(1 row) + +insert into test_ustore1 values('a ', 'a '); +insert into test_ustore1 values('A ', 'A '); +select c2 from test_ustore1 where c2 = 'a'; + c2 +---- + a +(1 row) + +select c2 from test_ustore1 where c2 = 'a' collate 'utf8_general_ci'; + c2 +---- + a + A +(2 rows) + +select c2 from test_ustore1 where c2 = c1; + c2 +---- + a + A +(2 rows) + +drop table test_ustore1; +-- test cstore(not supported) +create table test_cstore1(c1 set('a', 'b', 'c', 'd') collate 'utf8_bin') with (ORIENTATION = column); +NOTICE: CREATE TABLE will create implicit set "test_cstore1_c1_set" for column "test_cstore1.c1" +ERROR: type "test_cstore1_c1_set" is not supported in column store +-- test check constraint with collate +create table test_check1(a set('a', 'b', 'c') check(a >= 'b'))charset utf8; +NOTICE: CREATE TABLE will create implicit set "test_check1_a_set" for column "test_check1.a" +insert into test_check1 values('a'); +ERROR: new row for relation "test_check1" violates check constraint "test_check1_a_check" +DETAIL: N/A +insert into test_check1 values('B '); +insert into test_check1 values('C'); +insert into test_check1 values('c'); +drop table test_check1; \ No newline at end of file diff --git a/src/test/regress/expected/test_b_format_collate.out b/src/test/regress/expected/test_b_format_collate.out index 441ec1df1..14d0d6b74 100644 --- a/src/test/regress/expected/test_b_format_collate.out +++ b/src/test/regress/expected/test_b_format_collate.out @@ -80,6 +80,13 @@ DETAIL: this collation only support in B-format database create table t1(a blob); -- test B format \c test_collate_B +SET b_format_behavior_compat_options = 'enable_multi_charset'; +SHOW b_format_behavior_compat_options; + b_format_behavior_compat_options +---------------------------------- + enable_multi_charset +(1 row) + -- test create table/alter table drop table if exists t_collate; NOTICE: table "t_collate" does not exist, skipping @@ -980,7 +987,7 @@ select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f ERROR: syntax error at or near "select" LINE 2: select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 ... ^ -select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; --fail +select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; f1 | f1 ----+---- S | S @@ -1042,7 +1049,7 @@ select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f ERROR: syntax error at or near "select" LINE 2: select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 ... ^ -select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; --fail +select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; f1 | f1 ----+---- S | S @@ -1135,11 +1142,14 @@ select * from test_sep_option3 union select * from test_sep_option4 order by f1; Å  | Å  (4 rows) -select * from test_sep_option1 union select * from test_sep_option3; -- fail -ERROR: collation mismatch between implicit collations "utf8mb4_general_ci" and "utf8mb4_bin" -LINE 1: select * from test_sep_option1 union select * from test_sep_... - ^ -HINT: You can choose the collation by applying the COLLATE clause to one or both expressions. +select * from test_sep_option1 union select * from test_sep_option3 order by f1; + f1 | f2 +----+---- + s | s + Å› | Å› + Å  | Å  +(3 rows) + -- test setop drop table if exists test_sep_option1; drop table if exists test_sep_option2; diff --git a/src/test/regress/expected/test_b_format_gb_collate.out b/src/test/regress/expected/test_b_format_gb_collate.out new file mode 100644 index 000000000..21166113b --- /dev/null +++ b/src/test/regress/expected/test_b_format_gb_collate.out @@ -0,0 +1,1065 @@ +create database b_utf8 dbcompatibility = 'b' encoding = 'utf8' LC_CTYPE = 'C' LC_COLLATE = 'C'; +\c b_utf8 +SET b_format_behavior_compat_options = 'enable_multi_charset'; +select 'Å SÅ›s' collate "gbk_chinese_ci"; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Å SÅ›s' collate "gbk_chinese_ci"; + ^ +select _gbk'中文ŠSÅ›s' collate "gbk_chinese_ci"; + ?column? +------------- + 涓枃艩S艣s +(1 row) + +select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; + ^ +select 'Aaa' = 'aAA' collate gbk_chinese_ci; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Aaa' = 'aAA' collate gbk_chinese_ci; + ^ +select 'Å SÅ›s' collate "gbk_bin"; +ERROR: COLLATION "gbk_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Å SÅ›s' collate "gbk_bin"; + ^ +select _gbk'中文ŠSÅ›s' collate "gbk_bin"; + ?column? +------------- + 涓枃艩S艣s +(1 row) + +select _utf8'中文ŠSÅ›s' collate "gbk_bin"; +ERROR: COLLATION "gbk_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: select _utf8'中文ŠSÅ›s' collate "gbk_bin"; + ^ +select 'Aaa' = 'aAA' collate gbk_bin; +ERROR: COLLATION "gbk_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Aaa' = 'aAA' collate gbk_bin; + ^ +select 'Å SÅ›s' collate "gb18030_chinese_ci"; +ERROR: COLLATION "gb18030_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Å SÅ›s' collate "gb18030_chinese_ci"; + ^ +select _gb18030'中文ŠSÅ›s' collate "gb18030_chinese_ci"; + ?column? +------------- + 涓枃艩S艣s +(1 row) + +select _utf8'中文ŠSÅ›s' collate "gb18030_chinese_ci"; +ERROR: COLLATION "gb18030_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select _utf8'中文ŠSÅ›s' collate "gb18030_chinese_ci"; + ^ +select 'Aaa' = 'aAA' collate gb18030_chinese_ci; +ERROR: COLLATION "gb18030_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Aaa' = 'aAA' collate gb18030_chinese_ci; + ^ +select 'Å SÅ›s' collate "gb18030_bin"; +ERROR: COLLATION "gb18030_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Å SÅ›s' collate "gb18030_bin"; + ^ +select _gbk'中文ŠSÅ›s' collate "gb18030_bin"; +ERROR: COLLATION "gb18030_bin" is not valid for CHARACTER SET "GBK" +LINE 1: select _gbk'中文ŠSÅ›s' collate "gb18030_bin"; + ^ +select _utf8'中文ŠSÅ›s' collate "gb18030_bin"; +ERROR: COLLATION "gb18030_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: select _utf8'中文ŠSÅ›s' collate "gb18030_bin"; + ^ +select 'Aaa' = 'aAA' collate gb18030_bin; +ERROR: COLLATION "gb18030_bin" is not valid for CHARACTER SET "UTF8" +LINE 1: select 'Aaa' = 'aAA' collate gb18030_bin; + ^ +-- set names gbk; +-- select 'Å SÅ›s' collate "gbk_chinese_ci"; +-- select _gbk'中文ŠSÅ›s' collate "gbk_chinese_ci"; +-- select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; +create database b_gbk dbcompatibility = 'b' encoding = 'gbk' LC_CTYPE = 'C' LC_COLLATE = 'C'; +\c b_gbk +SET b_format_behavior_compat_options = 'enable_multi_charset'; +select _gbk'中文ŠSÅ›s' collate "gbk_chinese_ci"; + ?column? +-------------- + 中文ŠSÅ›s +(1 row) + +select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; +ERROR: COLLATION "gbk_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; + ^ +select 'Å SÅ›s' collate "gbk_chinese_ci"; -- fail + ?column? +---------- + Å SÅ›s +(1 row) + +select 'Aaa' = 'aAA' collate gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'a' = 'A ' collate gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'a' collate gbk_chinese_ci = 'A '; + ?column? +---------- + t +(1 row) + +select 'y' = '~' collate gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'y中文' = 'Y中文' collate gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'A' > '中文汉字' collate "gbk_chinese_ci"; + ?column? +---------- + f +(1 row) + +select '中文汉字AA' > '中文汉字' collate "gbk_chinese_ci"; + ?column? +---------- + t +(1 row) + +select '中文汉字AA' = '中文汉字aa' collate "gbk_chinese_ci"; + ?column? +---------- + t +(1 row) + +select '中文' < '高斯' collate gbk_chinese_ci; + ?column? +---------- + t +(1 row) + +select '中文' collate gbk_bin > '高斯' collate gbk_chinese_ci; +ERROR: collation mismatch between explicit collations "gbk_bin" and "gbk_chinese_ci" +LINE 1: select '中文' collate gbk_bin > '高斯' collate gbk_chine... + ^ +select '中文' collate gbk_bin > '高斯' collate gbk_chinese_ci; +ERROR: collation mismatch between explicit collations "gbk_bin" and "gbk_chinese_ci" +LINE 1: select '中文' collate gbk_bin > '高斯' collate gbk_chine... + ^ +drop table if exists t1; +NOTICE: table "t1" does not exist, skipping +create table t1(c1 text character set 'gbk' collate 'gbk_chinese_ci', c2 text collate 'gbk_bin', c3 text) charset utf8; +select pg_get_tabledef('t1'); + pg_get_tabledef +------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE t1 ( + + c1 text CHARACTER SET "GBK" COLLATE gbk_chinese_ci, + + c2 text CHARACTER SET "GBK" COLLATE gbk_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci+ + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, compression=no); +(1 row) + +insert into t1 values('中文ab','中文ab','中文ab'),('中文Ab ','中文Ab ','中文Ab '),('中文','中文','中文'),('中文 ','中文 ','中文 '),(null, null, null); +--test gbk_chinese_ci +select c1 from t1 where c1 = '中文'; + c1 +----------- + 中文 + 中文 +(2 rows) + +select c1 from t1 where c1 = '中文ab'; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 = '中文ab' collate 'gbk_bin'; + c1 +---------- + 中文ab +(1 row) + +select c1 from t1 where c1 = '中文ab' collate 'utf8mb4_bin'; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GBK" +LINE 1: select c1 from t1 where c1 = '中文ab' collate 'utf8mb4_bin... + ^ +select c1 from t1 where c1 in ('中文ab' collate 'utf8_bin'); +ERROR: COLLATION "utf8_bin" is not valid for CHARACTER SET "GBK" +LINE 1: select c1 from t1 where c1 in ('中文ab' collate 'utf8_bin'... + ^ +select c1 from t1 order by c1; + c1 +----------- + 中文 + 中文 + 中文ab + 中文Ab + +(5 rows) + +select distinct c1 from t1 order by c1; + c1 +---------- + 中文 + 中文ab + +(3 rows) + +select distinct c1 from t1 order by c1; + c1 +---------- + 中文 + 中文ab + +(3 rows) + +select count(c1), c1 from t1 group by c1 order by c1; + count | c1 +-------+---------- + 2 | 中文 + 2 | 中文ab + 0 | +(3 rows) + +-- like ,ilike +select c1 from t1 where c1 like '中文A_%' order by c1; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '%a%' order by c1; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '中文__'; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select distinct c1 from t1 where c1 like '中文A_%'; + c1 +---------- + 中文ab +(1 row) + +-- test gbk_bin +select c2 from t1 where c2 = '中文'; + c2 +----------- + 中文 + 中文 +(2 rows) + +select c2 from t1 where c2 = '中文ab'; + c2 +---------- + 中文ab +(1 row) + +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GBK" +LINE 1: select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin... + ^ +select c2 from t1 order by c2; + c2 +----------- + 中文 + 中文 + 中文Ab + 中文ab + +(5 rows) + +select distinct c2 from t1; + c2 +----------- + 中文Ab + + 中文 + 中文ab +(4 rows) + +select distinct c2 from t1 order by c2; + c2 +----------- + 中文 + 中文Ab + 中文ab + +(4 rows) + +select count(c2), c2 from t1 group by c2; + count | c2 +-------+----------- + 1 | 中文Ab + 0 | + 2 | 中文 + 1 | 中文ab +(4 rows) + +select count(c2), c2 from t1 group by c2 order by c2; + count | c2 +-------+----------- + 2 | 中文 + 1 | 中文Ab + 1 | 中文ab + 0 | +(4 rows) + +select c2 from t1 where c2 like '中文A_%'; + c2 +----------- + 中文Ab +(1 row) + +select c2 from t1 where c2 like '%a%'; + c2 +---------- + 中文ab +(1 row) + +select c2 from t1 where c2 like '中文__'; + c2 +---------- + 中文ab +(1 row) + +select distinct c2 from t1 where c2 like '中文A_%'; + c2 +----------- + 中文Ab +(1 row) + +--test char(n) +alter table t1 modify c1 char(20) collate gbk_chinese_ci; +alter table t1 modify c2 char(20) collate gbk_bin; +select pg_get_tabledef('t1'); + pg_get_tabledef +------------------------------------------------------------------ + SET search_path = public; + + CREATE TABLE t1 ( + + c1 character(20) CHARACTER SET "GBK" COLLATE gbk_chinese_ci,+ + c2 character(20) CHARACTER SET "GBK" COLLATE gbk_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, compression=no); +(1 row) + +select c1 from t1 where c1 = '中文'; + c1 +---------------------- + 中文 + 中文 +(2 rows) + +select c1 from t1 where c1 = '中文ab'; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 order by c1; + c1 +---------------------- + 中文 + 中文 + 中文ab + 中文Ab + +(5 rows) + +select distinct c1 from t1; + c1 +---------------------- + 中文ab + + 中文 +(3 rows) + +select distinct c1 from t1 order by c1; + c1 +---------------------- + 中文 + 中文ab + +(3 rows) + +select count(c1), c1 from t1 group by c1; + count | c1 +-------+---------------------- + 2 | 中文ab + 0 | + 2 | 中文 +(3 rows) + +select count(c1), c1 from t1 group by c1 order by c1; + count | c1 +-------+---------------------- + 2 | 中文 + 2 | 中文ab + 0 | +(3 rows) + +select c1 from t1 where c1 like '中文A_%' order by c1; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '%a%' order by c1; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '中文__'; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select distinct c1 from t1 where c1 like '中文A_%'; + c1 +---------------------- + 中文ab +(1 row) + +-- test gbk_bin +select c2 from t1 where c2 = '中文'; + c2 +---------------------- + 中文 + 中文 +(2 rows) + +select c2 from t1 where c2 = '中文ab'; + c2 +---------------------- + 中文ab +(1 row) + +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GBK" +LINE 1: select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin... + ^ +select c2 from t1 order by c2; + c2 +---------------------- + 中文 + 中文 + 中文Ab + 中文ab + +(5 rows) + +select distinct c2 from t1; + c2 +---------------------- + 中文Ab + + 中文 + 中文ab +(4 rows) + +select distinct c2 from t1 order by c2; + c2 +---------------------- + 中文 + 中文Ab + 中文ab + +(4 rows) + +select count(c2), c2 from t1 group by c2; + count | c2 +-------+---------------------- + 1 | 中文Ab + 0 | + 2 | 中文 + 1 | 中文ab +(4 rows) + +select count(c2), c2 from t1 group by c2 order by c2; + count | c2 +-------+---------------------- + 2 | 中文 + 1 | 中文Ab + 1 | 中文ab + 0 | +(4 rows) + +select c2 from t1 where c2 like '中文A_%'; + c2 +---------------------- + 中文Ab +(1 row) + +select c2 from t1 where c2 like '%a%'; + c2 +---------------------- + 中文ab +(1 row) + +select c2 from t1 where c2 like '中文__'; + c2 +---- +(0 rows) + +select distinct c2 from t1 where c2 like '中文A_%'; + c2 +---------------------- + 中文Ab +(1 row) + +-- create table as/like +create table t2 as select * from t1; +select pg_get_tabledef('t2'); + pg_get_tabledef +------------------------------------------------------------------ + SET search_path = public; + + CREATE TABLE t2 ( + + c1 character(20) CHARACTER SET "GBK" COLLATE gbk_chinese_ci,+ + c2 character(20) CHARACTER SET "GBK" COLLATE gbk_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + WITH (orientation=row, compression=no); +(1 row) + +create table t3 (like t1); +select pg_get_tabledef('t3'); + pg_get_tabledef +------------------------------------------------------------------ + SET search_path = public; + + CREATE TABLE t3 ( + + c1 character(20) CHARACTER SET "GBK" COLLATE gbk_chinese_ci,+ + c2 character(20) CHARACTER SET "GBK" COLLATE gbk_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + WITH (orientation=row, compression=no); +(1 row) + +create table t4(c1 text character set 'utf8' collate 'gbk_chinese_ci'); --fail +ERROR: collation "gbk_chinese_ci" for encoding "UTF8" does not exist +-- test gb18030 collate !!! +create database b_gb18030 dbcompatibility = 'b' encoding = 'gb18030' LC_CTYPE = 'C' LC_COLLATE = 'C'; +\c b_gb18030 +SET b_format_behavior_compat_options = 'enable_multi_charset'; +select _gb18030'中文ŠSÅ›s' collate "gb18030_chinese_ci"; + ?column? +-------------- + 中文ŠSÅ›s +(1 row) + +select _utf8'中文ŠSÅ›s' collate "gb18030_chinese_ci"; +ERROR: COLLATION "gb18030_chinese_ci" is not valid for CHARACTER SET "UTF8" +LINE 1: select _utf8'中文ŠSÅ›s' collate "gb18030_chinese_ci"; + ^ +select 'Å SÅ›s' collate "gb18030_chinese_ci"; -- fail + ?column? +---------- + Å SÅ›s +(1 row) + +select 'Aaa' = 'aAA' collate gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'a' = 'A ' collate gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'a' collate gb18030_chinese_ci = 'A '; + ?column? +---------- + t +(1 row) + +select 'y' = '~' collate gb18030_chinese_ci; + ?column? +---------- + f +(1 row) + +select 'y中文' = 'Y中文' collate gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +select 'A' > '中文汉字' collate "gb18030_chinese_ci"; + ?column? +---------- + f +(1 row) + +select '中文汉字AA' > '中文汉字' collate "gb18030_chinese_ci"; + ?column? +---------- + t +(1 row) + +select '中文汉字AA' = '中文汉字aa' collate "gb18030_chinese_ci"; + ?column? +---------- + t +(1 row) + +select '中文' < '高斯' collate gb18030_chinese_ci; + ?column? +---------- + t +(1 row) + +select '中文' collate gb18030_bin > '高斯' collate gb18030_chinese_ci; +ERROR: collation mismatch between explicit collations "gb18030_bin" and "gb18030_chinese_ci" +LINE 1: select '中文' collate gb18030_bin > '高斯' collate gb180... + ^ +select '中文' collate gb18030_bin > '高斯' collate gb18030_chinese_ci; +ERROR: collation mismatch between explicit collations "gb18030_bin" and "gb18030_chinese_ci" +LINE 1: select '中文' collate gb18030_bin > '高斯' collate gb180... + ^ +drop table if exists t1; +NOTICE: table "t1" does not exist, skipping +create table t1(c1 text character set 'gb18030' collate 'gb18030_chinese_ci', c2 text collate 'gb18030_bin', c3 text) charset utf8; +select pg_get_tabledef('t1'); + pg_get_tabledef +----------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE t1 ( + + c1 text CHARACTER SET "GB18030" COLLATE gb18030_chinese_ci,+ + c2 text CHARACTER SET "GB18030" COLLATE gb18030_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, compression=no); +(1 row) + +insert into t1 values('中文ab','中文ab','中文ab'),('中文Ab ','中文Ab ','中文Ab '),('中文','中文','中文'),('中文 ','中文 ','中文 '),(null, null, null); +--test gb18030_chinese_ci +select c1 from t1 where c1 = '中文'; + c1 +----------- + 中文 + 中文 +(2 rows) + +select c1 from t1 where c1 = '中文ab'; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 = '中文ab' collate 'gb18030_bin'; + c1 +---------- + 中文ab +(1 row) + +select c1 from t1 where c1 = '中文ab' collate 'utf8mb4_bin'; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GB18030" +LINE 1: select c1 from t1 where c1 = '中文ab' collate 'utf8mb4_bin... + ^ +select c1 from t1 where c1 in ('中文ab' collate 'utf8_bin'); +ERROR: COLLATION "utf8_bin" is not valid for CHARACTER SET "GB18030" +LINE 1: select c1 from t1 where c1 in ('中文ab' collate 'utf8_bin'... + ^ +select c1 from t1 order by c1; + c1 +----------- + 中文 + 中文 + 中文ab + 中文Ab + +(5 rows) + +select distinct c1 from t1; + c1 +---------- + 中文ab + + 中文 +(3 rows) + +select distinct c1 from t1 order by c1; + c1 +---------- + 中文 + 中文ab + +(3 rows) + +select count(c1), c1 from t1 group by c1; + count | c1 +-------+---------- + 2 | 中文ab + 0 | + 2 | 中文 +(3 rows) + +select count(c1), c1 from t1 group by c1 order by c1; + count | c1 +-------+---------- + 2 | 中文 + 2 | 中文ab + 0 | +(3 rows) + +select c1 from t1 where c1 like '中文A_%' order by c1; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '%a%' order by c1; + c1 +----------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '中文__'; + c1 +---------- + 中文ab +(1 row) + +select distinct c1 from t1 where c1 like '中文A_%'; + c1 +---------- + 中文ab +(1 row) + +-- test gb18030_bin +select c2 from t1 where c2 = '中文'; + c2 +----------- + 中文 + 中文 +(2 rows) + +select c2 from t1 where c2 = '中文ab'; + c2 +---------- + 中文ab +(1 row) + +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GB18030" +LINE 1: select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin... + ^ +select c2 from t1 order by c2; + c2 +----------- + 中文 + 中文 + 中文Ab + 中文ab + +(5 rows) + +select distinct c2 from t1; + c2 +----------- + 中文Ab + + 中文 + 中文ab +(4 rows) + +select distinct c2 from t1 order by c2; + c2 +----------- + 中文 + 中文Ab + 中文ab + +(4 rows) + +select count(c2), c2 from t1 group by c2; + count | c2 +-------+----------- + 1 | 中文Ab + 0 | + 2 | 中文 + 1 | 中文ab +(4 rows) + +select count(c2), c2 from t1 group by c2 order by c2; + count | c2 +-------+----------- + 2 | 中文 + 1 | 中文Ab + 1 | 中文ab + 0 | +(4 rows) + +select c2 from t1 where c2 like '中文A_%'; + c2 +----------- + 中文Ab +(1 row) + +select c2 from t1 where c2 like '%a%'; + c2 +---------- + 中文ab +(1 row) + +select c2 from t1 where c2 like '中文__'; + c2 +---------- + 中文ab +(1 row) + +select distinct c2 from t1 where c2 like '中文A_%'; + c2 +----------- + 中文Ab +(1 row) + +--test char(n) +alter table t1 modify c1 char(20) collate gb18030_chinese_ci; +alter table t1 modify c2 char(20) collate gb18030_bin; +select pg_get_tabledef('t1'); + pg_get_tabledef +-------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE t1 ( + + c1 character(20) CHARACTER SET "GB18030" COLLATE gb18030_chinese_ci,+ + c2 character(20) CHARACTER SET "GB18030" COLLATE gb18030_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci" + + WITH (orientation=row, compression=no); +(1 row) + +select c1 from t1 where c1 = '中文'; + c1 +---------------------- + 中文 + 中文 +(2 rows) + +select c1 from t1 where c1 = '中文ab'; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 order by c1; + c1 +---------------------- + 中文 + 中文 + 中文ab + 中文Ab + +(5 rows) + +select distinct c1 from t1 order by c1; + c1 +---------------------- + 中文 + 中文ab + +(3 rows) + +select distinct c1 from t1 order by c1; + c1 +---------------------- + 中文 + 中文ab + +(3 rows) + +select count(c1), c1 from t1 group by c1 order by c1; + count | c1 +-------+---------------------- + 2 | 中文 + 2 | 中文ab + 0 | +(3 rows) + +select c1 from t1 where c1 like '中文A_%' order by c1; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '%a%' order by c1; + c1 +---------------------- + 中文ab + 中文Ab +(2 rows) + +select c1 from t1 where c1 like '中文__'; + c1 +---- +(0 rows) + +select distinct c1 from t1 where c1 like '中文A_%'; + c1 +---------------------- + 中文ab +(1 row) + +-- test gbk_bin +select c2 from t1 where c2 = '中文'; + c2 +---------------------- + 中文 + 中文 +(2 rows) + +select c2 from t1 where c2 = '中文ab'; + c2 +---------------------- + 中文ab +(1 row) + +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GB18030" +LINE 1: select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin... + ^ +select c2 from t1 order by c2; + c2 +---------------------- + 中文 + 中文 + 中文Ab + 中文ab + +(5 rows) + +select distinct c2 from t1; + c2 +---------------------- + 中文Ab + + 中文 + 中文ab +(4 rows) + +select distinct c2 from t1 order by c2; + c2 +---------------------- + 中文 + 中文Ab + 中文ab + +(4 rows) + +select count(c2), c2 from t1 group by c2; + count | c2 +-------+---------------------- + 1 | 中文Ab + 0 | + 2 | 中文 + 1 | 中文ab +(4 rows) + +select count(c2), c2 from t1 group by c2 order by c2; + count | c2 +-------+---------------------- + 2 | 中文 + 1 | 中文Ab + 1 | 中文ab + 0 | +(4 rows) + +select c2 from t1 where c2 like '中文A_%'; + c2 +---------------------- + 中文Ab +(1 row) + +select c2 from t1 where c2 like '%a%'; + c2 +---------------------- + 中文ab +(1 row) + +select c2 from t1 where c2 like '中文__'; + c2 +---- +(0 rows) + +select distinct c2 from t1 where c2 like '中文A_%'; + c2 +---------------------- + 中文Ab +(1 row) + +-- create table as/like +create table t2 as select * from t1; +select pg_get_tabledef('t2'); + pg_get_tabledef +-------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE t2 ( + + c1 character(20) CHARACTER SET "GB18030" COLLATE gb18030_chinese_ci,+ + c2 character(20) CHARACTER SET "GB18030" COLLATE gb18030_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + WITH (orientation=row, compression=no); +(1 row) + +create table t3 (like t1); +select pg_get_tabledef('t3'); + pg_get_tabledef +-------------------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE t3 ( + + c1 character(20) CHARACTER SET "GB18030" COLLATE gb18030_chinese_ci,+ + c2 character(20) CHARACTER SET "GB18030" COLLATE gb18030_bin, + + c3 text CHARACTER SET "UTF8" COLLATE utf8mb4_general_ci + + ) + + WITH (orientation=row, compression=no); +(1 row) + +create table t4(c1 text character set 'utf8' collate 'gb18030_chinese_ci'); --fail +ERROR: collation "gb18030_chinese_ci" for encoding "UTF8" does not exist +\c regression +clean connection to all force for database b_utf8; +clean connection to all force for database b_gbk; +clean connection to all force for database b_gb18030; +DROP DATABASE IF EXISTS b_utf8; +DROP DATABASE IF EXISTS b_gbk; +DROP DATABASE IF EXISTS b_gb18030; diff --git a/src/test/regress/input/add_b_format_behavior_all.source b/src/test/regress/input/add_b_format_behavior_all.source new file mode 100644 index 000000000..1d3da70d9 --- /dev/null +++ b/src/test/regress/input/add_b_format_behavior_all.source @@ -0,0 +1,165 @@ +create database b_behavior_all dbcompatibility 'b'; +\c b_behavior_all + +CREATE TABLE t(a int); +CREATE TABLE test_at_modify_syntax1(a int, b int NOT NULL); +CREATE TABLE test_at_modify_syntax2(a int, b int NOT NULL); +create table company(name varchar(100), loc varchar(100), no integer); +insert into company values ('macrosoft', 'usa', 001); +insert into company values ('oracle', 'usa', 002); +insert into company values ('backberry', 'canada', 003); + +-- session all behavior +set b_format_behavior_compat_options = 'ALL'; + +set session transaction isolation level repeatable read; +start transaction; +select * from t; +\! @abs_bindir@/gsql -p @portstring@ -d b_behavior_all -c "insert into t values(1);"; +select * from t; +commit; +select * from t; +set @aa = 10; +select @aa; +ALTER TABLE test_at_modify_syntax1 MODIFY b varchar(8); +\d+ test_at_modify_syntax1; +create or replace procedure test_cursor_1 +as + company_name varchar(100); + company_loc varchar(100); + company_no integer; + +begin + declare c1_all cursor is + select name, loc, no from company order by 1, 2, 3; + if not c1_all%isopen then + open c1_all; + end if; + loop + fetch c1_all into company_name, company_loc, company_no; + raise notice '% : % : %',company_name,company_loc,company_no; + end loop; + if c1_all%isopen then + close c1_all; + end if; +end; +/ +call test_cursor_1(); +select _gbk'高斯'; + +\c +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options='all'" >/dev/null 2>&1 +select pg_sleep(1); +set session transaction isolation level repeatable read; +start transaction; +select * from t; +\! @abs_bindir@/gsql -p @portstring@ -d b_behavior_all -c "insert into t values(1);"; +select * from t; +commit; +select * from t; +set @aa = 20; +select @aa; +ALTER TABLE test_at_modify_syntax2 MODIFY b varchar(8); +\d+ test_at_modify_syntax2; +create or replace procedure test_cursor_2 +as + company_name varchar(100); + company_loc varchar(100); + company_no integer; + +begin + declare c1_all cursor is + select name, loc, no from company order by 1, 2, 3; + if not c1_all%isopen then + open c1_all; + end if; + loop + fetch c1_all into company_name, company_loc, company_no; + raise notice '% : % : %',company_name,company_loc,company_no; + end loop; + if c1_all%isopen then + close c1_all; + end if; +end; +/ +call test_cursor_2(); +select _gbk'高斯'; + +drop table t, test_at_modify_syntax1, test_at_modify_syntax2, company; +drop procedure test_cursor_2; +\c +set names utf8; +CREATE TABLE t_charset_1( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +CREATE TABLE t_charset_2( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_charset_1(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- test copy +copy (select * from t_charset_1) to '@abs_srcdir@/data/t_charset_1.data'; +\! cat @abs_srcdir@/data/t_charset_1.data +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.data'; +select * from t_charset_2; + +copy (select * from t_charset_1) to '@abs_srcdir@/data/t_charset_1.data' encoding 'utf8'; +\! cat @abs_srcdir@/data/t_charset_1.data +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.data' encoding 'utf8'; +select * from t_charset_2; + +copy (select * from t_charset_1) to '@abs_srcdir@/data/t_charset_1.data' encoding 'gbk'; +\! cat @abs_srcdir@/data/t_charset_1.data +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.data' encoding 'gbk'; +select * from t_charset_2; + +copy t_charset_1 to '@abs_srcdir@/data/t_charset_1.csv' encoding 'gbk' FIXED FORMATTER (futf8_bin(1, 10), futf8_uni(11, 10), futf8_gen(21, 10), fgbk_bin(31, 10), fgbk_chi(41, 10), fgb18030_bin(51, 10), fgb18030_chi(61, 10), fbytea(71, 20), fblob(91, 20), fbit(111, 60)); +\! cat @abs_srcdir@/data/t_charset_1.csv +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.csv' encoding 'gbk' FIXED FORMATTER (futf8_bin(1, 10), futf8_uni(11, 10), futf8_gen(21, 10), fgbk_bin(31, 10), fgbk_chi(41, 10), fgb18030_bin(51, 10), fgb18030_chi(61, 10)); +select * from t_charset_2; + +copy t_charset_1 to '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '分隔符' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); +\! cat @abs_srcdir@/data/t_charset_1.csv +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '分隔符' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); -- ERROR +copy t_charset_1 to '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '|' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); +\! cat @abs_srcdir@/data/t_charset_1.csv +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '|' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); +select * from t_charset_2; + +-- test select into outfile +select * from t_charset_1 into outfile '@abs_srcdir@/data/t_charset_1.data2'; +\! cat @abs_srcdir@/data/t_charset_1.data2 +select * from t_charset_1 into outfile '@abs_srcdir@/data/t_charset_1.data2' character set 'utf8'; +\! cat @abs_srcdir@/data/t_charset_1.data2 +select * from t_charset_1 into outfile '@abs_srcdir@/data/t_charset_1.data2' character set 'gbk'; +\! cat @abs_srcdir@/data/t_charset_1.data2 + +-- test gs_dump +create database b_behavior_all2 dbcompatibility 'b'; +\! @abs_bindir@/gs_dump b_behavior_all -p @portstring@ -f @abs_bindir@/t_charset_1.tar -F t >/dev/null 2>&1; echo $? +\! @abs_bindir@/gs_restore -d b_behavior_all2 -p @portstring@ @abs_bindir@/t_charset_1.tar >/dev/null 2>&1; echo $? +\c b_behavior_all2 +select * from t_charset_1; +select * from t_charset_2; + +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options=''" >/dev/null 2>&1 +select pg_sleep(1); +\c regression \ No newline at end of file diff --git a/src/test/regress/input/charset_b_format.source b/src/test/regress/input/charset_b_format.source index 2b3eb1e71..aea4d0d78 100644 --- a/src/test/regress/input/charset_b_format.source +++ b/src/test/regress/input/charset_b_format.source @@ -19,8 +19,7 @@ create schema s_charset_2 charset = utf8mb4 collate = utf8mb4_unicode_ci; create schema s_charset_3 charset = utf8mb4 collate = utf8mb4_general_ci; create schema s_charset_4 charset = utf8mb4; create schema s_charset_5 charset = utf8; -create schema s_charset_6 charset = gbk; -- error -create schema s_charset_6; +create schema s_charset_6 charset = gbk; create schema s_charset_7 default charset = utf8mb4 default collate = utf8mb4_unicode_ci; create schema s_charset_8 charset = "binary"; create schema s_charset_9 character set = utf8mb4; @@ -45,7 +44,7 @@ create schema s_charset_15 charset = gbk collate = "zh_CN.gbk"; -- error alter schema s_charset_1 charset utf8mb4 collate utf8mb4_general_ci; alter schema s_charset_2 charset = utf8mb4 collate = utf8mb4_general_ci; alter schema s_charset_3 collate = utf8mb4_unicode_ci; -alter schema s_charset_5 charset = gbk; -- error +alter schema s_charset_5 charset = gbk; alter schema s_charset_5 charset = gbk collate = "zh_CN.gbk"; -- error alter schema s_charset_9 character set = utf8 collate = utf8mb4_unicode_ci; select * from pg_namespace where nspname like 's_charset_%' order by 1; @@ -56,8 +55,7 @@ create table t_charset_2 (c1 varchar(20)) charset = utf8mb4 collate = utf8mb4_un create table t_charset_3 (c1 varchar(20)) charset = utf8mb4 collate = utf8mb4_general_ci; create table t_charset_4 (c1 varchar(20)) charset = utf8mb4; create table t_charset_5 (c1 varchar(20)) charset = utf8; -create table t_charset_6 (c1 varchar(20)) charset = gbk; -- error -create table t_charset_6 (c1 varchar(20)); +create table t_charset_6 (c1 varchar(20)) charset = gbk; create table t_charset_7 (c1 varchar(20)) default charset = utf8mb4 default collate = utf8mb4_unicode_ci; create table t_charset_8 (c1 varchar(20)) charset = binary; -- error create table t_charset_8 (c1 text) charset = binary; @@ -147,7 +145,7 @@ alter table a_charset_2 add a24 varchar(20) collate "zh_CN.gbk"; -- error; select pg_get_tabledef('a_charset_2'); alter table a_charset_2 add a8 varchar(20) charset utf8mb4 charset utf8mb4; -- error alter table a_charset_2 modify a1 int; -alter table a_charset_2 modify a9 varchar(20) character set gbk; -- error +alter table a_charset_2 modify a9 varchar(20) character set gbk; alter table a_charset_2 modify a10 varchar(20); alter table a_charset_2 modify a11 varchar(20) collate utf8mb4_unicode_ci; alter table a_charset_2 modify a12 varchar(20) charset utf8mb4; @@ -213,6 +211,19 @@ alter table tem_charset_1 collate utf8mb4_unicode_ci; insert into tem_charset_1 values('a中国a'); select r.relname,r.reloptions,a.attcollation from pg_class r,pg_attribute a where r.oid=a.attrelid and r.relname='tem_charset_1'; +-- cstore not supported +SET b_format_behavior_compat_options = 'default_collation, enable_multi_charset'; +create schema s_charset_multi charset = gbk; +create table s_charset_multi.cstore_charset_1(c1 varchar(20),c2 varchar(20),c3 int) with (ORIENTATION=column); -- ERROR +DROP schema s_charset_multi; +create table cstore_charset_1(c1 varchar(20),c2 varchar(20),c3 int) character set = gbk with (ORIENTATION=column); -- ERROR +create table cstore_charset_1(c1 varchar(20),c2 varchar(20) character set gbk,c3 int) with (ORIENTATION=column); -- ERROR +create table cstore_charset_1(c1 varchar(20),c2 varchar(20),c3 int) with (ORIENTATION=column); +ALTER TABLE cstore_charset_1 ADD COLUMN c4 varchar(20) character set gbk; -- ERROR +ALTER TABLE cstore_charset_1 MODIFY COLUMN c1 varchar(20) character set gbk; -- ERROR +drop table cstore_charset_1; + + \! @abs_bindir@/gs_dump d_charset -p @portstring@ -f @abs_bindir@/d_charset.tar -F t >/dev/null 2>&1; echo $? \! @abs_bindir@/gs_restore -d d_charset_bak -p @portstring@ @abs_bindir@/d_charset.tar >/dev/null 2>&1; echo $? \c d_charset_bak; diff --git a/src/test/regress/input/charset_connection_test.source b/src/test/regress/input/charset_connection_test.source new file mode 100644 index 000000000..8339088bd --- /dev/null +++ b/src/test/regress/input/charset_connection_test.source @@ -0,0 +1,144 @@ +\c regression +show client_encoding; +show character_set_connection; +show collation_connection; +select 'aa' = 'AA'; + +set names utf8; +show client_encoding; +show character_set_connection; +show collation_connection; +select 'aa' = 'AA'; + +-- error case +set names utf8 collate gbk_bin; + +create database charset_connection_test dbcompatibility 'b'; +\c charset_connection_test +-- show encoding settings +show client_encoding; +show character_set_connection; +show collation_connection; +select 'aa' = 'AA'; + +set names utf8; +show client_encoding; +show character_set_connection; +show collation_connection; +select 'aa' = 'AA'; + +-- expect error cases +SET NAMES utf8mb4 COLLATE utf8mb4_general_ci; + +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options='all'" >/dev/null 2>&1 +select pg_sleep(1); +\c + +-- show encoding settings +show client_encoding; +show character_set_connection; +show collation_connection; +select 'aa' = 'AA'; + +--error cases +SET NAMES 'utf8' COLLATE DEFAULT; +SET NAMES 'gbk' COLLATE 'utf8mb4_bin'; +SET NAMES utf8 COLLATE gbk_bin; +SET NAMES COLLATE 'utf8mb4_bin'; + +SET NAMES gbk; +show client_encoding; +show character_set_connection; +show collation_connection; +select '高斯aa' = '高斯AA'; +select '高斯aa' = '高斯AA' collate 'utf8mb4_bin'; --error case +select '高斯aa' = '高斯AA' collate 'gbk_bin'; + +set collation_connection = utf8mb4_bin; +show character_set_connection; +show collation_connection; +select 'aa' = 'AA'; + +set character_set_connection = gbk; +show character_set_connection; +show collation_connection; +select '高斯aa' = '高斯AA'; + +SET NAMES DEFAULT; +show client_encoding; +show character_set_connection; +show collation_connection; +select '高斯aa' = '高斯AA'; + +SET NAMES; +show client_encoding; +show character_set_connection; +show collation_connection; +select '高斯aa' = '高斯AA'; + +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options=''" >/dev/null 2>&1 +select pg_sleep(1); +\c +show client_encoding; +show character_set_connection; +show collation_connection; +select '高斯aa' = '高斯AA'; --false + +set b_format_behavior_compat_options = 'ALL'; +set @aa = '高斯aa'; +set @bb = (select '高斯aa'); +select @cc := '高斯aa'; +select @dd := (select '高斯aa'); +select '高斯aa' into @ee; +select @aa,@bb,@cc,@dd,@ee; +select collation for(@aa), collation for(@bb), collation for(@cc), collation for(@dd), collation for(@ee); + +set names gbk; +set @aa = '高斯aa'; +set @bb = (select '高斯aa'); +select @cc := '高斯aa'; +select @dd := (select '高斯aa'); +select '高斯aa' into @ee; +select @aa,@bb,@cc,@dd,@ee; +select collation for(@aa), collation for(@bb), collation for(@cc), collation for(@dd), collation for(@ee); + +set @aa = '高斯aa' collate utf8mb4_unicode_ci; +set @bb = (select '高斯aa' collate utf8mb4_unicode_ci); +select @cc := '高斯aa' collate utf8mb4_unicode_ci; +select @dd := (select '高斯aa' collate utf8mb4_unicode_ci); +select '高斯aa' collate utf8mb4_unicode_ci into @ee; + +set client_encoding = utf8mb4; +select @aa,@bb,@cc,@dd,@ee; + +set names utf8; +set @aa = '高斯aa' collate utf8mb4_unicode_ci; +set @bb = (select '高斯aa' collate utf8mb4_unicode_ci); +select @cc := '高斯aa' collate utf8mb4_unicode_ci; +select @dd := (select '高斯aa' collate utf8mb4_unicode_ci); +select '高斯aa' collate utf8mb4_unicode_ci into @ee; +select @aa,@bb,@cc,@dd,@ee; +select collation for(@aa), collation for(@bb), collation for(@cc), collation for(@dd), collation for(@ee); + +set names gbk; +create table t(a text collate utf8mb4_bin, b text collate utf8mb4_unicode_ci); +insert into t values('高斯aa', '高斯bb'); +select * from t into @a,@b; +select @a,@b; +select collation for(@a), collation for(@b); +select * from t where a = 'c' into @a,@b; +select @a,@b; +select collation for(@a), collation for(@b); +create database charset_gbk dbcompatibility 'b' encoding 'gbk' lc_ctype = 'C' lc_collate = 'C'; +\c charset_gbk +set client_encoding = utf8; +show client_encoding; +show character_set_connection; +show collation_connection; +create table t1(a text charset gbk collate gbk_bin); +insert into t1 values('高斯'); +select * from t1; +create database latin1_db dbcompatibility 'b' encoding 'latin1' lc_ctype = 'C' lc_collate = 'C'; +\c latin1_db +select '高斯aa' = '高斯AA'; +\c regression \ No newline at end of file diff --git a/src/test/regress/output/add_b_format_behavior_all.source b/src/test/regress/output/add_b_format_behavior_all.source new file mode 100644 index 000000000..6113a7458 --- /dev/null +++ b/src/test/regress/output/add_b_format_behavior_all.source @@ -0,0 +1,302 @@ +create database b_behavior_all dbcompatibility 'b'; +\c b_behavior_all +CREATE TABLE t(a int); +CREATE TABLE test_at_modify_syntax1(a int, b int NOT NULL); +CREATE TABLE test_at_modify_syntax2(a int, b int NOT NULL); +create table company(name varchar(100), loc varchar(100), no integer); +insert into company values ('macrosoft', 'usa', 001); +insert into company values ('oracle', 'usa', 002); +insert into company values ('backberry', 'canada', 003); +-- session all behavior +set b_format_behavior_compat_options = 'ALL'; +set session transaction isolation level repeatable read; +start transaction; +select * from t; + a +--- +(0 rows) + +\! @abs_bindir@/gsql -p @portstring@ -d b_behavior_all -c "insert into t values(1);"; +INSERT 0 1 +select * from t; + a +--- +(0 rows) + +commit; +select * from t; + a +--- + 1 +(1 row) + +set @aa = 10; +select @aa; + @aa +----- + 10 +(1 row) + +ALTER TABLE test_at_modify_syntax1 MODIFY b varchar(8); +\d+ test_at_modify_syntax1; + Table "public.test_at_modify_syntax1" + Column | Type | Modifiers | Storage | Stats target | Description +--------+----------------------+-----------------------------------------------+----------+--------------+------------- + a | integer | | plain | | + b | character varying(8) | character set UTF8 collate utf8mb4_general_ci | extended | | +Has OIDs: no +Options: orientation=row, compression=no + +create or replace procedure test_cursor_1 +as + company_name varchar(100); + company_loc varchar(100); + company_no integer; + +begin + declare c1_all cursor is + select name, loc, no from company order by 1, 2, 3; + if not c1_all%isopen then + open c1_all; + end if; + loop + fetch c1_all into company_name, company_loc, company_no; + raise notice '% : % : %',company_name,company_loc,company_no; + end loop; + if c1_all%isopen then + close c1_all; + end if; +end; +/ +call test_cursor_1(); +NOTICE: backberry : canada : 3 +NOTICE: macrosoft : usa : 1 +NOTICE: oracle : usa : 2 +ERROR: No data - zero rows fetched, selected, or processed +CONTEXT: PL/pgSQL function test_cursor_1() line 12 at FETCH +select _gbk'高斯'; + ?column? +---------- + 楂樻柉 +(1 row) + +\c +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options='all'" >/dev/null 2>&1 +select pg_sleep(1); + pg_sleep +---------- + +(1 row) + +set session transaction isolation level repeatable read; +start transaction; +select * from t; + a +--- + 1 +(1 row) + +\! @abs_bindir@/gsql -p @portstring@ -d b_behavior_all -c "insert into t values(1);"; +INSERT 0 1 +select * from t; + a +--- + 1 +(1 row) + +commit; +select * from t; + a +--- + 1 + 1 +(2 rows) + +set @aa = 20; +select @aa; + @aa +----- + 20 +(1 row) + +ALTER TABLE test_at_modify_syntax2 MODIFY b varchar(8); +\d+ test_at_modify_syntax2; + Table "public.test_at_modify_syntax2" + Column | Type | Modifiers | Storage | Stats target | Description +--------+----------------------+-----------------------------------------------+----------+--------------+------------- + a | integer | | plain | | + b | character varying(8) | character set UTF8 collate utf8mb4_general_ci | extended | | +Has OIDs: no +Options: orientation=row, compression=no + +create or replace procedure test_cursor_2 +as + company_name varchar(100); + company_loc varchar(100); + company_no integer; + +begin + declare c1_all cursor is + select name, loc, no from company order by 1, 2, 3; + if not c1_all%isopen then + open c1_all; + end if; + loop + fetch c1_all into company_name, company_loc, company_no; + raise notice '% : % : %',company_name,company_loc,company_no; + end loop; + if c1_all%isopen then + close c1_all; + end if; +end; +/ +call test_cursor_2(); +NOTICE: backberry : canada : 3 +NOTICE: macrosoft : usa : 1 +NOTICE: oracle : usa : 2 +ERROR: No data - zero rows fetched, selected, or processed +CONTEXT: PL/pgSQL function test_cursor_2() line 12 at FETCH +select _gbk'高斯'; + ?column? +---------- + 楂樻柉 +(1 row) + +drop table t, test_at_modify_syntax1, test_at_modify_syntax2, company; +drop procedure test_cursor_2; +\c +set names utf8; +CREATE TABLE t_charset_1( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +CREATE TABLE t_charset_2( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_charset_1(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- test copy +copy (select * from t_charset_1) to '@abs_srcdir@/data/t_charset_1.data'; +\! cat @abs_srcdir@/data/t_charset_1.data +高斯DB 高斯db 高斯db 高斯DB 高斯db 高斯DB 高斯db \\xe9ab98e696af4442 E9AB98E696AF 111010011010101110011000111001101001011010101111 +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.data'; +select * from t_charset_2; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +-----------+-----------+-----------+----------+----------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 +(1 row) + +copy (select * from t_charset_1) to '@abs_srcdir@/data/t_charset_1.data' encoding 'utf8'; +\! cat @abs_srcdir@/data/t_charset_1.data +高斯DB 高斯db 高斯db 高斯DB 高斯db 高斯DB 高斯db \\xe9ab98e696af4442 E9AB98E696AF 111010011010101110011000111001101001011010101111 +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.data' encoding 'utf8'; +select * from t_charset_2; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +-----------+-----------+-----------+----------+----------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 +(2 rows) + +copy (select * from t_charset_1) to '@abs_srcdir@/data/t_charset_1.data' encoding 'gbk'; +\! cat @abs_srcdir@/data/t_charset_1.data +¸ß˹DB ¸ß˹db ¸ß˹db ¸ß˹DB ¸ß˹db ¸ß˹DB ¸ß˹db \\xe9ab98e696af4442 E9AB98E696AF 111010011010101110011000111001101001011010101111 +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.data' encoding 'gbk'; +select * from t_charset_2; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +-----------+-----------+-----------+----------+----------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 +(3 rows) + +copy t_charset_1 to '@abs_srcdir@/data/t_charset_1.csv' encoding 'gbk' FIXED FORMATTER (futf8_bin(1, 10), futf8_uni(11, 10), futf8_gen(21, 10), fgbk_bin(31, 10), fgbk_chi(41, 10), fgb18030_bin(51, 10), fgb18030_chi(61, 10), fbytea(71, 20), fblob(91, 20), fbit(111, 60)); +\! cat @abs_srcdir@/data/t_charset_1.csv + ¸ß˹DB ¸ß˹db ¸ß˹db ¸ß˹DB ¸ß˹db ¸ß˹DB ¸ß˹db \xe9ab98e696af4442E9AB98E696AF 111010011010101110011000111001101001011010101111 +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.csv' encoding 'gbk' FIXED FORMATTER (futf8_bin(1, 10), futf8_uni(11, 10), futf8_gen(21, 10), fgbk_bin(31, 10), fgbk_chi(41, 10), fgb18030_bin(51, 10), fgb18030_chi(61, 10)); +select * from t_charset_2; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +------------+------------+------------+------------+------------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | | | +(4 rows) + +copy t_charset_1 to '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '分隔符' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); +\! cat @abs_srcdir@/data/t_charset_1.csv +¸ß˹DB分隔符¸ß˹db分隔符¸ß˹db分隔符¸ß˹DB分隔符¸ß˹db分隔符¸ß˹DB分隔符¸ß˹db分隔符\xe9ab98e696af4442分隔符E9AB98E696AF分隔符111010011010101110011000111001101001011010101111 +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '分隔符' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); -- ERROR +ERROR: invalid byte sequence for encoding "GBK": 0xa6 0x31 +CONTEXT: COPY t_charset_2, line 1 +copy t_charset_1 to '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '|' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); +\! cat @abs_srcdir@/data/t_charset_1.csv +¸ß˹DB|¸ß˹db|¸ß˹db|¸ß˹DB|¸ß˹db|¸ß˹DB|¸ß˹db|\xe9ab98e696af4442|E9AB98E696AF|111010011010101110011000111001101001011010101111 +copy t_charset_2 from '@abs_srcdir@/data/t_charset_1.csv' DELIMITERS '|' with (FORMAT CSV, ESCAPE '+', encoding 'gbk'); +select * from t_charset_2; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +------------+------------+------------+------------+------------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | | | + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 +(5 rows) + +-- test select into outfile +select * from t_charset_1 into outfile '@abs_srcdir@/data/t_charset_1.data2'; +\! cat @abs_srcdir@/data/t_charset_1.data2 +高斯DB 高斯db 高斯db 高斯DB 高斯db 高斯DB 高斯db \\xe9ab98e696af4442 E9AB98E696AF 111010011010101110011000111001101001011010101111 +select * from t_charset_1 into outfile '@abs_srcdir@/data/t_charset_1.data2' character set 'utf8'; +\! cat @abs_srcdir@/data/t_charset_1.data2 +高斯DB 高斯db 高斯db 高斯DB 高斯db 高斯DB 高斯db \\xe9ab98e696af4442 E9AB98E696AF 111010011010101110011000111001101001011010101111 +select * from t_charset_1 into outfile '@abs_srcdir@/data/t_charset_1.data2' character set 'gbk'; +\! cat @abs_srcdir@/data/t_charset_1.data2 +¸ß˹DB ¸ß˹db ¸ß˹db ¸ß˹DB ¸ß˹db ¸ß˹DB ¸ß˹db \\xe9ab98e696af4442 E9AB98E696AF 111010011010101110011000111001101001011010101111 +-- test gs_dump +create database b_behavior_all2 dbcompatibility 'b'; +\! @abs_bindir@/gs_dump b_behavior_all -p @portstring@ -f @abs_bindir@/t_charset_1.tar -F t >/dev/null 2>&1; echo $? +0 +\! @abs_bindir@/gs_restore -d b_behavior_all2 -p @portstring@ @abs_bindir@/t_charset_1.tar >/dev/null 2>&1; echo $? +0 +\c b_behavior_all2 +select * from t_charset_1; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +-----------+-----------+-----------+----------+----------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 +(1 row) + +select * from t_charset_2; + futf8_bin | futf8_uni | futf8_gen | fgbk_bin | fgbk_chi | fgb18030_bin | fgb18030_chi | fbytea | fblob | fbit +------------+------------+------------+------------+------------+--------------+--------------+--------------------+--------------+-------------------------------------------------- + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | | | + 高斯DB | 高斯db | 高斯db | 高斯DB | 高斯db | 高斯DB | 高斯db | \xe9ab98e696af4442 | E9AB98E696AF | 111010011010101110011000111001101001011010101111 +(5 rows) + +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options=''" >/dev/null 2>&1 +select pg_sleep(1); + pg_sleep +---------- + +(1 row) + +\c regression diff --git a/src/test/regress/output/charset_b_format.source b/src/test/regress/output/charset_b_format.source index 209600c3f..ebca7b093 100755 --- a/src/test/regress/output/charset_b_format.source +++ b/src/test/regress/output/charset_b_format.source @@ -33,9 +33,8 @@ create schema s_charset_2 charset = utf8mb4 collate = utf8mb4_unicode_ci; create schema s_charset_3 charset = utf8mb4 collate = utf8mb4_general_ci; create schema s_charset_4 charset = utf8mb4; create schema s_charset_5 charset = utf8; -create schema s_charset_6 charset = gbk; -- error -ERROR: default collation for encoding "GBK" does not exist -create schema s_charset_6; +create schema s_charset_6 charset = gbk; +ERROR: difference between the charset and the database encoding has not supported create schema s_charset_7 default charset = utf8mb4 default collate = utf8mb4_unicode_ci; create schema s_charset_8 charset = "binary"; create schema s_charset_9 character set = utf8mb4; @@ -77,11 +76,10 @@ select * from pg_namespace where nspname like 's_charset_%' order by 1; s_charset_3 | 10 | 0 | | n | f | 1537 s_charset_4 | 10 | 0 | | n | f | 1537 s_charset_5 | 10 | 0 | | n | f | 1537 - s_charset_6 | 10 | 0 | | n | f | s_charset_7 | 10 | 0 | | n | f | 1538 s_charset_8 | 10 | 0 | | n | f | 1026 s_charset_9 | 10 | 0 | | n | f | 1537 -(21 rows) +(20 rows) create schema s_charset_14 collate = "zh_CN.gbk"; -- error ERROR: this collation only cannot be specified here @@ -90,8 +88,8 @@ ERROR: this collation only cannot be specified here alter schema s_charset_1 charset utf8mb4 collate utf8mb4_general_ci; alter schema s_charset_2 charset = utf8mb4 collate = utf8mb4_general_ci; alter schema s_charset_3 collate = utf8mb4_unicode_ci; -alter schema s_charset_5 charset = gbk; -- error -ERROR: default collation for encoding "GBK" does not exist +alter schema s_charset_5 charset = gbk; +ERROR: difference between the charset and the database encoding has not supported alter schema s_charset_5 charset = gbk collate = "zh_CN.gbk"; -- error ERROR: this collation only cannot be specified here alter schema s_charset_9 character set = utf8 collate = utf8mb4_unicode_ci; @@ -115,11 +113,10 @@ select * from pg_namespace where nspname like 's_charset_%' order by 1; s_charset_3 | 10 | 0 | | n | f | 1538 s_charset_4 | 10 | 0 | | n | f | 1537 s_charset_5 | 10 | 0 | | n | f | 1537 - s_charset_6 | 10 | 0 | | n | f | s_charset_7 | 10 | 0 | | n | f | 1538 s_charset_8 | 10 | 0 | | n | f | 1026 s_charset_9 | 10 | 0 | | n | f | 1538 -(21 rows) +(20 rows) -- relation level charset and collate create table t_charset_1 (c1 varchar(20)) charset utf8mb4 collate utf8mb4_unicode_ci; @@ -127,9 +124,8 @@ create table t_charset_2 (c1 varchar(20)) charset = utf8mb4 collate = utf8mb4_un create table t_charset_3 (c1 varchar(20)) charset = utf8mb4 collate = utf8mb4_general_ci; create table t_charset_4 (c1 varchar(20)) charset = utf8mb4; create table t_charset_5 (c1 varchar(20)) charset = utf8; -create table t_charset_6 (c1 varchar(20)) charset = gbk; -- error -ERROR: default collation for encoding "GBK" does not exist -create table t_charset_6 (c1 varchar(20)); +create table t_charset_6 (c1 varchar(20)) charset = gbk; +ERROR: difference between the charset and the database encoding has not supported create table t_charset_7 (c1 varchar(20)) default charset = utf8mb4 default collate = utf8mb4_unicode_ci; create table t_charset_8 (c1 varchar(20)) charset = binary; -- error ERROR: Un-support feature @@ -211,11 +207,10 @@ select relname, reloptions from pg_class where relname like 't_charset_%' order t_charset_3 | {orientation=row,compression=no,collate=1537} t_charset_4 | {orientation=row,compression=no,collate=1537} t_charset_5 | {orientation=row,compression=no,collate=1537} - t_charset_6 | {orientation=row,compression=no,collate=1537} t_charset_7 | {orientation=row,compression=no,collate=1538} t_charset_8 | {orientation=row,compression=no,collate=1026} t_charset_9 | {orientation=row,compression=no,collate=1537} -(21 rows) +(20 rows) alter table t_charset_1 convert to charset binary; -- error ERROR: Un-support feature @@ -369,8 +364,8 @@ ERROR: syntax error at or near "charset" LINE 1: ...le a_charset_2 add a8 varchar(20) charset utf8mb4 charset ut... ^ alter table a_charset_2 modify a1 int; -alter table a_charset_2 modify a9 varchar(20) character set gbk; -- error -ERROR: default collation for encoding "GBK" does not exist +alter table a_charset_2 modify a9 varchar(20) character set gbk; +ERROR: difference between the charset and the database encoding has not supported alter table a_charset_2 modify a10 varchar(20); ERROR: Un-support feature DETAIL: type varchar cannot be set to binary collation currently @@ -932,6 +927,23 @@ select r.relname,r.reloptions,a.attcollation from pg_class r,pg_attribute a wher tem_charset_1 | {orientation=row,compression=no,collate=1538} | 0 (10 rows) +-- cstore not supported +SET b_format_behavior_compat_options = 'default_collation, enable_multi_charset'; +create schema s_charset_multi charset = gbk; +create table s_charset_multi.cstore_charset_1(c1 varchar(20),c2 varchar(20),c3 int) with (ORIENTATION=column); -- ERROR +ERROR: difference between the charset of column c1 and the database encoding has not supported +DROP schema s_charset_multi; +create table cstore_charset_1(c1 varchar(20),c2 varchar(20),c3 int) character set = gbk with (ORIENTATION=column); -- ERROR +ERROR: difference between the charset of column c1 and the database encoding has not supported +create table cstore_charset_1(c1 varchar(20),c2 varchar(20) character set gbk,c3 int) with (ORIENTATION=column); -- ERROR +ERROR: difference between the charset of column c2 and the database encoding has not supported +create table cstore_charset_1(c1 varchar(20),c2 varchar(20),c3 int) with (ORIENTATION=column); +ALTER TABLE cstore_charset_1 ADD COLUMN c4 varchar(20) character set gbk; -- ERROR +ERROR: difference between the charset of column c4 and the database encoding has not supported +ALTER TABLE cstore_charset_1 MODIFY COLUMN c1 varchar(20) character set gbk; -- ERROR +ERROR: Un-support feature +DETAIL: column-store relation doesn't support this ALTER yet +drop table cstore_charset_1; \! @abs_bindir@/gs_dump d_charset -p @portstring@ -f @abs_bindir@/d_charset.tar -F t >/dev/null 2>&1; echo $? 0 \! @abs_bindir@/gs_restore -d d_charset_bak -p @portstring@ @abs_bindir@/d_charset.tar >/dev/null 2>&1; echo $? @@ -957,11 +969,10 @@ select * from pg_namespace where nspname like 's_charset_%' order by 1; s_charset_3 | 10 | 0 | | n | f | 1538 s_charset_4 | 10 | 0 | | n | f | 1537 s_charset_5 | 10 | 0 | | n | f | 1537 - s_charset_6 | 10 | 0 | | n | f | s_charset_7 | 10 | 0 | | n | f | 1538 s_charset_8 | 10 | 0 | | n | f | 1026 s_charset_9 | 10 | 0 | | n | f | 1538 -(21 rows) +(20 rows) select relname, reloptions from pg_class where relname like 't_charset_%' order by 1; relname | reloptions @@ -983,11 +994,10 @@ select relname, reloptions from pg_class where relname like 't_charset_%' order t_charset_3 | {orientation=row,compression=no,collate=1537} t_charset_4 | {orientation=row,compression=no,collate=1537} t_charset_5 | {orientation=row,compression=no,collate=1537} - t_charset_6 | {orientation=row,compression=no,collate=1537} t_charset_7 | {orientation=row,compression=no,collate=1538} t_charset_8 | {orientation=row,compression=no,collate=1026} t_charset_9 | {orientation=row,compression=no,collate=1537} -(21 rows) +(20 rows) select *,rawtohex(a1),rawtohex(a2),length(a1),length(a2),lengthb(a1),lengthb(a2) from a_charset_1; a1 | a2 | a3 | rawtohex | rawtohex | length | length | lengthb | lengthb diff --git a/src/test/regress/output/charset_connection_test.source b/src/test/regress/output/charset_connection_test.source new file mode 100644 index 000000000..8d0816ecc --- /dev/null +++ b/src/test/regress/output/charset_connection_test.source @@ -0,0 +1,487 @@ +\c regression +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + +(1 row) + +select 'aa' = 'AA'; + ?column? +---------- + f +(1 row) + +set names utf8; +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + +(1 row) + +select 'aa' = 'AA'; + ?column? +---------- + f +(1 row) + +-- error case +set names utf8 collate gbk_bin; +ERROR: specifying character sets and collations is supported only in B-format database +create database charset_connection_test dbcompatibility 'b'; +\c charset_connection_test +-- show encoding settings +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + +(1 row) + +select 'aa' = 'AA'; + ?column? +---------- + f +(1 row) + +set names utf8; +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + +(1 row) + +select 'aa' = 'AA'; + ?column? +---------- + f +(1 row) + +-- expect error cases +SET NAMES utf8mb4 COLLATE utf8mb4_general_ci; +ERROR: character_set_connection can be changed when b_format_behavior_compat_options contains enable_multi_charset option +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options='all'" >/dev/null 2>&1 +select pg_sleep(1); + pg_sleep +---------- + +(1 row) + +\c +-- show encoding settings +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + utf8mb4_general_ci +(1 row) + +select 'aa' = 'AA'; + ?column? +---------- + t +(1 row) + +--error cases +SET NAMES 'utf8' COLLATE DEFAULT; +ERROR: syntax error at or near "DEFAULT" +LINE 1: SET NAMES 'utf8' COLLATE DEFAULT; + ^ +SET NAMES 'gbk' COLLATE 'utf8mb4_bin'; +ERROR: collation "utf8mb4_bin" for encoding "GBK" does not exist +SET NAMES utf8 COLLATE gbk_bin; +ERROR: collation "gbk_bin" for encoding "UTF8" does not exist +SET NAMES COLLATE 'utf8mb4_bin'; +ERROR: cannot specify collation without character set +LINE 1: SET NAMES COLLATE 'utf8mb4_bin'; + ^ +SET NAMES gbk; +show client_encoding; + client_encoding +----------------- + GBK +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + GBK +(1 row) + +show collation_connection; + collation_connection +---------------------- + gbk_chinese_ci +(1 row) + +select '高斯aa' = '高斯AA'; + ?column? +---------- + t +(1 row) + +select '高斯aa' = '高斯AA' collate 'utf8mb4_bin'; --error case +ERROR: COLLATION "utf8mb4_bin" is not valid for CHARACTER SET "GBK" +LINE 1: select '高斯aa' = '高斯AA' collate 'utf8mb4_bin'; + ^ +select '高斯aa' = '高斯AA' collate 'gbk_bin'; + ?column? +---------- + f +(1 row) + +set collation_connection = utf8mb4_bin; +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + utf8mb4_bin +(1 row) + +select 'aa' = 'AA'; + ?column? +---------- + f +(1 row) + +set character_set_connection = gbk; +show character_set_connection; + character_set_connection +-------------------------- + GBK +(1 row) + +show collation_connection; + collation_connection +---------------------- + gbk_chinese_ci +(1 row) + +select '高斯aa' = '高斯AA'; + ?column? +---------- + t +(1 row) + +SET NAMES DEFAULT; +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + utf8mb4_general_ci +(1 row) + +select '高斯aa' = '高斯AA'; + ?column? +---------- + t +(1 row) + +SET NAMES; +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + utf8mb4_general_ci +(1 row) + +select '高斯aa' = '高斯AA'; + ?column? +---------- + t +(1 row) + +\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "b_format_behavior_compat_options=''" >/dev/null 2>&1 +select pg_sleep(1); + pg_sleep +---------- + +(1 row) + +\c +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + UTF8 +(1 row) + +show collation_connection; + collation_connection +---------------------- + +(1 row) + +select '高斯aa' = '高斯AA'; --false + ?column? +---------- + f +(1 row) + +set b_format_behavior_compat_options = 'ALL'; +set @aa = '高斯aa'; +set @bb = (select '高斯aa'); +select @cc := '高斯aa'; + ?column? +---------- + 高斯aa +(1 row) + +select @dd := (select '高斯aa'); + ?column? +---------- + 高斯aa +(1 row) + +select '高斯aa' into @ee; +select @aa,@bb,@cc,@dd,@ee; + @aa | @bb | @cc | @dd | @ee +--------+--------+--------+--------+-------- + 高斯aa | 高斯aa | 高斯aa | 高斯aa | 高斯aa +(1 row) + +select collation for(@aa), collation for(@bb), collation for(@cc), collation for(@dd), collation for(@ee); + pg_collation_for | pg_collation_for | pg_collation_for | pg_collation_for | pg_collation_for +------------------+------------------+------------------+------------------+------------------ + "default" | "default" | "default" | "default" | "default" +(1 row) + +set names gbk; +set @aa = '高斯aa'; +set @bb = (select '高斯aa'); +select @cc := '高斯aa'; + ?column? +---------- + 高斯aa +(1 row) + +select @dd := (select '高斯aa'); + ?column? +---------- + 高斯aa +(1 row) + +select '高斯aa' into @ee; +select @aa,@bb,@cc,@dd,@ee; + @aa | @bb | @cc | @dd | @ee +----------+----------+----------+----------+---------- + 高斯aa | 高斯aa | 高斯aa | 高斯aa | 高斯aa +(1 row) + +select collation for(@aa), collation for(@bb), collation for(@cc), collation for(@dd), collation for(@ee); + pg_collation_for | pg_collation_for | pg_collation_for | pg_collation_for | pg_collation_for +------------------+------------------+------------------+------------------+------------------ + gbk_chinese_ci | gbk_chinese_ci | gbk_chinese_ci | gbk_chinese_ci | gbk_chinese_ci +(1 row) + +set @aa = '高斯aa' collate utf8mb4_unicode_ci; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: set @aa = '高斯aa' collate utf8mb4_unicode_ci; + ^ +set @bb = (select '高斯aa' collate utf8mb4_unicode_ci); +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: set @bb = (select '高斯aa' collate utf8mb4_unicode_ci); + ^ +select @cc := '高斯aa' collate utf8mb4_unicode_ci; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: select @cc := '高斯aa' collate utf8mb4_unicode_ci; + ^ +select @dd := (select '高斯aa' collate utf8mb4_unicode_ci); +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: select @dd := (select '高斯aa' collate utf8mb4_unicode_ci)... + ^ +select '高斯aa' collate utf8mb4_unicode_ci into @ee; +ERROR: COLLATION "utf8mb4_unicode_ci" is not valid for CHARACTER SET "GBK" +LINE 1: select '高斯aa' collate utf8mb4_unicode_ci into @ee; + ^ +set client_encoding = utf8mb4; +select @aa,@bb,@cc,@dd,@ee; + @aa | @bb | @cc | @dd | @ee +----------+----------+----------+----------+---------- + 楂樻柉aa | 楂樻柉aa | 楂樻柉aa | 楂樻柉aa | 楂樻柉aa +(1 row) + +set names utf8; +set @aa = '高斯aa' collate utf8mb4_unicode_ci; +set @bb = (select '高斯aa' collate utf8mb4_unicode_ci); +select @cc := '高斯aa' collate utf8mb4_unicode_ci; + ?column? +---------- + 高斯aa +(1 row) + +select @dd := (select '高斯aa' collate utf8mb4_unicode_ci); + ?column? +---------- + 高斯aa +(1 row) + +select '高斯aa' collate utf8mb4_unicode_ci into @ee; +select @aa,@bb,@cc,@dd,@ee; + @aa | @bb | @cc | @dd | @ee +--------+--------+--------+--------+-------- + 高斯aa | 高斯aa | 高斯aa | 高斯aa | 高斯aa +(1 row) + +select collation for(@aa), collation for(@bb), collation for(@cc), collation for(@dd), collation for(@ee); + pg_collation_for | pg_collation_for | pg_collation_for | pg_collation_for | pg_collation_for +--------------------+--------------------+--------------------+--------------------+-------------------- + utf8mb4_unicode_ci | utf8mb4_unicode_ci | utf8mb4_unicode_ci | utf8mb4_unicode_ci | utf8mb4_unicode_ci +(1 row) + +set names gbk; +create table t(a text collate utf8mb4_bin, b text collate utf8mb4_unicode_ci); +insert into t values('高斯aa', '高斯bb'); +select * from t into @a,@b; +select @a,@b; + @a | @b +----------+---------- + 高斯aa | 高斯bb +(1 row) + +select collation for(@a), collation for(@b); + pg_collation_for | pg_collation_for +------------------+-------------------- + utf8mb4_bin | utf8mb4_unicode_ci +(1 row) + +select * from t where a = 'c' into @a,@b; +select @a,@b; + @a | @b +----+---- + | +(1 row) + +select collation for(@a), collation for(@b); + pg_collation_for | pg_collation_for +------------------+-------------------- + utf8mb4_bin | utf8mb4_unicode_ci +(1 row) + +create database charset_gbk dbcompatibility 'b' encoding 'gbk' lc_ctype = 'C' lc_collate = 'C'; +\c charset_gbk +set client_encoding = utf8; +show client_encoding; + client_encoding +----------------- + UTF8 +(1 row) + +show character_set_connection; + character_set_connection +-------------------------- + GBK +(1 row) + +show collation_connection; + collation_connection +---------------------- + +(1 row) + +create table t1(a text charset gbk collate gbk_bin); +insert into t1 values('高斯'); +select * from t1; + a +------ + 高斯 +(1 row) + +create database latin1_db dbcompatibility 'b' encoding 'latin1' lc_ctype = 'C' lc_collate = 'C'; +\c latin1_db +select '高斯aa' = '高斯AA'; + ?column? +---------- + f +(1 row) + +\c regression diff --git a/src/test/regress/output/recovery_2pc_tools.source b/src/test/regress/output/recovery_2pc_tools.source index 2c23db2c7..d30841de7 100644 --- a/src/test/regress/output/recovery_2pc_tools.source +++ b/src/test/regress/output/recovery_2pc_tools.source @@ -99,6 +99,7 @@ select name,vartype,unit,min_val,max_val from pg_settings where name <> 'qunit_c candidate_buf_percent_target | real | | 0.1 | 0.85 catchup2normal_wait_time | integer | ms | -1 | 10000 cgroup_name | string | | | + character_set_connection | string | | | check_function_bodies | bool | | | check_implicit_conversions | bool | | | checkpoint_completion_target | real | | 0 | 1 @@ -113,6 +114,7 @@ select name,vartype,unit,min_val,max_val from pg_settings where name <> 'qunit_c cn_send_buffer_size | integer | kB | 8 | 128 codegen_cost_threshold | integer | | 0 | 2147483647 codegen_strategy | enum | | | + collation_connection | string | | | commit_delay | integer | | 0 | 100000 commit_siblings | integer | | 0 | 1000 comm_proxy_attr | string | | | diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index c08e46b2b..b50b8e459 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -90,7 +90,10 @@ test: event_dump_audit test: single_node_sha #test b format collation -test: test_b_format_collate charset_b_format +test: test_b_format_collate charset_b_format test_b_format_gb_collate +test: charset_utf8mb4_b_db charset_gbk_b_db +test: charset_connection_test +test: add_b_format_behavior_all # test subpartition test: hw_subpartition_createtable hw_subpartition_scan hw_subpartition_select hw_subpartition_split hw_subpartition_truncate hw_subpartition_update hw_subpartition_gpi hw_subpartition_analyze_vacuum hw_subpartition_alter_table hw_subpartition_index hw_subpartition_add_drop_partition hw_subpartition_tablespace hw_subpartition_ddl_index hw_subpartition_size hw_partition_size hw_cstore_partition_size @@ -651,10 +654,10 @@ test: select_into subselect_part2 gs_aggregate test: holdable_cursor #test: portals_p2 window tsearch temp__6 col_subplan_base_2 -test: alter_table_000 alter_table_002 alter_table_003 alter_table_modify +test: alter_table_000 alter_table_002 alter_table_003 #test: alter_table_001 alter_table_modify_ustore test: alter_table_modify_ltt alter_table_modify_gtt -test: alter_table_modify alter_table_modify_ustore alter_table_modify_ltt alter_table_modify_gtt +test: alter_table_modify alter_table_modify_ustore #test: with diff --git a/src/test/regress/sql/charset_gbk_b_db.sql b/src/test/regress/sql/charset_gbk_b_db.sql new file mode 100644 index 000000000..d6184389e --- /dev/null +++ b/src/test/regress/sql/charset_gbk_b_db.sql @@ -0,0 +1,999 @@ +CREATE DATABASE c_gbk_b_db WITH ENCODING 'gbk' LC_COLLATE='C' LC_CTYPE='C' DBCOMPATIBILITY 'B'; +\c c_gbk_b_db + +SET b_format_behavior_compat_options = 'all'; +SHOW b_format_behavior_compat_options; +-- ------------------------------------------ +SET NAMES 'gbk'; +SHOW client_encoding; +SHOW server_encoding; +SHOW character_set_connection; +SHOW collation_connection; +set enable_expr_fusion = ON; + +-- -- CONST charset and collation +SELECT _utf8mb4'高斯' COLLATE gbk_chinese_ci; -- ERROR +SELECT _utf8mb4'高斯' COLLATE 'binary'; -- ERROR +SELECT _utf8mb4'高斯' COLLATE "zh_CN.utf8"; +SELECT _utf8mb4'高斯' COLLATE "C"; -- ERROR +SELECT _gbk'高斯' COLLATE gbk_chinese_ci; +SELECT _gbk'高斯' COLLATE 'binary'; -- ERROR +SELECT _gbk'高斯' COLLATE "zh_CN.gbk"; -- support origin collation +SELECT _gbk'高斯' COLLATE "C"; -- support origin collation + +-- -- CONST collation only +SELECT X'E9AB98E696AF' COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT X'E9AB98E696AF' COLLATE "binary"; +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "binary"; +SELECT 1 COLLATE "utf8mb4_unicode_ci"; -- not support yet +SELECT 1 COLLATE "binary"; -- not support yet +SELECT CAST('高斯' AS bytea) COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT CAST('高斯' AS bytea) COLLATE "binary"; +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "binary"; +SELECT '高斯' COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT '高斯' COLLATE "gbk_chinese_ci"; +SELECT '高斯' COLLATE "gb18030_chinese_ci"; -- ERROR +SELECT '高斯' COLLATE "binary"; -- ERROR + +-- 中文 const charset +SELECT CAST('高斯' AS bytea); +SELECT CAST(_binary'高斯' AS bytea); +SELECT CAST(_utf8mb4'高斯' AS bytea); +SELECT CAST(_gbk'高斯' AS bytea); +SELECT _binary'高斯'; +SELECT _utf8mb4'高斯'; +SELECT _gbk'高斯'; +SELECT _gb18030'高斯'; +SELECT _gbk X'e9ab98e696af'; +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); -- ERROR +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); -- ERROR +SELECT COLLATION FOR(CAST('高斯' AS bytea)::text); + +-- -- 中文 const compare +-- -- -- same charset & explicit collation +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_general_ci = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "C"; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "zh_CN.utf8"; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "DEFAULT"; -- ERROR +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB' COLLATE utf8mb4_bin; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB' COLLATE "C"; -- ERROR +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB' COLLATE "zh_CN.gbk"; -- ERROR +SELECT _gbk'高斯db' COLLATE gbk_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +SELECT _gb18030'高斯db' COLLATE gb18030_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +-- -- -- same charset & implicit collation +SELECT _gbk'高斯DB' = '高斯DB'; +-- -- -- diff charset & explicit collation +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB' COLLATE 'binary'; -- not support yet +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; -- ERROR +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; -- ERROR +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +-- -- -- diff charset & implicit collation +SELECT _utf8mb4'高斯DB' = _binary'高斯DB'; +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB'; +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB'; +SELECT _utf8mb4'高斯DB' = '高斯DB'; +SELECT _gbk'高斯DB' = _utf8mb4'高斯DB'; +SELECT _gbk'高斯DB' = _binary'高斯DB'; -- not support yet +SELECT _gbk'高斯DB' = _gb18030'高斯DB'; -- ERROR +SELECT _gb18030'高斯DB' = _utf8mb4'高斯DB'; +SELECT _gb18030'高斯DB' = _binary'高斯DB'; -- not support yet +SELECT '高斯DB' = _utf8mb4'高斯DB'; +SELECT '高斯DB' = _gb18030'高斯DB'; -- ERROR +SELECT _binary'高斯DB' = _utf8mb4'高斯DB'; -- not support yet +SELECT _binary'高斯DB' = _gbk'高斯DB'; -- not support yet +SELECT _binary'高斯DB' = _gb18030'高斯DB'; -- not support yet +-- -- -- explicit & implicit +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "C"; +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "zh_CN.gbk"; +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'楂樻柉DB' = _gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'楂樻柉DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB'; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB'; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB'; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _binary'高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB'; +SELECT _gbk'高斯DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; +SELECT _gbk'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB'; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB'; +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB'; +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB'; + +-- -- 中文 const concat +-- -- -- same charset & explicit collation +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE "C"); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE "zh_CN.gbk"); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE gbk_chinese_ci); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB' COLLATE gbk_bin); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB' COLLATE gbk_chinese_ci); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB' COLLATE gbk_bin); +-- -- -- same charset & implicit collation +SELECT CONCAT(_gbk'高斯DB' , '高斯DB') result, collation for(result); +-- -- -- diff charset & explicit collation +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +-- -- -- diff charset & implicit collation +SELECT CONCAT(_utf8mb4'高斯DB' , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB' , '高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB' , _binary'高斯DB') result, collation for(result); +SELECT CONCAT( _binary'高斯DB', _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT( _binary'高斯DB', '高斯DB') result, collation for(result); +-- -- -- explicit & implicit +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "C") result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "zh_CN.gbk") result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gbk'高斯db' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gb18030'高斯db' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_binary'高斯DB', _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci) result, collation for(result); +SELECT CONCAT(_binary'高斯DB' COLLATE 'binary', _gbk'高斯DB') result, collation for(result); + +-- -- -- concat 3 args +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci, _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _binary'高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB' COLLATE gb18030_chinese_ci, _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci, _binary'高斯DB') result, collation for(result); +-- -- -- const compare CONCAT +SELECT _utf8mb4'楂樻柉DB' = CONCAT(_gbk'高斯DB'); +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); +SELECT _utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB'); +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB'); -- ERROR +-- -- -- const CONCAT CONCAT +SELECT CONCAT(_utf8mb4'楂樻柉DB', CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB', CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); +-- -- -- const CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT('高斯DB', opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), '高斯DB') result, collation for(result); +SELECT CONCAT('高斯DB', 123) result, collation for(result); +SELECT CONCAT(123, '高斯DB') result, collation for(result); +SELECT CONCAT('高斯DB', DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', '高斯DB') result, collation for(result); +SELECT CONCAT('高斯DB', NULL) result, collation for(result); +SELECT CONCAT(NULL, '高斯DB') result, collation for(result); +-- -- -- -- diff charset +SELECT CONCAT(_utf8mb4'高斯DB', opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', 123) result, collation for(result); +SELECT CONCAT(123, _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', NULL) result, collation for(result); +SELECT CONCAT(NULL, _utf8mb4'高斯DB') result, collation for(result); +-- -- -- CONCAT CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT(CONCAT('高斯DB'), opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), CONCAT('高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT('高斯DB'), 123) result, collation for(result); +SELECT CONCAT(123, CONCAT('高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT('高斯DB'), DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', CONCAT('高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT('高斯DB'), NULL) result, collation for(result); +SELECT CONCAT(NULL, CONCAT('高斯DB')) result, collation for(result); +-- -- -- -- diff charset +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), CONCAT(_utf8mb4'高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), 123) result, collation for(result); +SELECT CONCAT(123, CONCAT(_utf8mb4'高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', CONCAT(_utf8mb4'高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT(_utf8mb4'高斯DB'), NULL) result, collation for(result); +SELECT CONCAT(NULL, CONCAT(_utf8mb4'高斯DB')) result, collation for(result); +-- -- -- CONCAT NUMBERS +SELECT CONCAT('100', 200) result, collation for(result); +SELECT CONCAT('100', date'2021-01-01') result, collation for(result); +SELECT CONCAT('100', NULL) result, collation for(result); +SELECT CONCAT('100', NULL::bytea) result, collation for(result); +SELECT CONCAT('100', NULL::text) result, collation for(result); +SELECT CONCAT(100, 200) result, collation for(result); +SELECT CONCAT(100, date'2021-01-01') result, collation for(result); +SELECT CONCAT(100, NULL) result, collation for(result); +SELECT CONCAT(100, NULL::bytea) result, collation for(result); +SELECT CONCAT(100, NULL::text) result, collation for(result); +SELECT CONCAT(NULL, NULL::bytea) result, collation for(result); +SELECT CONCAT(NULL, NULL::text) result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL), '100') result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::bytea), '100') result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::text), '100') result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL), 100) result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::bytea), 100) result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::text), 100) result, collation for(result); + +-- -- 中文 with column charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +reset enable_seqscan; + +-- -- COLUMN collation only +SELECT futf8_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT futf8_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT futf8_bin COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +SELECT futf8_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; +SELECT fgbk_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_bin COLLATE "zh_CN.gbk" FROM t_diff_charset_columns; -- support origin collation +SELECT fgbk_bin COLLATE "C" FROM t_diff_charset_columns; -- support origin collation +SELECT fgb18030_bin COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; +SELECT fgb18030_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE "zh_CN.gb18030" FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT fbytea COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT fbytea COLLATE 'binary' FROM t_diff_charset_columns; +SELECT fbytea COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +SELECT fbytea COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT fblob COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT fblob COLLATE 'binary' FROM t_diff_charset_columns; +SELECT fblob COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +SELECT fblob COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE utf8mb4_unicode_ci FROM t_diff_charset_columns; +SELECT (fgbk_chi COLLATE "C") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +SELECT (fgbk_chi COLLATE "C") COLLATE gbk_chinese_ci FROM t_diff_charset_columns; +SELECT (fblob COLLATE "binary") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +SELECT fbit COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR + +-- -- COLUMN compare COLUMN +-- -- -- same charset & implicit collation +SELECT futf8_bin = futf8_uni, futf8_uni = futf8_bin FROM t_diff_charset_columns; +SELECT fgbk_bin = fgbk_chi, fgbk_chi = fgbk_bin FROM t_diff_charset_columns; +SELECT fgb18030_bin = fgb18030_chi, fgb18030_chi = fgb18030_bin FROM t_diff_charset_columns; +SELECT futf8_gen = futf8_uni, futf8_uni = futf8_gen FROM t_diff_charset_columns; -- ERROR +SELECT futf8_gen > futf8_uni, futf8_uni > futf8_gen FROM t_diff_charset_columns; -- ERROR +-- -- -- diff charset & implicit collation +SELECT futf8_bin = fgbk_bin, fgbk_bin = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_bin = fgbk_chi, fgbk_chi = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_bin = fgb18030_bin, fgb18030_bin = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_bin = fgb18030_chi, fgb18030_chi = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_uni = fgbk_bin, fgbk_bin = futf8_uni FROM t_diff_charset_columns; +SELECT futf8_uni = fgbk_chi, fgbk_chi = futf8_uni FROM t_diff_charset_columns; +SELECT futf8_uni = fgb18030_bin, fgb18030_bin = futf8_uni FROM t_diff_charset_columns; +SELECT futf8_uni = fgb18030_chi, fgb18030_chi = futf8_uni FROM t_diff_charset_columns; +SELECT fgbk_bin = fgb18030_bin, fgb18030_bin = fgbk_bin FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_bin = fgb18030_chi, fgb18030_chi = fgbk_bin FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_chi = fgb18030_chi, fgb18030_chi = fgbk_chi FROM t_diff_charset_columns; -- ERROR +-- -- -- with binary & implicit collation +SELECT futf8_bin = fbytea, fbytea = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT futf8_bin = fblob, fblob = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT futf8_uni = fbytea, fbytea = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT futf8_uni = fblob, fblob = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgbk_bin = fbytea, fbytea = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgbk_bin = fblob, fblob = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgb18030_bin = fbytea, fbytea = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgb18030_bin = fblob, fblob = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fbytea = fblob, fblob = fbytea FROM t_diff_charset_columns; + +-- -- COLUMN concat COLUMN +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgb18030_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_gen, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- result is _bin +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +SELECT CONCAT(fgbk_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +SELECT CONCAT(fgbk_chi, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- with binary & implicit collation +SELECT CONCAT(futf8_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(futf8_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(futf8_uni, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(futf8_uni, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgbk_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgbk_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgb18030_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgb18030_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fbytea, fblob) result, collation for(result) FROM t_diff_charset_columns; + +-- -- concat column and @uservar +set enable_set_variable_b_format=on; +-- -- -- string var utf8mb4_general_ci +set @var_utf8_gen = _utf8mb4'高斯DB' COLLATE utf8mb4_general_ci; -- should support +SELECT collation for(@var_utf8_gen); +SELECT CONCAT(futf8_uni, @var_utf8_gen) result, collation for(result) FROM t_diff_charset_columns; -- null collation +SELECT CONCAT(fgbk_bin, @var_utf8_gen) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_general_ci +SELECT CONCAT(@var_utf8_gen, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- _bin +-- -- -- string var gbk_chinese_ci +set @var_gbk_chi = '高斯DB' COLLATE gbk_chinese_ci; -- should support +SELECT collation for(@var_gbk_chi); +SELECT CONCAT(futf8_uni, @var_gbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- futf8_uni +SELECT CONCAT(@var_gbk_chi, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin +-- -- -- number var +set @var_num = 5.0; +SELECT CONCAT(futf8_bin, @var_num) result, collation for(result) FROM t_diff_charset_columns; -- futf8_bin +SELECT CONCAT(@var_num, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin +-- -- -- bytea var +set @var_binary = _binary'高斯DB'; -- not support yet +SELECT CONCAT(futf8_bin, @var_binary) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(@var_binary, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + +-- -- concat column and bind parameter +-- -- -- -- PBE with implicit collation +PREPARE test_merge_collation(text) AS +SELECT CONCAT(futf8_uni, $1) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- $1 use collation_connection, futf8_uni +EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate utf8mb4_unicode_ci); -- explicit noneffective, futf8_uni +EXECUTE test_merge_collation(_gbk'高斯DB'); -- _gbk noneffective, futf8_uni +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with implicit collation +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; -- $1 use collation_connection, ERROR +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate utf8mb4_unicode_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- $1 use collation_connection, ERROR +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate gbk_chinese_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- gbk_chinese_ci +EXECUTE test_merge_collation(_gbk'高斯DB'); -- gbk_chinese_ci +DEALLOCATE test_merge_collation; + +-- -- concat for DERIVATION +-- -- -- same charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(futf8_bin, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin collate utf8mb4_unicode_ci) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(futf8_bin collate utf8mb4_unicode_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- conflict +SELECT CONCAT(futf8_uni, CONCAT(futf8_gen)) result, collation for(result) FROM t_diff_charset_columns; -- conflict +SELECT CONCAT(futf8_uni, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(opengauss_version(), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT('高斯DB', fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, 123) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(123, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(DATE '2023-05-01', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, NULL) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(NULL, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +-- -- -- diff charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), CONCAT(fgbk_chi, fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(fgbk_chi, fgb18030_chi), CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(fgbk_chi, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(fgbk_chi COLLATE gbk_chinese_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(fgbk_chi, CONCAT(fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(CONCAT(fgb18030_bin), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(opengauss_version(), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT('高斯DB', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, 123) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(123, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(DATE '2023-05-01', fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, NULL) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(NULL, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + +-- -- test explicit collate on concat +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- with binary & implicit collation +SELECT CONCAT(fbytea, futf8_uni) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text +SELECT CONCAT(fbytea, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text + +-- -- test explicit collate on blob result +SELECT CAST('DEADBEEF' AS blob) COLLATE utf8mb4_general_ci result; -- ERROR +SELECT CAST('DEADBEEF' AS blob) COLLATE "binary" result; + +-- -- case when +-- -- -- condition same charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation +SELECT CASE WHEN (futf8_gen = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE futf8_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation +SELECT CASE futf8_gen WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- condition same charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE futf8_bin WHEN futf8_uni THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +-- -- -- condition diff charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_bin WHEN fgb18030_bin THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- condition diff charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgb18030_chi) ELSE (fgbk_chi) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_bin WHEN futf8_uni THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgb18030_chi WHEN fgbk_chi THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR + +-- -- in +-- -- -- column utf8 +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.futf8_gen FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.futf8_uni FROM t_diff_charset_columns t2); +-- -- -- column gbk +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB'); -- ERROR +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE gbk_bin); +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE gbk_bin); +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.fgbk_chi FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.futf8_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgb18030_bin FROM t_diff_charset_columns t2); -- ERROR + +-- -- COALESCE +SELECT COALESCE(fgbk_chi, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT COALESCE(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; +SELECT COALESCE(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +SELECT COALESCE(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR + +-- -- GREATEST +SELECT GREATEST(fgbk_chi, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; +SELECT GREATEST(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; +SELECT GREATEST(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +SELECT GREATEST(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR + +-- -- XMLEXPR +SELECT xmlelement(NAME a, fgbk_chi, futf8_bin) result FROM t_diff_charset_columns; +SELECT xmlelement(NAME a, futf8_gen, futf8_bin) result FROM t_diff_charset_columns; +SELECT xmlelement(NAME a, futf8_uni, futf8_gen) result FROM t_diff_charset_columns; -- conflict +SELECT xmlelement(NAME a, fgbk_chi, fgb18030_chi) result FROM t_diff_charset_columns; -- ERROR +SELECT xmlconcat(xmlelement(NAME a, fgbk_chi, futf8_bin), xmlelement(NAME b, fgb18030_chi)) result FROM t_diff_charset_columns; + +-- -- rowcompare +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db'); +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB'); + +-- -- aggregate +SELECT count(futf8_bin), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin; +SELECT count(fgbk_bin), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin; +SELECT count(fgb18030_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +SELECT group_concat(futf8_bin, fgbk_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +SELECT group_concat(fgbk_bin, fgbk_chi order by futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +SELECT group_concat(DISTINCT fgbk_bin, futf8_bin order by fgbk_bin, futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + +-- -- UNION +-- -- -- const +select _utf8mb4'高斯' union select _gbk'高斯'; +select _gb18030'高斯' union select _gbk'高斯'; -- ERROR +-- -- -- column +select futf8_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; +select fgb18030_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; -- ERROR +-- -- -- explicit +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union all + select fgbk_bin FROM t_diff_charset_columns; +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + INTERSECT + select fgbk_bin FROM t_diff_charset_columns; +-- -- -- mixed +select _utf8mb4'高斯', futf8_bin FROM t_diff_charset_columns + union + select _gbk'高斯', fgbk_bin FROM t_diff_charset_columns; +select _utf8mb4'GS', futf8_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_bin FROM t_diff_charset_columns; +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_chi FROM t_diff_charset_columns; +-- -- -- 3 select +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_bin FROM t_diff_charset_columns; +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; +-- -- -- complex select +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi COLLATE gb18030_chinese_ci), fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns GROUP BY fgb18030_chi; + +DROP TABLE t_diff_charset_columns; + +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); + +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; + +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB'; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db'; +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; -- ERROR +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + +DELETE FROM t_charset_utf8mb4 WHERE a='高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a='高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +DROP TABLE IF EXISTS t_charset_utf8mb4; + +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); + +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +INSERT INTO t_charset_gbk SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB'; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; -- ERROR + +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + +DELETE FROM t_charset_gbk WHERE a='高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea= _binary'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; +DROP TABLE IF EXISTS t_charset_gbk; + +set enable_expr_fusion = OFF; +-- ------------------------------------------ +-- SET NAMES utf8mb4; +SET NAMES utf8mb4; +SHOW client_encoding; +SHOW server_encoding; +SHOW character_set_connection; +SHOW collation_connection; + +-- 中文 +SELECT CAST('高斯' AS bytea); +SELECT CAST(_binary'高斯' AS bytea); +SELECT CAST(_utf8mb4'高斯' AS bytea); +SELECT CAST(_gbk'高斯' AS bytea); +SELECT _binary'高斯'; +SELECT _utf8mb4'高斯'; +SELECT _gbk'高斯'; +SELECT _binary X'E9AB98E696AF'; +SELECT _utf8mb4 X'E9AB98E696AF'; +SELECT _gbk X'E9AB98E696AF'; +SELECT '楂樻柉'; +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); -- ERROR +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); -- ERROR + +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); + +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_utf8mb4 SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + +DELETE FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a::bytea=_binary'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +DROP TABLE IF EXISTS t_charset_utf8mb4; + +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); + +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_gbk SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯DB' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; + +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_gbk SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + +DELETE FROM t_charset_gbk WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea=_binary'高斯DB'; -- DELETE 0 +DELETE FROM t_charset_gbk WHERE a::bytea= E'\\xB8DFCBB94442'::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; +DROP TABLE IF EXISTS t_charset_gbk; + +-- test multi charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; -- 5 +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +reset enable_seqscan; + +DROP TABLE t_diff_charset_columns; + +\c regression \ No newline at end of file diff --git a/src/test/regress/sql/charset_utf8mb4_b_db.sql b/src/test/regress/sql/charset_utf8mb4_b_db.sql new file mode 100644 index 000000000..62bc47084 --- /dev/null +++ b/src/test/regress/sql/charset_utf8mb4_b_db.sql @@ -0,0 +1,1414 @@ +CREATE DATABASE c_utf8mb4_b_db WITH ENCODING 'utf8mb4' LC_COLLATE='C' LC_CTYPE='C' DBCOMPATIBILITY 'B'; +\c c_utf8mb4_b_db + +-- test _charset syntax +-- -- test _charset COMPATIBILITY +SET b_format_behavior_compat_options = ''; +SHOW b_format_behavior_compat_options; +SELECT _gbk'ABCD' = _utf8mb4'ABCD'; -- ERROR +CREATE TABLE test_charset_syntax(_utf8 text); +DROP TABLE test_charset_syntax; + +SET b_format_behavior_compat_options = 'all'; +SHOW b_format_behavior_compat_options; +SELECT _gbk'ABCD' = _utf8mb4'ABCD'; +CREATE TABLE test_charset_syntax(_utf8 text); -- ERROR +CREATE TABLE test_charset_syntax(_column text); +DROP TABLE test_charset_syntax; + +-- -- test _charset + expression +SELECT _utf8mb4 10; -- ERROR +SELECT _utf8mb4 CONCAT('高斯', 'DB'); -- ERROR +SELECT _utf8_mb4'ABCD' = _Utf-8mB4'ABCD'; -- ERROR +SELECT __utf8mb4'ABCD' = __Utf8mB4'ABCD'; -- special +SELECT _gbk'ABCD' = _GbK'ABCD'; +SELECT _binary E'', _binary E'' IS NULL; +SELECT _binary E'\\xe9ab98e696af'; +SELECT _utf8mb4 E'\\xe9ab98e696af'; +SELECT _gbk E'\\xe9ab98e696af'; +SELECT _utf8mb4 X'\\xe9ab98e696af'; -- ERROR, X'string' equal 'string' +SELECT _binary X'', _binary X'' IS NULL; +SELECT _binary X'E9AB98E696AF'; +SELECT _utf8mb4 X'E9AB98E696AF'; +SELECT _gbk X'E9AB98E696AF'; +SELECT _binary B'', _binary B'' IS NULL; +SELECT _binary B'0'; +SELECT _binary B'111010011010101110011000111001101001011010101111'; +SELECT _utf8mb4 B'111010011010101110011000111001101001011010101111'; +SELECT _gbk B'111010011010101110011000111001101001011010101111'; +SELECT _utf8mb4 B'111010011010101110011000111001101001011010101111高斯'; -- ERROR +SELECT _binary X'000D' | X'0BC0'; -- ERROR not support yet + +-- ------------------------------------------ +-- SET NAMES utf8mb4; +SET NAMES 'utf8mb4'; +SHOW client_encoding; +SHOW server_encoding; +SHOW character_set_connection; +SHOW collation_connection; + +-- -- CONST charset and collation +SELECT _utf8mb4'高斯' COLLATE gbk_chinese_ci; -- ERROR +SELECT _utf8mb4'高斯' COLLATE 'binary'; -- ERROR +SELECT _utf8mb4'高斯' COLLATE "zh_CN.utf8"; -- support origin collation +SELECT _utf8mb4'高斯' COLLATE "C"; -- support origin collation +SELECT _gbk'高斯' COLLATE gbk_chinese_ci; +SELECT _gbk'高斯' COLLATE 'binary'; -- ERROR +SELECT _gbk'高斯' COLLATE "zh_CN.gbk"; -- ERROR +SELECT _gbk'高斯' COLLATE "C"; -- ERROR +SELECT _gb18030'高斯' COLLATE gb18030_chinese_ci; +SELECT _gb18030'高斯' COLLATE gbk_chinese_ci; -- ERROR +SELECT _gb18030'高斯' COLLATE 'binary'; -- ERROR +SELECT _gb18030'高斯' COLLATE "zh_CN.gb18030"; -- ERROR +SELECT _gb18030'高斯' COLLATE "C"; -- ERROR +SELECT _binary'高斯' COLLATE gbk_chinese_ci; -- ERROR +SELECT _binary'高斯' COLLATE 'binary'; +SELECT _binary'高斯' COLLATE "zh_CN.utf8"; -- ERROR +SELECT _binary'高斯' COLLATE "C"; -- ERROR +SELECT _binary'' COLLATE utf8mb4_bin; -- ERROR +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE gbk_chinese_ci; -- ERROR +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE 'binary'; -- ERROR +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE "zh_CN.utf8"; -- support origin collation +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE "C"; -- support origin collation +SELECT (_utf8mb4'高斯' COLLATE utf8mb4_bin) COLLATE utf8mb4_unicode_ci; +SELECT (_gbk'高斯' COLLATE "C") COLLATE utf8mb4_bin; -- ERROR +SELECT (_gbk'高斯' COLLATE "C") COLLATE gbk_chinese_ci; -- ERROR +SELECT (_binary'高斯' COLLATE "binary") COLLATE utf8mb4_bin; -- ERROR + +-- -- CONST collation only +SELECT X'E9AB98E696AF' COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT X'E9AB98E696AF' COLLATE "binary"; +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT B'111010011010101110011000111001101001011010101111' COLLATE "binary"; +SELECT 1 COLLATE "utf8mb4_unicode_ci"; -- not support yet +SELECT 1 COLLATE "binary"; -- not support yet +SELECT CAST('高斯' AS bytea) COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT CAST('高斯' AS bytea) COLLATE "binary"; +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "utf8mb4_unicode_ci"; -- ERROR +SELECT CAST('E9AB98E696AF' AS blob) COLLATE "binary"; +SELECT '高斯' COLLATE "utf8mb4_unicode_ci"; +SELECT '高斯' COLLATE "gbk_chinese_ci"; -- ERROR +SELECT '高斯' COLLATE "gb18030_chinese_ci"; -- ERROR +SELECT '高斯' COLLATE "binary"; -- ERROR + +-- 中文 const charset +SELECT CAST('高斯' AS bytea); +SELECT CAST(_binary'高斯' AS bytea); +SELECT CAST(_utf8mb4'高斯' AS bytea); +SELECT CAST(_gbk'高斯' AS bytea); +SELECT _binary'高斯'; +SELECT _utf8mb4'高斯'; +SELECT _gbk'高斯'; +SELECT _gb18030'高斯'; +SELECT _gbk X'e9ab98e696af'; +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); + +-- test datatype +-- -- ARRAY TEST +SELECT array[_utf8mb4'高斯']; +SELECT array[_gbk'高斯']; +create table tarray(a text[]); +insert into tarray values(array[_utf8mb4'高斯']); +insert into tarray values(array[_gbk'高斯']); -- ERROR +insert into tarray values(_utf8mb4'{高斯}'::text[]); +insert into tarray values(_gbk'{高斯}'::text[]); -- ERROR +drop table tarray; +-- -- JSON TEST +SELECT _utf8mb4'"高斯"'::json; +SELECT _gbk'"高斯"'::json; -- ERROR +create table tjson(a json); +insert into tjson values(_utf8mb4'"高斯"'::json); +insert into tjson values(_gbk'"高斯"'::json); -- ERROR +drop table tjson; +-- -- XML +SELECT xmlelement(NAME a, _utf8mb4'高斯'); +SELECT xmlelement(NAME a, _gbk'高斯'); -- ERROR +create table txml(a xml); +insert into txml values(_utf8mb4'高斯'::xml); +insert into txml values(_gbk'高斯'::xml); -- ERROR +drop table txml; +-- -- tsvector +SELECT to_tsvector( _utf8mb4'高斯'); +SELECT to_tsvector(_gbk'高斯'); -- ERROR +create table ttsvector(a tsvector); +insert into ttsvector values(_utf8mb4'高斯'::tsvector); +insert into ttsvector values(_gbk'高斯'::tsvector); -- ERROR +drop table ttsvector; +-- -- hll +SELECT hll_hash_text( _utf8mb4'高斯'); +SELECT hll_hash_text(_gbk'高斯'); -- ERROR + +-- test implicit type converion +select _gbk'111' collate "gbk_bin" = 111; + +-- -- 中文 const compare +-- -- -- same charset & explicit collation +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_general_ci = _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "C"; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "zh_CN.utf8"; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _utf8mb4'高斯DB' COLLATE "DEFAULT"; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB' COLLATE utf8mb4_unicode_ci; -- ERROR +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB' COLLATE utf8mb4_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB' COLLATE "C"; -- ERROR +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB' COLLATE "zh_CN.utf8"; -- ERROR +SELECT _gbk'高斯db' COLLATE gbk_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +SELECT _gb18030'高斯db' COLLATE gb18030_bin = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- ERROR +-- -- -- same charset & implicit collation +SELECT _utf8mb4'高斯DB' = '高斯DB'; +-- -- -- diff charset & explicit collation +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB' COLLATE 'binary'; -- not support yet +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; -- ERROR +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯db' COLLATE gb18030_chinese_ci; -- ERROR +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB' COLLATE gb18030_bin; -- ERROR +-- -- -- diff charset & implicit collation +SELECT _utf8mb4'高斯DB' = _binary'高斯DB'; +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB'; +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB'; +SELECT _gbk'高斯DB' = '高斯DB'; +SELECT _gbk'高斯DB' = _utf8mb4'高斯DB'; +SELECT _gbk'高斯DB' = _binary'高斯DB'; -- not support yet +SELECT _gbk'高斯DB' = _gb18030'高斯DB'; -- ERROR +SELECT _gb18030'高斯DB' = '高斯DB'; +SELECT _gb18030'高斯DB' = _utf8mb4'高斯DB'; +SELECT _gb18030'高斯DB' = _binary'高斯DB'; -- not support yet +SELECT '高斯DB' = _utf8mb4'高斯DB'; +SELECT '高斯DB' = _gbk'高斯DB'; +SELECT '高斯DB' = _gb18030'高斯DB'; +SELECT _binary'高斯DB' = _utf8mb4'高斯DB'; -- not support yet +SELECT _binary'高斯DB' = _gbk'高斯DB'; -- not support yet +SELECT _binary'高斯DB' = _gb18030'高斯DB'; -- not support yet +-- -- -- explicit & implicit +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE utf8mb4_unicode_ci; +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE utf8mb4_bin; +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "C"; +SELECT _utf8mb4'高斯DB' = '高斯DB' COLLATE "zh_CN.utf8"; +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'楂樻柉DB' = _gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT _utf8mb4'高斯DB' = _gbk'高斯DB' COLLATE gbk_bin; +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'楂樻柉DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; +SELECT _utf8mb4'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = '高斯DB'; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _binary'高斯DB'; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gbk'高斯DB'; +SELECT _utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci = _gb18030'高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = '高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _binary'高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gbk'高斯DB'; +SELECT _utf8mb4'高斯DB' COLLATE utf8mb4_bin = _gb18030'高斯DB'; +SELECT _gbk'高斯DB' = _gb18030'高斯db' COLLATE gb18030_chinese_ci; +SELECT _gbk'高斯DB' = _gb18030'高斯DB' COLLATE gb18030_bin; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = '高斯DB'; +SELECT _gbk'高斯db' COLLATE gbk_chinese_ci = _gb18030'高斯DB'; +SELECT _gbk'高斯DB' COLLATE gbk_bin = '高斯DB'; +SELECT _gbk'高斯DB' COLLATE gbk_bin = _gb18030'高斯DB'; + +-- -- 中文 const concat +-- -- -- same charset & explicit collation +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE "C"); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE "zh_CN.utf8"); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE utf8mb4_unicode_ci); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB' COLLATE utf8mb4_bin); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB' COLLATE utf8mb4_unicode_ci); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB' COLLATE utf8mb4_bin); +-- -- -- same charset & implicit collation +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB') result, collation for(result); +-- -- -- diff charset & explicit collation +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); -- ERROR +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); -- ERROR +-- -- -- diff charset & implicit collation +SELECT CONCAT(_utf8mb4'高斯DB' , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , '高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB' , '高斯DB') result, collation for(result); +SELECT CONCAT(_gb18030'高斯DB' , _binary'高斯DB') result, collation for(result); +SELECT CONCAT( _binary'高斯DB', _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT( _binary'高斯DB', '高斯DB') result, collation for(result); +-- -- -- explicit & implicit +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "C") result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE "zh_CN.utf8") result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE utf8mb4_unicode_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , '高斯DB' COLLATE utf8mb4_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gbk'高斯db' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB' COLLATE gbk_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB' , _gb18030'高斯db' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , '高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , '高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_bin , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_chinese_ci) result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' , _gb18030'高斯DB' COLLATE gb18030_bin) result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , '高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_chinese_ci , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , '高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB' COLLATE gbk_bin , _gb18030'高斯DB') result, collation for(result); +SELECT CONCAT(_binary'高斯DB', _utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci) result, collation for(result); +SELECT CONCAT(_binary'高斯DB' COLLATE 'binary', _gbk'高斯DB') result, collation for(result); + +-- -- -- concat 3 args +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_binary'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci) result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB', _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci, _binary'高斯DB') result, collation for(result); +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB', _binary'高斯DB') result, collation for(result); -- ERROR +SELECT CONCAT(_gb18030'高斯DB' COLLATE gb18030_chinese_ci, _gbk'高斯DB', _utf8mb4'高斯DB') result, collation for(result); +SELECT CONCAT(_gb18030'高斯DB', _gbk'高斯DB' COLLATE gbk_chinese_ci, _binary'高斯DB') result, collation for(result); +-- -- -- const compare CONCAT +SELECT _utf8mb4'楂樻柉DB' = CONCAT(_gbk'高斯DB'); +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); +SELECT _utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB'); +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin = CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci); +SELECT _utf8mb4'楂樻柉DB楂樻柉DB' = CONCAT(_gbk'高斯DB', _gb18030'高斯DB'); -- ERROR +-- -- -- const CONCAT CONCAT +SELECT CONCAT(_utf8mb4'楂樻柉DB', CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB', CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(_utf8mb4'楂樻柉DB楂樻柉DB' COLLATE utf8mb4_bin, CONCAT(_gbk'高斯DB', _gb18030'高斯DB' COLLATE gb18030_chinese_ci)) result, collation for(result); +-- -- -- const CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT('高斯DB', opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), '高斯DB') result, collation for(result); +SELECT CONCAT('高斯DB', 123) result, collation for(result); +SELECT CONCAT(123, '高斯DB') result, collation for(result); +SELECT CONCAT('高斯DB', DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', '高斯DB') result, collation for(result); +SELECT CONCAT('高斯DB', NULL) result, collation for(result); +SELECT CONCAT(NULL, '高斯DB') result, collation for(result); +-- -- -- -- diff charset +SELECT CONCAT(_gbk'高斯DB', opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB', 123) result, collation for(result); +SELECT CONCAT(123, _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB', DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', _gbk'高斯DB') result, collation for(result); +SELECT CONCAT(_gbk'高斯DB', NULL) result, collation for(result); +SELECT CONCAT(NULL, _gbk'高斯DB') result, collation for(result); +-- -- -- CONCAT CONCAT with other diff DERIVATION +-- -- -- -- same charset +SELECT CONCAT(CONCAT('高斯DB'), opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), CONCAT('高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT('高斯DB'), 123) result, collation for(result); +SELECT CONCAT(123, CONCAT('高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT('高斯DB'), DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', CONCAT('高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT('高斯DB'), NULL) result, collation for(result); +SELECT CONCAT(NULL, CONCAT('高斯DB')) result, collation for(result); +-- -- -- -- diff charset +SELECT CONCAT(CONCAT(_gbk'高斯DB'), opengauss_version()) result, collation for(result); +SELECT CONCAT(opengauss_version(), CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT(_gbk'高斯DB'), 123) result, collation for(result); +SELECT CONCAT(123, CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT(_gbk'高斯DB'), DATE '2023-05-01') result, collation for(result); +SELECT CONCAT(DATE '2023-05-01', CONCAT(_gbk'高斯DB')) result, collation for(result); +SELECT CONCAT(CONCAT(_gbk'高斯DB'), NULL) result, collation for(result); +SELECT CONCAT(NULL, CONCAT(_gbk'高斯DB')) result, collation for(result); +-- -- -- CONCAT NUMBERS +SELECT CONCAT('100', 200) result, collation for(result); +SELECT CONCAT('100', date'2021-01-01') result, collation for(result); +SELECT CONCAT('100', NULL) result, collation for(result); +SELECT CONCAT('100', NULL::bytea) result, collation for(result); +SELECT CONCAT('100', NULL::text) result, collation for(result); +SELECT CONCAT(100, 200) result, collation for(result); +SELECT CONCAT(100, date'2021-01-01') result, collation for(result); +SELECT CONCAT(100, NULL) result, collation for(result); +SELECT CONCAT(100, NULL::bytea) result, collation for(result); +SELECT CONCAT(100, NULL::text) result, collation for(result); +SELECT CONCAT(NULL, NULL::bytea) result, collation for(result); +SELECT CONCAT(NULL, NULL::text) result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL), '100') result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::bytea), '100') result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::text), '100') result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL), 100) result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::bytea), 100) result, collation for(result); +SELECT CONCAT(CONCAT(100, NULL::text), 100) result, collation for(result); + +-- -- 中文 with column charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +reset enable_seqscan; + +-- -- COLUMN collation only +SELECT futf8_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT futf8_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT futf8_bin COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- support origin collation +SELECT futf8_bin COLLATE "C" FROM t_diff_charset_columns; -- support origin collation +SELECT fgbk_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; +SELECT fgbk_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_bin COLLATE "zh_CN.gbk" FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; +SELECT fgb18030_bin COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE "zh_CN.gb18030" FROM t_diff_charset_columns; -- ERROR +SELECT fgb18030_bin COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT fbytea COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT fbytea COLLATE 'binary' FROM t_diff_charset_columns; +SELECT fbytea COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +SELECT fbytea COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT fblob COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT fblob COLLATE 'binary' FROM t_diff_charset_columns; +SELECT fblob COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- ERROR +SELECT fblob COLLATE "C" FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "zh_CN.utf8" FROM t_diff_charset_columns; -- support origin collation +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE "C" FROM t_diff_charset_columns; -- support origin collation +SELECT (futf8_uni COLLATE utf8mb4_bin) COLLATE utf8mb4_unicode_ci FROM t_diff_charset_columns; +SELECT (fgbk_chi COLLATE "C") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +SELECT (fgbk_chi COLLATE "C") COLLATE gbk_chinese_ci FROM t_diff_charset_columns; -- ERROR +SELECT (fblob COLLATE "binary") COLLATE utf8mb4_bin FROM t_diff_charset_columns; -- ERROR +SELECT fbit COLLATE 'binary' FROM t_diff_charset_columns; -- ERROR + +-- -- COLUMN compare COLUMN +-- -- -- same charset & implicit collation +SELECT futf8_bin = futf8_uni, futf8_uni = futf8_bin FROM t_diff_charset_columns; +SELECT fgbk_bin = fgbk_chi, fgbk_chi = fgbk_bin FROM t_diff_charset_columns; +SELECT fgb18030_bin = fgb18030_chi, fgb18030_chi = fgb18030_bin FROM t_diff_charset_columns; +SELECT futf8_gen = futf8_uni, futf8_uni = futf8_gen FROM t_diff_charset_columns; +SELECT futf8_gen > futf8_uni, futf8_uni > futf8_gen FROM t_diff_charset_columns; -- ERROR +-- -- -- diff charset & implicit collation +SELECT futf8_bin = fgbk_bin, fgbk_bin = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_bin = fgbk_chi, fgbk_chi = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_bin = fgb18030_bin, fgb18030_bin = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_bin = fgb18030_chi, fgb18030_chi = futf8_bin FROM t_diff_charset_columns; +SELECT futf8_uni = fgbk_bin, fgbk_bin = futf8_uni FROM t_diff_charset_columns; +SELECT futf8_uni = fgbk_chi, fgbk_chi = futf8_uni FROM t_diff_charset_columns; +SELECT futf8_uni = fgb18030_bin, fgb18030_bin = futf8_uni FROM t_diff_charset_columns; +SELECT futf8_uni = fgb18030_chi, fgb18030_chi = futf8_uni FROM t_diff_charset_columns; +SELECT fgbk_bin = fgb18030_bin, fgb18030_bin = fgbk_bin FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_bin = fgb18030_chi, fgb18030_chi = fgbk_bin FROM t_diff_charset_columns; -- ERROR +SELECT fgbk_chi = fgb18030_chi, fgb18030_chi = fgbk_chi FROM t_diff_charset_columns; -- ERROR +-- -- -- with binary & implicit collation +SELECT futf8_bin = fbytea, fbytea = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT futf8_bin = fblob, fblob = futf8_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT futf8_uni = fbytea, fbytea = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT futf8_uni = fblob, fblob = futf8_uni FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgbk_bin = fbytea, fbytea = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgbk_bin = fblob, fblob = fgbk_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgb18030_bin = fbytea, fbytea = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fgb18030_bin = fblob, fblob = fgb18030_bin FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT fbytea = fblob, fblob = fbytea FROM t_diff_charset_columns; + +-- -- COLUMN concat COLUMN +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgb18030_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_gen, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- result is _bin +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_bin, fgb18030_bin) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +SELECT CONCAT(fgbk_bin, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +SELECT CONCAT(fgbk_chi, fgb18030_chi) result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- with binary & implicit collation +SELECT CONCAT(futf8_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(futf8_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(futf8_uni, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(futf8_uni, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgbk_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgbk_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgb18030_bin, fbytea) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fgb18030_bin, fblob) result, collation for(result) FROM t_diff_charset_columns; -- NOT SUPPORTED +SELECT CONCAT(fbytea, fblob) result, collation for(result) FROM t_diff_charset_columns; + +-- -- concat column and @uservar +set enable_set_variable_b_format=on; +-- -- -- string var utf8mb4_general_ci +set @var_utf8_uni = '高斯DB' COLLATE utf8mb4_unicode_ci; -- should support +SELECT collation for(@var_utf8_uni); +SELECT CONCAT(futf8_gen, @var_utf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- null collation +SELECT CONCAT(fgbk_bin, @var_utf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_unicode_ci +SELECT CONCAT(@var_utf8_uni, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- _bin +-- -- -- string var gbk_chinese_ci +set @var_gbk_chi = _gbk'高斯DB' COLLATE gbk_chinese_ci; -- should support +SELECT collation for(@var_gbk_chi); +SELECT CONCAT(futf8_uni, @var_gbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- futf8_uni +SELECT CONCAT(@var_gbk_chi, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin +-- -- -- number var +set @var_num = 5.0; +SELECT CONCAT(futf8_bin, @var_num) result, collation for(result) FROM t_diff_charset_columns; -- futf8_bin +SELECT CONCAT(@var_num, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; -- fgbk_bin +-- -- -- bytea var +set @var_binary = _binary'高斯DB'; -- not support yet +SELECT CONCAT(futf8_bin, @var_binary) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(@var_binary, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + +-- -- concat column and bind parameter +-- -- -- -- PBE with implicit collation +PREPARE test_merge_collation(text) AS +SELECT CONCAT(futf8_uni, $1) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- $1 use collation_connection, conflict +EXECUTE test_merge_collation(_utf8mb4'高斯DB' collate utf8mb4_unicode_ci); -- explicit noneffective, conflict +EXECUTE test_merge_collation(_gbk'高斯DB'); -- _gbk noneffective, conflict +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with implicit 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 +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate utf8mb4_unicode_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; +EXECUTE test_merge_collation(_utf8mb4'高斯DB'); -- utf8mb4_unicode_ci +EXECUTE test_merge_collation(_gbk'高斯DB'); -- utf8mb4_unicode_ci +DEALLOCATE test_merge_collation; +-- -- -- -- PBE with explicit collation, +PREPARE test_merge_collation(text) AS +SELECT CONCAT($1 collate gbk_chinese_ci, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- $1 use collation_connection, ERROR +DEALLOCATE test_merge_collation; + +-- -- concat column and PROCEDURE parameter with CURSOR +-- -- -- implicit collation && string +create or replace procedure merge_collation_func(p1 text, p2 text) +as +DECLARE + concat_res text; + collation_res text; + concat_res_assign varchar(64); + CURSOR c1 IS + SELECT CONCAT(p1, p2) result, collation for(result); +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + concat_res_assign = concat_res; + set @concat_res = concat_res; + set @collation_res = collation_res; + set @concat_res_assign = concat_res_assign; +end; +/ + +CALL merge_collation_func('高斯DB', _gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation,@concat_res_assign; -- utf8mb4_general_ci +CALL merge_collation_func(_gb18030'高斯DB', _gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation,@concat_res_assign; -- utf8mb4_general_ci +CALL merge_collation_func(_gb18030'高斯DB', _gbk'高斯DB' collate gbk_chinese_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation,@concat_res_assign; -- utf8mb4_general_ci +DROP procedure merge_collation_func; +-- -- -- implicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(futf8_uni, p1) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ + +CALL merge_collation_func('高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict +CALL merge_collation_func(_gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation;; -- conflict +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation;; -- conflict +DROP procedure merge_collation_func; +-- -- -- implicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(p1, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ + + +CALL merge_collation_func('高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci +CALL merge_collation_func(_gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_general_ci +DROP procedure merge_collation_func; +-- -- -- explicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(p1, fgbk_bin collate gbk_bin) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ + + +CALL merge_collation_func('高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +CALL merge_collation_func(_gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +DROP procedure merge_collation_func; +-- -- -- implicit collation && int +create or replace procedure merge_collation_func(p1 int) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(fgbk_bin, p1) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ + +CALL merge_collation_func(100); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +DROP procedure merge_collation_func; +-- -- -- explicit collation && string +create or replace procedure merge_collation_func(p1 text) +as +DECLARE + concat_res text; + collation_res text; + CURSOR c1 IS + SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns; +begin + OPEN c1; + LOOP + FETCH c1 INTO concat_res, collation_res; + EXIT; + END LOOP; + CLOSE c1; + set @concat_res = concat_res; + set @collation_res = collation_res; +end; +/ + +CALL merge_collation_func('高斯DB'); -- ERROR +DROP procedure merge_collation_func; + +-- -- concat column and PROCEDURE parameter with select into +-- -- -- implicit collation +create or replace procedure merge_collation_func(p1 text) +as +begin + SELECT CONCAT(futf8_uni, p1) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res; +end; +/ + +CALL merge_collation_func('高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- conflict +CALL merge_collation_func(_gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_unicode_ci +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- utf8mb4_unicode_ci +DROP procedure merge_collation_func; +-- -- -- implicit collation +create or replace procedure merge_collation_func(p1 text) +as +begin + SELECT CONCAT(p1, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res; +end; +/ + +CALL merge_collation_func('高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +CALL merge_collation_func('高斯DB' collate utf8mb4_general_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +CALL merge_collation_func(_gbk'高斯DB'); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +CALL merge_collation_func(_gbk'高斯DB' collate gbk_chinese_ci); +SELECT @concat_res,@collation_res,collation for(@concat_res) real_collation; -- gbk_bin +DROP procedure merge_collation_func; +-- -- -- explicit collation +create or replace procedure merge_collation_func(p1 text) +as +begin + SELECT CONCAT(futf8_uni, p1 COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns into @concat_res,@collation_res; +end; +/ + +CALL merge_collation_func('高斯DB'); -- ERROR +DROP procedure merge_collation_func; + +-- -- concat for DERIVATION +-- -- -- same charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(futf8_bin, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), futf8_bin collate utf8mb4_unicode_ci) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_unicode_ci +SELECT CONCAT(futf8_bin collate utf8mb4_unicode_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- utf8mb4_unicode_ci +SELECT CONCAT(CONCAT(futf8_gen), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- conflict +SELECT CONCAT(futf8_uni, CONCAT(futf8_gen)) result, collation for(result) FROM t_diff_charset_columns; -- conflict +SELECT CONCAT(futf8_uni, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(opengauss_version(), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT('高斯DB', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, 123) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(123, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(DATE '2023-05-01', futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni, NULL) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(NULL, futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +-- -- -- diff charset & diff DERIVATION +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), CONCAT(fgbk_chi, fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(fgbk_chi, fgb18030_chi), CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(fgbk_chi, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- conflict in concat inside +SELECT CONCAT(CONCAT(futf8_gen, futf8_uni), fgbk_chi COLLATE gbk_chinese_ci) result, collation for(result) FROM t_diff_charset_columns; -- gbk_chinese_ci +SELECT CONCAT(fgbk_chi COLLATE gbk_chinese_ci, CONCAT(futf8_gen, futf8_uni)) result, collation for(result) FROM t_diff_charset_columns; -- gbk_chinese_ci +SELECT CONCAT(CONCAT(futf8_gen, fgbk_chi), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; -- conflict +SELECT CONCAT(futf8_uni, CONCAT(futf8_gen, fgbk_chi)) result, collation for(result) FROM t_diff_charset_columns; -- conflict +SELECT CONCAT(fgbk_chi, CONCAT(fgb18030_chi)) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(CONCAT(fgb18030_bin), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, opengauss_version()) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(opengauss_version(), fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, '高斯DB') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT('高斯DB', fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, 123) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(123, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, DATE '2023-05-01') result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(DATE '2023-05-01', fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(fgbk_chi, NULL) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(NULL, fgbk_bin) result, collation for(result) FROM t_diff_charset_columns; + +-- -- test explicit collate on concat +-- -- -- same charset & implicit collation +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, futf8_uni) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- diff charset & implicit collation +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_bin, fgbk_bin) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- with binary & implicit collation +SELECT CONCAT(fbytea, futf8_uni) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text +SELECT CONCAT(fbytea, futf8_uni) COLLATE utf8mb4_general_ci result, collation for(result) FROM t_diff_charset_columns; -- return datatype still text + +-- -- test explicit collate on blob result +SELECT CAST('DEADBEEF' AS blob) COLLATE utf8mb4_general_ci result; -- ERROR +SELECT CAST('DEADBEEF' AS blob) COLLATE "binary" result; + +-- -- case when +-- -- -- condition same charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation +SELECT CASE WHEN (futf8_gen = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE futf8_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_gen) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; -- null collation +SELECT CASE futf8_gen WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- condition same charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (fgbk_chi = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (futf8_bin = futf8_uni) THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE fgbk_chi WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE futf8_bin WHEN futf8_uni THEN (futf8_uni) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +-- -- -- condition diff charset & result same charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (futf8_bin) ELSE (futf8_uni) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_bin WHEN futf8_uni THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_bin WHEN fgb18030_bin THEN (fgbk_chi) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- condition diff charset & result diff charset & implicit collation +-- -- -- -- bool condition +SELECT CASE WHEN (futf8_uni = fgbk_bin) THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = futf8_uni) THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE WHEN (fgbk_bin = fgb18030_bin) THEN (fgb18030_chi) ELSE (fgbk_chi) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- case condition +SELECT CASE futf8_uni WHEN fgbk_bin THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgbk_bin WHEN futf8_uni THEN (futf8_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; +SELECT CASE fgb18030_chi WHEN fgbk_chi THEN (fgb18030_bin) ELSE (fgbk_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- -- conflict +SELECT CASE _gb18030'高斯' WHEN fgbk_bin THEN (fgbk_bin) ELSE (futf8_bin) END result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- in +-- -- -- column utf8 +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', _gbk'高斯DB'); -- ERROR +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB' COLLATE gb18030_chinese_ci, '高斯DB'); +EXPLAIN (costs off) +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); +SELECT futf8_bin FROM t_diff_charset_columns WHERE futf8_bin in (_gb18030'高斯DB', concat('高斯DB')); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.futf8_gen FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_bin in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE futf8_gen in (SELECT t2.futf8_uni FROM t_diff_charset_columns t2); +-- -- -- column gbk +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB'); +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE utf8mb4_bin); +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_gb18030'高斯DB', '高斯DB' COLLATE utf8mb4_bin); +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in (_utf8mb4'高斯DB', _gbk'高斯DB'); +EXPLAIN (costs off) +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); +SELECT fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin in ('高斯DB', concat(_gbk'高斯DB' COLLATE gbk_chinese_ci)); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.fgbk_chi FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_bin in (SELECT t2.futf8_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgbk_bin FROM t_diff_charset_columns t2); +SELECT futf8_bin FROM t_diff_charset_columns t1 WHERE fgbk_chi in (SELECT t2.fgb18030_bin FROM t_diff_charset_columns t2); -- ERROR + +-- -- COALESCE +SELECT COALESCE(fgbk_chi, futf8_bin) result, collation for(result) FROM t_diff_charset_columns; +SELECT COALESCE(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; +SELECT COALESCE(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +SELECT COALESCE(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR + +-- -- GREATEST +SELECT GREATEST(fgbk_chi, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; +SELECT GREATEST(futf8_gen, futf8_bin) result, collation for (result) FROM t_diff_charset_columns; +SELECT GREATEST(futf8_uni, futf8_gen) result, collation for (result) FROM t_diff_charset_columns; -- conflict +SELECT GREATEST(fgbk_chi, fgb18030_chi) result, collation for (result) FROM t_diff_charset_columns; -- ERROR + +-- -- rowcompare +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db'); +SELECT futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi FROM t_diff_charset_columns + WHERE (futf8_bin, futf8_uni, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi) = ('高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB', '高斯DB'); + +-- -- aggregate +SELECT count(futf8_bin), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin; +SELECT count(fgbk_bin), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin; +SELECT count(fgb18030_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +SELECT group_concat(futf8_bin, fgbk_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +SELECT group_concat(fgbk_bin, fgbk_chi order by futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +SELECT group_concat(DISTINCT fgbk_bin, futf8_bin order by fgbk_bin, futf8_bin), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; + +-- -- UNION +-- -- -- const +select _utf8mb4'高斯' union select _gbk'高斯'; +select _gb18030'高斯' union select _gbk'高斯'; -- ERROR +-- -- -- column +select futf8_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; +select fgb18030_bin FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; -- ERROR +-- -- -- explicit +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union + select fgbk_bin FROM t_diff_charset_columns; +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + union all + select fgbk_bin FROM t_diff_charset_columns; +select fgbk_chi COLLATE gbk_chinese_ci FROM t_diff_charset_columns + INTERSECT + select fgbk_bin FROM t_diff_charset_columns; +-- -- -- mixed +select _utf8mb4'高斯', futf8_bin FROM t_diff_charset_columns + union + select _gbk'高斯', fgbk_bin FROM t_diff_charset_columns; +select _utf8mb4'GS', futf8_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_bin FROM t_diff_charset_columns; +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', fgbk_chi FROM t_diff_charset_columns; +-- -- -- 3 select +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_bin FROM t_diff_charset_columns; +select _utf8mb4'GS', fgbk_bin FROM t_diff_charset_columns + union + select _gbk'GS', futf8_bin FROM t_diff_charset_columns + union + select _gb18030'GS', fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns; +-- -- -- complex select +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi), fgb18030_bin FROM t_diff_charset_columns GROUP BY fgb18030_bin; +select _utf8mb4'GS', GROUP_CONCAT(fgbk_bin, fgbk_chi), fgbk_bin FROM t_diff_charset_columns GROUP BY fgbk_bin + union + select _gbk'GS', GROUP_CONCAT(futf8_bin, futf8_uni), futf8_bin FROM t_diff_charset_columns GROUP BY futf8_bin + union + select _gb18030'GS', GROUP_CONCAT(fgb18030_bin, fgb18030_chi COLLATE gb18030_chinese_ci), fgb18030_chi COLLATE gb18030_chinese_ci FROM t_diff_charset_columns GROUP BY fgb18030_chi; + +-- -- test COLLATE for function +-- -- -- for string function +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) COLLATE utf8mb4_general_ci result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' COLLATE utf8mb4_unicode_ci , _gbk'高斯DB' COLLATE gbk_chinese_ci) COLLATE gbk_chinese_ci result, collation for(result); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE utf8mb4_bin result, collation for(result); +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE gbk_chinese_ci result, collation for(result); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB' , _gbk'高斯DB') COLLATE "binary" result, collation for(result); -- ERROR +SELECT CONCAT(futf8_uni , futf8_gen) COLLATE utf8mb4_bin result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(futf8_uni , futf8_gen) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- for binary argument string function +SELECT CONCAT(_utf8mb4'高斯DB', _binary'高斯DB') COLLATE "binary" result, collation for(result); -- ERROR +SELECT CONCAT(_utf8mb4'高斯DB', _binary'高斯DB') COLLATE utf8mb4_unicode_ci result, collation for(result); +SELECT CONCAT(futf8_uni, fbytea) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- ERROR +SELECT CONCAT(futf8_uni, fbytea) COLLATE gbk_chinese_ci result, collation for(result) FROM t_diff_charset_columns; -- ERROR +-- -- -- for binary function +SELECT CONVERT(fbytea, 'UTF8', 'GBK') COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- pg_collation_for binary type ERROR +SELECT CONVERT(fbytea, 'UTF8', 'GBK') COLLATE "binary" result FROM t_diff_charset_columns; +SELECT CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) result, collation for(result) FROM t_diff_charset_columns; +SELECT CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) COLLATE "binary" result, collation for(result) FROM t_diff_charset_columns; -- ERROR +SELECT CONCAT(CONVERT(fbytea, 'UTF8', 'GBK'), futf8_uni) COLLATE utf8mb4_unicode_ci result, collation for(result) FROM t_diff_charset_columns; + +DROP TABLE t_diff_charset_columns; + +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); + +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_utf8mb4 SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + +DELETE FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a::bytea=_binary'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +-- -- -- -- test assign expr +INSERT INTO t_charset_utf8mb4(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +INSERT INTO t_charset_utf8mb4(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +UPDATE t_charset_utf8mb4 SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +DROP TABLE IF EXISTS t_charset_utf8mb4; + +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); + +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB', (_gbk'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_gbk'高斯DB' COLLATE 'gbk_chinese_ci', + (_gbk'高斯DB' COLLATE 'gbk_chinese_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); +INSERT INTO t_charset_gbk SELECT 6,_gbk'高斯DB', (_gbk'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯DB' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; + +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_gbk'高斯DB' COLLATE 'gbk_chinese_ci'; +UPDATE t_charset_gbk SET a=_gbk'高斯DB', b=(_gbk'高斯DB')::bytea + WHERE a='楂樻柉'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_gbk'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + +DELETE FROM t_charset_gbk WHERE a=_utf8mb4'高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea=_binary'高斯DB'; -- DELETE 0 +DELETE FROM t_charset_gbk WHERE a::bytea= E'\\xB8DFCBB94442'::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; +-- -- -- -- test assign expr +INSERT INTO t_charset_gbk(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_gbk SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; +INSERT INTO t_charset_gbk(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_gbk ORDER BY id; +UPDATE t_charset_gbk SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_gbk ORDER BY id; +DROP TABLE IF EXISTS t_charset_gbk; + +-- -- test partkey +CREATE TABLE t_multi_charset_partkey (part varchar(32) collate utf8mb4_general_ci, a int) + PARTITION BY RANGE(part) ( + partition p1 values less than('高斯DB'), + partition p2 values less than('高斯db'), + partition p3 values less than(MAXVALUE) +); -- ERROR + +-- -- -- utf8mb4 +CREATE TABLE t_multi_charset_partkey (part varchar(32) collate utf8mb4_bin, a int) + PARTITION BY RANGE(part) ( + partition p1 values less than('楂樻柉DB'), + partition p2 values less than('楂樻柉db'), + partition p3 values less than('高斯DB'), + partition p4 values less than('高斯db'), + partition p5 values less than(MAXVALUE) +); +-- -- -- insert +INSERT INTO t_multi_charset_partkey VALUES(_gbk'高斯DB', 1); +INSERT INTO t_multi_charset_partkey VALUES(_gbk'高斯db', 2); +INSERT INTO t_multi_charset_partkey VALUES(_utf8mb4'高斯DB', 3); +INSERT INTO t_multi_charset_partkey VALUES(_utf8mb4'高斯db', 4); +-- -- -- select +SELECT * FROM t_multi_charset_partkey PARTITION(p1) order by 1,2; +SELECT * FROM t_multi_charset_partkey PARTITION(p2) order by 1,2; +SELECT * FROM t_multi_charset_partkey PARTITION(p3) order by 1,2; +SELECT * FROM t_multi_charset_partkey PARTITION(p4) order by 1,2; +SELECT * FROM t_multi_charset_partkey PARTITION(p5) order by 1,2; +-- -- -- partition pruning +EXPLAIN (costs off) +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' order by 1,2; +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' order by 1,2; +EXPLAIN (costs off) +SELECT * FROM t_multi_charset_partkey WHERE part=_utf8mb4'高斯db' order by 1,2; +SELECT * FROM t_multi_charset_partkey WHERE part=_utf8mb4'高斯db' order by 1,2; +EXPLAIN (costs off) +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' collate gbk_chinese_ci order by 1,2; -- ALL PARTS +SELECT * FROM t_multi_charset_partkey WHERE part=_gbk'高斯DB' collate gbk_chinese_ci order by 1,2; +DROP TABLE t_multi_charset_partkey; + +-- -- -- gbk +CREATE TABLE t_multi_charset_partkey (part varchar(32) CHARACTER set gbk collate gbk_bin, a int) + PARTITION BY RANGE(part) ( + partition p1 values less than('高斯DB'), + partition p2 values less than(MAXVALUE) +); -- error + +-- -- test column default value +CREATE TABLE t_default_charset( + a varchar(32) character set gbk collate gbk_bin DEFAULT '高斯DB', + b varchar(32) character set utf8mb4 collate utf8mb4_unicode_ci GENERATED ALWAYS AS (a) STORED, + c varchar(32) character set utf8mb4 collate utf8mb4_unicode_ci GENERATED ALWAYS AS (a||_utf8mb4'高斯DB') STORED); +INSERT INTO t_default_charset VALUES(DEFAULT, DEFAULT, DEFAULT); +select * from t_default_charset; +DROP TABLE t_default_charset; +-- ------------------------------------------ +-- SET NAMES GBK; +SET NAMES 'GBK'; +SHOW client_encoding; +SHOW server_encoding; +SHOW character_set_connection; +SHOW collation_connection; + +-- 中文 +SELECT CAST('高斯' AS bytea); +SELECT CAST(_binary'高斯' AS bytea); +SELECT CAST(_utf8mb4'高斯' AS bytea); +SELECT CAST(_gbk'高斯' AS bytea); +SELECT _binary'高斯'; +SELECT _utf8mb4'高斯'; +SELECT _gbk'高斯'; +SELECT _binary X'E9AB98E696AF'; +SELECT _utf8mb4 X'E9AB98E696AF'; +SELECT _gbk X'E9AB98E696AF'; +SELECT '楂樻柉'; -- ERROR '楂樻柉'(\xe6a582e6a8bbe69f89) will be converted to utf8 first +SELECT CONVERT_TO(_utf8mb4'楂樻柉', 'gbk'); -- ERROR '楂樻柉'(\xe6a582e6a8bbe69f89) will be converted to utf8 first +SELECT CONVERT_TO(_utf8mb4'高斯', 'gbk'); + +-- -- -- DML 中文 utf8mb4 COLUMNS +DROP TABLE IF EXISTS t_charset_utf8mb4; +CREATE TABLE t_charset_utf8mb4( + id int auto_increment primary key, + a text charset utf8mb4 collate 'utf8mb4_bin', + b bytea +); + +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +INSERT INTO t_charset_utf8mb4(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_utf8mb4(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; + +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB'; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db'; +SELECT id,a FROM t_charset_utf8mb4 WHERE a COLLATE utf8mb4_unicode_ci =_gbk'高斯db' into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_utf8mb4 WHERE a='楂樻柉' ORDER BY id; -- ERROR +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯DB' ORDER BY id; +SELECT * FROM t_charset_utf8mb4 WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; + +UPDATE t_charset_utf8mb4 SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +UPDATE t_charset_utf8mb4 SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; + +DELETE FROM t_charset_utf8mb4 WHERE a='高斯'; +DELETE FROM t_charset_utf8mb4 WHERE a='高斯DB'; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +-- -- -- -- test assign expr +INSERT INTO t_charset_utf8mb4(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_utf8mb4 SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +INSERT INTO t_charset_utf8mb4(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +UPDATE t_charset_utf8mb4 SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_utf8mb4 ORDER BY id; +DROP TABLE IF EXISTS t_charset_utf8mb4; + +-- -- -- DML 中文 gbk COLUMNS +DROP TABLE IF EXISTS t_charset_gbk; +CREATE TABLE t_charset_gbk( + id int auto_increment primary key, + a text charset gbk collate "gbk_bin", + b bytea +); + +INSERT INTO t_charset_gbk(a,b) VALUES('高斯', '高斯'); +INSERT INTO t_charset_gbk(a,b) VALUES('高斯DB', '高斯DB'); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES(_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci', + (_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci')::bytea); +INSERT INTO t_charset_gbk(a,b) VALUES('楂樻柉', '楂樻柉'); -- ERROR +INSERT INTO t_charset_gbk SELECT 6,_utf8mb4'高斯DB', (_utf8mb4'高斯DB')::bytea; +-- -- -- -- test deparse for explain and select into +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB'; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯DB' into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci; +SELECT id,a FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +EXPLAIN (costs off) +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1; +SELECT id,a FROM t_charset_gbk WHERE a COLLATE gbk_chinese_ci =_utf8mb4'高斯db' LIMIT 1 into @id_res,@a_res; +SELECT @id_res,@a_res; +-- -- -- -- test condition +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_gbk'高斯db' COLLATE gbk_chinese_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_binary'高斯DB' ORDER BY id; -- ERROR +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯DB' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯db' COLLATE utf8mb4_unicode_ci ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a=_utf8mb4'高斯' ORDER BY id; +SELECT * FROM t_charset_gbk WHERE a='楂樻柉' ORDER BY id; -- ERROR + +UPDATE t_charset_gbk SET a='高斯DB', b='高斯DB' + WHERE a=_utf8mb4'高斯DB' COLLATE 'utf8mb4_unicode_ci'; +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a='楂樻柉'; -- ERROR +UPDATE t_charset_gbk SET a=_utf8mb4'高斯DB', b=(_utf8mb4'高斯DB')::bytea + WHERE a=_utf8mb4'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; + +DELETE FROM t_charset_gbk WHERE a='高斯'; +DELETE FROM t_charset_gbk WHERE a::bytea= _binary'高斯DB'; +SELECT * FROM t_charset_gbk ORDER BY id; +-- -- -- -- test assign expr +INSERT INTO t_charset_gbk(a,b) VALUES(CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea); +INSERT INTO t_charset_gbk SELECT 0, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea; +SELECT * FROM t_charset_gbk ORDER BY id; +INSERT INTO t_charset_gbk(id,a,b) VALUES(7, CONCAT('高斯','DB'), (CONCAT('高斯','DB'))::bytea) ON DUPLICATE KEY UPDATE a=CONCAT('高斯','db'); +SELECT * FROM t_charset_gbk ORDER BY id; +UPDATE t_charset_gbk SET a=CONCAT('DB','高斯'), b=(CONCAT('DB','高斯'))::bytea + WHERE a=CONCAT('高斯','DB'); +SELECT * FROM t_charset_gbk ORDER BY id; +DROP TABLE IF EXISTS t_charset_gbk; + +-- test multi charset +CREATE TABLE t_diff_charset_columns( + futf8_bin varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_bin', + futf8_uni varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_unicode_ci', + futf8_gen varchar(16) CHARSET utf8mb4 COLLATE 'utf8mb4_general_ci', + fgbk_bin varchar(16) CHARSET gbk COLLATE 'gbk_bin', + fgbk_chi varchar(16) CHARSET gbk COLLATE 'gbk_chinese_ci', + fgb18030_bin varchar(16) CHARSET gb18030 COLLATE 'gb18030_bin', + fgb18030_chi varchar(16) CHARSET gb18030 COLLATE 'gb18030_chinese_ci', + fbytea bytea, + fblob blob, + fbit bit varying(64) +); +INSERT INTO t_diff_charset_columns(futf8_bin, futf8_uni, futf8_gen, fgbk_bin, fgbk_chi, fgb18030_bin, fgb18030_chi, fbytea, fblob, fbit) + VALUES('高斯DB', '高斯db', '高斯db', '高斯DB', '高斯db', '高斯DB', '高斯db', '高斯DB', 'E9AB98E696AF', B'111010011010101110011000111001101001011010101111'); +-- -- test character length +SELECT futf8_bin, + futf8_uni, + fgbk_bin, + fgbk_chi, + fgb18030_bin, + fgb18030_chi, + fbytea FROM t_diff_charset_columns; +SELECT length(futf8_bin), + length(futf8_uni), + length(fgbk_bin), + length(fgbk_chi), + length(fgb18030_bin), + length(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; -- 5 +SELECT lengthb(futf8_bin), + lengthb(futf8_uni), + lengthb(fgbk_bin), + lengthb(fgbk_chi), + lengthb(fgb18030_bin), + lengthb(fgb18030_chi), + length(fbytea) FROM t_diff_charset_columns; + +-- test prefixkey index +CREATE INDEX idx_prefixkey_futf8_bin on t_diff_charset_columns (futf8_bin(2) text_pattern_ops); +set enable_seqscan=off; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_futf8_bin) */ futf8_bin FROM t_diff_charset_columns WHERE futf8_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgbk_bin on t_diff_charset_columns (fgbk_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgbk_bin) */ fgbk_bin FROM t_diff_charset_columns WHERE fgbk_bin = '高斯DB'; +CREATE INDEX idx_prefixkey_fgb18030_bin on t_diff_charset_columns (fgb18030_bin(2) text_pattern_ops); +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin LIKE '高斯%'; +EXPLAIN (costs false) +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +SELECT /*+ indexscan(t_diff_charset_columns idx_prefixkey_fgb18030_bin) */ fgb18030_bin FROM t_diff_charset_columns WHERE fgb18030_bin = '高斯DB'; +reset enable_seqscan; + +DROP TABLE t_diff_charset_columns; + +\c regression \ No newline at end of file diff --git a/src/test/regress/sql/hw_datatype_set.sql b/src/test/regress/sql/hw_datatype_set.sql index fb47ee349..fc71a6e24 100644 --- a/src/test/regress/sql/hw_datatype_set.sql +++ b/src/test/regress/sql/hw_datatype_set.sql @@ -7,6 +7,7 @@ select find_in_set('a', 1); create database test dbcompatibility = 'B'; \c test +SET b_format_behavior_compat_options = 'enable_multi_charset'; drop table if exists tab; drop table if exists dual; @@ -732,4 +733,383 @@ insert into t2 values ('a,,b'); -- expect 2, not 0 insert into t2 values (',a,b'); -- expect 2, not 0 select c1, c1+0 from t2 order by 2; drop table t1; -drop table t2; \ No newline at end of file +drop table t2; + +-- test check duplicate set scenes +-- 1. column charset/collate +drop table if exists test_set_key1; +create table test_set_key1(a set('', ' ')); +create table test_set_key1(a set('', ' ') collate utf8_bin); +create table test_set_key1(a set('a', 'a ')); +create table test_set_key1(a set('a', 'a ') collate utf8_bin); +create table test_set_key1(a set('aaa', 'AAA ') collate utf8_general_ci); +create table test_set_key1(a set('高斯sS', '高斯ŠŠ ') collate utf8_general_ci); +create table test_set_key1(a set('aaa', 'aaA ') charset 'utf8'); +create table test_set_key1(a set('aaa', 'aaA ') charset 'gbk'); +create table test_set_key1(a set('aaa', 'aaA ') charset 'gb18030'); + +--succeed scenes +create table t_column_collation1(a set('a', 'b', 'A','B') collate utf8_bin); +create table t_column_collation2(a set('a', 'b', 'A','B') collate utf8_bin); +create table t_column_collation3(a set('aaa', 'bbb') charset 'utf8'); +create table t_column_collation4(a set('a', 'b', 'A','B') collate utf8_bin); +create table t_column_collation5(a set('高斯DB','1') character set utf8mb4 collate utf8mb4_general_ci default '高斯db'); +drop table t_column_collation1; +drop table t_column_collation2; +drop table t_column_collation3; +drop table t_column_collation4; +drop table t_column_collation5; + +-- 2. table charset/collate +create table test_set_key1(a set('aaa', 'aaA ')) charset 'utf8'; +create table test_set_key1(a set('aaa', 'aaA ')) collate 'utf8_general_ci'; +create table test_set_key1(a set('aaa', 'aaA ')) charset 'gbk'; +create table test_set_key1(a set('aaa', 'aaa ')) charset 'gbk' collate gbk_bin; +create table test_set_key1(a set('aaa', 'aaA ')) charset 'gb18030'; +create table test_set_key1(a set('aaa', 'aaa ')) charset 'gb18030' collate gb18030_bin; + +--succeed scenes +create table t_table_collation1(a set('aaa', 'bbb')) charset 'utf8'; +create table t_table_collation2(a set('aaa', 'aaA ') collate 'utf8_bin')charset 'utf8'; +drop table t_table_collation1; +drop table t_table_collation2; + +-- 3. schema charset/collate +create schema set_test_schema1 charset = utf8; +set current_schema='set_test_schema1'; + +create table t(a set('a', 'A')); --fail +create table t(a set('a', 'b')); -- succeed +alter table t add column b set('a', 'A', 'b'); -- fail +alter table t add column b set('a', 'A', 'b') collate utf8_bin; --succeed +insert into t values('a ', 'a '); +insert into t values('a ', 'A '); +insert into t values('B ', 'A '); +insert into t values('a ', 'B '); --fail +drop table t; + +create schema set_test_schema2 charset = utf8mb4 collate = utf8mb4_bin; +set current_schema='set_test_schema2'; +create table t(a set('a', 'A')); -- succeed +alter table t add column b set('a', 'A', 'b') collate utf8_general_ci; --fail +alter table t add column b set('a', 'A', 'b'); -- succeed +insert into t values ('a ', 'b '); +insert into t values ('a ', 'B '); -- fail +drop table t; + +drop schema set_test_schema1; +drop schema set_test_schema2; +\c test +SET b_format_behavior_compat_options = 'enable_multi_charset'; + +-- test insert value with collation +-- 1. insert value length ignore end space +create table test_set_len (col SET('ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd') collate utf8_bin); +insert into test_set_len values ('ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd '); +drop table test_set_len; + +-- 2. insert value while collate is binary + +-- 3. insert value while collate like _bin +create table test_collation2(a set('aaa', 'AAA','高斯SS', '高斯ss') collate utf8_bin); +insert into test_collation2 values('aaa '); +insert into test_collation2 values('aaa'); +insert into test_collation2 values('AAA'); +insert into test_collation2 values('AAA '); +insert into test_collation2 values('高斯ss '); +insert into test_collation2 values('高斯SS '); +insert into test_collation2 values('高斯sS '); --failed +insert into test_collation2 values('高斯ss,高斯ss '); + +-- 4. insert value while collate like _ci +create table test_collation3(a set('高斯sS', '汉字sS', 'aaa', 'bbb')) charset utf8; +select pg_get_tabledef('test_collation3'); + +insert into test_collation3 values('高斯sS '); +insert into test_collation3 values('高斯ss,高斯ss '); +insert into test_collation3 values('高斯ŠŠ'); +insert into test_collation3 values('汉字sS '); +insert into test_collation3 values('汉字ss,汉字ss '); +insert into test_collation3 values('汉字ŠŠ'); +insert into test_collation3 values('aaa '); +insert into test_collation3 values('aaa'); +insert into test_collation3 values('AAA '); + +-- test update with colalte +create table test_update(a set('a', 'A', 'b'))collate utf8_bin; +insert into test_update values('a'),('A'); +update test_update set a = 'b' where a = 'a'; +update test_update set a = 'b' where a = 'a' collate utf8_general_ci; +select * from test_update; +update test_update set a = 'a' where a = 'B' collate utf8_general_ci; +select * from test_update; +drop table test_update; + +-- test operator +create table test_collation_op(a set('a', 'A', 'b', 'B'), b set('a', 'A', 'b', 'B')) collate utf8_bin; +insert into test_collation_op values('a', 'A'),('A','a'),('b','B'),('B','b'); + +-- test '=' +select a from test_collation2 where a = 'aaa'; +select a from test_collation2 where a = '高斯ss' collate utf8_bin; +select a from test_collation2 where a = 'aaa' collate "utf8_general_ci"; -- set = text +select a from test_collation2 where a = '高斯ss' collate utf8_general_ci; + +select a from test_collation3 where a = '高斯ss'; +select a from test_collation3 where a = '高斯ss' collate utf8_bin; +select a from test_collation3 where a = 'aaa' collate "utf8_general_ci"; + +select a from test_collation2 where 'aaa' = a collate "utf8_general_ci"; -- text = set + +select + distinct t2.a, t3.a +from + test_collation2 as t2, + test_collation2 as t3 +where t2.a = t3.a collate "utf8_general_ci"; -- set = set + +select + distinct t2.a, t3.a +from + test_collation2 as t2, + test_collation2 as t3 +where t2.a = t3.a; + +-- '<>' +select a, b from test_collation_op where a <> b; -- set <> other set +select a, b from test_collation_op where a <> b collate 'utf8_general_ci'; +select a, b from test_collation_op where a <> 'a'; -- set <> text +select a, b from test_collation_op where a <> 'a' collate 'utf8_general_ci'; +select a, b from test_collation_op where 'a' <> a; +select a, b from test_collation_op where 'a' <> a collate 'utf8_general_ci'; -- text <> set + +-- '<' +select a, b from test_collation_op where a < b; -- set < other set +select a from test_collation_op where a < b collate 'utf8_general_ci'; +select a from test_collation_op where a < 'C'; -- set < text +select a from test_collation_op where a < 'C' collate 'utf8_general_ci'; +select a from test_collation_op where 'B' < a; +select a from test_collation_op where 'B' < a collate 'utf8_general_ci'; + +-- '<=' +select a, b from test_collation_op where a <= b; -- set <= other set +select a from test_collation_op where a <= b collate 'utf8_general_ci'; +select a from test_collation_op where a <= 'A'; -- set <= text +select a from test_collation_op where a <= 'A' collate 'utf8_general_ci'; +select a from test_collation_op where 'B' <= a; -- text <= set +select a from test_collation_op where 'B' <= a collate 'utf8_general_ci'; + +-- '>' +select a, b from test_collation_op where a > b; -- set > other set +select a from test_collation_op where a > b collate 'utf8_general_ci'; +select a from test_collation_op where a > 'B'; -- set > text +select a from test_collation_op where a > 'B' collate 'utf8_general_ci'; +select a from test_collation_op where 'C' > a; +select a from test_collation_op where 'C' > a collate 'utf8_general_ci'; + +-- '>=' +select a, b from test_collation_op where a >= b; -- set >= other set +select a from test_collation_op where a >= b collate 'utf8_general_ci'; +select a from test_collation_op where a >= 'B'; -- set >= text +select a from test_collation_op where a >= 'B' collate 'utf8_general_ci'; +select a from test_collation_op where 'C' >= a; +select a from test_collation_op where 'C' >= a collate 'utf8_general_ci'; + +-- test order by +select a from test_collation2 order by a; +select a from test_collation2 order by a collate 'utf8_general_ci'; +select a from test_collation2 order by a collate 'utf8_bin'; + +select a from test_collation3 order by a; +select a from test_collation3 order by a collate 'utf8_general_ci'; +select a from test_collation3 order by a collate 'utf8_bin'; + +-- test distinct +select distinct a from test_collation2; +select distinct a collate 'utf8_bin' from test_collation2; +select distinct a collate 'utf8_general_ci' from test_collation2; + +select distinct a from test_collation3; +select distinct a collate 'utf8_bin' from test_collation3; +select distinct a collate 'utf8_general_ci' from test_collation3; + +-- test like +select a from test_collation2 where a like 'aa%'; +select a from test_collation2 where a like 'aa%' collate 'utf8_general_ci'; + +select a from test_collation3 where a like 'aa%'; +select a from test_collation3 where a like 'aa%' collate 'utf8_general_ci'; + +-- test alter table modify/add +alter table test_collation3 modify a char(10) collate utf8_bin; +select a from test_collation3 where a = '高斯ss'; +select a from test_collation3 where a = '高斯sS' collate utf8_bin; +alter table test_collation3 modify a set('高斯sS', '汉字sS', 'aaa', 'bbb'); +select pg_get_tabledef('test_collation3'); +insert into test_collation3 values('高斯ŠŠ '); +alter table test_collation3 add b set('a','b', 'c'); +insert into test_collation3(b) values('A'), ('b '), (3); + +-- test unique/primary key +create table t_collation_set5(a set('aaa', 'bbb') collate utf8_general_ci unique); +insert into t_collation_set5 values('aaa'); +insert into t_collation_set5 values('aaa '); +insert into t_collation_set5 values('AAA '); + +create table t_collation_set6(a set('aaa', 'bbb') collate utf8_general_ci primary key); +insert into t_collation_set6 values('aaa '); +insert into t_collation_set6 values('aaa'); +insert into t_collation_set6 values('AAA '); + +drop table t_collation_set5; +drop table t_collation_set6; + +-- test join +create table test_join1( + c_char char(10), + c_varchar varchar(10), + c_nvarchar2 nvarchar2(10), + c_text text, + c_set set('a') +) collate utf8_bin; + +create table test_join2( + c_set set('A') +) collate utf8_bin; + +insert into test_join1 values('a ', 'a ', 'a ', 'a ','a '); +insert into test_join2 values('A'); + +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_char; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_char collate 'utf8_general_ci'; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_char; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_char collate 'utf8_general_ci'; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_char > t2.c_set; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_char > t2.c_set collate 'utf8_general_ci'; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_char; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_char collate 'utf8_general_ci'; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_char; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_char collate 'utf8_general_ci'; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_char; +select t1.c_char, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_char collate 'utf8_general_ci'; + +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_varchar; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_varchar collate 'utf8_general_ci'; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_varchar; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_varchar collate 'utf8_general_ci'; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_varchar > t2.c_set; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_varchar > t2.c_set collate 'utf8_general_ci'; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_varchar; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_varchar collate 'utf8_general_ci'; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_varchar; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_varchar collate 'utf8_general_ci'; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_varchar; +select t1.c_varchar, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_varchar collate 'utf8_general_ci'; + +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_nvarchar2; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_nvarchar2 collate 'utf8_general_ci'; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_nvarchar2; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_nvarchar2 collate 'utf8_general_ci'; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_nvarchar2 > t2.c_set; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_nvarchar2 > t2.c_set collate 'utf8_general_ci'; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_nvarchar2; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_nvarchar2 collate 'utf8_general_ci'; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_nvarchar2; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_nvarchar2 collate 'utf8_general_ci'; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_nvarchar2; +select t1.c_nvarchar2, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_nvarchar2 collate 'utf8_general_ci'; + +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_text; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_text collate 'utf8_general_ci'; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_text; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_text collate 'utf8_general_ci'; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_text > t2.c_set; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_text > t2.c_set collate 'utf8_general_ci'; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_text; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_text collate 'utf8_general_ci'; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_text; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_text collate 'utf8_general_ci'; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_text; +select t1.c_text, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_text collate 'utf8_general_ci'; + +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_set; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set = t1.c_set collate 'utf8_general_ci'; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_set; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <> t1.c_set collate 'utf8_general_ci'; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_set > t2.c_set; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t1.c_set > t2.c_set collate 'utf8_general_ci'; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_set; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set >= t1.c_set collate 'utf8_general_ci'; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_set; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set < t1.c_set collate 'utf8_general_ci'; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_set; +select t1.c_set, t2.c_set from test_join1 t1 join test_join2 t2 on t2.c_set <= t1.c_set collate 'utf8_general_ci'; + +drop table test_join1; +drop table test_join2; +-- test partition table with collate +create table test_part_tab1(c1 int, c2 set('a', 'b', 'A', 'B'))charset utf8 partition by range(c1) --fail +( + partition test_set_tab_p1 values less than (5), + partition test_set_tab_p2 values less than (10) +); + +create table test_part_tab1(c1 int, c2 set('a', 'b', 'A', 'B'))charset utf8 collate utf8_bin partition by range(c1) -- success +( + partition test_set_tab_p1 values less than (5), + partition test_set_tab_p2 values less than (10) +); +select pg_get_tabledef('test_part_tab1'); +insert into test_part_tab1 values(1, 'a '); +insert into test_part_tab1 values(6, 'A '); +insert into test_part_tab1 values(2, 'b '); +insert into test_part_tab1 values(7, 'B '); + +create table test_part_tab2(c1 int, c2 set('a', 'b', 'c', 'd'))charset utf8 partition by range(c1) -- success +( + partition test_set_tab_p1 values less than (5), + partition test_set_tab_p2 values less than (10) +); +insert into test_part_tab2 values(1, 'a '); +insert into test_part_tab2 values(6, 'A '); +insert into test_part_tab2 values(2, 'b '); +insert into test_part_tab2 values(7, 'B '); + +drop table test_part_tab1; +drop table test_part_tab2; + +-- test local/global temp table with collate +create local temp table test_temp_tab1 (c1 set('a', 'b')) charset utf8; +insert into test_temp_tab1 values('a '); +insert into test_temp_tab1 values('A '); + +create global temp table test_temp_tab2 (c1 set('a', 'b')) charset utf8 collate utf8_bin; +insert into test_temp_tab2 values('a '); +insert into test_temp_tab2 values('A '); --fail + +drop table test_temp_tab1; +drop table test_temp_tab2; +-- test ustore +create table test_ustore1( + c1 set('a', 'b', 'c', 'd'), + c2 set('a', 'b','A', 'B') collate 'gbk_bin' +) charset utf8 with (STORAGE_TYPE = ustore); + +select pg_get_tabledef('test_ustore1'); +insert into test_ustore1 values('a ', 'a '); +insert into test_ustore1 values('A ', 'A '); +select c2 from test_ustore1 where c2 = 'a'; +select c2 from test_ustore1 where c2 = 'a' collate 'utf8_general_ci'; +select c2 from test_ustore1 where c2 = c1; +drop table test_ustore1; + +-- test cstore(not supported) +create table test_cstore1(c1 set('a', 'b', 'c', 'd') collate 'utf8_bin') with (ORIENTATION = column); + +-- test check constraint with collate +create table test_check1(a set('a', 'b', 'c') check(a >= 'b'))charset utf8; +insert into test_check1 values('a'); +insert into test_check1 values('B '); +insert into test_check1 values('C'); +insert into test_check1 values('c'); +drop table test_check1; \ No newline at end of file diff --git a/src/test/regress/sql/test_b_format_collate.sql b/src/test/regress/sql/test_b_format_collate.sql index 2b95a7c1e..f9c6660a4 100644 --- a/src/test/regress/sql/test_b_format_collate.sql +++ b/src/test/regress/sql/test_b_format_collate.sql @@ -37,6 +37,8 @@ create table t1(a blob); -- test B format \c test_collate_B +SET b_format_behavior_compat_options = 'enable_multi_charset'; +SHOW b_format_behavior_compat_options; -- test create table/alter table drop table if exists t_collate; @@ -222,7 +224,7 @@ select tab1.f1, tab2.f1 from test_join1 as tab1, test_join2 as tab2 where tab1.f select tab1.f1, tab2.f1 from test_join1 as tab1, test_join2 as tab2 where tab1.f1 = tab2.f1 collate "C"; select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1 collate "utf8mb4_bin" select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1 collate "utf8mb4_general_ci"; -select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; --fail +select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; create table hashjoin1(id int, f1 text, f2 text) collate 'utf8mb4_bin'; create table hashjoin2(id int, f3 text, f4 text) collate 'utf8mb4_bin'; @@ -248,7 +250,7 @@ select tab1.f1, tab2.f1 from test_join1 as tab1, test_join2 as tab2 where tab1.f select tab1.f1, tab2.f1 from test_join1 as tab1, test_join2 as tab2 where tab1.f1 = tab2.f1 collate "C"; select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1 collate "utf8mb4_bin" select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1 collate "utf8mb4_general_ci"; -select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; --fail +select tab1.f1, tab3.f1 from test_join1 as tab1, test_join3 as tab3 where tab1.f1 = tab3.f1; -- test mergejoin set enable_hashjoin=off; @@ -279,7 +281,7 @@ insert into test_sep_option4 values ('S','S'); select * from test_sep_option1 union select * from test_sep_option2 order by f1; select * from test_sep_option3 union select * from test_sep_option4 order by f1; -select * from test_sep_option1 union select * from test_sep_option3; -- fail +select * from test_sep_option1 union select * from test_sep_option3 order by f1; -- test setop drop table if exists test_sep_option1; diff --git a/src/test/regress/sql/test_b_format_gb_collate.sql b/src/test/regress/sql/test_b_format_gb_collate.sql new file mode 100644 index 000000000..f52c4bf89 --- /dev/null +++ b/src/test/regress/sql/test_b_format_gb_collate.sql @@ -0,0 +1,240 @@ +create database b_utf8 dbcompatibility = 'b' encoding = 'utf8' LC_CTYPE = 'C' LC_COLLATE = 'C'; +\c b_utf8 +SET b_format_behavior_compat_options = 'enable_multi_charset'; +select 'Å SÅ›s' collate "gbk_chinese_ci"; +select _gbk'中文ŠSÅ›s' collate "gbk_chinese_ci"; +select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; +select 'Aaa' = 'aAA' collate gbk_chinese_ci; + +select 'Å SÅ›s' collate "gbk_bin"; +select _gbk'中文ŠSÅ›s' collate "gbk_bin"; +select _utf8'中文ŠSÅ›s' collate "gbk_bin"; +select 'Aaa' = 'aAA' collate gbk_bin; + +select 'Å SÅ›s' collate "gb18030_chinese_ci"; +select _gb18030'中文ŠSÅ›s' collate "gb18030_chinese_ci"; +select _utf8'中文ŠSÅ›s' collate "gb18030_chinese_ci"; +select 'Aaa' = 'aAA' collate gb18030_chinese_ci; + +select 'Å SÅ›s' collate "gb18030_bin"; +select _gbk'中文ŠSÅ›s' collate "gb18030_bin"; +select _utf8'中文ŠSÅ›s' collate "gb18030_bin"; +select 'Aaa' = 'aAA' collate gb18030_bin; + +-- set names gbk; +-- select 'Å SÅ›s' collate "gbk_chinese_ci"; +-- select _gbk'中文ŠSÅ›s' collate "gbk_chinese_ci"; +-- select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; + +create database b_gbk dbcompatibility = 'b' encoding = 'gbk' LC_CTYPE = 'C' LC_COLLATE = 'C'; +\c b_gbk +SET b_format_behavior_compat_options = 'enable_multi_charset'; +select _gbk'中文ŠSÅ›s' collate "gbk_chinese_ci"; +select _utf8'中文ŠSÅ›s' collate "gbk_chinese_ci"; +select 'Å SÅ›s' collate "gbk_chinese_ci"; -- fail +select 'Aaa' = 'aAA' collate gbk_chinese_ci; +select 'a' = 'A ' collate gbk_chinese_ci; +select 'a' collate gbk_chinese_ci = 'A '; +select 'y' = '~' collate gbk_chinese_ci; +select 'y中文' = 'Y中文' collate gbk_chinese_ci; +select 'A' > '中文汉字' collate "gbk_chinese_ci"; +select '中文汉字AA' > '中文汉字' collate "gbk_chinese_ci"; +select '中文汉字AA' = '中文汉字aa' collate "gbk_chinese_ci"; +select '中文' < '高斯' collate gbk_chinese_ci; +select '中文' collate gbk_bin > '高斯' collate gbk_chinese_ci; +select '中文' collate gbk_bin > '高斯' collate gbk_chinese_ci; + +drop table if exists t1; +create table t1(c1 text character set 'gbk' collate 'gbk_chinese_ci', c2 text collate 'gbk_bin', c3 text) charset utf8; +select pg_get_tabledef('t1'); +insert into t1 values('中文ab','中文ab','中文ab'),('中文Ab ','中文Ab ','中文Ab '),('中文','中文','中文'),('中文 ','中文 ','中文 '),(null, null, null); + +--test gbk_chinese_ci +select c1 from t1 where c1 = '中文'; +select c1 from t1 where c1 = '中文ab'; +select c1 from t1 where c1 = '中文ab' collate 'gbk_bin'; +select c1 from t1 where c1 = '中文ab' collate 'utf8mb4_bin'; +select c1 from t1 where c1 in ('中文ab' collate 'utf8_bin'); + +select c1 from t1 order by c1; +select distinct c1 from t1 order by c1; +select distinct c1 from t1 order by c1; +select count(c1), c1 from t1 group by c1 order by c1; + +-- like ,ilike +select c1 from t1 where c1 like '中文A_%' order by c1; +select c1 from t1 where c1 like '%a%' order by c1; +select c1 from t1 where c1 like '中文__'; +select distinct c1 from t1 where c1 like '中文A_%'; + +-- test gbk_bin +select c2 from t1 where c2 = '中文'; +select c2 from t1 where c2 = '中文ab'; +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; + +select c2 from t1 order by c2; +select distinct c2 from t1; +select distinct c2 from t1 order by c2; +select count(c2), c2 from t1 group by c2; +select count(c2), c2 from t1 group by c2 order by c2; + +select c2 from t1 where c2 like '中文A_%'; +select c2 from t1 where c2 like '%a%'; +select c2 from t1 where c2 like '中文__'; +select distinct c2 from t1 where c2 like '中文A_%'; + +--test char(n) +alter table t1 modify c1 char(20) collate gbk_chinese_ci; +alter table t1 modify c2 char(20) collate gbk_bin; +select pg_get_tabledef('t1'); + +select c1 from t1 where c1 = '中文'; +select c1 from t1 where c1 = '中文ab'; + +select c1 from t1 order by c1; +select distinct c1 from t1; +select distinct c1 from t1 order by c1; +select count(c1), c1 from t1 group by c1; +select count(c1), c1 from t1 group by c1 order by c1; + +select c1 from t1 where c1 like '中文A_%' order by c1; +select c1 from t1 where c1 like '%a%' order by c1; +select c1 from t1 where c1 like '中文__'; +select distinct c1 from t1 where c1 like '中文A_%'; + +-- test gbk_bin +select c2 from t1 where c2 = '中文'; +select c2 from t1 where c2 = '中文ab'; +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; + +select c2 from t1 order by c2; +select distinct c2 from t1; +select distinct c2 from t1 order by c2; +select count(c2), c2 from t1 group by c2; +select count(c2), c2 from t1 group by c2 order by c2; + +select c2 from t1 where c2 like '中文A_%'; +select c2 from t1 where c2 like '%a%'; +select c2 from t1 where c2 like '中文__'; +select distinct c2 from t1 where c2 like '中文A_%'; + +-- create table as/like +create table t2 as select * from t1; +select pg_get_tabledef('t2'); +create table t3 (like t1); +select pg_get_tabledef('t3'); +create table t4(c1 text character set 'utf8' collate 'gbk_chinese_ci'); --fail + + + + + + + + +-- test gb18030 collate !!! +create database b_gb18030 dbcompatibility = 'b' encoding = 'gb18030' LC_CTYPE = 'C' LC_COLLATE = 'C'; +\c b_gb18030 +SET b_format_behavior_compat_options = 'enable_multi_charset'; +select _gb18030'中文ŠSÅ›s' collate "gb18030_chinese_ci"; +select _utf8'中文ŠSÅ›s' collate "gb18030_chinese_ci"; +select 'Å SÅ›s' collate "gb18030_chinese_ci"; -- fail +select 'Aaa' = 'aAA' collate gb18030_chinese_ci; +select 'a' = 'A ' collate gb18030_chinese_ci; +select 'a' collate gb18030_chinese_ci = 'A '; +select 'y' = '~' collate gb18030_chinese_ci; +select 'y中文' = 'Y中文' collate gb18030_chinese_ci; +select 'A' > '中文汉字' collate "gb18030_chinese_ci"; +select '中文汉字AA' > '中文汉字' collate "gb18030_chinese_ci"; +select '中文汉字AA' = '中文汉字aa' collate "gb18030_chinese_ci"; +select '中文' < '高斯' collate gb18030_chinese_ci; +select '中文' collate gb18030_bin > '高斯' collate gb18030_chinese_ci; +select '中文' collate gb18030_bin > '高斯' collate gb18030_chinese_ci; + +drop table if exists t1; +create table t1(c1 text character set 'gb18030' collate 'gb18030_chinese_ci', c2 text collate 'gb18030_bin', c3 text) charset utf8; +select pg_get_tabledef('t1'); +insert into t1 values('中文ab','中文ab','中文ab'),('中文Ab ','中文Ab ','中文Ab '),('中文','中文','中文'),('中文 ','中文 ','中文 '),(null, null, null); + +--test gb18030_chinese_ci +select c1 from t1 where c1 = '中文'; +select c1 from t1 where c1 = '中文ab'; +select c1 from t1 where c1 = '中文ab' collate 'gb18030_bin'; +select c1 from t1 where c1 = '中文ab' collate 'utf8mb4_bin'; +select c1 from t1 where c1 in ('中文ab' collate 'utf8_bin'); + +select c1 from t1 order by c1; +select distinct c1 from t1; +select distinct c1 from t1 order by c1; +select count(c1), c1 from t1 group by c1; +select count(c1), c1 from t1 group by c1 order by c1; + +select c1 from t1 where c1 like '中文A_%' order by c1; +select c1 from t1 where c1 like '%a%' order by c1; +select c1 from t1 where c1 like '中文__'; +select distinct c1 from t1 where c1 like '中文A_%'; + +-- test gb18030_bin +select c2 from t1 where c2 = '中文'; +select c2 from t1 where c2 = '中文ab'; +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; + +select c2 from t1 order by c2; +select distinct c2 from t1; +select distinct c2 from t1 order by c2; +select count(c2), c2 from t1 group by c2; +select count(c2), c2 from t1 group by c2 order by c2; + +select c2 from t1 where c2 like '中文A_%'; +select c2 from t1 where c2 like '%a%'; +select c2 from t1 where c2 like '中文__'; +select distinct c2 from t1 where c2 like '中文A_%'; + +--test char(n) +alter table t1 modify c1 char(20) collate gb18030_chinese_ci; +alter table t1 modify c2 char(20) collate gb18030_bin; +select pg_get_tabledef('t1'); + +select c1 from t1 where c1 = '中文'; +select c1 from t1 where c1 = '中文ab'; + +select c1 from t1 order by c1; +select distinct c1 from t1 order by c1; +select distinct c1 from t1 order by c1; +select count(c1), c1 from t1 group by c1 order by c1; + +select c1 from t1 where c1 like '中文A_%' order by c1; +select c1 from t1 where c1 like '%a%' order by c1; +select c1 from t1 where c1 like '中文__'; +select distinct c1 from t1 where c1 like '中文A_%'; + +-- test gbk_bin +select c2 from t1 where c2 = '中文'; +select c2 from t1 where c2 = '中文ab'; +select c2 from t1 where c2 = '中文ab' collate 'utf8mb4_bin'; + +select c2 from t1 order by c2; +select distinct c2 from t1; +select distinct c2 from t1 order by c2; +select count(c2), c2 from t1 group by c2; +select count(c2), c2 from t1 group by c2 order by c2; + +select c2 from t1 where c2 like '中文A_%'; +select c2 from t1 where c2 like '%a%'; +select c2 from t1 where c2 like '中文__'; +select distinct c2 from t1 where c2 like '中文A_%'; + +-- create table as/like +create table t2 as select * from t1; +select pg_get_tabledef('t2'); +create table t3 (like t1); +select pg_get_tabledef('t3'); +create table t4(c1 text character set 'utf8' collate 'gb18030_chinese_ci'); --fail + +\c regression +clean connection to all force for database b_utf8; +clean connection to all force for database b_gbk; +clean connection to all force for database b_gb18030; +DROP DATABASE IF EXISTS b_utf8; +DROP DATABASE IF EXISTS b_gbk; +DROP DATABASE IF EXISTS b_gb18030; \ No newline at end of file