From 1ab1ad7fa0a8b9d87334cc5a02c5d667347eccbd Mon Sep 17 00:00:00 2001 From: yelingzhi Date: Wed, 23 Apr 2025 00:51:18 +0000 Subject: [PATCH] . --- .../shark/src/backend_parser/gram-tsql-rule.y | 12 +-- src/common/backend/parser/analyze.cpp | 22 +++-- src/common/backend/parser/gram.y | 92 +++++++++++++------ src/common/backend/parser/parse_clause.cpp | 34 ++++++- .../optimizer/rewrite/rewriteHandler.cpp | 26 ++++++ src/include/nodes/parsenodes.h | 1 + src/include/nodes/parsenodes_common.h | 1 + 7 files changed, 142 insertions(+), 46 deletions(-) diff --git a/contrib/shark/src/backend_parser/gram-tsql-rule.y b/contrib/shark/src/backend_parser/gram-tsql-rule.y index 5e032592c9..fdfd9018f3 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-rule.y +++ b/contrib/shark/src/backend_parser/gram-tsql-rule.y @@ -307,7 +307,7 @@ tsql_IndexStmt: InsertStmt: opt_with_clause INSERT hint_string insert_target insert_rest returning_clause { - $5->relation = $4; + $5->relation = (RangeVar*)$4; $5->returningList = $6; $5->withClause = $1; $5->isReplace = false; @@ -355,7 +355,7 @@ InsertStmt: opt_with_clause INSERT hint_string insert_target insert_rest returni m->is_insert_update = true; /* for UPSERT, keep the INSERT statement as well */ - $5->relation = $4; + $5->relation = (RangeVar*)$4; $5->returningList = $7; $5->isReplace = false; $5->withClause = $1; @@ -373,10 +373,10 @@ InsertStmt: opt_with_clause INSERT hint_string insert_target insert_rest returni m->insert_stmt = (Node *)copyObject($5); /* fill a MERGE statement*/ - m->relation = $4; + m->relation = (RangeVar*)$4; - Alias *a1 = makeAlias(($4->relname), NIL); - $4->alias = a1; + Alias *a1 = makeAlias((((RangeVar*)$4)->relname), NIL); + ((RangeVar*)$4)->alias = a1; Alias *a2 = makeAlias("excluded", NIL); RangeSubselect *r = makeNode(RangeSubselect); @@ -397,7 +397,7 @@ InsertStmt: opt_with_clause INSERT hint_string insert_target insert_rest returni $$ = (Node *)m; } else { - $5->relation = $4; + $5->relation = (RangeVar*)$4; $5->returningList = $7; $5->withClause = $1; $5->upsertClause = (UpsertClause *)$6; diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 067107f662..1df8714217 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -824,14 +824,17 @@ static bool checkDeleteStmtForPlanTable(List* relations) ListCell *lc = NULL; Oid plan_table_data_oid = RelnameGetRelid(T_PLAN_TABLE_DATA); foreach (lc, relations) { - RangeVar* rv = (RangeVar*)lfirst(lc); - if (strcasecmp(rv->relname, target_rel) == 0 && plan_table_data_oid != InvalidOid) { - if (list_length(relations) > 1) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plan_table cannot be deleted in mutiple tables delete"))); - } else { - return true; + Node* n = (Node*)lfirst(lc); + if (IsA(n, RangeVar)) { + RangeVar* rv = (RangeVar*)lfirst(lc); + if (strcasecmp(rv->relname, target_rel) == 0 && plan_table_data_oid != InvalidOid) { + if (list_length(relations) > 1) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("plan_table cannot be deleted in mutiple tables delete"))); + } else { + return true; + } } } } @@ -4474,7 +4477,8 @@ static Query* transformUpdateStmt(ParseState* pstate, UpdateStmt* stmt) qry->hasModifyingCTE = pstate->p_hasModifyingCTE; } - if (list_length(stmt->relationClause) > 1 || !IsA(linitial(stmt->relationClause), RangeVar)) { + if (list_length(stmt->relationClause) > 1 || + (!IsA(linitial(stmt->relationClause), RangeVar) && !IsA(linitial(stmt->relationClause), RangeSubselect))) { /* add all relations from relationClause to resultRelations. */ transformFromClause(pstate, stmt->relationClause, true, false, true); qry->resultRelations = pstate->p_updateRelations; diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 01643038ac..ae9bd766da 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -312,6 +312,7 @@ static Node* MakeNoArgFunctionCall(List* funcName, int location); static char* IdentResolveToChar(char *ident, core_yyscan_t yyscanner); static void contain_unsupport_node(Node* node, bool* has_unsupport_default_node); static List* TransformToConstStrNode(List *inExprList, char* raw_str); +static void forbreak(int a); /* Please note that the following line will be replaced with the contents of given file name even if with starting with a comment */ /*$$include "gram-tsql-prologue.y.h"*/ @@ -521,8 +522,9 @@ static List* TransformToConstStrNode(List *inExprList, char* raw_str); opt_class opt_inline_handler opt_validator validator_clause opt_collation -%type qualified_name insert_target OptConstrFromTable opt_index_name insert_partition_clause update_delete_partition_clause +%type qualified_name OptConstrFromTable opt_index_name insert_partition_clause update_delete_partition_clause qualified_trigger_name qualified_name_for_delete +%type insert_target %type all_Op MathOp @@ -698,7 +700,8 @@ static List* TransformToConstStrNode(List *inExprList, char* raw_str); %type table_ref_for_no_table_function %type joined_table %type relation_expr relation_expr_for_delete relation_expr_common -%type relation_expr_opt_alias delete_relation_expr_opt_alias relation_expr_opt_alias_for_delete +%type relation_expr_opt_alias +%type relation_expr_opt_alias_for_delete delete_relation_expr_opt_alias %type target_el single_set_clause set_target insert_column_item connect_by_root_expr %type tablesample_clause timecapsule_clause opt_timecapsule_clause opt_repeatable_clause end_expr start_expr @@ -24129,7 +24132,10 @@ update_delete_partition_clause: PARTITION '(' name ')' InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest returning_clause { - $6->relation = $5; + InsertStmt* stmt = $6; + forbreak(1); + $6->relation = (RangeVar*)$5; + $6->insertTarget = $5; $6->returningList = $7; $6->withClause = $1; $6->isReplace = false; @@ -24142,7 +24148,7 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re #ifndef ENABLE_MULTIPLE_NODES if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { - $5->relation = $4; + $5->relation = (RangeVar*)$4; $5->returningList = $6; $5->hintState = create_hintstate($2); $5->isReplace = true; @@ -24168,7 +24174,7 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { InsertStmt* n = makeNode(InsertStmt); - n->relation = $4; + n->relation = (RangeVar*)$4; n->targetList = $6; n->hintState = create_hintstate($2); n->isReplace = true; @@ -24229,7 +24235,7 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re m->is_insert_update = true; /* for UPSERT, keep the INSERT statement as well */ - $6->relation = $5; + $6->relation = (RangeVar*)$5; $6->returningList = $8; $6->isReplace = false; $6->withClause = $1; @@ -24248,10 +24254,10 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re m->insert_stmt = (Node *)copyObject($6); /* fill a MERGE statement*/ - m->relation = $5; + m->relation = (RangeVar*)$5; - Alias *a1 = makeAlias(($5->relname), NIL); - $5->alias = a1; + Alias *a1 = makeAlias((((RangeVar*)$5)->relname), NIL); + ((RangeVar*)$5)->alias = a1; Alias *a2 = makeAlias("excluded", NIL); RangeSubselect *r = makeNode(RangeSubselect); @@ -24272,7 +24278,7 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re $$ = (Node *)m; } else { - $6->relation = $5; + $6->relation = (RangeVar*)$5; $6->returningList = $8; $6->withClause = $1; $6->upsertClause = (UpsertClause *)$7; @@ -24302,7 +24308,7 @@ insert_target: $1->subpartitionname = $2->subpartitionname; $1->issubpartition = $2->issubpartition; } - $$ = $1; + $$ = (Node*) $1; } | qualified_name insert_partition_clause AS ColId { @@ -24314,13 +24320,32 @@ insert_target: $1->issubpartition = $2->issubpartition; } $1->alias = makeAlias($4, NIL); - $$ = $1; + $$ = (Node*) $1; + } + | select_with_parens ColId + { + RangeSubselect *n = makeNode(RangeSubselect); + Alias *alias = makeNode(Alias); + alias->aliasname = $2; + n->subquery = $1; + n->alias = alias; + $$ = (Node*) n; + } + | select_with_parens AS ColId + { + RangeSubselect *n = makeNode(RangeSubselect); + Alias *alias = makeNode(Alias); + alias->aliasname = $3; + n->subquery = $1; + n->alias = alias; + $$ = (Node*) n; } ; insert_rest: SelectStmt { + forbreak(1); $$ = makeNode(InsertStmt); $$->cols = NIL; $$->selectStmt = $1; @@ -24330,6 +24355,7 @@ insert_rest: } | '(' insert_column_list ')' SelectStmt { + forbreak(1); $$ = makeNode(InsertStmt); $$->cols = $2; $$->selectStmt = $4; @@ -24555,7 +24581,7 @@ UpdateStmt: opt_with_clause UPDATE hint_string from_list_for_no_table_function (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("multi-relation update is not yet supported."))); } - if (!IsA(linitial($4), RangeVar)) { + if (!IsA(linitial($4), RangeVar) && !IsA(linitial($4), RangeSubselect)) { ereport(errstate, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid target relation name."), @@ -24568,7 +24594,7 @@ UpdateStmt: opt_with_clause UPDATE hint_string from_list_for_no_table_function (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("multi-relation update only support in B-format or D-format database"))); } - if (!IsA(linitial($4), RangeVar)) { + if (!IsA(linitial($4), RangeVar) && !IsA(linitial($4), RangeSubselect)) { ereport(errstate, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid target relation name."), @@ -26846,11 +26872,12 @@ delete_relation_expr_opt_alias: * a subpartition name instead of a strict partition name. * Put it in partitionNameList to avoid error reporting. */ + RangeVar* rv = (RangeVar*)$1; if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT && - $1->partitionname != NULL && $1->alias == NULL) { - $1->partitionNameList = list_make1(makeString($1->partitionname)); - $1->partitionname = NULL; - $1->ispartition = FALSE; + rv->partitionname != NULL && rv->alias == NULL) { + rv->partitionNameList = list_make1(makeString(rv->partitionname)); + rv->partitionname = NULL; + rv->ispartition = FALSE; } $$ = $1; } @@ -26868,7 +26895,7 @@ delete_relation_expr_opt_alias: errmsg("this partition syntax is supported only in B-format database"))); } $1->partitionNameList = lcons(makeString($4), $6); - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete ColId PARTITION '(' name_list ')' { @@ -26887,7 +26914,7 @@ delete_relation_expr_opt_alias: alias->aliasname = $2; $1->alias = alias; $1->partitionNameList = $5; - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete AS ColId PARTITION '(' name_list ')' { @@ -26906,7 +26933,7 @@ delete_relation_expr_opt_alias: alias->aliasname = $3; $1->alias = alias; $1->partitionNameList = $6; - $$ = $1; + $$ = (Node*) $1; } ; @@ -26981,21 +27008,21 @@ relation_expr_opt_alias: relation_expr %prec UMINUS /* used for multi delete stmt */ relation_expr_opt_alias_for_delete: relation_expr_for_delete %prec UMINUS { - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete ColId { Alias *alias = makeNode(Alias); alias->aliasname = $2; $1->alias = alias; - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete AS ColId { Alias *alias = makeNode(Alias); alias->aliasname = $3; $1->alias = alias; - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete update_delete_partition_clause %prec UMINUS { @@ -27006,7 +27033,7 @@ relation_expr_opt_alias_for_delete: relation_expr_for_delete %prec UMINUS $1->subpartitionname = $2->subpartitionname; $1->issubpartition = $2->issubpartition; } - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete update_delete_partition_clause ColId { @@ -27020,7 +27047,7 @@ relation_expr_opt_alias_for_delete: relation_expr_for_delete %prec UMINUS Alias *alias = makeNode(Alias); alias->aliasname = $3; $1->alias = alias; - $$ = $1; + $$ = (Node*) $1; } | relation_expr_for_delete update_delete_partition_clause AS ColId { @@ -27034,7 +27061,14 @@ relation_expr_opt_alias_for_delete: relation_expr_for_delete %prec UMINUS Alias *alias = makeNode(Alias); alias->aliasname = $4; $1->alias = alias; - $$ = $1; + $$ = (Node*) $1; + } + | select_with_parens alias_clause %prec UMINUS + { + RangeSubselect *n = makeNode(RangeSubselect); + n->subquery = $1; + n->alias = $2; + $$ = (Node *) n; } ; @@ -34946,6 +34980,10 @@ void contain_unsupport_node(Node* node, bool* has_unsupport_default_node) (void)raw_expression_tree_walker(node, (bool (*)())contain_unsupport_node, (void*)has_unsupport_default_node); } +static void forbreak(int a) +{ + a = 1; +} static List* TransformToConstStrNode(List *inExprList, char* raw_str) { diff --git a/src/common/backend/parser/parse_clause.cpp b/src/common/backend/parser/parse_clause.cpp index a9ed2fe5a9..c03368dc0b 100644 --- a/src/common/backend/parser/parse_clause.cpp +++ b/src/common/backend/parser/parse_clause.cpp @@ -26,6 +26,7 @@ #include "catalog/pg_type.h" #include "commands/defrem.h" #include "commands/tablecmds.h" +#include "commands/view.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" @@ -368,11 +369,36 @@ List* setTargetTables(ParseState* pstate, List* relations, bool expandInh, bool * but *not* release the lock. */ foreach (l, relations) { - RangeVar* relRv = (RangeVar*)lfirst(l); - if (expandInh) { - inhOpt = interpretInhOption(relRv->inhOpt); + Node* n = (Node*)lfirst(l); + if (IsA(n, RangeVar)) { + RangeVar* relRv = (RangeVar*)lfirst(l); + if (expandInh) { + inhOpt = interpretInhOption(relRv->inhOpt); + } + rtindex = lappend_int(rtindex, setTargetTable(pstate, relRv, inhOpt, alsoSource, requiredPerms, multiModify)); + } else if (IsA(n, RangeSubselect)) { + RangeSubselect* sub = (RangeSubselect*) n; + // transformRangeSubselect(pstate, sub); + ViewStmt* stmt = makeNode(ViewStmt); + // char tempviewName[NAMEDATALEN]; + // int ret; + RangeVar* tmpRv = makeRangeVar(NULL, sub->alias->aliasname, -1); + // ret = snprintf_s(tempviewName, sizeof(tempviewName)) + tmpRv->relpersistence = RELPERSISTENCE_TEMP; + stmt->view = tmpRv; + stmt->aliases = NULL; + stmt->query = sub->subquery; + stmt->replace = false; + stmt->options = NULL; + stmt->sql_statement = NULL; + stmt->withCheckOption = NO_CHECK_OPTION; + stmt->viewSecurityOption = VIEW_SQL_SECURITY_NONE; + DefineView(stmt, pstate->p_sourcetext); + int rti = setTargetTable(pstate, tmpRv, inhOpt, alsoSource, requiredPerms, multiModify); + rtindex = lappend_int(rtindex, rti); + RangeTblEntry* relRte = rt_fetch(rti, pstate->p_rtable); + relRte->needDrop = true; } - rtindex = lappend_int(rtindex, setTargetTable(pstate, relRv, inhOpt, alsoSource, requiredPerms, multiModify)); } return rtindex; } diff --git a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp index ea511cff23..539ad7c31f 100644 --- a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp +++ b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp @@ -4896,6 +4896,32 @@ List* RewriteQuery(Query* parsetree, List* rewrite_events) } heap_close(rt_entry_relation, NoLock); + if (rt_entry->needDrop) { + DropStmt* stmt = makeNode(DropStmt); + stmt->removeType = OBJECT_VIEW; + stmt->missing_ok = true; + stmt->objects = list_make1(list_make1(makeString(rt_entry->relname))); + stmt->arguments = NIL; + stmt->behavior = DROP_RESTRICT; + stmt->concurrent = false; + stmt->purge = false; + stmt->isProcedure = false; + StringInfo tmp_query_string = makeStringInfo(); + RemoteQueryExecType exec_type = EXEC_ON_ALL_NODES; + RemoveRelations(stmt, tmp_query_string, &exec_type); + /* Create a dumb RTE to substitute the removed one */ + RangeTblEntry* reprte = makeNode(RangeTblEntry); + reprte->rtekind = RTE_RESULT; + reprte->eref = makeAlias("*RESULT*", NIL); + ListCell* lc = NULL; + int i = 1; + foreach (lc, parsetree->rtable) { + if (i == result_relation) { + lfirst(lc) = (void*)reprte; + } + i++; + } + } #ifdef PGXC } else { foreach (pt_cell, parsetree_list) { diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index e25079a5f5..7570341f64 100755 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -391,6 +391,7 @@ typedef struct RangeTblEntry { * Get names when partition tables deleted. */ int cursorDop; /* for functionscan with cursor param */ + bool needDrop; } RangeTblEntry; /* diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index f89e1d564c..1709292cf5 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -485,6 +485,7 @@ typedef struct UpsertClause { typedef struct InsertStmt { NodeTag type; RangeVar *relation; /* relation to insert into */ + Node *insertTarget; /* target to insert into */ List *cols; /* optional: names of the target columns */ Node *selectStmt; /* the source SELECT/VALUES, or NULL */ List *returningList; /* list of expressions to return */ -- Gitee