From bf05f669324b97efbdf3772680b717b79d336440 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Fri, 6 Dec 2024 14:03:41 +0900 Subject: [PATCH 01/32] [CBRD-25708] enable partition pruning when the partition key is a function expression and the WHERE clause uses the original column --- src/query/partition.c | 131 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/src/query/partition.c b/src/query/partition.c index a031c231743..92bf02e31af 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -108,6 +108,7 @@ static void pruningset_set_all (PRUNING_BITSET *); static void pruningset_copy (PRUNING_BITSET *, const PRUNING_BITSET *); static void pruningset_add (PRUNING_BITSET *, int); static void pruningset_remove (PRUNING_BITSET *, int); +static void pruningset_except (PRUNING_BITSET *, const PRUNING_BITSET *); static void pruningset_intersect (PRUNING_BITSET *, const PRUNING_BITSET *); static void pruningset_union (PRUNING_BITSET *, const PRUNING_BITSET *); static bool pruningset_is_set (const PRUNING_BITSET *, int); @@ -137,6 +138,8 @@ static MATCH_STATUS partition_match_key_range (PRUNING_CONTEXT * pinfo, const KE PRUNING_BITSET * pruned); static bool partition_do_regu_variables_match (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right); +static bool partition_do_regu_variables_contain (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, + const REGU_VARIABLE * right); static MATCH_STATUS partition_prune (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * arg, const PRUNING_OP op, PRUNING_BITSET * pruned); static MATCH_STATUS partition_prune_db_val (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUNING_OP op, @@ -167,6 +170,8 @@ static int partition_attrinfo_get_key (THREAD_ENTRY * thread_p, PRUNING_CONTEXT /* misc pruning functions */ static bool partition_decrement_value (DB_VALUE * val); +static void partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val); +static bool partition_check_key_function (PRUNING_OP op, OPERATOR_TYPE opcode); /* PRUNING_BITSET manipulation functions */ @@ -237,6 +242,17 @@ pruningset_remove (PRUNING_BITSET * s, int i) s->set[i / BITS_IN_WORD] &= ~(1 << (i % BITS_IN_WORD)); } +static void +pruningset_except (PRUNING_BITSET * left, const PRUNING_BITSET * right) +{ + unsigned int i; + + for (i = 0; i < BITSET_LENGTH (left); i++) + { + left->set[i] &= ~(right->set[i]); + } +} + /* * pruningset_intersect () - perform intersection on two PRUNING_BITSET * objects @@ -1668,6 +1684,14 @@ partition_is_reguvar_const (const REGU_VARIABLE * regu_var) /* either all arguments are constants of this is an expression with no arguments */ return true; } + case TYPE_ATTR_ID: + { + if (regu_var->value.attr_descr.cache_dbvalp == NULL) + { + return false; + } + return true; + } default: return false; } @@ -1910,7 +1934,8 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN /* see if part_expr matches right or left */ REGU_VARIABLE *left, *right; PRUNING_OP op; - + DB_VALUE val; + bool is_value = false; left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); @@ -1924,6 +1949,38 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, left, op, pruned); } + else if (partition_do_regu_variables_contain (pinfo, left, part_expr) + && partition_check_key_function (op, part_expr->value.arithptr->opcode)) + { + if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + { + if (tp_value_cast (&val, part_expr->value.arithptr->value, + part_expr->value.arithptr->domain, false) == DOMAIN_COMPATIBLE) + { + partition_cache_dbvalp (part_expr, &val); + status = partition_prune (pinfo, part_expr, op, pruned); + } + } + } + else if (partition_do_regu_variables_contain (pinfo, right, part_expr) + && partition_check_key_function (op, part_expr->value.arithptr->opcode)) + { + + if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + { + if (tp_value_cast + (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, + false) == DOMAIN_COMPATIBLE) + { + partition_cache_dbvalp (part_expr, &val); + status = partition_prune (pinfo, part_expr, op, pruned); + } + } + } + + partition_cache_dbvalp (part_expr, NULL); + pr_clear_value (&val); + break; } @@ -1971,6 +2028,48 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN return status; } +static bool +partition_check_key_function (PRUNING_OP op, OPERATOR_TYPE opcode) +{ + switch (op) + { + case PO_LE: + case PO_LT: + case PO_GE: + case PO_GT: + switch (opcode) + { + case T_YEAR: + case T_TODAYS: + case T_UNIX_TIMESTAMP: + return true; + default: + return false; + } + default: + return true; + } +} + +static bool +partition_do_regu_variables_contain (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right) +{ + if (left == NULL || right == NULL) + { + return left == right; + } + + if (left->type == TYPE_ATTR_ID && right->type == TYPE_INARITH) + { + if (left->value.attr_descr.id == pinfo->attr_id) + { + return true; + } + } + + return false; +} + /* * partition_match_key_range () - perform pruning using a key_range * return : pruned list @@ -2575,6 +2674,36 @@ partition_set_cache_info_for_expr (REGU_VARIABLE * var, ATTR_ID attr_id, HEAP_CA } } +static void +partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val) +{ + assert (var != NULL); + switch (var->type) + { + case TYPE_ATTR_ID: + var->value.attr_descr.cache_dbvalp = val; + break; + + case TYPE_INARITH: + if (var->value.arithptr->leftptr != NULL) + { + partition_cache_dbvalp (var->value.arithptr->leftptr, val); + } + + if (var->value.arithptr->rightptr != NULL) + { + partition_cache_dbvalp (var->value.arithptr->rightptr, val); + } + + if (var->value.arithptr->thirdptr != NULL) + { + partition_cache_dbvalp (var->value.arithptr->thirdptr, val); + } + default: + break; + } +} + /* * partition_get_attribute_id () - get the id of the attribute of the * partition expression From 7f9912a0450db8214da88ba2a8483fc4dac74a50 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 10 Dec 2024 12:25:18 +0900 Subject: [PATCH 02/32] [CBRD-25708] rename function and reorder conditions --- src/query/partition.c | 65 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 92bf02e31af..5ee18422d9f 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -108,7 +108,6 @@ static void pruningset_set_all (PRUNING_BITSET *); static void pruningset_copy (PRUNING_BITSET *, const PRUNING_BITSET *); static void pruningset_add (PRUNING_BITSET *, int); static void pruningset_remove (PRUNING_BITSET *, int); -static void pruningset_except (PRUNING_BITSET *, const PRUNING_BITSET *); static void pruningset_intersect (PRUNING_BITSET *, const PRUNING_BITSET *); static void pruningset_union (PRUNING_BITSET *, const PRUNING_BITSET *); static bool pruningset_is_set (const PRUNING_BITSET *, int); @@ -171,7 +170,7 @@ static int partition_attrinfo_get_key (THREAD_ENTRY * thread_p, PRUNING_CONTEXT static bool partition_decrement_value (DB_VALUE * val); static void partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val); -static bool partition_check_key_function (PRUNING_OP op, OPERATOR_TYPE opcode); +static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const OPERATOR_TYPE opcode); /* PRUNING_BITSET manipulation functions */ @@ -242,17 +241,6 @@ pruningset_remove (PRUNING_BITSET * s, int i) s->set[i / BITS_IN_WORD] &= ~(1 << (i % BITS_IN_WORD)); } -static void -pruningset_except (PRUNING_BITSET * left, const PRUNING_BITSET * right) -{ - unsigned int i; - - for (i = 0; i < BITSET_LENGTH (left); i++) - { - left->set[i] &= ~(right->set[i]); - } -} - /* * pruningset_intersect () - perform intersection on two PRUNING_BITSET * objects @@ -1934,8 +1922,6 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN /* see if part_expr matches right or left */ REGU_VARIABLE *left, *right; PRUNING_OP op; - DB_VALUE val; - bool is_value = false; left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); @@ -1949,38 +1935,41 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, left, op, pruned); } - else if (partition_do_regu_variables_contain (pinfo, left, part_expr) - && partition_check_key_function (op, part_expr->value.arithptr->opcode)) + else if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode)) { - if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + DB_VALUE val; + bool is_value; + + if (partition_do_regu_variables_contain (pinfo, left, part_expr)) { - if (tp_value_cast (&val, part_expr->value.arithptr->value, - part_expr->value.arithptr->domain, false) == DOMAIN_COMPATIBLE) + if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { - partition_cache_dbvalp (part_expr, &val); - status = partition_prune (pinfo, part_expr, op, pruned); + if (tp_value_cast + (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, + false) == DOMAIN_COMPATIBLE) + { + partition_cache_dbvalp (part_expr, &val); + status = partition_prune (pinfo, part_expr, op, pruned); + } } } - } - else if (partition_do_regu_variables_contain (pinfo, right, part_expr) - && partition_check_key_function (op, part_expr->value.arithptr->opcode)) - { - - if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + else if (partition_do_regu_variables_contain (pinfo, right, part_expr)) { - if (tp_value_cast - (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, - false) == DOMAIN_COMPATIBLE) + if (partition_get_value_from_regu_var (pinfo, left, &val, &is_value) == NO_ERROR) { - partition_cache_dbvalp (part_expr, &val); - status = partition_prune (pinfo, part_expr, op, pruned); + if (tp_value_cast + (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, + false) == DOMAIN_COMPATIBLE) + { + partition_cache_dbvalp (part_expr, &val); + status = partition_prune (pinfo, part_expr, op, pruned); + } } } - } - - partition_cache_dbvalp (part_expr, NULL); - pr_clear_value (&val); + partition_cache_dbvalp (part_expr, NULL); + pr_clear_value (&val); + } break; } @@ -2029,7 +2018,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN } static bool -partition_check_key_function (PRUNING_OP op, OPERATOR_TYPE opcode) +partition_supports_pruning_op_for_function (const PRUNING_OP op, const OPERATOR_TYPE opcode) { switch (op) { From df95b48cf43691f4e166a1911f1c7dcda1e10598 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 10 Dec 2024 14:22:15 +0900 Subject: [PATCH 03/32] [CBRD-25708] only check pruning operator support for arithmetic partition keys --- src/query/partition.c | 50 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 5ee18422d9f..4d56c6ff489 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1925,6 +1925,8 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); + DB_VALUE val; + bool is_value; status = MATCH_NOT_FOUND; if (partition_do_regu_variables_match (pinfo, left, part_expr)) @@ -1935,41 +1937,39 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, left, op, pruned); } - else if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode)) - { - DB_VALUE val; - bool is_value; - if (partition_do_regu_variables_contain (pinfo, left, part_expr)) + else if (partition_do_regu_variables_contain (pinfo, left, part_expr)) + { + if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode) + && partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { - if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + if (tp_value_cast + (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, + false) == DOMAIN_COMPATIBLE) { - if (tp_value_cast - (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, - false) == DOMAIN_COMPATIBLE) - { - partition_cache_dbvalp (part_expr, &val); - status = partition_prune (pinfo, part_expr, op, pruned); - } + partition_cache_dbvalp (part_expr, &val); + status = partition_prune (pinfo, part_expr, op, pruned); } } - else if (partition_do_regu_variables_contain (pinfo, right, part_expr)) + } + else if (partition_do_regu_variables_contain (pinfo, right, part_expr)) + { + if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode) + && partition_get_value_from_regu_var (pinfo, left, &val, &is_value) == NO_ERROR) { - if (partition_get_value_from_regu_var (pinfo, left, &val, &is_value) == NO_ERROR) + if (tp_value_cast + (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, + false) == DOMAIN_COMPATIBLE) { - if (tp_value_cast - (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, - false) == DOMAIN_COMPATIBLE) - { - partition_cache_dbvalp (part_expr, &val); - status = partition_prune (pinfo, part_expr, op, pruned); - } + partition_cache_dbvalp (part_expr, &val); + status = partition_prune (pinfo, part_expr, op, pruned); } } - - partition_cache_dbvalp (part_expr, NULL); - pr_clear_value (&val); } + + partition_cache_dbvalp (part_expr, NULL); + pr_clear_value (&val); + break; } From 53e8727227d6f3e90cd3116a8ee22ebde9823427 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 10 Dec 2024 17:48:38 +0900 Subject: [PATCH 04/32] =?UTF-8?q?[CBRD-25708]=20modify=20constant=20value?= =?UTF-8?q?=20checks=20to=20ensure=20compatibility=20with=20the=20column?= =?UTF-8?q?=20type=20being=20compared,=20instead=20of=20relying=20on=20the?= =?UTF-8?q?=20function=E2=80=99s=20return=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/query/partition.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 4d56c6ff489..472060d10e6 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1925,7 +1925,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); - DB_VALUE val; + DB_VALUE val, casted_val; bool is_value; status = MATCH_NOT_FOUND; @@ -1937,17 +1937,14 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, left, op, pruned); } - else if (partition_do_regu_variables_contain (pinfo, left, part_expr)) { if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode) && partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { - if (tp_value_cast - (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, - false) == DOMAIN_COMPATIBLE) + if (tp_value_cast (&val, &casted_val, left->domain, false) == DOMAIN_COMPATIBLE) { - partition_cache_dbvalp (part_expr, &val); + partition_cache_dbvalp (part_expr, &casted_val); status = partition_prune (pinfo, part_expr, op, pruned); } } @@ -1957,9 +1954,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode) && partition_get_value_from_regu_var (pinfo, left, &val, &is_value) == NO_ERROR) { - if (tp_value_cast - (&val, part_expr->value.arithptr->value, part_expr->value.arithptr->domain, - false) == DOMAIN_COMPATIBLE) + if (tp_value_cast (&val, &casted_val, right->domain, false) == DOMAIN_COMPATIBLE) { partition_cache_dbvalp (part_expr, &val); status = partition_prune (pinfo, part_expr, op, pruned); @@ -1969,6 +1964,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN partition_cache_dbvalp (part_expr, NULL); pr_clear_value (&val); + pr_clear_value (&casted_val); break; } From b14ecbb73bcbcb6393274250fb362520d1b6a6d6 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Wed, 11 Dec 2024 17:29:34 +0900 Subject: [PATCH 05/32] [CBRD-25708] extract logic from partition_match_pred_expr() into separate functions --- src/query/partition.c | 103 ++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 30 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 472060d10e6..c0569b37ccc 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -170,7 +170,10 @@ static int partition_attrinfo_get_key (THREAD_ENTRY * thread_p, PRUNING_CONTEXT static bool partition_decrement_value (DB_VALUE * val); static void partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val); -static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const OPERATOR_TYPE opcode); +static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr); +static MATCH_STATUS partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, + const REGU_VARIABLE * right, REGU_VARIABLE * part_expr, const PRUNING_OP op, + PRUNING_BITSET * pruned); /* PRUNING_BITSET manipulation functions */ @@ -1925,8 +1928,6 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); - DB_VALUE val, casted_val; - bool is_value; status = MATCH_NOT_FOUND; if (partition_do_regu_variables_match (pinfo, left, part_expr)) @@ -1937,35 +1938,17 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, left, op, pruned); } - else if (partition_do_regu_variables_contain (pinfo, left, part_expr)) + else if (partition_supports_pruning_op_for_function (op, part_expr)) { - if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode) - && partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + if (partition_do_regu_variables_contain (pinfo, left, part_expr)) { - if (tp_value_cast (&val, &casted_val, left->domain, false) == DOMAIN_COMPATIBLE) - { - partition_cache_dbvalp (part_expr, &casted_val); - status = partition_prune (pinfo, part_expr, op, pruned); - } + status = partition_prune_arith (pinfo, left, right, part_expr, op, pruned); } - } - else if (partition_do_regu_variables_contain (pinfo, right, part_expr)) - { - if (partition_supports_pruning_op_for_function (op, part_expr->value.arithptr->opcode) - && partition_get_value_from_regu_var (pinfo, left, &val, &is_value) == NO_ERROR) + else if (partition_do_regu_variables_contain (pinfo, right, part_expr)) { - if (tp_value_cast (&val, &casted_val, right->domain, false) == DOMAIN_COMPATIBLE) - { - partition_cache_dbvalp (part_expr, &val); - status = partition_prune (pinfo, part_expr, op, pruned); - } + status = partition_prune_arith (pinfo, right, left, part_expr, op, pruned); } } - - partition_cache_dbvalp (part_expr, NULL); - pr_clear_value (&val); - pr_clear_value (&casted_val); - break; } @@ -1993,6 +1976,10 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, list, op, pruned); } + else if (partition_do_regu_variables_contain (pinfo, regu, part_expr)) + { + status = partition_prune_arith (pinfo, regu, list, part_expr, op, pruned); + } } break; @@ -2013,15 +2000,64 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN return status; } +static MATCH_STATUS +partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right, + REGU_VARIABLE * part_expr, const PRUNING_OP op, PRUNING_BITSET * pruned) +{ + MATCH_STATUS status = MATCH_NOT_FOUND; + DB_VALUE val, casted_val; + TP_DOMAIN_STATUS dom_status; + bool is_value; + + if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) + { + if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&val)) + { + dom_status = tp_value_cast (&val, &casted_val, left->domain, false); + + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, val, left->domain); + + pinfo->error_code = ER_FAILED; + return MATCH_NOT_FOUND; + + } + + partition_cache_dbvalp (part_expr, &casted_val); + } + else + { + partition_cache_dbvalp (part_expr, &val); + } + + status = partition_prune (pinfo, part_expr, op, pruned); + partition_cache_dbvalp (part_expr, NULL); + } + pr_clear_value (&val); + pr_clear_value (&casted_val); + + return status; +} + static bool -partition_supports_pruning_op_for_function (const PRUNING_OP op, const OPERATOR_TYPE opcode) +partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr) { + OPERATOR_TYPE opcode; + + if (part_expr->type != TYPE_INARITH) + { + return false; + } + + opcode = part_expr->value.arithptr->opcode; + switch (op) { - case PO_LE: case PO_LT: - case PO_GE: + case PO_LE: case PO_GT: + case PO_GE: switch (opcode) { case T_YEAR: @@ -2031,9 +2067,16 @@ partition_supports_pruning_op_for_function (const PRUNING_OP op, const OPERATOR_ default: return false; } - default: + case PO_EQ: + case PO_NE: + case PO_IN: + case PO_NOT_IN: + case PO_IS_NULL: return true; + default: + return false; } + } static bool From b6aa622f721818c656ed838a9a479e4281561310 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Wed, 11 Dec 2024 17:37:49 +0900 Subject: [PATCH 06/32] [CBRD-25708] modify code to ensure successful build --- src/query/partition.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index c0569b37ccc..0ce474093be 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2017,11 +2017,12 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons if (dom_status != DOMAIN_COMPATIBLE) { - (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, val, left->domain); + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &val, left->domain); pinfo->error_code = ER_FAILED; + pr_clear_value (&val); + pr_clear_value (&casted_val); return MATCH_NOT_FOUND; - } partition_cache_dbvalp (part_expr, &casted_val); From dc69f1e9f0bd11de8a2f087bcf62100a55fda08b Mon Sep 17 00:00:00 2001 From: Hamkua Date: Wed, 11 Dec 2024 18:31:41 +0900 Subject: [PATCH 07/32] [CBRD-25708] call partition_supports_pruning_op_for_function() for PRED_EXPR containing ALL/SOME --- src/query/partition.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 0ce474093be..b40c23e7ebc 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1976,9 +1976,12 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { status = partition_prune (pinfo, list, op, pruned); } - else if (partition_do_regu_variables_contain (pinfo, regu, part_expr)) + else if (partition_supports_pruning_op_for_function (op, part_expr)) { - status = partition_prune_arith (pinfo, regu, list, part_expr, op, pruned); + if (partition_do_regu_variables_contain (pinfo, regu, part_expr)) + { + status = partition_prune_arith (pinfo, regu, list, part_expr, op, pruned); + } } } break; From 326c52936f923e3607d57660b3cfca6ade230e43 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 12 Dec 2024 15:44:58 +0900 Subject: [PATCH 08/32] [CBRD-25708] modify partition pruning to support column in partition key expression used in ALSM --- src/query/partition.c | 82 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index b40c23e7ebc..06f9499cdbf 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2014,33 +2014,89 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { - if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&val)) + DB_COLLECTION *collection = NULL; + DB_VALUE collection_val; + DB_VALUE part_expr_val; + + int size = 0; + if (db_value_type_is_collection (&val)) { - dom_status = tp_value_cast (&val, &casted_val, left->domain, false); + DB_VALUE *new_collection_dbval = NULL; + DB_COLLECTION *new_collection = NULL; + collection = db_get_collection (&val); + size = db_set_size (collection); + new_collection = db_seq_create (NULL, NULL, size); - if (dom_status != DOMAIN_COMPATIBLE) + for (int i = 0; i < size; i++) { - (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &val, left->domain); + db_set_get (collection, i, &collection_val); + + if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&collection_val)) + { + dom_status = tp_value_cast (&collection_val, &casted_val, left->domain, false); + + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &collection_val, left->domain); + + pinfo->error_code = ER_FAILED; + pr_clear_value (&val); + pr_clear_value (&collection_val); + pr_clear_value (&casted_val); + return MATCH_NOT_FOUND; + } + + partition_cache_dbvalp (part_expr, &casted_val); + } + else + { + partition_cache_dbvalp (part_expr, &collection_val); + } + + if (partition_get_value_from_regu_var (pinfo, part_expr, &part_expr_val, &is_value) == NO_ERROR) + { + db_set_add (new_collection, &part_expr_val); + } - pinfo->error_code = ER_FAILED; - pr_clear_value (&val); - pr_clear_value (&casted_val); - return MATCH_NOT_FOUND; } - partition_cache_dbvalp (part_expr, &casted_val); + new_collection_dbval = db_value_copy (&val); + new_collection_dbval->data.set = new_collection; + + status = partition_prune_db_val (pinfo, new_collection_dbval, op, pruned); + pr_clear_value (&part_expr_val); + pr_clear_value (new_collection_dbval); } else { - partition_cache_dbvalp (part_expr, &val); + if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&val)) + { + dom_status = tp_value_cast (&val, &casted_val, left->domain, false); + + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &val, left->domain); + + pinfo->error_code = ER_FAILED; + pr_clear_value (&val); + pr_clear_value (&casted_val); + return MATCH_NOT_FOUND; + } + + partition_cache_dbvalp (part_expr, &casted_val); + } + else + { + partition_cache_dbvalp (part_expr, &val); + } } status = partition_prune (pinfo, part_expr, op, pruned); partition_cache_dbvalp (part_expr, NULL); - } - pr_clear_value (&val); - pr_clear_value (&casted_val); + pr_clear_value (&val); + pr_clear_value (&casted_val); + } return status; } From 6803bb84befbeddad79554dbe6ba4e2719cfc48c Mon Sep 17 00:00:00 2001 From: Hamkua Date: Fri, 13 Dec 2024 16:28:04 +0900 Subject: [PATCH 09/32] [CBRD-25708] fix core dump in partition pruning for ALSM operations --- src/query/partition.c | 82 +++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 06f9499cdbf..95a8ae5517b 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2009,63 +2009,76 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons { MATCH_STATUS status = MATCH_NOT_FOUND; DB_VALUE val, casted_val; + DB_COLLECTION *collection = NULL; + DB_COLLECTION *new_collection = NULL; + DB_VALUE old_collection_val, new_collection_val, part_key_val; TP_DOMAIN_STATUS dom_status; bool is_value; + db_make_null (&val); + db_make_null (&casted_val); + db_make_null (&old_collection_val); + db_make_null (&new_collection_val); + db_make_null (&part_key_val); + if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { - DB_COLLECTION *collection = NULL; - DB_VALUE collection_val; - DB_VALUE part_expr_val; - int size = 0; + if (db_value_type_is_collection (&val)) { - DB_VALUE *new_collection_dbval = NULL; - DB_COLLECTION *new_collection = NULL; collection = db_get_collection (&val); - size = db_set_size (collection); - new_collection = db_seq_create (NULL, NULL, size); + new_collection = db_col_copy (collection); + // new_collection = db_col_create (type, size, NULL); + if (new_collection == NULL) + { + goto cleanup; + } + + size = db_col_size (collection); for (int i = 0; i < size; i++) { - db_set_get (collection, i, &collection_val); + if (db_col_get (collection, i, &old_collection_val) != NO_ERROR) + { + goto cleanup; + } - if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&collection_val)) + if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&old_collection_val)) { - dom_status = tp_value_cast (&collection_val, &casted_val, left->domain, false); + dom_status = tp_value_cast (&old_collection_val, &casted_val, left->domain, false); if (dom_status != DOMAIN_COMPATIBLE) { - (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &collection_val, left->domain); + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &old_collection_val, left->domain); pinfo->error_code = ER_FAILED; - pr_clear_value (&val); - pr_clear_value (&collection_val); - pr_clear_value (&casted_val); - return MATCH_NOT_FOUND; + goto cleanup; } + // TODO: need to inspect collection's data type partition_cache_dbvalp (part_expr, &casted_val); } else { - partition_cache_dbvalp (part_expr, &collection_val); + partition_cache_dbvalp (part_expr, &old_collection_val); } - if (partition_get_value_from_regu_var (pinfo, part_expr, &part_expr_val, &is_value) == NO_ERROR) + if (partition_get_value_from_regu_var (pinfo, part_expr, &part_key_val, &is_value) == NO_ERROR) { - db_set_add (new_collection, &part_expr_val); + if (is_value) + { + db_col_put (new_collection, i, &part_key_val); + } } - } - new_collection_dbval = db_value_copy (&val); - new_collection_dbval->data.set = new_collection; + if (db_make_collection (&new_collection_val, new_collection) != NO_ERROR) + { + goto cleanup; + } - status = partition_prune_db_val (pinfo, new_collection_dbval, op, pruned); - pr_clear_value (&part_expr_val); - pr_clear_value (new_collection_dbval); + status = partition_prune_db_val (pinfo, &new_collection_val, op, pruned); } else { @@ -2078,9 +2091,7 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &val, left->domain); pinfo->error_code = ER_FAILED; - pr_clear_value (&val); - pr_clear_value (&casted_val); - return MATCH_NOT_FOUND; + goto cleanup; } partition_cache_dbvalp (part_expr, &casted_val); @@ -2092,11 +2103,20 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons } status = partition_prune (pinfo, part_expr, op, pruned); - partition_cache_dbvalp (part_expr, NULL); + } - pr_clear_value (&val); - pr_clear_value (&casted_val); +cleanup: + partition_cache_dbvalp (part_expr, NULL); + if (new_collection != NULL) + { + db_col_free (new_collection); } + pr_clear_value (&old_collection_val); + pr_clear_value (&new_collection_val); + pr_clear_value (&part_key_val); + pr_clear_value (&casted_val); + pr_clear_value (&val); + return status; } From ffc2c025088c9413ca1f8b3fef7fa9acb705d06e Mon Sep 17 00:00:00 2001 From: Hamkua Date: Fri, 20 Dec 2024 16:44:37 +0900 Subject: [PATCH 10/32] [CBRD-25708] modify to enable partition pruning with collection type constant values in range partition table --- src/query/partition.c | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/query/partition.c b/src/query/partition.c index b3879cf5c14..b969b7e9aa6 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1346,6 +1346,55 @@ partition_prune_range (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUN int rmin = DB_UNK, rmax = DB_UNK; MATCH_STATUS status; + if (db_value_type_is_collection (val)) + { + PRUNING_BITSET new_pruned; + DB_COLLECTION *values = NULL; + DB_VALUE col; + int size, j; + + values = db_get_set (val); + size = db_set_size (values); + if (size < 0) + { + pinfo->error_code = ER_FAILED; + status = MATCH_NOT_FOUND; + goto cleanup; + } + + for (j = 0; j < size; j++) + { + if (db_set_get (values, j, &col) != NO_ERROR) + { + pinfo->error_code = ER_FAILED; + status = MATCH_NOT_FOUND; + goto cleanup; + } + + pruningset_init (&new_pruned, PARTITIONS_COUNT (pinfo)); + status = partition_prune_range (pinfo, &col, op, &new_pruned); + if (j > 0) + { + if (op == PO_EQ) + { + pruningset_intersect (pruned, &new_pruned); + } + else + { + pruningset_union (pruned, &new_pruned); + } + } + else + { + pruningset_copy (pruned, &new_pruned); + } + + pr_clear_value (&col); + } + + goto cleanup; + } + db_make_null (&min); db_make_null (&max); @@ -1401,6 +1450,7 @@ partition_prune_range (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUN status = MATCH_OK; switch (op) { + case PO_IN: case PO_EQ: /* Filter is part_expr = value. Find the *only* partition for which min <= value < max */ if ((rmin == DB_EQ || rmin == DB_LT) && rmax == DB_LT) From a006090676399cd127113964032319d70c1de540 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 23 Dec 2024 21:07:47 +0900 Subject: [PATCH 11/32] [CBRD-25708] temporary implementation of partition pruning for composite IN conditions --- src/query/partition.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/query/partition.c b/src/query/partition.c index b969b7e9aa6..77758cc2216 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -35,6 +35,7 @@ #include "xasl.h" #include "xasl_predicate.hpp" #include "xasl_unpack_info.hpp" +#include "set_object.h" // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -1975,12 +1976,50 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN /* see if part_expr matches right or left */ REGU_VARIABLE *left, *right; PRUNING_OP op; + REGU_VARIABLE *seq_var; + REGU_VARIABLE_LIST seq_list; + left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); status = MATCH_NOT_FOUND; - if (partition_do_regu_variables_match (pinfo, left, part_expr)) + + /* TODO: This is a temporary implementation for sequence handling. */ + if ((left->type == TYPE_FUNC || right->type == TYPE_FUNC) && part_expr->type == TYPE_ATTR_ID) + { + if ((left->type == TYPE_FUNC && left->value.funcp->ftype == F_SEQUENCE) || + (right->type == TYPE_FUNC && right->value.funcp->ftype == F_SEQUENCE)) + { + seq_var = (left->type == TYPE_FUNC) ? left : right; + seq_list = seq_var->value.funcp->operand; + int i = 0; + + while (seq_list != NULL) + { + // TODO: Need to verify if the value is constant + seq_var = &seq_list->value; + if (seq_var->value.attr_descr.id == part_expr->value.attr_descr.id) + { + break; + } + i++; + seq_list = seq_list->next; + } + + if (seq_list == NULL) + { + /* Attribute not found in sequence */ + // pinfo->error_code = ER_FAILED; + status = MATCH_NOT_FOUND; + break; + } + + DB_VALUE *val = (left->type == TYPE_FUNC) ? &right->value.dbval : &left->value.dbval; + status = partition_prune_db_val (pinfo, val->data.set->set->array[i], op, pruned); + } + } + else if (partition_do_regu_variables_match (pinfo, left, part_expr)) { status = partition_prune (pinfo, right, op, pruned); } From 50a55328ea75d181ece18fa0c7d7be3458f784af Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 26 Dec 2024 11:38:21 +0900 Subject: [PATCH 12/32] Revert "[CBRD-25708] temporary implementation of partition pruning for composite IN conditions" This reverts commit a006090676399cd127113964032319d70c1de540. --- src/query/partition.c | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 77758cc2216..b969b7e9aa6 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -35,7 +35,6 @@ #include "xasl.h" #include "xasl_predicate.hpp" #include "xasl_unpack_info.hpp" -#include "set_object.h" // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -1976,50 +1975,12 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN /* see if part_expr matches right or left */ REGU_VARIABLE *left, *right; PRUNING_OP op; - REGU_VARIABLE *seq_var; - REGU_VARIABLE_LIST seq_list; - left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); status = MATCH_NOT_FOUND; - - /* TODO: This is a temporary implementation for sequence handling. */ - if ((left->type == TYPE_FUNC || right->type == TYPE_FUNC) && part_expr->type == TYPE_ATTR_ID) - { - if ((left->type == TYPE_FUNC && left->value.funcp->ftype == F_SEQUENCE) || - (right->type == TYPE_FUNC && right->value.funcp->ftype == F_SEQUENCE)) - { - seq_var = (left->type == TYPE_FUNC) ? left : right; - seq_list = seq_var->value.funcp->operand; - int i = 0; - - while (seq_list != NULL) - { - // TODO: Need to verify if the value is constant - seq_var = &seq_list->value; - if (seq_var->value.attr_descr.id == part_expr->value.attr_descr.id) - { - break; - } - i++; - seq_list = seq_list->next; - } - - if (seq_list == NULL) - { - /* Attribute not found in sequence */ - // pinfo->error_code = ER_FAILED; - status = MATCH_NOT_FOUND; - break; - } - - DB_VALUE *val = (left->type == TYPE_FUNC) ? &right->value.dbval : &left->value.dbval; - status = partition_prune_db_val (pinfo, val->data.set->set->array[i], op, pruned); - } - } - else if (partition_do_regu_variables_match (pinfo, left, part_expr)) + if (partition_do_regu_variables_match (pinfo, left, part_expr)) { status = partition_prune (pinfo, right, op, pruned); } From 96fd4b46059d524c017f2b0d0edce6fb0a80ff1e Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 26 Dec 2024 12:13:29 +0900 Subject: [PATCH 13/32] [CBRD-25708] modify partition_do_regu_variable_contain function to find columns in expressions --- src/query/partition.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index b969b7e9aa6..e960670ef43 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2217,15 +2217,49 @@ partition_do_regu_variables_contain (PRUNING_CONTEXT * pinfo, const REGU_VARIABL return left == right; } - if (left->type == TYPE_ATTR_ID && right->type == TYPE_INARITH) + if (left->type != TYPE_ATTR_ID) { - if (left->value.attr_descr.id == pinfo->attr_id) + return false; + } + + switch (right->type) + { + case TYPE_ATTR_ID: + if (left->value.attr_descr.id == right->value.attr_descr.id) { return true; } - } + else + { + return false; + } + case TYPE_INARITH: + if (right->value.arithptr->leftptr != NULL) + { + if (partition_do_regu_variables_contain (pinfo, left, right->value.arithptr->leftptr)) + { + return true; + } + } + if (right->value.arithptr->rightptr != NULL) + { + if (partition_do_regu_variables_contain (pinfo, left, right->value.arithptr->rightptr)) + { + return true; + } + } + if (right->value.arithptr->thirdptr != NULL) + { + if (partition_do_regu_variables_contain (pinfo, left, right->value.arithptr->thirdptr)) + { + return true; + } + } + return false; - return false; + default: + return false; + } } /* From 4dfe2a397331a386a285e750bc99afc77399a7a5 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 30 Dec 2024 19:38:26 +0900 Subject: [PATCH 14/32] [CBRD-25708] modify DB_VALUE initialization and clearing in each iteration --- src/query/partition.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index e960670ef43..025e971fab0 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2067,29 +2067,26 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons db_make_null (&val); db_make_null (&casted_val); - db_make_null (&old_collection_val); - db_make_null (&new_collection_val); - db_make_null (&part_key_val); if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { - int size = 0; - if (db_value_type_is_collection (&val)) { collection = db_get_collection (&val); new_collection = db_col_copy (collection); - // new_collection = db_col_create (type, size, NULL); if (new_collection == NULL) { goto cleanup; } - size = db_col_size (collection); + int size = db_col_size (new_collection); for (int i = 0; i < size; i++) { - if (db_col_get (collection, i, &old_collection_val) != NO_ERROR) + db_make_null (&part_key_val); + db_make_null (&old_collection_val); + + if (db_col_get (new_collection, i, &old_collection_val) != NO_ERROR) { goto cleanup; } @@ -2106,7 +2103,6 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons goto cleanup; } - // TODO: need to inspect collection's data type partition_cache_dbvalp (part_expr, &casted_val); } else @@ -2120,9 +2116,16 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons { db_col_put (new_collection, i, &part_key_val); } + else + { + goto cleanup; + } } + pr_clear_value (&part_key_val); + pr_clear_value (&old_collection_val); } + db_make_null (&new_collection_val); if (db_make_collection (&new_collection_val, new_collection) != NO_ERROR) { goto cleanup; @@ -2150,9 +2153,9 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons { partition_cache_dbvalp (part_expr, &val); } - } - status = partition_prune (pinfo, part_expr, op, pruned); + status = partition_prune (pinfo, part_expr, op, pruned); + } } cleanup: From 5b7a7e8dfc27d737372a409b8153c0d93b94ab16 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 31 Dec 2024 11:57:24 +0900 Subject: [PATCH 15/32] [CBRD-25708] remove unnecessary code --- src/query/partition.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 025e971fab0..50b6ddd5b35 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2065,9 +2065,6 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons TP_DOMAIN_STATUS dom_status; bool is_value; - db_make_null (&val); - db_make_null (&casted_val); - if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { if (db_value_type_is_collection (&val)) @@ -2081,10 +2078,11 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons } int size = db_col_size (new_collection); + for (int i = 0; i < size; i++) { - db_make_null (&part_key_val); - db_make_null (&old_collection_val); + pr_clear_value (&part_key_val); + pr_clear_value (&old_collection_val); if (db_col_get (new_collection, i, &old_collection_val) != NO_ERROR) { @@ -2121,11 +2119,8 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons goto cleanup; } } - pr_clear_value (&part_key_val); - pr_clear_value (&old_collection_val); } - db_make_null (&new_collection_val); if (db_make_collection (&new_collection_val, new_collection) != NO_ERROR) { goto cleanup; @@ -2160,10 +2155,6 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons cleanup: partition_cache_dbvalp (part_expr, NULL); - if (new_collection != NULL) - { - db_col_free (new_collection); - } pr_clear_value (&old_collection_val); pr_clear_value (&new_collection_val); pr_clear_value (&part_key_val); @@ -2872,7 +2863,11 @@ partition_set_cache_info_for_expr (REGU_VARIABLE * var, ATTR_ID attr_id, HEAP_CA static void partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val) { - assert (var != NULL); + if (var == NULL) + { + return; + } + switch (var->type) { case TYPE_ATTR_ID: @@ -2880,20 +2875,10 @@ partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val) break; case TYPE_INARITH: - if (var->value.arithptr->leftptr != NULL) - { - partition_cache_dbvalp (var->value.arithptr->leftptr, val); - } - - if (var->value.arithptr->rightptr != NULL) - { - partition_cache_dbvalp (var->value.arithptr->rightptr, val); - } + (void) partition_cache_dbvalp (var->value.arithptr->leftptr, val); + (void) partition_cache_dbvalp (var->value.arithptr->rightptr, val); + (void) partition_cache_dbvalp (var->value.arithptr->thirdptr, val); - if (var->value.arithptr->thirdptr != NULL) - { - partition_cache_dbvalp (var->value.arithptr->thirdptr, val); - } default: break; } From 1d5d6ccf200a4b2b74f72e41ad1d55849ca3082e Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 31 Dec 2024 12:50:07 +0900 Subject: [PATCH 16/32] [CBRD-25708] revert changes except partition.c --- src/sp/jsp_cl.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/sp/jsp_cl.cpp b/src/sp/jsp_cl.cpp index 0ae9498bff5..873446a8d6f 100644 --- a/src/sp/jsp_cl.cpp +++ b/src/sp/jsp_cl.cpp @@ -1856,7 +1856,7 @@ alter_stored_procedure_code (PARSER_CONTEXT *parser, MOP sp_mop, const char *nam goto error; } - db_make_string (&value, sp_info.target_class.data ()); + db_make_string (&value, code_info.name.data ()); err = dbt_put_internal (obt_p, SP_ATTR_TARGET_CLASS, &value); pr_clear_value (&value); if (err != NO_ERROR) @@ -1864,14 +1864,6 @@ alter_stored_procedure_code (PARSER_CONTEXT *parser, MOP sp_mop, const char *nam goto error; } - db_make_string (&value, sp_info.target_method.data ()); - err = dbt_put_internal (obt_p, SP_ATTR_TARGET_METHOD, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - object_p = dbt_finish_object (obt_p); if (!object_p) { From e8655662283f095f8aaa5adb6f04ff37d915f887 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 31 Dec 2024 13:35:11 +0900 Subject: [PATCH 17/32] [CBRD-25708] remove unnecessary changes and clarify function name --- src/query/partition.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 50b6ddd5b35..311fab3f6d1 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -169,7 +169,7 @@ static int partition_attrinfo_get_key (THREAD_ENTRY * thread_p, PRUNING_CONTEXT /* misc pruning functions */ static bool partition_decrement_value (DB_VALUE * val); -static void partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val); +static void partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val); static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr); static MATCH_STATUS partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right, REGU_VARIABLE * part_expr, const PRUNING_OP op, @@ -1975,6 +1975,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN /* see if part_expr matches right or left */ REGU_VARIABLE *left, *right; PRUNING_OP op; + left = pr->pe.m_eval_term.et.et_comp.lhs; right = pr->pe.m_eval_term.et.et_comp.rhs; op = partition_rel_op_to_pruning_op (pr->pe.m_eval_term.et.et_comp.rel_op); @@ -2101,11 +2102,11 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons goto cleanup; } - partition_cache_dbvalp (part_expr, &casted_val); + partition_set_cache_dbvalp_for_attribute (part_expr, &casted_val); } else { - partition_cache_dbvalp (part_expr, &old_collection_val); + partition_set_cache_dbvalp_for_attribute (part_expr, &old_collection_val); } if (partition_get_value_from_regu_var (pinfo, part_expr, &part_key_val, &is_value) == NO_ERROR) @@ -2142,11 +2143,11 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons goto cleanup; } - partition_cache_dbvalp (part_expr, &casted_val); + partition_set_cache_dbvalp_for_attribute (part_expr, &casted_val); } else { - partition_cache_dbvalp (part_expr, &val); + partition_set_cache_dbvalp_for_attribute (part_expr, &val); } status = partition_prune (pinfo, part_expr, op, pruned); @@ -2154,7 +2155,7 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons } cleanup: - partition_cache_dbvalp (part_expr, NULL); + partition_set_cache_dbvalp_for_attribute (part_expr, NULL); pr_clear_value (&old_collection_val); pr_clear_value (&new_collection_val); pr_clear_value (&part_key_val); @@ -2861,7 +2862,7 @@ partition_set_cache_info_for_expr (REGU_VARIABLE * var, ATTR_ID attr_id, HEAP_CA } static void -partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val) +partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val) { if (var == NULL) { @@ -2875,9 +2876,9 @@ partition_cache_dbvalp (REGU_VARIABLE * var, DB_VALUE * val) break; case TYPE_INARITH: - (void) partition_cache_dbvalp (var->value.arithptr->leftptr, val); - (void) partition_cache_dbvalp (var->value.arithptr->rightptr, val); - (void) partition_cache_dbvalp (var->value.arithptr->thirdptr, val); + (void) partition_set_cache_dbvalp_for_attribute (var->value.arithptr->leftptr, val); + (void) partition_set_cache_dbvalp_for_attribute (var->value.arithptr->rightptr, val); + (void) partition_set_cache_dbvalp_for_attribute (var->value.arithptr->thirdptr, val); default: break; From 018e7b695d751947e29ea3b4be33872e7c9aae2e Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 6 Jan 2025 14:58:43 +0900 Subject: [PATCH 18/32] [CBRD-25708] add comments --- src/query/partition.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/query/partition.c b/src/query/partition.c index 311fab3f6d1..08f947e741d 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1727,6 +1727,10 @@ partition_is_reguvar_const (const REGU_VARIABLE * regu_var) } case TYPE_ATTR_ID: { + /* For TYPE_ATTR_ID, if cache_dbvalp is not NULL, it means the attribute value + * has been cached and can be treated as a constant. + * This happens when attribute values are cached in pred_expr's attr_cache. + * See fetch_peek_dbval for details. */ if (regu_var->value.attr_descr.cache_dbvalp == NULL) { return false; @@ -2872,6 +2876,8 @@ partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val) switch (var->type) { case TYPE_ATTR_ID: + /* Since partition key expression can only contain a single column, + * we can skip checking attribute id and simply check if the value is cached. */ var->value.attr_descr.cache_dbvalp = val; break; From 206317318debb722172fe3b0e1f3a1316a058fb8 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 6 Jan 2025 15:02:22 +0900 Subject: [PATCH 19/32] [CBRD-25708] fix partition pruning to consider all values in ALSM expression --- src/query/partition.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 08f947e741d..dd6198b78b9 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2075,21 +2075,21 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons if (db_value_type_is_collection (&val)) { collection = db_get_collection (&val); - new_collection = db_col_copy (collection); + DB_TYPE domain_type = DB_VALUE_DOMAIN_TYPE(&val); + int size = db_col_size (collection); + new_collection = db_col_create (domain_type, size, NULL); if (new_collection == NULL) { goto cleanup; } - int size = db_col_size (new_collection); - for (int i = 0; i < size; i++) { pr_clear_value (&part_key_val); pr_clear_value (&old_collection_val); - if (db_col_get (new_collection, i, &old_collection_val) != NO_ERROR) + if (db_col_get (collection, i, &old_collection_val) != NO_ERROR) { goto cleanup; } From b4efea680193203450d6c145a6992c5287f87ae3 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 6 Jan 2025 16:23:19 +0900 Subject: [PATCH 20/32] [CBRD-25708] fix partition pruning to consider all values in ALSM expression --- src/query/partition.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index dd6198b78b9..111f88f643d 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2070,15 +2070,22 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons TP_DOMAIN_STATUS dom_status; bool is_value; + db_make_null (&val); + db_make_null (&casted_val); + db_make_null (&part_key_val); + if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { if (db_value_type_is_collection (&val)) { + db_make_null (&old_collection_val); + db_make_null (&new_collection_val); + + DB_TYPE domain_type = DB_VALUE_DOMAIN_TYPE (&val); collection = db_get_collection (&val); - DB_TYPE domain_type = DB_VALUE_DOMAIN_TYPE(&val); - int size = db_col_size (collection); - new_collection = db_col_create (domain_type, size, NULL); + int size = db_col_size (collection); + new_collection = db_col_create (domain_type, size, NULL); if (new_collection == NULL) { goto cleanup; @@ -2088,6 +2095,7 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons { pr_clear_value (&part_key_val); pr_clear_value (&old_collection_val); + pr_clear_value (&casted_val); if (db_col_get (collection, i, &old_collection_val) != NO_ERROR) { From c85ff5f7737ff11fd00a7623714a85942c9c7aa7 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 6 Jan 2025 17:35:33 +0900 Subject: [PATCH 21/32] [CBRD-25708] add db_make_null to prevent errors on repeated query execution --- src/query/partition.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 111f88f643d..fb65c2ec734 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1346,6 +1346,9 @@ partition_prune_range (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUN int rmin = DB_UNK, rmax = DB_UNK; MATCH_STATUS status; + db_make_null (&min); + db_make_null (&max); + if (db_value_type_is_collection (val)) { PRUNING_BITSET new_pruned; @@ -1395,9 +1398,6 @@ partition_prune_range (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUN goto cleanup; } - db_make_null (&min); - db_make_null (&max); - for (i = 0; i < PARTITIONS_COUNT (pinfo); i++) { part = &pinfo->partitions[i + 1]; @@ -2073,23 +2073,17 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons db_make_null (&val); db_make_null (&casted_val); db_make_null (&part_key_val); + db_make_null (&old_collection_val); + db_make_null (&new_collection_val); if (partition_get_value_from_regu_var (pinfo, right, &val, &is_value) == NO_ERROR) { if (db_value_type_is_collection (&val)) { - db_make_null (&old_collection_val); - db_make_null (&new_collection_val); - DB_TYPE domain_type = DB_VALUE_DOMAIN_TYPE (&val); collection = db_get_collection (&val); int size = db_col_size (collection); - new_collection = db_col_create (domain_type, size, NULL); - if (new_collection == NULL) - { - goto cleanup; - } for (int i = 0; i < size; i++) { From 7b24d1f35a000c52ee2bedd13b2aac6f2afabff5 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 6 Jan 2025 18:06:17 +0900 Subject: [PATCH 22/32] [CBRD-25708] remove unnecessary goto statements in partition_prune_range --- src/query/partition.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index fb65c2ec734..36834a5fd04 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1346,9 +1346,6 @@ partition_prune_range (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUN int rmin = DB_UNK, rmax = DB_UNK; MATCH_STATUS status; - db_make_null (&min); - db_make_null (&max); - if (db_value_type_is_collection (val)) { PRUNING_BITSET new_pruned; @@ -1395,9 +1392,12 @@ partition_prune_range (PRUNING_CONTEXT * pinfo, const DB_VALUE * val, const PRUN pr_clear_value (&col); } - goto cleanup; + return status; } + db_make_null (&min); + db_make_null (&max); + for (i = 0; i < PARTITIONS_COUNT (pinfo); i++) { part = &pinfo->partitions[i + 1]; From 9cb18fcab6981c6330865eee98253672f76d01c8 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 6 Jan 2025 18:11:33 +0900 Subject: [PATCH 23/32] [CBRD-25708] apply code review feedback --- src/query/partition.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/partition.c b/src/query/partition.c index 36834a5fd04..3f031aa5b0e 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2215,7 +2215,7 @@ partition_do_regu_variables_contain (PRUNING_CONTEXT * pinfo, const REGU_VARIABL { if (left == NULL || right == NULL) { - return left == right; + return false; } if (left->type != TYPE_ATTR_ID) From 7ce3f735de88d5783cd9fcc046c7c298e6be1ed0 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 13 Jan 2025 14:56:27 +0900 Subject: [PATCH 24/32] [CBRD-25708] update comment for partition_is_reguvar_const function --- src/query/partition.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 3f031aa5b0e..4324443923f 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1727,10 +1727,10 @@ partition_is_reguvar_const (const REGU_VARIABLE * regu_var) } case TYPE_ATTR_ID: { - /* For TYPE_ATTR_ID, if cache_dbvalp is not NULL, it means the attribute value - * has been cached and can be treated as a constant. - * This happens when attribute values are cached in pred_expr's attr_cache. - * See fetch_peek_dbval for details. */ + /* TYPE_ATTR_ID normally represents a non-constant. + * As an exception, in partition.c, partition_set_cache_dbvalp_for_attribute + * can cache a db_value in cache_dbvalp for TYPE_ATTR_ID. + * This cached value is used specifically for partition pruning purposes. */ if (regu_var->value.attr_descr.cache_dbvalp == NULL) { return false; From 3d4d21b7b32cf68c2dc1246950895cc184f68cb4 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 13 Jan 2025 16:44:08 +0900 Subject: [PATCH 25/32] [CBRD-25708] add comments for newly added partition functions --- src/query/partition.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/query/partition.c b/src/query/partition.c index 4324443923f..a5ae7447346 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2058,6 +2058,16 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN return status; } +/* + * partition_prune_arith () - perform pruning on the specified partitions list based on partition key expression + * return : match status + * pinfo (in) : pruning context + * left (in) : left operand + * right (in) : right operand + * part_expr (in) : partition key expression + * op (in) : pruning operator + * pruned (in/out): pruned partitions + */ static MATCH_STATUS partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right, REGU_VARIABLE * part_expr, const PRUNING_OP op, PRUNING_BITSET * pruned) @@ -2171,6 +2181,13 @@ partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, cons return status; } +/* + * partition_supports_pruning_op_for_function () - check if the specified pruning operator is supported for the + * specified partition key expression + * return : true if supported, false otherwise + * op (in) : pruning operator + * part_expr (in) : partition key expression + */ static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr) { @@ -2210,6 +2227,13 @@ partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARI } +/* + * partition_do_regu_variables_contain () - check if the left regu variable contains the right regu variable + * return : true if the left regu variable contains the right regu variable, false otherwise + * pinfo (in) : pruning context + * left (in) : left regu variable, must be TYPE_ATTR_ID + * right (in) : right regu variable + */ static bool partition_do_regu_variables_contain (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right) { @@ -2867,6 +2891,13 @@ partition_set_cache_info_for_expr (REGU_VARIABLE * var, ATTR_ID attr_id, HEAP_CA } } +/* + * partition_set_cache_dbvalp_for_attribute () - set cache_dbvalp for the + * partition key expression + * return : void + * var (in/out) : expression to cache + * val (in) : value to be cached + */ static void partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val) { From d7a45214bc3d5a946fb80cdc1eb8e58c2c62c40e Mon Sep 17 00:00:00 2001 From: Hamkua Date: Mon, 13 Jan 2025 16:57:29 +0900 Subject: [PATCH 26/32] [CBRD-25708] rename partition_prune_arith to partition_prune_for_function --- src/query/partition.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index a5ae7447346..0130b5f1c13 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -171,9 +171,9 @@ static bool partition_decrement_value (DB_VALUE * val); static void partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val); static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr); -static MATCH_STATUS partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, - const REGU_VARIABLE * right, REGU_VARIABLE * part_expr, const PRUNING_OP op, - PRUNING_BITSET * pruned); +static MATCH_STATUS partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, + const REGU_VARIABLE * right, REGU_VARIABLE * part_expr, + const PRUNING_OP op, PRUNING_BITSET * pruned); /* PRUNING_BITSET manipulation functions */ @@ -1997,11 +1997,11 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { if (partition_do_regu_variables_contain (pinfo, left, part_expr)) { - status = partition_prune_arith (pinfo, left, right, part_expr, op, pruned); + status = partition_prune_for_function (pinfo, left, right, part_expr, op, pruned); } else if (partition_do_regu_variables_contain (pinfo, right, part_expr)) { - status = partition_prune_arith (pinfo, right, left, part_expr, op, pruned); + status = partition_prune_for_function (pinfo, right, left, part_expr, op, pruned); } } break; @@ -2035,7 +2035,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN { if (partition_do_regu_variables_contain (pinfo, regu, part_expr)) { - status = partition_prune_arith (pinfo, regu, list, part_expr, op, pruned); + status = partition_prune_for_function (pinfo, regu, list, part_expr, op, pruned); } } } @@ -2059,7 +2059,7 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN } /* - * partition_prune_arith () - perform pruning on the specified partitions list based on partition key expression + * partition_prune_for_function () - perform pruning on the specified partitions list based on partition key expression * return : match status * pinfo (in) : pruning context * left (in) : left operand @@ -2069,8 +2069,8 @@ partition_match_pred_expr (PRUNING_CONTEXT * pinfo, const PRED_EXPR * pr, PRUNIN * pruned (in/out): pruned partitions */ static MATCH_STATUS -partition_prune_arith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right, - REGU_VARIABLE * part_expr, const PRUNING_OP op, PRUNING_BITSET * pruned) +partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * left, const REGU_VARIABLE * right, + REGU_VARIABLE * part_expr, const PRUNING_OP op, PRUNING_BITSET * pruned) { MATCH_STATUS status = MATCH_NOT_FOUND; DB_VALUE val, casted_val; From 12bdd5fdb553b9f0f1d36f75a7610f45c5a8e3c1 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Tue, 14 Jan 2025 17:30:41 +0900 Subject: [PATCH 27/32] [CBRD-25708] store error code in pruning_context and update status --- src/query/partition.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/query/partition.c b/src/query/partition.c index 0130b5f1c13..438a90a1f3b 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2093,7 +2093,18 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef DB_TYPE domain_type = DB_VALUE_DOMAIN_TYPE (&val); collection = db_get_collection (&val); int size = db_col_size (collection); + if (size <= 0) + { + pinfo->error_code = ER_FAILED; + goto cleanup; + } + new_collection = db_col_create (domain_type, size, NULL); + if (new_collection == NULL) + { + pinfo->error_code = ER_FAILED; + goto cleanup; + } for (int i = 0; i < size; i++) { @@ -2103,6 +2114,7 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef if (db_col_get (collection, i, &old_collection_val) != NO_ERROR) { + pinfo->error_code = ER_FAILED; goto cleanup; } @@ -2129,10 +2141,15 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef { if (is_value) { - db_col_put (new_collection, i, &part_key_val); + if (db_col_put (new_collection, i, &part_key_val) != NO_ERROR) + { + pinfo->error_code = ER_FAILED; + goto cleanup; + } } else { + pinfo->error_code = ER_FAILED; goto cleanup; } } @@ -2140,6 +2157,7 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef if (db_make_collection (&new_collection_val, new_collection) != NO_ERROR) { + pinfo->error_code = ER_FAILED; goto cleanup; } @@ -2171,6 +2189,11 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef } cleanup: + if (pinfo->error_code != NO_ERROR) + { + status = MATCH_NOT_FOUND; + } + partition_set_cache_dbvalp_for_attribute (part_expr, NULL); pr_clear_value (&old_collection_val); pr_clear_value (&new_collection_val); From d5a70e25313f13c26736ce651508da11f07872e0 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 16 Jan 2025 13:45:28 +0900 Subject: [PATCH 28/32] [CBRD-25708] apply partition pruning to ELT and INSERT functions --- src/query/partition.c | 117 +++++++++++++++++++++++++++++++++++------- 1 file changed, 98 insertions(+), 19 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 3f7639bd15a..2609e0322df 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -1650,16 +1650,31 @@ partition_get_value_from_regu_var (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE case TYPE_FUNC: { - if (regu->value.funcp->ftype != F_MIDXKEY) + if (regu->value.funcp->ftype == F_MIDXKEY) + { + if (partition_get_value_from_key (pinfo, regu, value_p, is_value) != NO_ERROR) + { + goto error; + } + } + else if (regu->value.funcp->ftype == F_ELT || regu->value.funcp->ftype == F_INSERT_SUBSTRING) + { + /* + * Exceptionally use partition_get_value_from_inarith for these specific functions + * as they can be evaluated in the same way as arithmetic operations. + * Other TYPE_FUNC types are not handled here. + */ + if (partition_get_value_from_inarith (pinfo, regu, value_p, is_value) != NO_ERROR) + { + goto error; + } + } + else { *is_value = false; db_make_null (value_p); return NO_ERROR; } - if (partition_get_value_from_key (pinfo, regu, value_p, is_value) != NO_ERROR) - { - goto error; - } break; } @@ -1696,6 +1711,8 @@ partition_get_value_from_regu_var (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE static bool partition_is_reguvar_const (const REGU_VARIABLE * regu_var) { + REGU_VARIABLE_LIST op; + if (regu_var == NULL) { return false; @@ -1726,6 +1743,19 @@ partition_is_reguvar_const (const REGU_VARIABLE * regu_var) /* either all arguments are constants of this is an expression with no arguments */ return true; } + case TYPE_FUNC: + { + op = regu_var->value.funcp->operand; + while (op != NULL) + { + if (!partition_is_reguvar_const (&op->value)) + { + return false; + } + op = op->next; + } + return true; + } case TYPE_ATTR_ID: { /* TYPE_ATTR_ID normally represents a non-constant. @@ -1843,14 +1873,17 @@ partition_get_value_from_key (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * key } /* - * partition_get_value_from_key () - get a value from a reguvariable of type - * INARITH + * partition_get_value_from_inarith () - get a value from a reguvariable of type TYPE_INARITH, TYPE_FUNC (pseudo constants) * return : error code or NO_ERROR * pinfo (in) : pruning context * src (in) : source reguvariable * value_p (in/out) : the requested value * is_value (in/out) : set to true if the value was successfully fetched * + * Note: This function is primarily used for TYPE_INARITH operations. + * Additionally, it handles F_ELT and F_INSERT_SUBSTRING functions since they + * can be evaluated in the same way as arithmetic operations. + * Other TYPE_FUNC types are not handled here. */ static int partition_get_value_from_inarith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * src, DB_VALUE * value_p, @@ -1861,7 +1894,7 @@ partition_get_value_from_inarith (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * assert_release (src != NULL); assert_release (value_p != NULL); - assert_release (src->type == TYPE_INARITH); + assert_release (src->type == TYPE_INARITH || src->type == TYPE_FUNC); *is_value = false; db_make_null (value_p); @@ -2216,35 +2249,54 @@ static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr) { OPERATOR_TYPE opcode; + FUNC_CODE func_code; - if (part_expr->type != TYPE_INARITH) + if (part_expr->type != TYPE_INARITH && part_expr->type != TYPE_FUNC) { return false; } - opcode = part_expr->value.arithptr->opcode; - switch (op) { case PO_LT: case PO_LE: case PO_GT: case PO_GE: - switch (opcode) + if (part_expr->type == TYPE_INARITH) { - case T_YEAR: - case T_TODAYS: - case T_UNIX_TIMESTAMP: - return true; - default: - return false; + opcode = part_expr->value.arithptr->opcode; + + switch (opcode) + { + case T_YEAR: + case T_TODAYS: + case T_UNIX_TIMESTAMP: + return true; + default: + return false; + } } + return false; + case PO_EQ: case PO_NE: case PO_IN: case PO_NOT_IN: case PO_IS_NULL: + if (part_expr->type == TYPE_FUNC) + { + func_code = part_expr->value.funcp->ftype; + switch (func_code) + { + case F_ELT: + case F_INSERT_SUBSTRING: + return true; + default: + return false; + } + } return true; + default: return false; } @@ -2306,6 +2358,22 @@ partition_do_regu_variables_contain (PRUNING_CONTEXT * pinfo, const REGU_VARIABL } return false; + case TYPE_FUNC: + if (right->value.funcp->operand != NULL) + { + REGU_VARIABLE_LIST op = right->value.funcp->operand; + + while (op != NULL) + { + if (partition_do_regu_variables_contain (pinfo, left, &op->value)) + { + return true; + } + op = op->next; + } + } + return false; + default: return false; } @@ -2925,6 +2993,7 @@ partition_set_cache_info_for_expr (REGU_VARIABLE * var, ATTR_ID attr_id, HEAP_CA static void partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val) { + REGU_VARIABLE_LIST op = NULL; if (var == NULL) { return; @@ -2942,9 +3011,19 @@ partition_set_cache_dbvalp_for_attribute (REGU_VARIABLE * var, DB_VALUE * val) (void) partition_set_cache_dbvalp_for_attribute (var->value.arithptr->leftptr, val); (void) partition_set_cache_dbvalp_for_attribute (var->value.arithptr->rightptr, val); (void) partition_set_cache_dbvalp_for_attribute (var->value.arithptr->thirdptr, val); + break; + case TYPE_FUNC: + op = var->value.funcp->operand; - default: + while (op != NULL) + { + (void) partition_set_cache_dbvalp_for_attribute (&op->value, val); + op = op->next; + } break; + + default: + return; } } From 75d5efce4edf23b1f8c6597134785023163831b1 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 16 Jan 2025 14:16:28 +0900 Subject: [PATCH 29/32] Sync jsp_cl.cpp with upstream/feature/partition-table --- src/sp/jsp_cl.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/sp/jsp_cl.cpp b/src/sp/jsp_cl.cpp index 7979ce97095..f8d728c2802 100644 --- a/src/sp/jsp_cl.cpp +++ b/src/sp/jsp_cl.cpp @@ -1905,7 +1905,7 @@ alter_stored_procedure_code (PARSER_CONTEXT *parser, MOP sp_mop, const char *nam goto error; } - db_make_string (&value, code_info.name.data ()); + db_make_string (&value, sp_info.target_class.data ()); err = dbt_put_internal (obt_p, SP_ATTR_TARGET_CLASS, &value); pr_clear_value (&value); if (err != NO_ERROR) @@ -1913,6 +1913,14 @@ alter_stored_procedure_code (PARSER_CONTEXT *parser, MOP sp_mop, const char *nam goto error; } + db_make_string (&value, sp_info.target_method.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_TARGET_METHOD, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + object_p = dbt_finish_object (obt_p); if (!object_p) { From 465fc9b7eaa96f1ff03aad111ee7ebed211a9ed6 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Wed, 22 Jan 2025 18:17:35 +0900 Subject: [PATCH 30/32] [CBRD-25708] restrict partition pruning to integer-returning expressions --- src/query/partition.c | 74 ++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 2609e0322df..69ee2d908d0 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2248,59 +2248,55 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef static bool partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARIABLE * part_expr) { - OPERATOR_TYPE opcode; - FUNC_CODE func_code; - - if (part_expr->type != TYPE_INARITH && part_expr->type != TYPE_FUNC) + if (part_expr->type != TYPE_INARITH) { return false; } - switch (op) + switch (part_expr->value.arithptr->opcode) { - case PO_LT: - case PO_LE: - case PO_GT: - case PO_GE: - if (part_expr->type == TYPE_INARITH) + /* although partition key expressions allow various functions and types, + * partition pruning is restricted to functions returning integer types */ + case T_YEAR: + case T_TODAYS: + case T_UNIX_TIMESTAMP: + if (op == PO_EQ || op == PO_IN || op == PO_GE || op == PO_GT || op == PO_LE || op == PO_LT) { - opcode = part_expr->value.arithptr->opcode; - - switch (opcode) - { - case T_YEAR: - case T_TODAYS: - case T_UNIX_TIMESTAMP: - return true; - default: - return false; - } + return true; } - return false; + break; - case PO_EQ: - case PO_NE: - case PO_IN: - case PO_NOT_IN: - case PO_IS_NULL: - if (part_expr->type == TYPE_FUNC) + case T_ADD: + case T_SUB: + case T_MUL: + case T_DIV: + case T_ABS: + case T_CEIL: + case T_DATEDIFF: + case T_DAY: + case T_DAYOFWEEK: + case T_DAYOFYEAR: + case T_EXTRACT: + case T_FLOOR: + case T_HOUR: + case T_SECOND: + case T_MINUTE: + case T_MOD: + case T_MONTH: + case T_QUARTER: + case T_TIMETOSEC: + case T_WEEKDAY: + if (op == PO_EQ || op == PO_IN) { - func_code = part_expr->value.funcp->ftype; - switch (func_code) - { - case F_ELT: - case F_INSERT_SUBSTRING: - return true; - default: - return false; - } + return true; } - return true; + break; default: - return false; + break; } + return false; } /* From 11db4d6150adbae761338a4f4b3c2f3691c01ae0 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 23 Jan 2025 14:25:59 +0900 Subject: [PATCH 31/32] [CBRD-25708] modify allowed partition pruning operators --- src/query/partition.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/query/partition.c b/src/query/partition.c index 69ee2d908d0..4f714b84670 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2260,11 +2260,7 @@ partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARI case T_YEAR: case T_TODAYS: case T_UNIX_TIMESTAMP: - if (op == PO_EQ || op == PO_IN || op == PO_GE || op == PO_GT || op == PO_LE || op == PO_LT) - { - return true; - } - break; + return true; case T_ADD: case T_SUB: @@ -2286,7 +2282,7 @@ partition_supports_pruning_op_for_function (const PRUNING_OP op, const REGU_VARI case T_QUARTER: case T_TIMETOSEC: case T_WEEKDAY: - if (op == PO_EQ || op == PO_IN) + if (op != PO_LT && op != PO_LE && op != PO_GT && op != PO_GE) { return true; } From 6d3c9016bc89a47c8befc34a560e9ec986eece21 Mon Sep 17 00:00:00 2001 From: Hamkua Date: Thu, 23 Jan 2025 16:29:30 +0900 Subject: [PATCH 32/32] [CBRD-25708] enable partition pruning for IS NULL predicate --- src/query/partition.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/query/partition.c b/src/query/partition.c index 4f714b84670..29175a88d14 100644 --- a/src/query/partition.c +++ b/src/query/partition.c @@ -2114,6 +2114,12 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef TP_DOMAIN_STATUS dom_status; bool is_value; + if (right == NULL) + { + status = partition_prune (pinfo, right, op, pruned); + return status; + } + db_make_null (&val); db_make_null (&casted_val); db_make_null (&part_key_val); @@ -2152,7 +2158,17 @@ partition_prune_for_function (PRUNING_CONTEXT * pinfo, const REGU_VARIABLE * lef goto cleanup; } - if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&old_collection_val)) + if (db_value_is_null (&old_collection_val)) + { + if (db_col_put (new_collection, i, &old_collection_val) != NO_ERROR) + { + pinfo->error_code = ER_FAILED; + goto cleanup; + } + continue; + } + + else if (TP_DOMAIN_TYPE (left->domain) != DB_VALUE_TYPE (&old_collection_val)) { dom_status = tp_value_cast (&old_collection_val, &casted_val, left->domain, false);