diff --git a/src/parser/parse_tree.h b/src/parser/parse_tree.h index 2695476804..bbdc3cbf4a 100644 --- a/src/parser/parse_tree.h +++ b/src/parser/parse_tree.h @@ -1702,7 +1702,9 @@ typedef enum PT_SPEC_FLAG_BTREE_NODE_INFO_SCAN = 0x200, /* one of the spec's indexes will be scanned for b-tree node info */ PT_SPEC_FLAG_MVCC_COND_REEV = 0x400, /* the spec is used in mvcc condition reevaluation */ PT_SPEC_FLAG_MVCC_ASSIGN_REEV = 0x800, /* the spec is used in UPDATE assignment reevaluation */ - PT_SPEC_FLAG_DOESNT_HAVE_UNIQUE = 0x1000 /* the spec was checked and does not have any uniques */ + PT_SPEC_FLAG_DOESNT_HAVE_UNIQUE = 0x1000, /* the spec was checked and does not have any uniques */ + PT_SPEC_FLAG_SAMPLING_SCAN = 0x2000, /* spec for sampling scan, only available from version 11.4 onwards */ + PT_SPEC_FLAG_REFERENCED_AT_ODKU = 0x4000 /* spec for odku assignment */ } PT_SPEC_FLAG; typedef enum diff --git a/src/parser/view_transform.c b/src/parser/view_transform.c index b5ccb457a1..d6762b0e23 100644 --- a/src/parser/view_transform.c +++ b/src/parser/view_transform.c @@ -382,7 +382,8 @@ static PT_NODE *mq_reset_references_to_query_string (PARSER_CONTEXT * parser, PT static void mq_auto_param_merge_clauses (PARSER_CONTEXT * parser, PT_NODE * stmt); static PT_NODE *pt_check_for_update_subquery (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk); - +static PT_NODE *pt_check_odku_refs_pre (PARSER_CONTEXT * parser, PT_NODE * odku, void *arg, int *continue_walk); +static void pt_check_odku_refs_view (PARSER_CONTEXT * parser, PT_NODE * statement); static int pt_check_for_update_clause (PARSER_CONTEXT * parser, PT_NODE * query, bool root); static int pt_for_update_prepare_query_internal (PARSER_CONTEXT * parser, PT_NODE * query); @@ -1645,6 +1646,66 @@ mq_substitute_spec_in_method_names (PARSER_CONTEXT * parser, PT_NODE * node, voi return node; } +/* + * check if it refers view or inline view at "on duplicate key update" clause + */ +static PT_NODE * +pt_check_odku_refs_pre (PARSER_CONTEXT * parser, PT_NODE * odku, void *arg, int *continue_walk) +{ + PT_NODE *sel_spec = (PT_NODE *) arg; + PT_NODE *spec; + + *continue_walk = PT_CONTINUE_WALK; + + if (odku == NULL || odku->node_type != PT_NAME) + { + return odku; + } + + for (spec = sel_spec; spec; spec = spec->next) + { + if (spec->info.spec.id == odku->info.name.spec_id) + { + spec->info.spec.flag = (PT_SPEC_FLAG) (spec->info.spec.flag | PT_SPEC_FLAG_REFERENCED_AT_ODKU); + } + } + + return odku; +} + +/* + * Checks if there is a view or inline view referenced in the odku clause. + * If there is a referenced the view, set a flag + * for the view to indicate that it is referenced in odku. + * This flag will be used when determining "pushable" in mq_is_pushable_subquery. + */ +static void +pt_check_odku_refs_view (PARSER_CONTEXT * parser, PT_NODE * statement) +{ + PT_NODE *odku = statement->info.insert.odku_assignments; + + if (odku) + { + PT_NODE *sel_spec, *values; + + values = statement->info.insert.value_clauses->info.node_list.list; + while (values) + { + if (values->node_type == PT_SELECT) + { + sel_spec = values->info.query.q.select.from; + while (odku) + { + (void) parser_walk_tree (parser, odku->info.expr.arg2, pt_check_odku_refs_pre, sel_spec, NULL, NULL); + odku = odku->next; + } + } + + values = values->next; + } + } +} + /* * mq_is_pushable_subquery () - check if a subquery is pushable * returns: true if pushable, false otherwise @@ -1746,6 +1807,15 @@ mq_is_pushable_subquery (PARSER_CONTEXT * parser, PT_NODE * subquery, PT_NODE * return HAS_ERROR; } + /****************************/ + /*** ODKU REFERENCE CHECK ***/ + /****************************/ + /* odku refers view or inline view */ + if (PT_IS_SPEC_FLAG_SET (class_spec, PT_SPEC_FLAG_REFERENCED_AT_ODKU)) + { + return NON_PUSHABLE; + } + /*****************************/ /**** 1. MAIN QUERY CHECK ****/ /*****************************/ @@ -2486,7 +2556,6 @@ mq_substitute_subquery_in_statement (PARSER_CONTEXT * parser, PT_NODE * statemen goto exit_on_error; } - /* check whether subquery is pushable */ is_mergeable = mq_is_pushable_subquery (parser, query_spec, tmp_result, class_spec, true, order_by, class_); if (is_mergeable == HAS_ERROR) { @@ -7370,6 +7439,9 @@ mq_rewrite_upd_del_top_level_specs (PARSER_CONTEXT * parser, PT_NODE * statement break; case PT_INSERT: + /* checks if there is a view or inline view referenced in the odku clause. */ + pt_check_odku_refs_view (parser, statement); + /* INSERT does not support rewrites so we must check that no rewrite is needed */ spec = &statement->info.insert.spec; break;