Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
8a3ef04
end_one_iteration 에서 분석함수 평가를 위해 값 누적하도록 구현
Hamkua Nov 10, 2025
aec7678
불필요하게 qexec_generate_tuple_descriptor 를 호출하지 않도록 수정
Hamkua Nov 10, 2025
3838eeb
partition by + order by 컬럼이 인덱스에 포함되는 경우 end_one_iteration 에서 평가
Hamkua Nov 11, 2025
348d9e4
임시 구현
Hamkua Nov 13, 2025
8436f5a
불필요한 주석 제거
Hamkua Nov 13, 2025
68946ae
초기화 함수로 분리
Hamkua Nov 14, 2025
c2e47ea
포인터 사용으로 변경
Hamkua Nov 14, 2025
f37754f
distinct 를 포함하는 분석함수, 플래그를 설정해야 하는 분석함수 처리
Hamkua Nov 17, 2025
4a42478
Merge remote-tracking branch 'upstream/develop' into RND-2105
Hamkua Nov 17, 2025
dff6205
limit 절이 있을 때, qexec_end_one_iteration 에서 분석함수를 평가할 수 없음
Hamkua Nov 18, 2025
cf314d5
불필요한 수정사항 제거
Hamkua Nov 18, 2025
dc4823f
xasl->list_id를 interm_file로 사용하는 경우, xasl->outptr_list도 교체
Hamkua Nov 20, 2025
0d05a84
Merge branch 'CUBRID:develop' into RND-2105
Hamkua Nov 20, 2025
1e18560
PARALLEL_LIST_MERGE 인 경우, 마지막 튜플에 집계 결과가 포함되어 있지 않을 수 있음
Hamkua Nov 25, 2025
4d3c4da
Merge remote-tracking branch 'upstream/develop' into RND-2105
Hamkua Nov 25, 2025
6a8fe18
분석 함수와 LIMIT 절을 함께 사용할 때, 일부 함수는 end_one_iteration에서 전체 튜플을 읽을 필요가 없음
Hamkua Nov 25, 2025
dc6a6fd
PARALLEL_LIST_MERGE 대신 PARALLEL_PAGE_BY_PAGE 로 변경
Hamkua Nov 25, 2025
9a12167
indent 정리, 불필요한 수정 제거
Hamkua Nov 25, 2025
3b96a26
불필요한 수정사항 제거
Hamkua Nov 25, 2025
3dcd322
qexec_initialize_analytic_state 에서 초기화
Hamkua Nov 26, 2025
f0ed19c
ntile, interpolation 함수인 경우 analytic_stage 가 변경되는 문제 수정
Hamkua Nov 26, 2025
491c030
limit 절 관련 수정
Hamkua Nov 27, 2025
22dca92
regu_list를 clear 하지 않아 REGU_VARIABLE_FETCH_ALL_CONST flag가 남아있던 문제 수정
Hamkua Dec 1, 2025
babf586
클릭 카운터 함수 사용 시 end_one_iteration 에서 분석함수를 평가하지 못하도록 제한
Hamkua Dec 1, 2025
3099d58
클릭 카운터 사용 가능하도록 링크
Hamkua Dec 1, 2025
661c6ec
Merge branch 'CUBRID:develop' into RND-2105
Hamkua Dec 2, 2025
15332ef
기존 xasl->outptr_list 사용하도록 수정, 정리
Hamkua Dec 2, 2025
6020e81
limit 절에 명시된 만큼 행을 읽고 멈출 수 있는 분석함수(ROW_NUMBER, RANK, DENSE_RANK , IGN…
Hamkua Dec 2, 2025
2bb9043
클릭 카운터 함수가 있을 때만 REGU_VARIABLE_ANALYTIC_WINDOW 설정
Hamkua Dec 3, 2025
0c03067
page by page 이면 불필요한 튜플까지 스캔하므로, cannot parallel로 변경
Hamkua Dec 3, 2025
839c0e8
Merge remote-tracking branch 'upstream/develop' into RND-2105
Hamkua Dec 3, 2025
e55ed99
잘못 수정된 코드
Hamkua Dec 3, 2025
44d0ac6
코드 수정
Hamkua Dec 5, 2025
dea144d
inst_num 조건이 중복 적용되는 문제 수정
Hamkua Dec 5, 2025
847eceb
if 조건 수정
Hamkua Dec 5, 2025
37e519d
Merge remote-tracking branch 'upstream/develop' into RND-2105
Hamkua Dec 5, 2025
6a63291
코드 정리
Hamkua Dec 8, 2025
3dca5f8
Merge remote-tracking branch 'upstream/develop' into RND-2105
Hamkua Dec 8, 2025
26f3fe1
주석 추가
Hamkua Dec 8, 2025
fd7fe14
코드 리뷰 반영
Hamkua Dec 11, 2025
6cc5115
Merge branch 'CUBRID:develop' into RND-2105
Hamkua Dec 11, 2025
67b37a0
리뷰 반영
Hamkua Dec 18, 2025
daeae29
코드 정리
Hamkua Dec 18, 2025
0972fd3
Merge branch 'CUBRID:develop' into RND-2105
Hamkua Dec 18, 2025
1001ab0
코드 정리
Hamkua Dec 22, 2025
3612095
주석 추가
Hamkua Dec 22, 2025
09ec605
Merge branch 'CUBRID:develop' into RND-2105
Hamkua Dec 22, 2025
c6ee7e0
코드 리뷰 반영
Hamkua Dec 23, 2025
05ff0d5
qexec_execute_analytic 을 건너뛰도록 수정
Hamkua Dec 24, 2025
a3b938b
코드 리뷰 반영
Hamkua Dec 30, 2025
d435365
Merge remote-tracking branch 'upstream/develop' into RND-2105
Hamkua Dec 30, 2025
436f46a
코드 수정
Hamkua Jan 5, 2026
bb0c443
Merge branch 'CUBRID:develop' into RND-2105
Hamkua Jan 8, 2026
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
20 changes: 9 additions & 11 deletions src/parser/view_transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,6 @@ static PT_NODE *mq_update_analytic_sort_spec_expr (PARSER_CONTEXT * parser, PT_N
static PT_NODE *mq_inline_cte_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
static PT_NODE *mq_rewrite_cte_as_derived (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
static PT_NODE *mq_count_cte_references (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
static PT_NODE *mq_check_inline_cte (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
static void mq_check_cte_inline_or_materialize (PARSER_CONTEXT * parser, PT_NODE * node);
/*
* mq_is_outer_join_spec () - determine if a spec is outer joined in a spec list
Expand Down Expand Up @@ -5292,7 +5291,7 @@ mq_check_cte_inline_or_materialize (PARSER_CONTEXT * parser, PT_NODE * node)
{
PT_NODE *cte;
PT_HINT_ENUM hint;
bool is_inlinable = true;
bool has_click_counter = false;

assert (node->node_type == PT_WITH_CLAUSE);

Expand All @@ -5311,14 +5310,14 @@ mq_check_cte_inline_or_materialize (PARSER_CONTEXT * parser, PT_NODE * node)
continue;
}

is_inlinable = true;
has_click_counter = false;
/* CTE containing functions like incr, rownum etc. cannot be rewritten as inline view
* since it may change the query results. Handle it same as CTE with materialize hint. */
(void) parser_walk_tree (parser, cte->info.cte.non_recursive_part,
mq_check_inline_cte, &is_inlinable, NULL, NULL);
mq_has_click_counter, &has_click_counter, NULL, NULL);

/* false subquery cannot be rewritten as inline view */
if (is_inlinable && pt_is_query (cte->info.cte.non_recursive_part))
if (!has_click_counter && pt_is_query (cte->info.cte.non_recursive_part))
{
hint = pt_get_hint_from_query (parser, cte->info.cte.non_recursive_part);

Expand Down Expand Up @@ -5398,16 +5397,16 @@ mq_count_cte_references (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int
}

/*
* mq_check_inline_cte () -
* mq_has_click_counter () -
* return:
* parser(in):
* node(in):
* arg(in):
*/
static PT_NODE *
mq_check_inline_cte (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
PT_NODE *
mq_has_click_counter (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
{
bool *can_inlining = (bool *) arg;
bool *has_click_counter = (bool *) arg;

if (node == NULL)
{
Expand All @@ -5416,11 +5415,10 @@ mq_check_inline_cte (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *co

switch (node->node_type)
{
/* CTE cannot contain WITH clause inside, so we don't need to handle this case */
case PT_EXPR:
if (node->info.expr.op == PT_INCR || node->info.expr.op == PT_DECR)
{
*can_inlining = false;
*has_click_counter = true;
*continue_walk = PT_STOP_WALK;
}
break;
Expand Down
2 changes: 2 additions & 0 deletions src/parser/view_transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,6 @@ extern PT_NODE *mq_rewrite_aggregate_as_derived (PARSER_CONTEXT * parser, PT_NOD
extern PT_NODE *mq_rewrite_query_as_derived (PARSER_CONTEXT * parser, PT_NODE * query);

extern int mq_copypush_sargable_terms (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE * spec);

extern PT_NODE *mq_has_click_counter (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
#endif /* _VIEW_TRANSFORM_H_ */
139 changes: 137 additions & 2 deletions src/parser/xasl_generation.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,8 @@ static PT_NODE *pt_check_corr_subquery_not_cachable_expr (PARSER_CONTEXT * parse
static PT_NODE *pt_make_result_ref (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * groupby_list,
VAL_LIST * vallist);

static int pt_check_analytic_limit_optimization (XASL_NODE * xasl, ANALYTIC_EVAL_TYPE * eval_list);

static void
pt_init_xasl_supp_info ()
{
Expand Down Expand Up @@ -16595,6 +16597,17 @@ pt_to_buildlist_proc (PARSER_CONTEXT * parser, PT_NODE * select_node, QO_PLAN *
goto analytic_exit_on_error;
}

int *attr_offsets;
attr_offsets = pt_make_identity_offsets (select_list_ex);

buildlist->a_scan_regu_list =
pt_to_regu_variable_list (parser, select_list_ex, UNBOX_AS_VALUE, buildlist->a_val_list, attr_offsets);

if (attr_offsets != NULL)
{
free_and_init (attr_offsets);
}

/* generate regu list (identity fetching from temp tuple) */
buildlist->a_regu_list =
pt_to_position_regu_variable_list (parser, select_list_ex, buildlist->a_val_list, NULL);
Expand Down Expand Up @@ -16640,6 +16653,52 @@ pt_to_buildlist_proc (PARSER_CONTEXT * parser, PT_NODE * select_node, QO_PLAN *
/* optimize analytic function list */
xasl->proc.buildlist.a_eval_list = pt_optimize_analytic_list (parser, &analytic_info, &no_optimization_done);

if (pt_check_analytic_limit_optimization (xasl, xasl->proc.buildlist.a_eval_list) != NO_ERROR)
{
PT_ERRORm (parser, select_list_ex, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_OUT_OF_MEMORY);
goto analytic_exit_on_error;
}


if (XASL_IS_FLAGED (xasl, XASL_ANALYTIC_USES_LIMIT_OPT))
{
PT_NODE *final_node = NULL;
REGU_VARIABLE_LIST regu_list_new, prev = NULL;
REGU_VARIABLE *regu_var_temp;

for (final_node = select_list_final; final_node != NULL; final_node = final_node->next)
{
if (pt_is_instnum (final_node))
{
buildlist->a_outptr_list_ex->valptr_cnt++;

regu_alloc (regu_list_new);
if (regu_list_new == NULL)
{
goto analytic_exit_on_error;
}

regu_var_temp = pt_make_regu_numbering (parser, final_node);
regu_list_new->value = *regu_var_temp;

if (prev == NULL)
{
prev = regu_list_new;
regu_list_new->next = buildlist->a_outptr_list_ex->valptrp;
buildlist->a_outptr_list_ex->valptrp = regu_list_new;
}
else
{
regu_list_new->next = prev->next;
prev->next = regu_list_new;
}
prev = prev->next;
}

prev = (prev != NULL) ? prev->next : buildlist->a_outptr_list_ex->valptrp;
}
}

/* FIXME - Fix it with pt_build_analytic_eval_list (). */
if (no_optimization_done == true)
{
Expand Down Expand Up @@ -16739,7 +16798,14 @@ pt_to_buildlist_proc (PARSER_CONTEXT * parser, PT_NODE * select_node, QO_PLAN *
select_list_ex = NULL;

/* register initial outlist */
xasl->outptr_list = buildlist->a_outptr_list_ex;
if (XASL_IS_FLAGED (xasl, XASL_ANALYTIC_USES_LIMIT_OPT))
{
xasl->outptr_list = buildlist->a_outptr_list;
}
else
{
xasl->outptr_list = buildlist->a_outptr_list_ex;
}

/* all done */
goto analytic_exit;
Expand Down Expand Up @@ -16935,7 +17001,7 @@ pt_to_buildlist_proc (PARSER_CONTEXT * parser, PT_NODE * select_node, QO_PLAN *
}

if ((xasl->instnum_pred != NULL || xasl->instnum_flag & XASL_INSTNUM_FLAG_EVAL_DEFER)
&& pt_has_analytic (parser, select_node))
&& pt_has_analytic (parser, select_node) && !XASL_IS_FLAGED (xasl, XASL_ANALYTIC_USES_LIMIT_OPT))
{
/* we have an inst_num() which should not get evaluated in the initial fetch(processing stage)
* qexec_execute_analytic(post-processing stage) will use it in the final sort */
Expand Down Expand Up @@ -24428,6 +24494,11 @@ pt_to_analytic_final_node (PARSER_CONTEXT * parser, PT_NODE * tree, PT_NODE ** e
return NULL;
}

if (PT_IS_VALUE_NODE (tree))
{
return tree;
}

if (PT_IS_ANALYTIC_NODE (tree))
{
/* select ntile(select stddev(...)...)... from ... is allowed */
Expand Down Expand Up @@ -25050,6 +25121,11 @@ pt_substitute_analytic_references (PARSER_CONTEXT * parser, PT_NODE * node, PT_N
return node;
}

if (PT_IS_VALUE_NODE (node))
{
return node;
}

if (PT_IS_POINTER_REF_NODE (node))
{
PT_NODE *real_node = node->info.pointer.node;
Expand Down Expand Up @@ -28241,3 +28317,62 @@ pt_make_result_ref (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * groupby_l

return new_node;
}

/*
* pt_check_analytic_limit_optimization () -
* Check if analytic functions are optimizable for limit optimization.
* If optimizable, set the XASL_ANALYTIC_USES_LIMIT_OPT flag.
*
* return :
* xasl (in) :
* eval_list (in) :
*/
static int
pt_check_analytic_limit_optimization (XASL_NODE * xasl, ANALYTIC_EVAL_TYPE * eval_list)
{
ANALYTIC_EVAL_TYPE *eval;
ANALYTIC_TYPE *a_func_list;
bool is_optimizable = false;

if (!xasl->instnum_pred && !xasl->instnum_val)
{
return NO_ERROR;
}

/* NOTE: If eval->sort_list is NULL, eval_list length is always 1.
* If eval_list length >= 2, all eval entries have non-NULL sort_list.
* Since we check sort_list == NULL here, checking only one eval is sufficient. */
for (eval = eval_list; eval != NULL; eval = eval->next)
{
is_optimizable = !(eval->sort_list) ? true : false;

for (a_func_list = eval->head; a_func_list && is_optimizable; a_func_list = a_func_list->next)
{
switch (a_func_list->function)
{
case PT_FIRST_VALUE:
if (a_func_list->ignore_nulls)
{
is_optimizable = false;
break;
}

case PT_ROW_NUMBER:
case PT_RANK:
case PT_DENSE_RANK:
break;

default:
is_optimizable = false;
break;
}
}
}

if (is_optimizable)
{
XASL_SET_FLAG (xasl, XASL_ANALYTIC_USES_LIMIT_OPT);
}

return NO_ERROR;
}
9 changes: 8 additions & 1 deletion src/query/parallel/px_heap_scan/px_heap_scan_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,14 @@ namespace parallel_heap_scan
}
if (xasl->proc.buildlist.a_eval_list)
{
result = CHECK_RESULT::PARALLEL_LIST_MERGE;
if (XASL_IS_FLAGED (xasl, XASL_ANALYTIC_USES_LIMIT_OPT))
{
result = CHECK_RESULT::PARALLEL_PAGE_BY_PAGE;
}
else
{
result = CHECK_RESULT::PARALLEL_LIST_MERGE;
}
}
break;
case BUILDVALUE_PROC:
Expand Down
Loading
Loading