Skip to content

Commit

Permalink
[CBRD-25680] When using a correlated subquery that includes columns f…
Browse files Browse the repository at this point in the history
…rom an outer table in the select clause, it is not selected as a cache key (#5623)

http://jira.cubrid.org/browse/CBRD-25680

When using a correlated subquery that includes columns from an outer table in the select clause, the subquery cache does not use those columns as keys, resulting in improper caching. Consequently, cache hits occur even in situations where cache misses are expected. To address this, we modified the code to include regu_var from xasl outptr_list as part of the caching key. Additionally, unlike pred, xasl outptr_list uses the outer table as a constant regu_var during joins, which could mistakenly utilize even non-outer columns as cache keys. Therefore, we adjusted the code to only enable caching when there is no table from the subquery that matches the specification.
  • Loading branch information
xmilex-git authored Nov 20, 2024
1 parent 0a3df82 commit 2b1a584
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/parser/view_transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -4944,8 +4944,9 @@ mq_rewrite_aggregate_as_derived (PARSER_CONTEXT * parser, PT_NODE * agg_sel)
* Therefore, the NO_MERGE hint is not moved to the derived subquery.
* Additionally, if the subquery has the QUERY_CACHE hint, it should not be merged, so it is treated together with the NO_MERGE hint.
* All hints except for NO_MERGE and QUERY_CACHE are moved to the derived subquery. */
derived->info.query.q.select.hint = agg_sel->info.query.q.select.hint & ~(PT_HINT_NO_MERGE | PT_HINT_QUERY_CACHE);
agg_sel->info.query.q.select.hint &= (PT_HINT_NO_MERGE | PT_HINT_QUERY_CACHE);
derived->info.query.q.select.hint =
agg_sel->info.query.q.select.hint & ~(PT_HINT_NO_MERGE | PT_HINT_QUERY_CACHE | PT_HINT_NO_SUBQUERY_CACHE);
agg_sel->info.query.q.select.hint &= (PT_HINT_NO_MERGE | PT_HINT_QUERY_CACHE | PT_HINT_NO_SUBQUERY_CACHE);

derived->info.query.q.select.leading = agg_sel->info.query.q.select.leading;
agg_sel->info.query.q.select.leading = NULL;
Expand Down
54 changes: 54 additions & 0 deletions src/parser/xasl_generation.c
Original file line number Diff line number Diff line change
Expand Up @@ -10125,6 +10125,7 @@ pt_attribute_to_regu (PARSER_CONTEXT * parser, PT_NODE * attr)
{
/* The attribute is correlated variable. Find it in an enclosing scope(s). Note that this subquery has
* also just been determined to be a correlated subquery. */
REGU_VARIABLE_SET_FLAG (regu, REGU_VARIABLE_CORRELATED);
if (symbols->stack == NULL)
{
if (!pt_has_error (parser))
Expand Down Expand Up @@ -27436,6 +27437,7 @@ pt_make_sq_cache_key_struct (QPROC_DB_VALUE_LIST key_struct, void *p, int type)
ACCESS_SPEC_TYPE *spec;
PRED_EXPR *pred_src;
REGU_VARIABLE *regu_src;
REGU_VARIABLE_LIST regu_var_list_p;
if (!p)
{
return 0;
Expand Down Expand Up @@ -27546,6 +27548,54 @@ pt_make_sq_cache_key_struct (QPROC_DB_VALUE_LIST key_struct, void *p, int type)
cnt += ret;
}
}
if (xasl_src->outptr_list)
{
regu_var_list_p = xasl_src->outptr_list->valptrp;
for (i = 0; i < xasl_src->outptr_list->valptr_cnt; i++)
{
if (!regu_var_list_p)
{
assert (false);
return ER_FAILED;
}
regu_src = &regu_var_list_p->value;
ret = pt_make_sq_cache_key_struct (key_struct, (void *) regu_src, SQ_TYPE_REGU_VAR);
if (ret == ER_FAILED)
{
return ER_FAILED;
}
else
{
cnt += ret;
}
regu_var_list_p = regu_var_list_p->next;
}
}
if (xasl_src->type == BUILDVALUE_PROC || xasl_src->type == BUILDLIST_PROC)
{
AGGREGATE_TYPE *agg_list =
(xasl_src->type ==
BUILDVALUE_PROC) ? xasl_src->proc.buildvalue.agg_list : xasl_src->proc.buildlist.g_agg_list;
while (agg_list)
{
regu_var_list_p = agg_list->operands;
while (regu_var_list_p)
{
ret = pt_make_sq_cache_key_struct (key_struct, (void *) &regu_var_list_p->value, SQ_TYPE_REGU_VAR);
if (ret == ER_FAILED)
{
return ER_FAILED;
}
else
{
cnt += ret;
}
regu_var_list_p = regu_var_list_p->next;
}
agg_list = agg_list->next;
}

}
break;
case SQ_TYPE_PRED:
pred_src = (PRED_EXPR *) p;
Expand Down Expand Up @@ -27614,6 +27664,10 @@ pt_make_sq_cache_key_struct (QPROC_DB_VALUE_LIST key_struct, void *p, int type)
switch (regu_src->type)
{
case TYPE_CONSTANT:
if (!REGU_VARIABLE_IS_FLAGED (regu_src, REGU_VARIABLE_CORRELATED))
{
break;
}
ret = pt_make_sq_cache_key_struct (key_struct, (void *) regu_src->value.dbvalptr, SQ_TYPE_DBVAL);
if (ret == ER_FAILED)
{
Expand Down
1 change: 1 addition & 0 deletions src/query/regu_var.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ const int REGU_VARIABLE_FETCH_NOT_CONST = 0x80; /* is not constant */
const int REGU_VARIABLE_CLEAR_AT_CLONE_DECACHE = 0x100; /* clears regu variable at clone decache */
const int REGU_VARIABLE_UPD_INS_LIST = 0x200; /* for update or insert query */
const int REGU_VARIABLE_STRICT_TYPE_CAST = 0x400;/* for update or insert query */
const int REGU_VARIABLE_CORRELATED = 0x800; /* for correlated scalar subquery cache */

class regu_variable_node
{
Expand Down

0 comments on commit 2b1a584

Please sign in to comment.