From 19ceba332606b413907bdc9ba5358512ea62d57d Mon Sep 17 00:00:00 2001 From: wuyuechuan Date: Mon, 10 Aug 2020 09:23:51 +0800 Subject: [PATCH] pg compatibility support --- src/bin/initdb/initdb.cpp | 9 ++-- src/common/backend/parser/analyze.cpp | 10 ++--- src/common/backend/parser/gram.y | 29 ++----------- src/common/backend/parser/hint_gram.y | 2 +- src/common/backend/parser/parse_coerce.cpp | 4 +- src/common/backend/parser/parse_func.cpp | 6 +-- src/common/backend/parser/parse_merge.cpp | 2 +- src/common/backend/parser/parse_type.cpp | 2 +- src/common/backend/utils/adt/a_compat.cpp | 20 ++++----- src/common/backend/utils/adt/format_type.cpp | 2 +- src/common/backend/utils/adt/formatting.cpp | 2 +- src/common/backend/utils/adt/int8.cpp | 6 +-- src/common/backend/utils/adt/numeric.cpp | 6 +-- src/common/backend/utils/adt/numutils.cpp | 27 ++++++------ src/common/backend/utils/adt/regexp.cpp | 6 +-- src/common/backend/utils/adt/varchar.cpp | 2 +- src/common/backend/utils/adt/varlena.cpp | 43 +++++++++---------- src/common/backend/utils/misc/guc.cpp | 10 +++-- src/gausskernel/optimizer/commands/copy.cpp | 2 +- .../optimizer/rewrite/rewriteHandler.cpp | 2 +- src/gausskernel/process/tcop/postgres.cpp | 35 ++++++++++++--- .../codegen/codegenutil/varlenacodegen.cpp | 23 ++++++---- .../codegen/vecexecutor/vecexprcodegen.cpp | 6 +-- src/gausskernel/runtime/executor/opfusion.cpp | 2 +- .../vecexecutor/vecprimitive/varchar.inl | 2 +- .../storage/access/dfs/common_reader.cpp | 2 +- .../storage/access/dfs/dfs_query.cpp | 2 +- .../storage/access/dfs/orc/orc_reader.cpp | 10 ++--- .../storage/access/dfs/orc/orc_rw.h | 6 +-- .../dfs/parquet/parquet_column_reader.cpp | 20 ++++----- .../knl/knl_guc/knl_session_attr_sql.h | 2 +- src/include/miscadmin.h | 9 ++-- src/include/postgres.h | 11 ++++- .../regress/expected/pg_compatibility.out | 31 +++++++++++++ src/test/regress/parallel_schedule | 3 +- src/test/regress/sql/pg_compatibility.sql | 16 +++++++ 36 files changed, 219 insertions(+), 153 deletions(-) create mode 100644 src/test/regress/expected/pg_compatibility.out create mode 100644 src/test/regress/sql/pg_compatibility.sql diff --git a/src/bin/initdb/initdb.cpp b/src/bin/initdb/initdb.cpp index 55ea5c1759..0396de9c83 100644 --- a/src/bin/initdb/initdb.cpp +++ b/src/bin/initdb/initdb.cpp @@ -1370,13 +1370,14 @@ static void bootstrap_template1(void) * If we do not assign compatibility, A is default. * Invalid input is avoided. */ - if (pg_strcasecmp(dbcompatibility, DBCOMPATIBILITY_A) == 0 || - pg_strcasecmp(dbcompatibility, DBCOMPATIBILITY_C) == 0 || - pg_strcasecmp(dbcompatibility, DBCOMPATIBILITY_B) == 0) { + if (pg_strcasecmp(dbcompatibility, DB_CMPT_OPT_A) == 0 || + pg_strcasecmp(dbcompatibility, DB_CMPT_OPT_C) == 0 || + pg_strcasecmp(dbcompatibility, DB_CMPT_OPT_B) == 0 || + pg_strcasecmp(dbcompatibility, DB_CMPT_OPT_PG) == 0) { bki_lines = replace_token(bki_lines, "DB_COMPATIBILITY", dbcompatibility); } else if (strlen(dbcompatibility) == 0) { /* If we do not specify database compatibility, set A defaultly */ - bki_lines = replace_token(bki_lines, "DB_COMPATIBILITY", DBCOMPATIBILITY_A); + bki_lines = replace_token(bki_lines, "DB_COMPATIBILITY", DB_CMPT_OPT_A); } else { write_stderr(_("dbcompatibility \"%s\" is invalid\n"), dbcompatibility); exit_nicely(); diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index efa5a80a12..f2d6ac26b6 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -192,7 +192,7 @@ Query* parse_sub_analyze(Node* parseTree, ParseState* parentParseState, CommonTa pstate->p_parent_cte = parentCTE; pstate->p_locked_from_parent = locked_from_parent; pstate->p_resolve_unknowns = resolve_unknowns; - if (u_sess->attr.attr_sql.td_compatible_truncation && u_sess->attr.attr_sql.sql_compatibility == C_FORMAT) + if (u_sess->attr.attr_sql.td_compatible_truncation && DB_IS_CMPT(DB_CMPT_C)) set_subquery_is_under_insert(pstate); /* Set p_is_in_insert for parse state. */ query = transformStmt(pstate, parseTree); @@ -1222,7 +1222,7 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt) * If td_compatible_truncation equal true and no foreign table found, * the auto truncation funciton should be enabled. */ - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && pstate->p_target_relation != NULL && + if (DB_IS_CMPT(DB_CMPT_C) && pstate->p_target_relation != NULL && !RelationIsForeignTable(pstate->p_target_relation)) { if (u_sess->attr.attr_sql.td_compatible_truncation) { pstate->p_is_td_compatible_truncation = true; @@ -1297,7 +1297,7 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt) * If td_compatible_truncation equal true and no foreign table found, * the auto truncation funciton should be enabled. */ - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && pstate->p_target_relation != NULL && + if (DB_IS_CMPT(DB_CMPT_C) && pstate->p_target_relation != NULL && !RelationIsForeignTable(pstate->p_target_relation)) { if (u_sess->attr.attr_sql.td_compatible_truncation) { pstate->p_is_td_compatible_truncation = true; @@ -1399,7 +1399,7 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt) * If td_compatible_truncation equal true and no foreign table found, * the auto truncation funciton should be enabled. */ - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && pstate->p_target_relation != NULL && + if (DB_IS_CMPT(DB_CMPT_C) && pstate->p_target_relation != NULL && !RelationIsForeignTable(pstate->p_target_relation)) { if (u_sess->attr.attr_sql.td_compatible_truncation) { pstate->p_is_td_compatible_truncation = true; @@ -1738,7 +1738,7 @@ static Query* transformSelectStmt(ParseState* pstate, SelectStmt* stmt, bool isF * If query is under one insert statement and include a foreign table, * then set top level parsestate p_is_foreignTbl_exist to true. */ - if (u_sess->attr.attr_sql.td_compatible_truncation && u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && + if (u_sess->attr.attr_sql.td_compatible_truncation && DB_IS_CMPT(DB_CMPT_C) && pstate->p_is_in_insert && checkForeignTableExist(pstate->p_rtable)) set_ancestor_ps_contain_foreigntbl(pstate); diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index d8e86397df..653930a3f0 100755 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -185,7 +185,6 @@ static void check_outarg_info(const bool *have_assigend, const char *argmodes,const int proargnum); bool IsValidIdent(char *input); bool IsValidGroupname(const char *input); -static bool checkCompArgs(const char *compFormat); static bool checkNlssortArgs(const char *argname); static void ParseUpdateMultiSet(List *set_target_list, SelectStmt *stmt, core_yyscan_t yyscanner); @@ -11277,7 +11276,7 @@ createdb_opt_item: } | DBCOMPATIBILITY_P opt_equal Sconst { - if (checkCompArgs($3) == false) + if (CheckCompArgs($3) == false) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -14891,7 +14890,7 @@ ConstDatetime: } | DATE_P { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { $$ = SystemTypeName("timestamp"); $$->typmods = list_make1(makeIntConst(0,-1)); @@ -16223,7 +16222,7 @@ func_expr_common_subexpr: } | TIMESTAMPDIFF '(' timestamp_arg_list ')' { - if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) + if (DB_IS_CMPT(DB_CMPT_B)) { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("timestamp_diff"); @@ -18248,7 +18247,7 @@ makeStringConst(char *str, int location) A_Const *n = makeNode(A_Const); - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { if (NULL == str || 0 == strlen(str)) { @@ -19492,26 +19491,6 @@ IsValidGroupname(const char *input) return true; } -/* - * check whether sql_compatibility is valid - * sql_compatibility has 3 values: A, B, C. - */ -static bool -checkCompArgs(const char *compFormat) -{ - /* make sure input is not null */ - if (compFormat == NULL) - { - return false; - } - if (pg_strncasecmp(compFormat, "A", sizeof("A")) != 0 && pg_strncasecmp(compFormat, "B", sizeof("B")) != 0 && - pg_strncasecmp(compFormat, "C", sizeof("C")) != 0) - { - return false; - } - return true; -} - static bool checkNlssortArgs(const char *argname) { diff --git a/src/common/backend/parser/hint_gram.y b/src/common/backend/parser/hint_gram.y index 4de930d41a..e619f2c6df 100755 --- a/src/common/backend/parser/hint_gram.y +++ b/src/common/backend/parser/hint_gram.y @@ -404,7 +404,7 @@ makeStringValue(char *str) { Value *val = makeNode(Value); - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { if (NULL == str || 0 == strlen(str)) { diff --git a/src/common/backend/parser/parse_coerce.cpp b/src/common/backend/parser/parse_coerce.cpp index 0bc06c9b5d..631719c634 100755 --- a/src/common/backend/parser/parse_coerce.cpp +++ b/src/common/backend/parser/parse_coerce.cpp @@ -1050,7 +1050,7 @@ int parser_coercion_errposition(ParseState* pstate, int coerce_location, Node* i } /* choose_specific_expr_type - * Choose case when and coalesce return value type in C_FORMAT. + * Choose case when and coalesce return value type in DB_FMT_C. */ static Oid choose_specific_expr_type(ParseState* pstate, List* exprs, const char* context) { @@ -1327,7 +1327,7 @@ Oid select_common_type(ParseState* pstate, List* exprs, const char* context, Nod } } - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && context != NULL && + if (DB_IS_CMPT(DB_CMPT_C) && context != NULL && (0 == strncmp(context, "CASE", sizeof("CASE")) || 0 == strncmp(context, "COALESCE", sizeof("COALESCE")))) { /* To TD format, we need handle numeric and string mix situation*/ ptype = choose_specific_expr_type(pstate, exprs, context); diff --git a/src/common/backend/parser/parse_func.cpp b/src/common/backend/parser/parse_func.cpp index b7c4972a68..fc3c25f21e 100755 --- a/src/common/backend/parser/parse_func.cpp +++ b/src/common/backend/parser/parse_func.cpp @@ -506,8 +506,8 @@ Node* ParseFuncOrColumn(ParseState* pstate, List* funcname, List* fargs, FuncCal funcexpr->refSynOid = refSynOid; retval = (Node*)funcexpr; - /* Return type of to_date function will be changed from timestamp to date type in C_FORMAT */ - if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT && + /* Return type of to_date function will be changed from timestamp to date type in DB_CMPT_C */ + if (DB_IS_CMPT(DB_CMPT_B | DB_CMPT_C) && (funcid == TODATEFUNCOID || funcid == TODATEDEFAULTFUNCOID)) { FuncExpr* timestamp_date_fun = makeNode(FuncExpr); @@ -1082,7 +1082,7 @@ FuncCandidateList func_select_candidate(int nargs, Oid* input_typeids, FuncCandi * so we should also admit highest type conversion for operations * between different type categories */ - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && !different_category && + if (DB_IS_CMPT(DB_CMPT_C) && !different_category && slot_category[i] != TYPCATEGORY_UNKNOWN) { if (current_category == TYPCATEGORY_INVALID) { current_category = slot_category[i]; diff --git a/src/common/backend/parser/parse_merge.cpp b/src/common/backend/parser/parse_merge.cpp index 076a938487..bc054149b3 100644 --- a/src/common/backend/parser/parse_merge.cpp +++ b/src/common/backend/parser/parse_merge.cpp @@ -1087,7 +1087,7 @@ Query* transformMergeStmt(ParseState* pstate, MergeStmt* stmt) * If td_compatible_truncation equal true and no foreign table found, * the auto truncation funciton should be enabled. */ - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && pstate->p_target_relation != NULL && + if (DB_IS_CMPT(DB_CMPT_C) && pstate->p_target_relation != NULL && !RelationIsForeignTable(pstate->p_target_relation)) { if (u_sess->attr.attr_sql.td_compatible_truncation) { pstate->p_is_td_compatible_truncation = true; diff --git a/src/common/backend/parser/parse_type.cpp b/src/common/backend/parser/parse_type.cpp index a74549d40d..478eaa0b20 100755 --- a/src/common/backend/parser/parse_type.cpp +++ b/src/common/backend/parser/parse_type.cpp @@ -804,7 +804,7 @@ bool IsTypeSupportedByORCRelation(_in_ Oid typeOid) TIMETZOID, SMALLDATETIMEOID, CASHOID}; - if (DATEOID == typeOid && C_FORMAT == u_sess->attr.attr_sql.sql_compatibility) { + if (typeOid == DATEOID && DB_IS_CMPT(DB_CMPT_C)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_HDFS), diff --git a/src/common/backend/utils/adt/a_compat.cpp b/src/common/backend/utils/adt/a_compat.cpp index 20f429e1b4..c9a835d04c 100644 --- a/src/common/backend/utils/adt/a_compat.cpp +++ b/src/common/backend/utils/adt/a_compat.cpp @@ -203,7 +203,7 @@ Datum lpad(PG_FUNCTION_ARGS) SET_VARSIZE(ret, ptr_ret - (char*)ret); - if (VARSIZE_ANY_EXHDR(ret) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if (VARSIZE_ANY_EXHDR(ret) == 0 && DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -309,7 +309,7 @@ Datum rpad(PG_FUNCTION_ARGS) SET_VARSIZE(ret, ptr_ret - (char*)ret); - if (VARSIZE_ANY_EXHDR(ret) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if (VARSIZE_ANY_EXHDR(ret) == 0 && DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -337,7 +337,7 @@ Datum btrim(PG_FUNCTION_ARGS) text* ret = NULL; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), true, true); - if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -355,7 +355,7 @@ Datum btrim1(PG_FUNCTION_ARGS) text* ret = NULL; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, true, true); - if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -601,7 +601,7 @@ Datum ltrim(PG_FUNCTION_ARGS) text* ret = NULL; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), true, false); - if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -619,7 +619,7 @@ Datum ltrim1(PG_FUNCTION_ARGS) text* ret = NULL; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, true, false); - if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -647,7 +647,7 @@ Datum rtrim(PG_FUNCTION_ARGS) text* ret = NULL; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), false, true); - if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -665,7 +665,7 @@ Datum rtrim1(PG_FUNCTION_ARGS) text* ret = NULL; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, false, true); - if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((ret == NULL || VARSIZE_ANY_EXHDR(ret) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret); @@ -778,7 +778,7 @@ Datum translate(PG_FUNCTION_ARGS) m -= source_len; } - if (retlen == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (retlen == 0 && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { SET_VARSIZE(result, retlen + VARHDRSZ); @@ -991,7 +991,7 @@ Datum repeat(PG_FUNCTION_ARGS) tlen -= slen; } - if (VARSIZE_ANY_EXHDR(result) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if (VARSIZE_ANY_EXHDR(result) == 0 && DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { PG_RETURN_NULL(); } else PG_RETURN_TEXT_P(result); diff --git a/src/common/backend/utils/adt/format_type.cpp b/src/common/backend/utils/adt/format_type.cpp index 70265027f3..78da1e8486 100755 --- a/src/common/backend/utils/adt/format_type.cpp +++ b/src/common/backend/utils/adt/format_type.cpp @@ -458,7 +458,7 @@ Datum oidvectortypes(PG_FUNCTION_ARGS) left -= slen; } - if ((!strcmp(result, "")) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if ((!strcmp(result, "")) && DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { pfree_ext(result); PG_RETURN_NULL(); } diff --git a/src/common/backend/utils/adt/formatting.cpp b/src/common/backend/utils/adt/formatting.cpp index c895b5435c..6839791cfa 100755 --- a/src/common/backend/utils/adt/formatting.cpp +++ b/src/common/backend/utils/adt/formatting.cpp @@ -6265,7 +6265,7 @@ static char* NUM_processor(FormatNode* node, NUMDesc* Num, char* inout, char* nu } } if (!CORRECT_TO_NUMBER) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && *Np->inout_p != ',') { + if (DB_IS_CMPT(DB_CMPT_A) && *Np->inout_p != ',') { ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), errmsg("invalid data."))); } } else if (*Np->inout_p != ',') { diff --git a/src/common/backend/utils/adt/int8.cpp b/src/common/backend/utils/adt/int8.cpp index b30747ded9..98ace28515 100755 --- a/src/common/backend/utils/adt/int8.cpp +++ b/src/common/backend/utils/adt/int8.cpp @@ -76,13 +76,13 @@ bool scanint8(const char* str, bool errorOK, int64* result) if (errorOK) { return false; } - else if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + else if (DB_IS_CMPT(DB_CMPT_A | DB_CMPT_PG)) { ereport(ERROR, (errmodule(MOD_FUNCTION), errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s: \"%s\"", "bigint", str))); } - else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + else if (DB_IS_CMPT(DB_CMPT_B)) { *result = tmp; return true; } @@ -112,7 +112,7 @@ bool scanint8(const char* str, bool errorOK, int64* result) return false; } else { - /* Empty string will be treated as NULL if sql_compatibility == A_FORMAT, + /* Empty string will be treated as NULL if sql_compatibility == DB_CMPT_A, Other wise whitespace will be convert to 0 */ ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), diff --git a/src/common/backend/utils/adt/numeric.cpp b/src/common/backend/utils/adt/numeric.cpp index d876379003..7c4ed3cb86 100644 --- a/src/common/backend/utils/adt/numeric.cpp +++ b/src/common/backend/utils/adt/numeric.cpp @@ -264,8 +264,8 @@ Datum numeric_in(PG_FUNCTION_ARGS) cp++; } - /* the first parameter is null, we should convert to 0 if u_sess->attr.attr_sql.sql_compatibility == C_FORMAT */ - if (u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && *cp == '\0') { + /* the first parameter is null, we should convert to 0 if u_sess->attr.attr_sql.sql_compatibility is DB_CMPT_C */ + if (DB_IS_CMPT(DB_CMPT_C) && *cp == '\0') { NumericVar value; init_var(&value); @@ -3949,7 +3949,7 @@ static const char* set_var_from_str(const char* str, const char* cp, NumericVar* cp++; } - if (!isdigit((unsigned char)*cp) && u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + if (!isdigit((unsigned char)*cp) && DB_IS_CMPT(DB_CMPT_B)) { char* cp = (char*)palloc0(sizeof(char)); return cp; } diff --git a/src/common/backend/utils/adt/numutils.cpp b/src/common/backend/utils/adt/numutils.cpp index f9533abe46..5f98e2a7ea 100755 --- a/src/common/backend/utils/adt/numutils.cpp +++ b/src/common/backend/utils/adt/numutils.cpp @@ -47,14 +47,14 @@ int32 pg_atoi(char* s, int size, int c) if (s == NULL) { ereport(ERROR, (errmodule(MOD_FUNCTION), errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("NULL pointer"))); } - if ((*s == 0) && (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT)) { + if ((*s == 0) && DB_IS_CMPT(DB_CMPT_A | DB_CMPT_PG)) { ereport(ERROR, (errmodule(MOD_FUNCTION), errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", s))); } /* In b compatibility, empty str is treated as 0 */ - if ((*s == 0) && (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT)) { + if ((*s == 0) && DB_IS_CMPT(DB_CMPT_B)) { long l = 0; return (int32)l; } @@ -64,16 +64,15 @@ int32 pg_atoi(char* s, int size, int c) /* We made no progress parsing the string, so bail out */ if (s == badp) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A | DB_CMPT_PG)) { ereport(ERROR, (errmodule(MOD_FUNCTION), errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", s))); } /* string is treated as 0 in b compatibility */ - if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { - long l = 0; - return (int32)l; + if (DB_IS_CMPT(DB_CMPT_B)) { + return (int32)0; } } @@ -116,7 +115,7 @@ int32 pg_atoi(char* s, int size, int c) badp++; } - if (*badp && *badp != c && u_sess->attr.attr_sql.sql_compatibility != B_FORMAT) { + if (*badp && *badp != c && !DB_IS_CMPT(DB_CMPT_B)) { ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", s))); } @@ -155,10 +154,10 @@ int16 pg_strtoint16(const char* s) /* require at least one digit */ if (unlikely(!isdigit((unsigned char)*ptr))) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A | DB_CMPT_PG)) { goto invalid_syntax; - } - if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + } + if (DB_IS_CMPT(DB_CMPT_B)) { return tmp; } } @@ -176,7 +175,7 @@ int16 pg_strtoint16(const char* s) ptr++; } - if (unlikely(*ptr != '\0') && u_sess->attr.attr_sql.sql_compatibility != B_FORMAT) { + if (unlikely(*ptr != '\0') && !DB_IS_CMPT(DB_CMPT_B)) { goto invalid_syntax; } @@ -231,10 +230,10 @@ int32 pg_strtoint32(const char* s) /* require at least one digit */ if (unlikely(!isdigit((unsigned char)*ptr))) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A | DB_CMPT_PG)) { goto invalid_syntax; } - else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + else if (DB_IS_CMPT(DB_CMPT_B)) { return tmp; } } @@ -252,7 +251,7 @@ int32 pg_strtoint32(const char* s) ptr++; } - if (unlikely(*ptr != '\0') && u_sess->attr.attr_sql.sql_compatibility != B_FORMAT) { + if (unlikely(*ptr != '\0') && !DB_IS_CMPT(DB_CMPT_B)) { goto invalid_syntax; } if (!neg) { diff --git a/src/common/backend/utils/adt/regexp.cpp b/src/common/backend/utils/adt/regexp.cpp index 74c11f8ee7..3756bc06e4 100755 --- a/src/common/backend/utils/adt/regexp.cpp +++ b/src/common/backend/utils/adt/regexp.cpp @@ -531,7 +531,7 @@ Datum textregexreplace_noopt(PG_FUNCTION_ARGS) re = RE_compile_and_cache(p, REG_ADVANCED, PG_GET_COLLATION()); result = replace_text_regexp(s, (void*)re, r, false); - if (VARHDRSZ == VARSIZE(result) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A) && VARHDRSZ == VARSIZE(result)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(result); @@ -577,7 +577,7 @@ Datum textregexreplace(PG_FUNCTION_ARGS) re = RE_compile_and_cache(p, flags.cflags, PG_GET_COLLATION()); result = replace_text_regexp(s, (void*)re, r, flags.glob); - if (VARHDRSZ == VARSIZE(result) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A) && VARHDRSZ == VARSIZE(result)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(result); @@ -941,7 +941,7 @@ static ArrayType* build_regexp_matches_result(regexp_matches_ctx* matchctx) /* return value datatype must be text */ #define RESET_NULL_FLAG(_result) \ do { \ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { \ + if (DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { \ if ((_result) == ((Datum)0)) { \ fcinfo->isnull = true; \ } else { \ diff --git a/src/common/backend/utils/adt/varchar.cpp b/src/common/backend/utils/adt/varchar.cpp index b3298d0bbb..6cb9f0dae0 100755 --- a/src/common/backend/utils/adt/varchar.cpp +++ b/src/common/backend/utils/adt/varchar.cpp @@ -1482,7 +1482,7 @@ static void vlpad_internal(ScalarVector* parg1, ScalarVector* parg2, ScalarVecto SET_VARSIZE(ret, ptr_ret - (char*)ret); - if (VARSIZE_ANY_EXHDR(ret) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if (VARSIZE_ANY_EXHDR(ret) == 0 && DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { SET_NULL(pflags_res[idx]); } else { vec_ret->m_vals[idx] = PointerGetDatum(ret); diff --git a/src/common/backend/utils/adt/varlena.cpp b/src/common/backend/utils/adt/varlena.cpp index 495dd96e4c..d54efabe04 100644 --- a/src/common/backend/utils/adt/varlena.cpp +++ b/src/common/backend/utils/adt/varlena.cpp @@ -2944,8 +2944,7 @@ Datum bytea_substr_orclcompat(PG_FUNCTION_ARGS) total = toast_raw_datum_size(str) - VARHDRSZ; if ((length < 0) || (start > total) || (start + total < 0)) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT || - u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A | DB_CMPT_B)) { PG_RETURN_NULL(); } else { result = PG_STR_GET_BYTEA(""); @@ -2958,7 +2957,7 @@ Datum bytea_substr_orclcompat(PG_FUNCTION_ARGS) */ result = bytea_substring_orclcompat(str, start, length, false); - if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_BYTEA_P(result); @@ -2977,7 +2976,7 @@ Datum bytea_substr_no_len_orclcompat(PG_FUNCTION_ARGS) total = toast_raw_datum_size(str) - VARHDRSZ; if ((start > total) || (start + total < 0)) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { result = PG_STR_GET_BYTEA(""); @@ -2990,7 +2989,7 @@ Datum bytea_substr_no_len_orclcompat(PG_FUNCTION_ARGS) */ result = bytea_substring_orclcompat(str, start, -1, true); - if (( result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (( result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_BYTEA_P(result); @@ -4020,7 +4019,7 @@ Datum replace_text(PG_FUNCTION_ARGS) ret_text = cstring_to_text_with_len(str.data, str.len); pfree_ext(str.data); - if (VARHDRSZ == VARSIZE(ret_text) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (VARHDRSZ == VARSIZE(ret_text) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(ret_text); @@ -4307,7 +4306,7 @@ Datum split_text(PG_FUNCTION_ARGS) /* return empty string for empty input string */ if (inputstring_len < 1) { text_position_cleanup(&state); - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if (DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { PG_RETURN_NULL(); } PG_RETURN_TEXT_P(cstring_to_text("")); @@ -4321,7 +4320,7 @@ Datum split_text(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(inputstring); } - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !RETURN_NS) { + if (DB_IS_CMPT(DB_CMPT_A) && !RETURN_NS) { PG_RETURN_NULL(); } @@ -4340,7 +4339,7 @@ Datum split_text(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(inputstring); } - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } @@ -4368,7 +4367,7 @@ Datum split_text(PG_FUNCTION_ARGS) result_text = text_substring(PointerGetDatum(inputstring), start_posn, end_posn - start_posn, false); } - if (TEXTISORANULL(result_text) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (TEXTISORANULL(result_text) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } @@ -4566,7 +4565,7 @@ Datum array_to_text(PG_FUNCTION_ARGS) result = array_to_text_internal(fcinfo, v, fldsep, NULL); /* To a, empty string need return NULL. */ - if (VARSIZE_ANY_EXHDR(result) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (VARSIZE_ANY_EXHDR(result) == 0 && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(result); @@ -4603,7 +4602,7 @@ Datum array_to_text_null(PG_FUNCTION_ARGS) result = array_to_text_internal(fcinfo, v, fldsep, null_string); /* To a db, empty string need return NULL. */ - if (VARSIZE_ANY_EXHDR(result) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (VARSIZE_ANY_EXHDR(result) == 0 && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(result); @@ -5700,7 +5699,7 @@ static text* concat_internal(const char* sepstr, int seplen, int argidx, Functio } getTypeOutputInfo(val_type, &typ_output, &typ_is_varlena); appendStringInfoString(&str, OidOutputFunctionCall(typ_output, value)); - } else if (PG_ARGISNULL(i) && u_sess->attr.attr_sql.sql_compatibility == B_FORMAT && !is_concat_ws) { + } else if (PG_ARGISNULL(i) && DB_IS_CMPT(DB_CMPT_B) && !is_concat_ws) { pfree_ext(str.data); fcinfo->isnull = true; return NULL; @@ -5711,8 +5710,8 @@ static text* concat_internal(const char* sepstr, int seplen, int argidx, Functio pfree_ext(str.data); if ((result == NULL || - (VARSIZE_ANY_EXHDR(result) == 0 && u_sess->attr.attr_sql.sql_compatibility != B_FORMAT)) && - (CONCAT_VARIADIC || u_sess->attr.attr_sql.sql_compatibility == A_FORMAT)) { + (VARSIZE_ANY_EXHDR(result) == 0 && !DB_IS_CMPT(DB_CMPT_B | DB_CMPT_PG))) && + (CONCAT_VARIADIC || DB_IS_CMPT(DB_CMPT_A))) { fcinfo->isnull = true; return NULL; } else { @@ -5776,7 +5775,7 @@ Datum text_left(PG_FUNCTION_ARGS) } rlen = pg_mbcharcliplen(p, len, part_off); - if (rlen == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (rlen == 0 && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(cstring_to_text_with_len(p, rlen)); @@ -5809,7 +5808,7 @@ Datum text_right(PG_FUNCTION_ARGS) } } off = pg_mbcharcliplen(p, len, part_off); - if ((len - off) == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((len - off) == 0 && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(cstring_to_text_with_len(p + off, len - off)); @@ -6106,7 +6105,7 @@ Datum text_format(PG_FUNCTION_ARGS) result = cstring_to_text_with_len(str.data, str.len); pfree_ext(str.data); - if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { PG_RETURN_TEXT_P(result); @@ -6479,7 +6478,7 @@ Datum substrb_with_lenth(PG_FUNCTION_ARGS) int32 total = 0; total = toast_raw_datum_size(str) - VARHDRSZ; if ((length < 0) || (total == 0) || (start > total) || (start + total < 0)) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { result = cstring_to_text(""); @@ -6488,7 +6487,7 @@ Datum substrb_with_lenth(PG_FUNCTION_ARGS) } result = get_substring_really(str, start, length, false); - if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } PG_RETURN_TEXT_P(result); @@ -6504,7 +6503,7 @@ Datum substrb_without_lenth(PG_FUNCTION_ARGS) int32 total = 0; total = toast_raw_datum_size(str) - VARHDRSZ; if ((total == 0) || (start > total) || (start + total < 0)) { - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } else { result = cstring_to_text(""); @@ -6513,7 +6512,7 @@ Datum substrb_without_lenth(PG_FUNCTION_ARGS) } result = get_substring_really(str, start, -1, true); - if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if ((result == NULL || VARSIZE_ANY_EXHDR(result) == 0) && DB_IS_CMPT(DB_CMPT_A)) { PG_RETURN_NULL(); } PG_RETURN_TEXT_P(result); diff --git a/src/common/backend/utils/misc/guc.cpp b/src/common/backend/utils/misc/guc.cpp index 95af67d25f..8d0b19d6ab 100644 --- a/src/common/backend/utils/misc/guc.cpp +++ b/src/common/backend/utils/misc/guc.cpp @@ -788,9 +788,11 @@ static const struct config_enum_entry xmloption_options[] = { {"content", XMLOPTION_CONTENT, false}, {"document", XMLOPTION_DOCUMENT, false}, {NULL, 0, false}}; /* change the char * sql_compatibility to enum */ -static const struct config_enum_entry adapt_database[] = {{DBCOMPATIBILITY_A, A_FORMAT, false}, - {DBCOMPATIBILITY_B, B_FORMAT, false}, - {DBCOMPATIBILITY_C, C_FORMAT, false}, +static const struct config_enum_entry adapt_database[] = { + {DB_CMPT_OPT_A, DB_CMPT_A, false}, + {DB_CMPT_OPT_B, DB_CMPT_B, false}, + {DB_CMPT_OPT_C, DB_CMPT_C, false}, + {DB_CMPT_OPT_PG, DB_CMPT_PG, false}, {NULL, 0, false}}; /* change the char * enable_performance_data to enum */ @@ -11426,7 +11428,7 @@ static void init_configure_names_enum() GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE }, &u_sess->attr.attr_sql.sql_compatibility, - A_FORMAT, + DB_CMPT_A, adapt_database, NULL, NULL, diff --git a/src/gausskernel/optimizer/commands/copy.cpp b/src/gausskernel/optimizer/commands/copy.cpp index 261a4bff53..f05ddc7571 100644 --- a/src/gausskernel/optimizer/commands/copy.cpp +++ b/src/gausskernel/optimizer/commands/copy.cpp @@ -5250,7 +5250,7 @@ bool NextCopyFrom(CopyState cstate, ExprContext* econtext, Datum* values, bool* * 1. A db SQL compatibility requires; or * 2. This column donesn't accept any empty string. */ - if ((u_sess->attr.attr_sql.sql_compatibility == A_FORMAT || !accept_empty_str[m]) && + if ((DB_IS_CMPT(DB_CMPT_A) || !accept_empty_str[m]) && (string != NULL && string[0] == '\0')) { /* for any type, '' = null */ string = NULL; diff --git a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp index 0f6615e241..3b0ab1d1b4 100644 --- a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp +++ b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp @@ -950,7 +950,7 @@ Node* build_column_default(Relation rel, int attrno, bool isInsertCmd) * value to isExplicte args to true, to let bpchar know one explict cast has been added to * this default value already. */ - if (u_sess->attr.attr_sql.td_compatible_truncation && u_sess->attr.attr_sql.sql_compatibility == C_FORMAT && + if (u_sess->attr.attr_sql.td_compatible_truncation && DB_IS_CMPT(DB_CMPT_C) && isInsertCmd && (atttype == BPCHAROID || atttype == VARCHAROID) && expr != NULL) { AssertEreport(IsA(expr, FuncExpr), MOD_OPT, ""); diff --git a/src/gausskernel/process/tcop/postgres.cpp b/src/gausskernel/process/tcop/postgres.cpp index b5f166f158..72150d6c9a 100755 --- a/src/gausskernel/process/tcop/postgres.cpp +++ b/src/gausskernel/process/tcop/postgres.cpp @@ -3384,10 +3384,11 @@ static int getSingleNodeIdx(StringInfo input_message, CachedPlanSource* psrc, co plength = pq_getmsgint(input_message, 4); isNull = (plength == -1); /* add null value process for date type */ - if ((VARCHAROID == ptype || TIMESTAMPOID == ptype || TIMESTAMPTZOID == ptype || TIMEOID == ptype || - TIMETZOID == ptype || INTERVALOID == ptype || SMALLDATETIMEOID == ptype) && - 0 == plength && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (plength == 0 && DB_IS_CMPT(DB_CMPT_A) && + (VARCHAROID == ptype || TIMESTAMPOID == ptype || TIMESTAMPTZOID == ptype || TIMEOID == ptype || + TIMETZOID == ptype || INTERVALOID == ptype || SMALLDATETIMEOID == ptype)) { isNull = true; + } /* * Insert into bind values support illegal characters import, @@ -4063,7 +4064,7 @@ static void exec_bind_message(StringInfo input_message) /* add null value process for date type */ if ((VARCHAROID == ptype || TIMESTAMPOID == ptype || TIMESTAMPTZOID == ptype || TIMEOID == ptype || TIMETZOID == ptype || INTERVALOID == ptype || SMALLDATETIMEOID == ptype) && - 0 == plength && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + 0 == plength && DB_IS_CMPT(DB_CMPT_A)) isNull = true; /* @@ -10338,9 +10339,10 @@ static void exec_batch_bind_execute(StringInfo input_message) isNull = (plength == -1); /* add null value process for date type */ if ((VARCHAROID == ptype || TIMESTAMPOID == ptype || TIMESTAMPTZOID == ptype || TIMEOID == ptype || - TIMETZOID == ptype || INTERVALOID == ptype || SMALLDATETIMEOID == ptype) && - 0 == plength && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + TIMETZOID == ptype || INTERVALOID == ptype || SMALLDATETIMEOID == ptype) && + plength == 0 && DB_IS_CMPT(DB_CMPT_A)) { isNull = true; + } /* * Insert into bind values support illegal characters import, @@ -10789,3 +10791,24 @@ OM_ONLINE_STATE get_om_online_state() return OM_ONLINE_NODE_REPLACE; } } + +/* + * check whether sql_compatibility is valid + * sql_compatibility has 4 values: A, B, C, PG + */ +bool CheckCompArgs(const char *cmptFmt) +{ + /* make sure input is not null */ + if (cmptFmt == NULL) { + return false; + } + + if (pg_strcasecmp(cmptFmt, DB_CMPT_OPT_A) == 0 || + pg_strcasecmp(cmptFmt, DB_CMPT_OPT_B) == 0 || + pg_strcasecmp(cmptFmt, DB_CMPT_OPT_C) == 0 || + pg_strcasecmp(cmptFmt, DB_CMPT_OPT_PG) == 0) { + return true; + } + + return false; +} diff --git a/src/gausskernel/runtime/codegen/codegenutil/varlenacodegen.cpp b/src/gausskernel/runtime/codegen/codegenutil/varlenacodegen.cpp index 67a524a507..987107254c 100755 --- a/src/gausskernel/runtime/codegen/codegenutil/varlenacodegen.cpp +++ b/src/gausskernel/runtime/codegen/codegenutil/varlenacodegen.cpp @@ -452,8 +452,9 @@ llvm::Function* substr_codegen() * in case of a db compatible format we have to prepare a flag to indicate whether * result string is NULL, so we add one more parameter. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { fn_prototype.addArgument(GsCodeGen::NamedVariable("isNull", int8PtrType)); + } llvm::Function* jitted_substr = fn_prototype.generatePrototype(&builder, &llvmargs[0]); @@ -461,8 +462,9 @@ llvm::Function* substr_codegen() start = llvmargs[1]; len = llvmargs[2]; - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { isNull = llvmargs[3]; + } /* * Convert the first arg to {i32, i8*} type to get the length and the real value. @@ -499,7 +501,7 @@ llvm::Function* substr_codegen() *in case of ORC, we should set isNull to True if res_len == 0; *otherwise, just return the result. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { DEFINE_BLOCK(be_null, jitted_substr); DEFINE_BLOCK(bnot_null, jitted_substr); DEFINE_BLOCK(ret_bb, jitted_substr); @@ -570,14 +572,16 @@ llvm::Function* rtrim1_codegen() * in case of a db compatible format we have to prepare a flag to indicate whether * result string is NULL, so we add one more parameter. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { fn_prototype.addArgument(GsCodeGen::NamedVariable("isNull", int8PtrType)); + } llvm::Function* jitted_rtrim1 = fn_prototype.generatePrototype(&builder, &llvmargs[0]); argval = llvmargs[0]; - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { isNull = llvmargs[1]; + } /* load rtrim1 ir function from module */ llvm::Function* func_rtrim1_cc = llvmCodeGen->module()->getFunction("LLVMIRrtrim1"); @@ -601,7 +605,7 @@ llvm::Function* rtrim1_codegen() *in case of ORC, we should set isNull to True if res_len == 0; *otherwise, just return the result. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { DEFINE_BLOCK(be_null, jitted_rtrim1); DEFINE_BLOCK(bnot_null, jitted_rtrim1); DEFINE_BLOCK(ret_bb, jitted_rtrim1); @@ -673,12 +677,13 @@ llvm::Function* btrim1_codegen() * in case of a compatible format we have to prepare a flag to indicate whether * result string is NULL, so we add one more parameter. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) { fn_prototype.addArgument(GsCodeGen::NamedVariable("isNull", int8PtrType)); + } llvm::Function* jitted_btrim1 = fn_prototype.generatePrototype(&builder, &llvmargs[0]); argval = llvmargs[0]; - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if (DB_IS_CMPT(DB_CMPT_A)) isNull = llvmargs[1]; /* load rtrim1 ir function from IR file*/ @@ -703,7 +708,7 @@ llvm::Function* btrim1_codegen() *in case of ORC, we should set isNull to True if res_len == 0; *otherwise, just return the result. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { DEFINE_BLOCK(be_null, jitted_btrim1); DEFINE_BLOCK(bnot_null, jitted_btrim1); DEFINE_BLOCK(ret_bb, jitted_btrim1); diff --git a/src/gausskernel/runtime/codegen/vecexecutor/vecexprcodegen.cpp b/src/gausskernel/runtime/codegen/vecexecutor/vecexprcodegen.cpp index 367c642181..3af29310d3 100755 --- a/src/gausskernel/runtime/codegen/vecexecutor/vecexprcodegen.cpp +++ b/src/gausskernel/runtime/codegen/vecexecutor/vecexprcodegen.cpp @@ -2869,7 +2869,7 @@ llvm::Value* VecExprCodeGen::FuncCodeGen(ExprCodeGenArgs* args) * then we have to set 'isNull' flag to True, * and then jump to the be_null block. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { res1 = inner_builder.CreateCall(func_substr, {inargs[0], inargs[1], inargs[2], isNull}); llvm::Value* res_flag = inner_builder.CreateAlignedLoad(isNull, 1, "resflag"); llvm::Value* cmp = inner_builder.CreateICmpEQ(res_flag, null_true, "check"); @@ -2892,7 +2892,7 @@ llvm::Value* VecExprCodeGen::FuncCodeGen(ExprCodeGenArgs* args) * then we have to set 'isNull' flag to True, * and then jump to the be_null block. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { res1 = inner_builder.CreateCall(func_rtrim1, {inargs[0], isNull}); llvm::Value* res_flag = inner_builder.CreateAlignedLoad(isNull, 1, "resflag"); llvm::Value* cmp = inner_builder.CreateICmpEQ(res_flag, null_true, "check"); @@ -2914,7 +2914,7 @@ llvm::Value* VecExprCodeGen::FuncCodeGen(ExprCodeGenArgs* args) * then we have to set 'isNull' flag to True, * and then jump to the be_null block. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + if (DB_IS_CMPT(DB_CMPT_A)) { res1 = inner_builder.CreateCall(func_btrim1, {inargs[0], isNull}); llvm::Value* res_flag = inner_builder.CreateAlignedLoad(isNull, 1, "resflag"); llvm::Value* cmp = inner_builder.CreateICmpEQ(res_flag, null_true, "check"); diff --git a/src/gausskernel/runtime/executor/opfusion.cpp b/src/gausskernel/runtime/executor/opfusion.cpp index db67067220..a53f4d6b55 100644 --- a/src/gausskernel/runtime/executor/opfusion.cpp +++ b/src/gausskernel/runtime/executor/opfusion.cpp @@ -453,7 +453,7 @@ void OpFusion::updatePreAllocParamter(StringInfo input_message) /* add null value process for date type */ if ((VARCHAROID == ptype || TIMESTAMPOID == ptype || TIMESTAMPTZOID == ptype || TIMEOID == ptype || TIMETZOID == ptype || INTERVALOID == ptype || SMALLDATETIMEOID == ptype) && - plength == 0 && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) { + plength == 0 && DB_IS_CMPT(DB_CMPT_A)) { isNull = true; } diff --git a/src/gausskernel/runtime/vecexecutor/vecprimitive/varchar.inl b/src/gausskernel/runtime/vecexecutor/vecprimitive/varchar.inl index 0af25e32b2..1f894fce9c 100755 --- a/src/gausskernel/runtime/vecexecutor/vecprimitive/varchar.inl +++ b/src/gausskernel/runtime/vecexecutor/vecprimitive/varchar.inl @@ -321,7 +321,7 @@ inline static Datum null_return(bool *is_null) { text *result = NULL; - if(u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) + if(DB_IS_CMPT(DB_CMPT_A)) { *is_null = true; return (Datum)0; diff --git a/src/gausskernel/storage/access/dfs/common_reader.cpp b/src/gausskernel/storage/access/dfs/common_reader.cpp index 3198355f77..81ab419ce1 100644 --- a/src/gausskernel/storage/access/dfs/common_reader.cpp +++ b/src/gausskernel/storage/access/dfs/common_reader.cpp @@ -433,7 +433,7 @@ void CommonReader::parserFields(char **raw_fields, int fields) * 1. A db SQL compatibility requires; or * 2. This column donesn't accept any empty string. */ - if ((u_sess->attr.attr_sql.sql_compatibility == A_FORMAT || !m_accept_empty_str[i]) && + if ((DB_IS_CMPT(DB_CMPT_A) || !m_accept_empty_str[i]) && (field_str != NULL && field_str[0] == '\0')) { /* for any type, '' = null */ field_str = NULL; diff --git a/src/gausskernel/storage/access/dfs/dfs_query.cpp b/src/gausskernel/storage/access/dfs/dfs_query.cpp index dddfe8bc29..3f13ae0528 100755 --- a/src/gausskernel/storage/access/dfs/dfs_query.cpp +++ b/src/gausskernel/storage/access/dfs/dfs_query.cpp @@ -2452,7 +2452,7 @@ void OrcCheckDataType(TypeName *typName, char *ColName, char *fileType) } } - if (DATEOID == TypeOid && C_FORMAT == u_sess->attr.attr_sql.sql_compatibility) { + if (DATEOID == TypeOid && DB_IS_CMPT(DB_CMPT_C)) { ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_DATA_TYPE), errmsg("Date type is unsupported for hdfs table in TD-format database."))); } diff --git a/src/gausskernel/storage/access/dfs/orc/orc_reader.cpp b/src/gausskernel/storage/access/dfs/orc/orc_reader.cpp index 58b442d253..3ffd699db1 100755 --- a/src/gausskernel/storage/access/dfs/orc/orc_reader.cpp +++ b/src/gausskernel/storage/access/dfs/orc/orc_reader.cpp @@ -2011,7 +2011,7 @@ void OrcColumnReaderImpl::predicateFilter(uint64_t numValues, bool *i char lastChar = '\0'; char *tmpValue = data[i]; int64_t length = lengths[i]; - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && 0 == length) { + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { tmpValue = NULL; } else { lastChar = tmpValue[length]; @@ -2259,8 +2259,8 @@ void OrcColumnReaderImpl::fillScalarVectorInternal(uint64_t numValues } else { int64_t length = lengths[i]; - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (A_FORMAT == u_sess->attr.attr_sql.sql_compatibility && 0 == length) { + /* Check compatibility and convert '' into null if the db is DB_CMPT_A. */ + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { vec->SetNull(offset); } else { char *tmpValue = values[i]; @@ -2371,8 +2371,8 @@ void OrcColumnReaderImpl::fillScalarVectorInternal(uint64_t numVal } else { int64_t length = lengths[i]; - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (A_FORMAT == u_sess->attr.attr_sql.sql_compatibility && 0 == length) { + /* Check compatibility and convert '' into null if the db is DB_CMPT_A. */ + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { vec->SetNull(offset); } else { char *tmpValue = values[i]; diff --git a/src/gausskernel/storage/access/dfs/orc/orc_rw.h b/src/gausskernel/storage/access/dfs/orc/orc_rw.h index 9d149e0b1e..7f85e95403 100755 --- a/src/gausskernel/storage/access/dfs/orc/orc_rw.h +++ b/src/gausskernel/storage/access/dfs/orc/orc_rw.h @@ -221,7 +221,7 @@ Datum convertToDatumT(orc::ColumnVectorBatch *primitiveBatch, uint64 rowId, int3 int64_t length = static_cast(primitiveBatch)->length[rowId]; /* Check compatibility and convert '' into null if the db is ORA_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + if (DB_IS_CMPT(DB_CMPT_A) && length == 0) { isNull = true; break; } @@ -251,7 +251,7 @@ Datum convertToDatumT(orc::ColumnVectorBatch *primitiveBatch, uint64 rowId, int3 int64_t length = static_cast(primitiveBatch)->length[rowId]; /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + if (DB_IS_CMPT(DB_CMPT_A) && length == 0) { isNull = true; break; } @@ -281,7 +281,7 @@ Datum convertToDatumT(orc::ColumnVectorBatch *primitiveBatch, uint64 rowId, int3 int64_t length = static_cast(primitiveBatch)->length[rowId]; /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + if (DB_IS_CMPT(DB_CMPT_A) && length == 0) { isNull = true; break; } diff --git a/src/gausskernel/storage/access/dfs/parquet/parquet_column_reader.cpp b/src/gausskernel/storage/access/dfs/parquet/parquet_column_reader.cpp index 146bced0fb..b1d74889f3 100644 --- a/src/gausskernel/storage/access/dfs/parquet/parquet_column_reader.cpp +++ b/src/gausskernel/storage/access/dfs/parquet/parquet_column_reader.cpp @@ -169,8 +169,8 @@ Datum convertToDatumT(void *primitiveBatch, uint64 rowId, parquet::Type::type ph char *tmpValue = (char *)baValue.ptr; int64_t length = static_cast(baValue.len); - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + /* Check compatibility and convert '' into null if the db is DB_FMT_A. */ + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { isNull = true; break; } @@ -1092,8 +1092,8 @@ void ParquetColumnReaderImpl::fillScalarVectorInternalForChar(uint64 auto value = m_values[i]; auto length = (int32_t)value.len; - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + /* Check compatibility and convert '' into null if the db is DB_CMPT_A. */ + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { vec->SetNull(offset); } else { char *tmpValue = (char *)value.ptr; @@ -1200,8 +1200,8 @@ void ParquetColumnReaderImpl::fillScalarVectorInternalForVarchar( auto value = m_values[i]; auto length = (int32_t)value.len; - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + /* Check compatibility and convert '' into null if the db is DB_CMPT_A. */ + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { vec->SetNull(offset); } else { char *tmpValue = (char *)value.ptr; @@ -1455,8 +1455,8 @@ void ParquetColumnReaderImpl::predicateFilter(uint64_t numValues, bo char *tmpValue = (char *)baValue.ptr; int64_t length = static_cast(baValue.len); - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + /* Check compatibility and convert '' into null if the db is DB_CMPT_A. */ + if (length == 0 && DB_IS_CMPT(DB_CMPT_A)) { tmpValue = NULL; } @@ -1491,8 +1491,8 @@ void ParquetColumnReaderImpl::predicateFilter(uint64_t numValues, bo int64_t length = static_cast(baValue.len); char lastChar = '\0'; - /* Check compatibility and convert '' into null if the db is A_FORMAT. */ - if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && length == 0) { + /* Check compatibility and convert '' into null if the db is DB_CMPT_A. */ + if (DB_IS_CMPT(DB_CMPT_A) && length == 0) { tmpValue = NULL; } else { lastChar = tmpValue[length]; diff --git a/src/include/knl/knl_guc/knl_session_attr_sql.h b/src/include/knl/knl_guc/knl_session_attr_sql.h index 1fdc498a74..e3c7a2102d 100644 --- a/src/include/knl/knl_guc/knl_session_attr_sql.h +++ b/src/include/knl/knl_guc/knl_session_attr_sql.h @@ -178,7 +178,7 @@ typedef struct knl_session_attr_sql { int backslash_quote; int constraint_exclusion; int rewrite_rule; - int sql_compatibility; + int sql_compatibility; /* reference to DB_Compatibility */ int guc_explain_perf_mode; int skew_strategy_store; int codegen_strategy; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 13f435d4fe..3ca70ddc20 100755 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -66,9 +66,12 @@ extern const uint32 GRAND_VERSION_NUM; #define MEGRE_UPDATE_MULTI (u_sess->utils_cxt.behavior_compat_flags & OPT_MEGRE_UPDATE_MULTI) #define CONVERT_STRING_DIGIT_TO_NUMERIC (u_sess->utils_cxt.behavior_compat_flags & OPT_CONVERT_TO_NUMERIC) -#define DBCOMPATIBILITY_A "A" -#define DBCOMPATIBILITY_B "B" -#define DBCOMPATIBILITY_C "C" +#define DB_CMPT_OPT_A "A" +#define DB_CMPT_OPT_B "B" +#define DB_CMPT_OPT_C "C" +#define DB_CMPT_OPT_PG "PG" + +extern bool CheckCompArgs(const char *cmptFmt); /* in tcop/postgres.c */ extern void ProcessInterrupts(void); diff --git a/src/include/postgres.h b/src/include/postgres.h index 40ddaab0a1..df68c0f1e1 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -130,6 +130,7 @@ typedef enum { OM_ONLINE_EXPANSION, OM_ONLINE_NODE_REPLACE } OM_ONLINE_STATE; extern void reload_configfile(void); extern void reload_online_pooler(void); extern OM_ONLINE_STATE get_om_online_state(void); +extern bool CheckCompArgs(const char *cmptFmt); /* ---------------------------------------------------------------- * Section 1: variable-length datatypes (TOAST support) @@ -220,7 +221,15 @@ typedef struct { } varattrib_1b_e; /* Type of database; increase for sql compatibility */ -typedef enum { A_FORMAT, B_FORMAT, C_FORMAT } DatabaseType; +typedef enum { + DB_CMPT_A = 0x0001, + DB_CMPT_B = 0x0002, + DB_CMPT_C = 0x0004, + DB_CMPT_PG = 0x0008 /* be compatible with Postgre SQL syntax */ +} DB_Compatibility; + +#define IS_CMPT(cmpt, flag) (((uint32)cmpt & (uint32)(flag)) != 0) +#define DB_IS_CMPT(flag) IS_CMPT(u_sess->attr.attr_sql.sql_compatibility, (flag)) typedef enum { EXPLAIN_NORMAL, EXPLAIN_PRETTY, EXPLAIN_SUMMARY, EXPLAIN_RUN } ExplainStyle; diff --git a/src/test/regress/expected/pg_compatibility.out b/src/test/regress/expected/pg_compatibility.out new file mode 100644 index 0000000000..1dba798d55 --- /dev/null +++ b/src/test/regress/expected/pg_compatibility.out @@ -0,0 +1,31 @@ +-- pg compatibility case +drop database if exists pg_type_databse; +NOTICE: database "pg_type_databse" does not exist, skipping +create database pg_type_databse dbcompatibility 'PG'; + +\c pg_type_databse +create table d_format_test(a varchar(10) not null); +insert into d_format_test values(''); + + + +-- concat test +select concat(null,'','','') is null; + ?column? +---------- + f +(1 row) + + +select concat('','') is null; + ?column? +---------- + f +(1 row) + + +select ''::int; +ERROR: invalid input syntax for integer: "" +LINE 1: select ''::int; + ^ +CONTEXT: referenced column: int4 \ No newline at end of file diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index fbcec5ab4a..55404c2684 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -580,5 +580,4 @@ test: gtt_clean # procedure, Function Test -test: create_procedure -test: create_function +test: create_procedure create_function pg_compatibility \ No newline at end of file diff --git a/src/test/regress/sql/pg_compatibility.sql b/src/test/regress/sql/pg_compatibility.sql new file mode 100644 index 0000000000..3db2d3bb2d --- /dev/null +++ b/src/test/regress/sql/pg_compatibility.sql @@ -0,0 +1,16 @@ +-- pg compatibility case +drop database if exists pg_type_databse; +create database pg_type_databse dbcompatibility 'PG'; + +\c pg_type_databse +create table d_format_test(a varchar(10) not null); +insert into d_format_test values(''); + + + +-- concat test +select concat(null,'','','') is null; + +select concat('','') is null; + +select ''::int; \ No newline at end of file -- Gitee