diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 31ccd8b9d..32bc15f2c 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -2022,7 +2022,6 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt) sub_pstate->p_resolve_unknowns = false; selectQuery = transformStmt(sub_pstate, stmt->selectStmt); - selectQuery->hasIgnore = stmt->hasIgnore; Assert(selectQuery != NULL); free_parsestate(sub_pstate); @@ -2386,6 +2385,7 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt) } assign_query_collations(pstate, qry); + assign_query_ignore_flag(pstate, qry); CheckUnsupportInsertSelectClause(qry); @@ -4277,6 +4277,7 @@ static Query* transformUpdateStmt(ParseState* pstate, UpdateStmt* stmt) UpdateParseCheck(pstate, (Node *)qry); assign_query_collations(pstate, qry); + assign_query_ignore_flag(pstate, qry); qry->hintState = stmt->hintState; qry->hasIgnore = stmt->hasIgnore; diff --git a/src/common/backend/parser/parse_compatibility.cpp b/src/common/backend/parser/parse_compatibility.cpp index 86a9d26f7..f30fddbe5 100644 --- a/src/common/backend/parser/parse_compatibility.cpp +++ b/src/common/backend/parser/parse_compatibility.cpp @@ -95,6 +95,7 @@ static void unsupport_syntax_plus_outerjoin(const OperatorPlusProcessContext* ct static bool contain_JoinExpr(List* l); static bool contain_AEXPR_AND_OR(Node* clause); static bool contain_AEXPR_AND_OR_walker(Node* node, void* context); +static bool assign_query_ignore_flag_walker(Node* node, void *context); bool getOperatorPlusFlag() { @@ -1007,3 +1008,45 @@ void transformOperatorPlus(ParseState* pstate, Node** whereClause) } } +/* + * assign_query_ignore_flag + * Mark all query in the given Query with ignore information. + * + * Now only INSERT and UPDATE support ignore, so it only be called in + * InsertStmt and UpdateStmt. + */ +void assign_query_ignore_flag(ParseState* pstate, Query* query) +{ + /* we only set ignore to true, cause false is default value. So if there is no ignore, we can return */ + if (!pstate->p_has_ignore) { + return; + } + + (void)query_tree_walker(query, (bool (*)())assign_query_ignore_flag_walker, NULL, 0); +} + +/* + * Walker for assign_query_ignore_flag + * + * Each expression found by query_tree_walker is processed independently. + * Note that query_tree_walker may pass us a whole List, such as the + * targetlist, in which case each subexpression must be processed + * independently. + */ +static bool assign_query_ignore_flag_walker(Node* node, void *context) +{ + /* Need do nothing for empty subexpressions */ + if (node == NULL) { + return false; + } + + if (IsA(node, Query)) { + Query *query = (Query *) node; + + /* set it to true and continue to traverse the query tree */ + query->hasIgnore = true; + return query_tree_walker(query, (bool (*)())assign_query_ignore_flag_walker, NULL, 0); + } + return expression_tree_walker(node, (bool (*)())assign_query_ignore_flag_walker, NULL); +} + diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index dbcb7c022..dbfb5d247 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -92,6 +92,7 @@ extern void resetOperatorPlusFlag(); extern void fixResTargetNameWithTableNameRef(Relation rd, RangeVar* rel, ResTarget* res); extern void fixResTargetListWithTableNameRef(Relation rd, RangeVar* rel, List* clause_list); extern void UpdateParseCheck(ParseState *pstate, Node *qry); +extern void assign_query_ignore_flag(ParseState* pstate, Query* query); #endif /* !FRONTEND_PARSER */ extern bool getOperatorPlusFlag(); diff --git a/src/test/regress/expected/ignore/ignore_invalid_input.out b/src/test/regress/expected/ignore/ignore_invalid_input.out index 40e5495f1..1c737175a 100644 --- a/src/test/regress/expected/ignore/ignore_invalid_input.out +++ b/src/test/regress/expected/ignore/ignore_invalid_input.out @@ -1188,7 +1188,7 @@ select * from varbit; reset sql_ignore_strategy; drop table net, ran, hashvec, varbit; --- insert + subquery +-- insert/update + subquery create table t1(a int); insert /*+ ignore_error */ into t1 select 'abc'::time; WARNING: invalid input syntax for type time: "abc" @@ -1197,6 +1197,21 @@ LINE 1: insert /*+ ignore_error */ into t1 select 'abc'::time; CONTEXT: referenced column: time WARNING: column "a" is of type integer but expression is of type time without time zone. Data truncated automatically. CONTEXT: referenced column: a +insert /*+ ignore_error */ into t1 select (select 'abc'::time); +WARNING: invalid input syntax for type time: "abc" +LINE 1: insert /*+ ignore_error */ into t1 select (select 'abc'::tim... + ^ +CONTEXT: referenced column: time +WARNING: column "a" is of type integer but expression is of type time without time zone. Data truncated automatically. +CONTEXT: referenced column: a +update /*+ ignore_error */ t1 set a =(select (select 'abc'::time)); +WARNING: invalid input syntax for type time: "abc" +LINE 1: ...ate /*+ ignore_error */ t1 set a =(select (select 'abc'::tim... + ^ +CONTEXT: referenced column: time +referenced column: a +WARNING: column "a" is of type integer but expression is of type time without time zone. Data truncated automatically. +CONTEXT: referenced column: a drop table t1; -- restore context reset timezone; diff --git a/src/test/regress/sql/ignore/ignore_invalid_input.sql b/src/test/regress/sql/ignore/ignore_invalid_input.sql index a1e2b4bd3..c4156fe97 100644 --- a/src/test/regress/sql/ignore/ignore_invalid_input.sql +++ b/src/test/regress/sql/ignore/ignore_invalid_input.sql @@ -317,9 +317,11 @@ reset sql_ignore_strategy; drop table net, ran, hashvec, varbit; --- insert + subquery +-- insert/update + subquery create table t1(a int); insert /*+ ignore_error */ into t1 select 'abc'::time; +insert /*+ ignore_error */ into t1 select (select 'abc'::time); +update /*+ ignore_error */ t1 set a =(select (select 'abc'::time)); drop table t1; -- restore context