Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CBRD-25505] backport: 뷰가 포함된 insert ... select .. on duplicate key update 쿼리 결과 오류 (#5400) #5933

Open
wants to merge 3 commits into
base: release/11.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/parser/parse_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 74 additions & 2 deletions src/parser/view_transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ****/
/*****************************/
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down
Loading