diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index a3b113785..b90803a29 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -4885,6 +4885,9 @@ static Query* _copyQuery(const Query* from) COPY_SCALAR_FIELD(isReplace); } COPY_NODE_FIELD(indexhintList); + if (t_thrd.proc->workingVersionNum >= SELECT_STMT_HAS_USERVAR) { + COPY_SCALAR_FIELD(has_uservar); + } newnode->rightRefState = CopyRightRefState(from->rightRefState); diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 5a8ee2bd5..c36f2e84a 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -983,6 +983,10 @@ static bool _equalQuery(const Query* a, const Query* b) } COMPARE_NODE_FIELD(indexhintList); + if (t_thrd.proc->workingVersionNum >= SELECT_STMT_HAS_USERVAR) { + COMPARE_SCALAR_FIELD(has_uservar); + } + return true; } diff --git a/src/common/backend/nodes/outfuncs.cpp b/src/common/backend/nodes/outfuncs.cpp index da6077f2f..9d40ea3bd 100755 --- a/src/common/backend/nodes/outfuncs.cpp +++ b/src/common/backend/nodes/outfuncs.cpp @@ -4933,6 +4933,9 @@ static void _outQuery(StringInfo str, Query* node) if (t_thrd.proc->workingVersionNum >= INDEX_HINT_VERSION_NUM) { WRITE_NODE_FIELD(indexhintList); } + if (t_thrd.proc->workingVersionNum >= SELECT_STMT_HAS_USERVAR) { + WRITE_BOOL_FIELD(has_uservar); + } } static void _outWithCheckOption(StringInfo str, const WithCheckOption* node) diff --git a/src/common/backend/nodes/readfuncs.cpp b/src/common/backend/nodes/readfuncs.cpp index 017851ae4..ad1bf3192 100755 --- a/src/common/backend/nodes/readfuncs.cpp +++ b/src/common/backend/nodes/readfuncs.cpp @@ -1655,6 +1655,10 @@ static Query* _readQuery(void) IF_EXIST(indexhintList) { READ_NODE_FIELD(indexhintList); } + IF_EXIST(has_uservar) + { + READ_BOOL_FIELD(has_uservar); + } READ_DONE(); } diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index a0d6df209..9c21f9cdf 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -691,6 +691,7 @@ Query* transformStmt(ParseState* pstate, Node* parseTree, bool isFirstNode, bool /* Mark as original query until we learn differently */ result->querySource = QSRC_ORIGINAL; result->canSetTag = true; + result->has_uservar = pstate->has_uservar; /* Mark whether synonym object is in rtables or not. */ result->hasSynonyms = pstate->p_hasSynonyms; diff --git a/src/common/backend/parser/parse_expr.cpp b/src/common/backend/parser/parse_expr.cpp index 0c07adfb7..932652526 100644 --- a/src/common/backend/parser/parse_expr.cpp +++ b/src/common/backend/parser/parse_expr.cpp @@ -463,6 +463,7 @@ Node *transformExprRecurse(ParseState *pstate, Node *expr) case T_UserVar: { result = transformUserVar((UserVar *)expr); + pstate->has_uservar = true; break; } diff --git a/src/common/backend/utils/init/globals.cpp b/src/common/backend/utils/init/globals.cpp index 58b742005..8a320bfdc 100644 --- a/src/common/backend/utils/init/globals.cpp +++ b/src/common/backend/utils/init/globals.cpp @@ -75,7 +75,7 @@ bool will_shutdown = false; * NEXT | 92899 | ? | ? * ********************************************/ -const uint32 GRAND_VERSION_NUM = 92923; +const uint32 GRAND_VERSION_NUM = 92924; /******************************************** * 2.VERSION NUM FOR EACH FEATURE @@ -121,6 +121,7 @@ const uint32 PLAN_SELECT_VERSION_NUM = 92826; const uint32 MULTI_PARTITIONS_VERSION_NUM = 92825; const uint32 MULTI_MODIFY_VERSION_NUM = 92814; const uint32 CSN_TIME_BARRIER_VERSION = 92801; +const uint32 SELECT_STMT_HAS_USERVAR = 92924; const uint32 SQL_PATCH_VERSION_NUM = 92675; const uint32 SWITCH_ROLE_VERSION_NUM = 92668; diff --git a/src/gausskernel/optimizer/commands/view.cpp b/src/gausskernel/optimizer/commands/view.cpp index ab4674fb4..d0a2b9aad 100644 --- a/src/gausskernel/optimizer/commands/view.cpp +++ b/src/gausskernel/optimizer/commands/view.cpp @@ -626,6 +626,11 @@ ObjectAddress DefineView(ViewStmt* stmt, const char* queryString, bool send_remo } else { viewParse = (Query *)stmt->query; } + if (viewParse->has_uservar && IsA(stmt->query, SelectStmt)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("View's SELECT contains a variable or parameter"))); + } /* * The grammar should ensure that the result is a single SELECT Query. diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 77b1d5038..3d3f414ce 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -139,6 +139,7 @@ extern const uint32 GB18030_2022_VERSION_NUM; extern const uint32 PARTITION_ACCESS_EXCLUSIVE_LOCK_UPGRADE_VERSION; extern const uint32 SPQ_VERSION_NUM; extern const uint32 UPSERT_ALIAS_VERSION_NUM; +extern const uint32 SELECT_STMT_HAS_USERVAR; extern void register_backend_version(uint32 backend_version); extern bool contain_backend_version(uint32 version_number); diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index 7588f8630..629f1afad 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -2114,6 +2114,7 @@ typedef struct Query { void* intoPolicy; ParentStmtType parentStmtType; #endif + bool has_uservar; } Query; /* ---------------------- diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index b27b9f5cb..45cca960c 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -284,6 +284,7 @@ struct ParseState { */ List* orderbyCols; List* p_indexhintLists; /*Force or use index in index hint list*/ + bool has_uservar; }; /* An element of p_relnamespace or p_varnamespace */ diff --git a/src/test/regress/input/set_user_defined_variables_test.source b/src/test/regress/input/set_user_defined_variables_test.source index 44d23115a..bc1cd388d 100644 --- a/src/test/regress/input/set_user_defined_variables_test.source +++ b/src/test/regress/input/set_user_defined_variables_test.source @@ -617,6 +617,10 @@ end; call test(1,1); +\c test_set +drop view v1; +create view v1 as select @a = 1; + \c test_set set @a := 1, @b := @a; select @a, @b; diff --git a/src/test/regress/output/set_user_defined_variables_test.source b/src/test/regress/output/set_user_defined_variables_test.source index b25f0073e..db0e1528e 100644 --- a/src/test/regress/output/set_user_defined_variables_test.source +++ b/src/test/regress/output/set_user_defined_variables_test.source @@ -1274,6 +1274,11 @@ call test(1,1); (1 row) +\c test_set +drop view v1; +ERROR: view "v1" does not exist +create view v1 as select @a = 1; +ERROR: View's SELECT contains a variable or parameter \c test_set set @a := 1, @b := @a; select @a, @b;