[FEAT MERGE] patch new query range
Co-authored-by: ChangerR <dingjinchengyx@163.com> Co-authored-by: akaError <lzg020616@163.com> Co-authored-by: xianyu-w <707512433@qq.com>
This commit is contained in:
parent
e64abec880
commit
e19b90c9ad
2
deps/oblib/src/common/ob_common_types.h
vendored
2
deps/oblib/src/common/ob_common_types.h
vendored
@ -264,6 +264,8 @@ struct ObQueryFlag
|
||||
set_not_use_block_cache();
|
||||
set_not_use_bloomfilter_cache();
|
||||
}
|
||||
inline void set_is_new_query_range() { is_new_query_range_ = true; }
|
||||
inline bool is_new_query_range() const { return is_new_query_range_; }
|
||||
inline bool is_mr_mview_refresh_base_scan() const { return RefreshMode == mr_mv_scan_; }
|
||||
inline bool is_mr_rt_mview_base_scan() const { return RealTimeMode == mr_mv_scan_; }
|
||||
inline bool is_mr_mview_query() const { return is_mr_mview_refresh_base_scan() || is_mr_rt_mview_base_scan(); }
|
||||
|
27
deps/oblib/src/common/ob_range.h
vendored
27
deps/oblib/src/common/ob_range.h
vendored
@ -470,6 +470,33 @@ public:
|
||||
return cmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* compare endkey of current range with startkey of other range
|
||||
* if endkey is equal to startkey, return value follows these rules:
|
||||
* 1. if last obj of endkey is max_value or min value, compare result is 0
|
||||
* 2. if last obj of endkey is not max_value or min_value, check inclusive_end
|
||||
* of current range and inclusive_start of other range. current range only
|
||||
* less than other range when inclusive_end and inclusive_start are both false.
|
||||
*/
|
||||
inline int compare_endkey_with_startkey(const ObNewRange &r) const
|
||||
{
|
||||
int cmp = 0;
|
||||
if (end_key_.is_max_row()) {
|
||||
cmp = 1;
|
||||
} else {
|
||||
cmp = end_key_.compare(r.start_key_);
|
||||
if (0 == cmp) {
|
||||
if (end_key_.get_obj_ptr()[end_key_.get_obj_cnt() - 1].is_max_value() ||
|
||||
end_key_.get_obj_ptr()[end_key_.get_obj_cnt() - 1].is_min_value()) {
|
||||
// do nothing
|
||||
} else if (!border_flag_.inclusive_end() && !r.border_flag_.inclusive_start()) {
|
||||
cmp = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
inline bool is_valid() const { return !empty(); }
|
||||
|
||||
inline bool empty() const
|
||||
|
2
deps/oblib/src/lib/ob_name_def.h
vendored
2
deps/oblib/src/lib/ob_name_def.h
vendored
@ -1138,6 +1138,8 @@
|
||||
|
||||
#define N_INEER_IS_TRUE "inner_is_true"
|
||||
#define N_INNER_DECODE_LIKE "inner_decode_like"
|
||||
#define N_INNER_DOUBLE_TO_INT "inner_double_to_int"
|
||||
#define N_INNER_DECIMAL_TO_YEAR "inner_decimal_to_year"
|
||||
#define N_BM25 "bm25"
|
||||
#define N_EXTRACT_CERT_EXPIRED_TIME "extract_cert_expired_time"
|
||||
#define N_INNER_ROW_CMP_VALUE "inner_row_cmp_value"
|
||||
|
@ -2740,7 +2740,8 @@ typedef enum ObOutlineType
|
||||
|| ((op) == T_OP_OUTPUT_PACK) \
|
||||
|| ((op) == T_FUN_SYS_JSON_OBJECT) \
|
||||
|| ((op) == T_FUN_SYS_JSON_ARRAY) \
|
||||
|| ((op) == T_OP_TO_OUTFILE_ROW)) \
|
||||
|| ((op) == T_OP_TO_OUTFILE_ROW) \
|
||||
|| ((op) == T_FUNC_SYS_INNER_IS_TRUE)) \
|
||||
|
||||
|
||||
|
||||
|
@ -34,7 +34,6 @@ namespace sql
|
||||
class ObDASTabletLoc;
|
||||
class ObExecContext;
|
||||
class ObExternalTableAccessService;
|
||||
class ObQueryRange;
|
||||
class ObExprRegexContext;
|
||||
class ObExprRegexpSessionVariables;
|
||||
}
|
||||
|
@ -2105,9 +2105,9 @@ DEF_BOOL(_enable_range_extraction_for_not_in, OB_TENANT_PARAMETER, "True",
|
||||
"Enable extract query range for not in predicate",
|
||||
ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));
|
||||
|
||||
// DEF_BOOL(_enable_new_query_range_extraction, OB_TENANT_PARAMETER, "True",
|
||||
// "decide whether use new algorithm to extract query range.",
|
||||
// ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));
|
||||
DEF_BOOL(_enable_new_query_range_extraction, OB_TENANT_PARAMETER, "True",
|
||||
"decide whether use new algorithm to extract query range.",
|
||||
ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));
|
||||
DEF_TIME(_ha_diagnose_history_recycle_interval, OB_CLUSTER_PARAMETER, "7d", "[2m, 180d]",
|
||||
"The recycle interval time of diagnostic history data. Range: [2m, 180d]",
|
||||
ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));
|
||||
|
@ -427,6 +427,9 @@ ob_set_subtarget(ob_sql engine_expr
|
||||
engine/expr/ob_expr_ifnull.cpp
|
||||
engine/expr/ob_expr_inet.cpp
|
||||
engine/expr/ob_expr_initcap.cpp
|
||||
engine/expr/ob_expr_inner_decode_like.cpp
|
||||
engine/expr/ob_expr_inner_double_to_int.cpp
|
||||
engine/expr/ob_expr_inner_decimal_to_year.cpp
|
||||
engine/expr/ob_expr_inner_trim.cpp
|
||||
engine/expr/ob_expr_insert.cpp
|
||||
engine/expr/ob_expr_instr.cpp
|
||||
@ -1410,6 +1413,10 @@ ob_set_subtarget(ob_sql rewrite
|
||||
rewrite/ob_key_part.cpp
|
||||
rewrite/ob_predicate_deduce.cpp
|
||||
rewrite/ob_query_range.cpp
|
||||
rewrite/ob_expr_range_converter.cpp
|
||||
rewrite/ob_query_range_define.cpp
|
||||
rewrite/ob_range_generator.cpp
|
||||
rewrite/ob_range_graph_generator.cpp
|
||||
rewrite/ob_stmt_comparer.cpp
|
||||
rewrite/ob_transform_count_to_exists.cpp
|
||||
rewrite/ob_transform_aggr_subquery.cpp
|
||||
|
@ -5267,51 +5267,59 @@ int ObStaticEngineCG::generate_normal_tsc(ObLogTableScan &op, ObTableScanSpec &s
|
||||
? NULL
|
||||
: op.get_plan()->get_optimizer_context().get_sql_schema_guard();
|
||||
CK(OB_NOT_NULL(schema_guard));
|
||||
if (OB_SUCC(ret) && NULL != op.get_pre_query_range()) {
|
||||
OZ(spec.tsc_ctdef_.pre_query_range_.deep_copy(*op.get_pre_query_range()));
|
||||
if (OB_SUCC(ret) && NULL != op.get_pre_graph()) {
|
||||
if (op.is_new_query_range()) {
|
||||
OZ(spec.tsc_ctdef_.pre_range_graph_.deep_copy(*op.get_pre_range_graph()));
|
||||
if (!op.is_skip_scan()) {
|
||||
OZ(spec.tsc_ctdef_.pre_range_graph_.reset_skip_scan_range());
|
||||
}
|
||||
} else {
|
||||
OZ(spec.tsc_ctdef_.pre_query_range_.deep_copy(*op.get_pre_query_range()));
|
||||
if (!op.is_skip_scan()) {
|
||||
OZ(spec.tsc_ctdef_.pre_query_range_.reset_skip_scan_range());
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (!op.is_skip_scan() && OB_FAIL(spec.tsc_ctdef_.pre_query_range_.reset_skip_scan_range())) {
|
||||
LOG_WARN("reset skip scan range failed", K(ret));
|
||||
} else if (OB_FAIL(spec.tsc_ctdef_.pre_query_range_.is_get(spec.tsc_ctdef_.scan_ctdef_.is_get_))) {
|
||||
} else if (OB_FAIL(op.get_pre_graph()->is_get(spec.tsc_ctdef_.scan_ctdef_.is_get_))) {
|
||||
LOG_WARN("extract the query range whether get failed", K(ret));
|
||||
}
|
||||
}
|
||||
OZ(generate_tsc_flags(op, spec));
|
||||
OX(spec.set_est_cost_simple_info(op.get_est_cost_simple_info()));
|
||||
|
||||
bool is_equal_and = true;
|
||||
ObKeyPart* root = spec.tsc_ctdef_.pre_query_range_.get_table_grapth().key_part_head_;
|
||||
ObSEArray<ObQueryRange::ObEqualOff, 1> equal_offs;
|
||||
while (OB_SUCC(ret) && NULL != root && is_equal_and) {
|
||||
is_equal_and = is_equal_and & root->is_equal_condition();
|
||||
if (NULL != root->item_next_ || NULL != root->or_next_) {
|
||||
is_equal_and = false;
|
||||
} else if (root->is_normal_key()) {
|
||||
int64_t param_idx = OB_INVALID_ID;
|
||||
ObObj& cur = root->normal_keypart_->start_;
|
||||
ObQueryRange::ObEqualOff equal_off;
|
||||
if (cur.is_ext() || root->null_safe_) {
|
||||
is_equal_and = false; //rollback old version
|
||||
} else if (root->is_rowid_key_part()) {
|
||||
is_equal_and = false; //not deal with rowid
|
||||
} else if (cur.is_unknown()) {
|
||||
if (OB_FAIL(cur.get_unknown(param_idx))) {
|
||||
LOG_WARN("get question mark value failed", K(ret), K(cur));
|
||||
} else {
|
||||
equal_off.param_idx_ = param_idx;
|
||||
equal_off.pos_off_ = root->pos_.offset_;
|
||||
equal_off.pos_type_ = root->pos_.column_type_.get_type();
|
||||
equal_offs.push_back(equal_off);
|
||||
}
|
||||
} else {
|
||||
equal_off.only_pos_ = true;
|
||||
equal_off.pos_off_ = root->pos_.offset_;
|
||||
equal_off.pos_value_ = root->normal_keypart_->start_;
|
||||
equal_offs.push_back(equal_off);
|
||||
}
|
||||
}
|
||||
root = root->and_next_;
|
||||
}
|
||||
// bool is_equal_and = true;
|
||||
// ObKeyPart* root = spec.tsc_ctdef_.pre_query_range_.get_table_grapth().key_part_head_;
|
||||
// ObSEArray<ObQueryRange::ObEqualOff, 1> equal_offs;
|
||||
// while (OB_SUCC(ret) && NULL != root && is_equal_and) {
|
||||
// is_equal_and = is_equal_and & root->is_equal_condition();
|
||||
// if (NULL != root->item_next_ || NULL != root->or_next_) {
|
||||
// is_equal_and = false;
|
||||
// } else if (root->is_normal_key()) {
|
||||
// int64_t param_idx = OB_INVALID_ID;
|
||||
// ObObj& cur = root->normal_keypart_->start_;
|
||||
// ObQueryRange::ObEqualOff equal_off;
|
||||
// if (cur.is_ext() || root->null_safe_) {
|
||||
// is_equal_and = false; //rollback old version
|
||||
// } else if (root->is_rowid_key_part()) {
|
||||
// is_equal_and = false; //not deal with rowid
|
||||
// } else if (cur.is_unknown()) {
|
||||
// if (OB_FAIL(cur.get_unknown(param_idx))) {
|
||||
// LOG_WARN("get question mark value failed", K(ret), K(cur));
|
||||
// } else {
|
||||
// equal_off.param_idx_ = param_idx;
|
||||
// equal_off.pos_off_ = root->pos_.offset_;
|
||||
// equal_off.pos_type_ = root->pos_.column_type_.get_type();
|
||||
// equal_offs.push_back(equal_off);
|
||||
// }
|
||||
// } else {
|
||||
// equal_off.only_pos_ = true;
|
||||
// equal_off.pos_off_ = root->pos_.offset_;
|
||||
// equal_off.pos_value_ = root->normal_keypart_->start_;
|
||||
// equal_offs.push_back(equal_off);
|
||||
// }
|
||||
// }
|
||||
// root = root->and_next_;
|
||||
// }
|
||||
// TODO the above optimization is overrode by ObTscCgService::generate_tsc_ctdef before this commit
|
||||
// but after the deep copy of pre_query_range_ is removed in ObTscCgService::generate_tsc_ctdef,
|
||||
// error is returned in such sql 'set global x=y', should fix this;
|
||||
|
@ -517,7 +517,8 @@ int ObStaticEngineExprCG::cg_expr_by_operator(const ObIArray<ObRawExpr *> &raw_e
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("arg is null", K(raw_expr), K(rt_expr), K(ret));
|
||||
} else if (T_QUESTIONMARK == rt_expr->type_ &&
|
||||
(raw_expr->has_flag(IS_TABLE_ASSIGN) || rt_question_mark_eval_)) {
|
||||
(raw_expr->has_flag(IS_TABLE_ASSIGN) ||
|
||||
(rt_question_mark_eval_ && (!is_dynamic_eval_qm(*raw_expr) || !contain_dynamic_eval_rt_qm_)))) {
|
||||
// generate question mark expr for get param from param store directly
|
||||
// if the questionmark is from TABLE_ASSIGN, use eval_assign_question_mark_func
|
||||
ObConstRawExpr *c_expr = static_cast<ObConstRawExpr*>(raw_expr);
|
||||
@ -1818,7 +1819,8 @@ int ObStaticEngineExprCG::gen_expr_with_row_desc(const ObRawExpr *expr,
|
||||
ObIAllocator &allocator,
|
||||
ObSQLSessionInfo *session,
|
||||
ObSchemaGetterGuard *schema_guard,
|
||||
ObTempExpr *&temp_expr)
|
||||
ObTempExpr *&temp_expr,
|
||||
bool contain_dynamic_eval_rt_qm_/* = false */)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
temp_expr = NULL;
|
||||
@ -1849,6 +1851,7 @@ int ObStaticEngineExprCG::gen_expr_with_row_desc(const ObRawExpr *expr,
|
||||
GET_MIN_CLUSTER_VERSION()); // ?
|
||||
expr_cg.set_rt_question_mark_eval(true);
|
||||
expr_cg.set_need_flatten_gen_col(false);
|
||||
expr_cg.set_contain_dynamic_eval_rt_qm(contain_dynamic_eval_rt_qm_);
|
||||
OZ(expr_cg.generate(const_cast<ObRawExpr *>(expr), flattened_raw_exprs, *temp_expr));
|
||||
}
|
||||
// generate row_idx to column expr pair;
|
||||
|
@ -107,7 +107,8 @@ public:
|
||||
rt_question_mark_eval_(false),
|
||||
need_flatten_gen_col_(true),
|
||||
cur_cluster_version_(cur_cluster_version),
|
||||
gen_questionmarks_(allocator, param_cnt)
|
||||
gen_questionmarks_(allocator, param_cnt),
|
||||
contain_dynamic_eval_rt_qm_(false)
|
||||
{
|
||||
}
|
||||
virtual ~ObStaticEngineExprCG() {}
|
||||
@ -156,6 +157,7 @@ public:
|
||||
void set_batch_size(const int64_t v) { batch_size_ = v; }
|
||||
|
||||
void set_rt_question_mark_eval(const bool v) { rt_question_mark_eval_ = v; }
|
||||
void set_contain_dynamic_eval_rt_qm(const bool v) { contain_dynamic_eval_rt_qm_ = v; }
|
||||
|
||||
static int generate_partial_expr_frame(const ObPhysicalPlan &plan,
|
||||
ObExprFrameInfo &partial_expr_frame_info,
|
||||
@ -169,7 +171,8 @@ public:
|
||||
ObIAllocator &alloctor,
|
||||
ObSQLSessionInfo *session,
|
||||
share::schema::ObSchemaGetterGuard *schema_guard,
|
||||
ObTempExpr *&temp_expr);
|
||||
ObTempExpr *&temp_expr,
|
||||
bool contain_dynamic_eval_rt_qm_ = false);
|
||||
|
||||
static int init_temp_expr_mem_size(ObTempExpr &temp_expr);
|
||||
|
||||
@ -499,6 +502,7 @@ private:
|
||||
bool need_flatten_gen_col_;
|
||||
uint64_t cur_cluster_version_;
|
||||
common::ObFixedArray<ObRawExpr *, common::ObIAllocator> gen_questionmarks_;
|
||||
bool contain_dynamic_eval_rt_qm_;
|
||||
};
|
||||
|
||||
} // end namespace sql
|
||||
|
@ -44,6 +44,9 @@ int ObTscCgService::generate_tsc_ctdef(ObLogTableScan &op, ObTableScanCtDef &tsc
|
||||
} else {
|
||||
query_flag.scan_order_ = ObQueryFlag::Forward;
|
||||
}
|
||||
if (op.is_new_query_range()) {
|
||||
query_flag.set_is_new_query_range();
|
||||
}
|
||||
OZ(generate_mr_mv_scan_flag(op, query_flag));
|
||||
tsc_ctdef.scan_flags_ = query_flag;
|
||||
if (op.use_index_merge()) {
|
||||
|
@ -1228,16 +1228,21 @@ REG_SER_FUNC_ARRAY(OB_SFA_DECIMAL_INT_CAST_EXPR_EVAL_BATCH, g_decimalint_cast_ba
|
||||
int eval_questionmark_decint2nmb(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
// child is questionmark, do not need evaluation.
|
||||
const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx);
|
||||
ObScale in_scale = expr.args_[0]->datum_meta_.scale_;
|
||||
ObNumStackOnceAlloc tmp_alloc;
|
||||
number::ObNumber out_nmb;
|
||||
if (OB_FAIL(wide::to_number(child.get_decimal_int(), child.get_int_bytes(), in_scale,
|
||||
tmp_alloc, out_nmb))) {
|
||||
LOG_WARN("to_number failed", K(ret));
|
||||
ObDatum *child_eval_datum = NULL;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, child_eval_datum))) {
|
||||
LOG_WARN("failef to eval child datum");
|
||||
} else {
|
||||
expr_datum.set_number(out_nmb);
|
||||
// child is questionmark, do not need evaluation.
|
||||
const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx);
|
||||
ObScale in_scale = expr.args_[0]->datum_meta_.scale_;
|
||||
ObNumStackOnceAlloc tmp_alloc;
|
||||
number::ObNumber out_nmb;
|
||||
if (OB_FAIL(wide::to_number(child.get_decimal_int(), child.get_int_bytes(), in_scale,
|
||||
tmp_alloc, out_nmb))) {
|
||||
LOG_WARN("to_number failed", K(ret));
|
||||
} else {
|
||||
expr_datum.set_number(out_nmb);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1246,21 +1251,26 @@ static int _eval_questionmark_nmb2decint(const ObExpr &expr, ObEvalCtx &ctx, ObD
|
||||
const ObCastMode cm)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
// child is questionmark, do not need evaluation.
|
||||
const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx);
|
||||
ObDecimalIntBuilder tmp_alloc, res_val;
|
||||
number::ObNumber in_nmb(child.get_number());
|
||||
ObScale in_scale = in_nmb.get_scale();
|
||||
ObPrecision out_prec = expr.datum_meta_.precision_;
|
||||
ObScale out_scale = expr.datum_meta_.scale_;
|
||||
ObDecimalInt *decint = nullptr;
|
||||
int32_t int_bytes = 0;
|
||||
if (OB_FAIL(wide::from_number(in_nmb, tmp_alloc, in_scale, decint, int_bytes))) {
|
||||
LOG_WARN("from number failed", K(ret));
|
||||
} else if (OB_FAIL(scale_const_decimalint_expr(decint, int_bytes, in_scale, out_scale, out_prec, cm, res_val))) {
|
||||
LOG_WARN("scale const decimal int failed", K(ret));
|
||||
ObDatum *child_eval_datum = NULL;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, child_eval_datum))) {
|
||||
LOG_WARN("failef to eval child datum");
|
||||
} else {
|
||||
expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes());
|
||||
// child is questionmark, do not need evaluation.
|
||||
const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx);
|
||||
ObDecimalIntBuilder tmp_alloc, res_val;
|
||||
number::ObNumber in_nmb(child.get_number());
|
||||
ObScale in_scale = in_nmb.get_scale();
|
||||
ObPrecision out_prec = expr.datum_meta_.precision_;
|
||||
ObScale out_scale = expr.datum_meta_.scale_;
|
||||
ObDecimalInt *decint = nullptr;
|
||||
int32_t int_bytes = 0;
|
||||
if (OB_FAIL(wide::from_number(in_nmb, tmp_alloc, in_scale, decint, int_bytes))) {
|
||||
LOG_WARN("from number failed", K(ret));
|
||||
} else if (OB_FAIL(scale_const_decimalint_expr(decint, int_bytes, in_scale, out_scale, out_prec, cm, res_val))) {
|
||||
LOG_WARN("scale const decimal int failed", K(ret));
|
||||
} else {
|
||||
expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1269,16 +1279,21 @@ static int _eval_questionmark_decint2decint(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
const ObCastMode cm)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObScale out_scale = expr.datum_meta_.scale_;
|
||||
ObPrecision out_prec = expr.datum_meta_.precision_;
|
||||
ObScale in_scale = expr.args_[0]->datum_meta_.scale_;
|
||||
ObDecimalIntBuilder res_val;
|
||||
const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx);
|
||||
if (OB_FAIL(ObDatumCast::common_scale_decimalint(child.get_decimal_int(), child.get_int_bytes(),
|
||||
in_scale, out_scale, out_prec, cm, res_val))) {
|
||||
LOG_WARN("common scale decimal int failed", K(ret));
|
||||
ObDatum *child_eval_datum = NULL;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, child_eval_datum))) {
|
||||
LOG_WARN("failef to eval child datum");
|
||||
} else {
|
||||
expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes());
|
||||
ObScale out_scale = expr.datum_meta_.scale_;
|
||||
ObPrecision out_prec = expr.datum_meta_.precision_;
|
||||
ObScale in_scale = expr.args_[0]->datum_meta_.scale_;
|
||||
ObDecimalIntBuilder res_val;
|
||||
const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx);
|
||||
if (OB_FAIL(ObDatumCast::common_scale_decimalint(child.get_decimal_int(), child.get_int_bytes(),
|
||||
in_scale, out_scale, out_prec, cm, res_val))) {
|
||||
LOG_WARN("common scale decimal int failed", K(ret));
|
||||
} else {
|
||||
expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -415,6 +415,9 @@
|
||||
#include "ob_expr_audit_log_func.h"
|
||||
#include "ob_expr_can_access_trigger.h"
|
||||
#include "ob_expr_split_part.h"
|
||||
#include "ob_expr_inner_decode_like.h"
|
||||
#include "ob_expr_inner_double_to_int.h"
|
||||
#include "ob_expr_inner_decimal_to_year.h"
|
||||
#include "ob_expr_array_overlaps.h"
|
||||
#include "ob_expr_array_contains_all.h"
|
||||
#include "ob_expr_array_distinct.h"
|
||||
@ -1140,15 +1143,15 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
ObExprIs::decimal_int_is_false, /* 612 */
|
||||
ObExprIsNot::decimal_int_is_not_true, /* 613 */
|
||||
ObExprIsNot::decimal_int_is_not_false, /* 614 */
|
||||
NULL, //ObExprInnerIsTrue::int_is_true_start, /* 615 */
|
||||
NULL, //ObExprInnerIsTrue::int_is_true_end, /* 616 */
|
||||
NULL, //ObExprInnerIsTrue::float_is_true_start, /* 617 */
|
||||
NULL, //ObExprInnerIsTrue::float_is_true_end, /* 618 */
|
||||
NULL, //ObExprInnerIsTrue::double_is_true_start, /* 619 */
|
||||
NULL, //ObExprInnerIsTrue::double_is_true_end, /* 620 */
|
||||
NULL, //ObExprInnerIsTrue::number_is_true_start, /* 621 */
|
||||
NULL, //ObExprInnerIsTrue::number_is_true_end, /* 622 */
|
||||
NULL, //ObExprInnerDecodeLike::eval_inner_decode_like /* 623 */
|
||||
ObExprInnerIsTrue::int_is_true_start, /* 615 */
|
||||
ObExprInnerIsTrue::int_is_true_end, /* 616 */
|
||||
ObExprInnerIsTrue::float_is_true_start, /* 617 */
|
||||
ObExprInnerIsTrue::float_is_true_end, /* 618 */
|
||||
ObExprInnerIsTrue::double_is_true_start, /* 619 */
|
||||
ObExprInnerIsTrue::double_is_true_end, /* 620 */
|
||||
ObExprInnerIsTrue::number_is_true_start, /* 621 */
|
||||
ObExprInnerIsTrue::number_is_true_end, /* 622 */
|
||||
ObExprInnerDecodeLike::eval_inner_decode_like, /* 623 */
|
||||
ObExprJsonSchemaValid::eval_json_schema_valid, /* 624 */
|
||||
ObExprJsonSchemaValidationReport::eval_json_schema_validation_report, /* 625 */
|
||||
ObExprInsertChildXml::eval_insert_child_xml, /* 626 */
|
||||
@ -1253,8 +1256,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
ObExprVectorDims::calc_dims, /* 725 */
|
||||
ObExprVectorNorm::calc_norm, /* 726 */
|
||||
ObExprVectorDistance::calc_distance, /* 727 */
|
||||
NULL, // ObExprInnerDoubleToInt::eval_inner_double_to_int /* 728 */
|
||||
NULL, // ObExprInnerDecimalToYear::eval_inner_decimal_to_year /* 729 */
|
||||
ObExprInnerDoubleToInt::eval_inner_double_to_int, /* 728 */
|
||||
ObExprInnerDecimalToYear::eval_inner_decimal_to_year, /* 729 */
|
||||
ObExprSm3::eval_sm3, /* 730 */
|
||||
ObExprSm4Encrypt::eval_sm4_encrypt, /* 731 */
|
||||
ObExprSm4Decrypt::eval_sm4_decrypt, /* 732 */
|
||||
@ -1289,10 +1292,10 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
NULL, // ObExprMysqlProcInfo::eval_mysql_proc_info /* 761 */
|
||||
ObExprArrayOverlaps::eval_array_overlaps, /* 762 */
|
||||
ObExprArrayContainsAll::eval_array_contains_all, /* 763 */
|
||||
NULL, // ObExprInnerIsTrue::decimal_int_is_true_start, /* 764 */
|
||||
NULL, // ObExprInnerIsTrue::decimal_int_is_true_end, /* 765 */
|
||||
NULL, // ObExprInnerIsTrue::json_is_true_start, /* 766 */
|
||||
NULL, // ObExprInnerIsTrue::json_is_true_end, /* 767 */
|
||||
ObExprInnerIsTrue::decimal_int_is_true_start, /* 764 */
|
||||
ObExprInnerIsTrue::decimal_int_is_true_end, /* 765 */
|
||||
ObExprInnerIsTrue::json_is_true_start, /* 766 */
|
||||
ObExprInnerIsTrue::json_is_true_end, /* 767 */
|
||||
ObExprGetMySQLRoutineParameterTypeStr::get_mysql_routine_parameter_type_str, /* 768 */
|
||||
ObExprArrayDistinct::eval_array_distinct, /* 769 */
|
||||
ObExprArrayRemove::eval_array_remove_int64_t, /* 770 */
|
||||
|
119
src/sql/engine/expr/ob_expr_inner_decimal_to_year.cpp
Normal file
119
src/sql/engine/expr/ob_expr_inner_decimal_to_year.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
* This file contains implementation for _st_asewkb expr.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "ob_expr_inner_decimal_to_year.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
ObExprInnerDecimalToYear::ObExprInnerDecimalToYear(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_INNER_DECIMAL_TO_YEAR, N_INNER_DECIMAL_TO_YEAR, 1,
|
||||
NOT_VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION,
|
||||
INTERNAL_IN_MYSQL_MODE, INTERNAL_IN_ORACLE_MODE)
|
||||
{
|
||||
}
|
||||
const int64_t YEAR_MIN = 1901;
|
||||
const int64_t YEAR_MAX = 2155;
|
||||
const int64_t YEAR_BASE = 1900;
|
||||
const uint8_t OBJ_YEAR_MIN = 1;
|
||||
const uint8_t OBJ_YEAR_MAX = 255;
|
||||
const uint8_t OBJ_YEAR_LOW = 0;
|
||||
|
||||
int ObExprInnerDecimalToYear::eval_inner_decimal_to_year(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum* val_datum = NULL;
|
||||
int64_t year_int = 0;
|
||||
bool is_start = (expr.extra_ & 1) == 1;
|
||||
bool is_equal = (expr.extra_ & 2) == 2;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, val_datum))) {
|
||||
LOG_WARN("fail to eval conv", K(ret), K(expr));
|
||||
} else if (val_datum->is_null()) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
const number::ObNumber& val = val_datum->get_number();
|
||||
if (val.is_negative()) {
|
||||
if (is_equal) {
|
||||
expr_datum.set_year(is_start ? (int8_t)OBJ_YEAR_MAX : (int8_t)OBJ_YEAR_LOW);
|
||||
} else {
|
||||
expr_datum.set_year((int8_t)OBJ_YEAR_LOW);
|
||||
}
|
||||
} else if (OB_FAIL(val.extract_valid_int64_with_trunc(year_int))) {
|
||||
LOG_WARN("extract_valid_int64_with_trunc fail.", K(ret), K(year_int));
|
||||
} else if (val.is_valid_int()) {
|
||||
if (year_int > YEAR_BASE && year_int <= YEAR_MAX) {
|
||||
expr_datum.set_year((int8_t)(year_int - YEAR_BASE));
|
||||
} else if (year_int == 0) {
|
||||
expr_datum.set_year((int8_t)OBJ_YEAR_LOW);
|
||||
} else if (is_equal) {
|
||||
expr_datum.set_year(is_start ? (int8_t)OBJ_YEAR_MAX : (int8_t)OBJ_YEAR_LOW);
|
||||
} else if (year_int > YEAR_MAX) {
|
||||
expr_datum.set_year((int8_t)OBJ_YEAR_MAX);
|
||||
} else if (year_int <= YEAR_BASE && year_int > 0) {
|
||||
expr_datum.set_year(is_start ? (int8_t)OBJ_YEAR_MIN : (int8_t)OBJ_YEAR_LOW);
|
||||
}
|
||||
} else {
|
||||
if (is_equal) {
|
||||
expr_datum.set_year(is_start ? (int8_t)OBJ_YEAR_MAX : (int8_t)OBJ_YEAR_LOW);
|
||||
} else {
|
||||
if (year_int >= YEAR_BASE && year_int < YEAR_MAX) {
|
||||
year_int = is_start ? year_int + 1 : year_int;
|
||||
expr_datum.set_year((int8_t)(year_int - YEAR_BASE));
|
||||
} else if (year_int >= YEAR_MAX) {
|
||||
expr_datum.set_year((int8_t)OBJ_YEAR_MAX);
|
||||
} else if (year_int < YEAR_BASE && year_int >= 0) {
|
||||
expr_datum.set_year(is_start ? (int8_t)OBJ_YEAR_MIN : (int8_t)OBJ_YEAR_LOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDecimalToYear::calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(type_ctx);
|
||||
type.set_year();
|
||||
type1.set_calc_type(ObNumberType);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDecimalToYear::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(expr_cg_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(1 != rt_expr.arg_cnt_)) {
|
||||
ret = OB_ERR_PARAM_SIZE;
|
||||
LOG_WARN("invalid arg cnt of expr", K(ret), K(rt_expr));
|
||||
} else if (OB_ISNULL(rt_expr.args_[0])) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("the arg of inner double to int is null.", K(ret), K(rt_expr));
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprInnerDecimalToYear::eval_inner_decimal_to_year;
|
||||
rt_expr.extra_ = raw_expr.get_extra();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
44
src/sql/engine/expr/ob_expr_inner_decimal_to_year.h
Normal file
44
src/sql/engine/expr/ob_expr_inner_decimal_to_year.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DECIMAL_TO_YEAR_
|
||||
#define OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DECIMAL_TO_YEAR_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
//This expression is used to extract double to int range.
|
||||
//inner_decimal_to_year(val)
|
||||
//for example: inner_decimal_to_year(1991) = 1991
|
||||
class ObExprInnerDecimalToYear : public ObFuncExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprInnerDecimalToYear(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprInnerDecimalToYear() {};
|
||||
|
||||
virtual int calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_inner_decimal_to_year(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprInnerDecimalToYear) const;
|
||||
};
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
||||
#endif // OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DECIMAL_TO_YEAR_
|
230
src/sql/engine/expr/ob_expr_inner_decode_like.cpp
Normal file
230
src/sql/engine/expr/ob_expr_inner_decode_like.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
* This file contains implementation for _st_asewkb expr.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "ob_expr_inner_decode_like.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "sql/engine/expr/ob_datum_cast.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
ObExprInnerDecodeLike::ObExprInnerDecodeLike(ObIAllocator &alloc)
|
||||
: ObStringExprOperator(alloc, T_FUN_SYS_INNER_DECODE_LIKE, N_INNER_DECODE_LIKE, 6, NOT_VALID_FOR_GENERATED_COL,
|
||||
INTERNAL_IN_MYSQL_MODE, INTERNAL_IN_ORACLE_MODE)
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprInnerDecodeLike::cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(6 != rt_expr.arg_cnt_)) {
|
||||
ret = OB_ERR_PARAM_SIZE;
|
||||
LOG_WARN("invalid arg cnt of expr", K(ret), K(rt_expr));
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprInnerDecodeLike::eval_inner_decode_like;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDecodeLike::eval_inner_decode_like(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum) {
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *pattern = NULL;
|
||||
ObDatum *escape = NULL;
|
||||
ObDatum *is_start = NULL;
|
||||
ObDatum *col_type = NULL;
|
||||
ObDatum *col_collation = NULL;
|
||||
ObDatum *col_length = NULL;
|
||||
ObDatum *pattern_val = NULL;
|
||||
const ObDataTypeCastParams &dtc_params = ctx.exec_ctx_.get_my_session()->get_dtc_params();
|
||||
if (OB_ISNULL(expr.args_[0]) ||OB_ISNULL(expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret));
|
||||
} else if (OB_FAIL(expr.eval_param_value(ctx, pattern, escape, is_start, col_type, col_collation, col_length))) {
|
||||
LOG_WARN("eval args failed", K(ret));
|
||||
} else if (OB_ISNULL(pattern) || OB_ISNULL(escape)
|
||||
|| OB_ISNULL(is_start) || OB_ISNULL(col_collation) || OB_ISNULL(col_length)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("params are unexpected null", K(ret), K(pattern), K(escape),
|
||||
K(is_start), K(col_collation), K(col_length));
|
||||
} else if (pattern->is_null()) {
|
||||
//a like null return empty range
|
||||
expr_datum.set_null();
|
||||
} else if (col_length->get_int() <= 0) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument, unexpected length", K(ret));
|
||||
} else if (OB_FAIL(cast_like_obj_if_needed(ctx, *expr.args_[0], pattern, expr, pattern_val))) {
|
||||
LOG_WARN("failed to cast like obj if needed", K(ret));
|
||||
} else {
|
||||
int64_t mbmaxlen = 1;
|
||||
ObCollationType cs_type = static_cast<ObCollationType>(col_collation->get_int());
|
||||
int32_t col_len = static_cast<int32_t>(col_length->get_int());
|
||||
ObString escape_str;
|
||||
ObString pattern_str = pattern_val->get_string();
|
||||
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
|
||||
if (escape->is_null()) { //如果escape是null,则给默认的'\\'
|
||||
escape_str.assign_ptr("\\", 1);
|
||||
} else {
|
||||
ObString escape_val = escape->get_string();
|
||||
ObCollationType escape_collation = expr.args_[1]->datum_meta_.cs_type_;
|
||||
if (ObCharset::is_cs_nonascii(escape_collation)) {
|
||||
if (OB_FAIL(ObCharset::charset_convert(tmp_alloc_g.get_allocator(),
|
||||
escape_val,
|
||||
escape_collation,
|
||||
CS_TYPE_UTF8MB4_GENERAL_CI,
|
||||
escape_str, true))) {
|
||||
LOG_WARN("failed to do charset convert", K(ret), K(escape_val));
|
||||
}
|
||||
} else {
|
||||
escape_str = escape->get_string();
|
||||
if (escape_str.empty()) {
|
||||
escape_str.assign_ptr("\\", 1);
|
||||
} else { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
// do nothing;
|
||||
} else if (OB_FAIL(ObCharset::get_mbmaxlen_by_coll(cs_type, mbmaxlen))) {
|
||||
LOG_WARN("fail to get mbmaxlen", K(ret), K(cs_type), K(pattern), K(escape));
|
||||
} else if (OB_ISNULL(escape_str.ptr())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Escape str should not be NULL", K(ret));
|
||||
} else if (OB_UNLIKELY(1 > escape_str.length())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("failed to check escape length", K(escape_str), K(escape_str.length()));
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "ESCAPE");
|
||||
} else {
|
||||
//convert character counts to len in bytes
|
||||
col_len = static_cast<int32_t>(col_len * mbmaxlen);
|
||||
size_t min_str_len = col_len;
|
||||
size_t max_str_len = col_len;
|
||||
size_t res_len = 0;
|
||||
int32_t start_flag = is_start->get_int();
|
||||
common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator();
|
||||
char *min_str_buf = NULL;
|
||||
char *max_str_buf = NULL;
|
||||
char *res_buf = NULL;
|
||||
if (OB_ISNULL(min_str_buf = (char*)temp_allocator.alloc(min_str_len))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("alloc memory failed", K(min_str_len));
|
||||
} else if (OB_ISNULL(max_str_buf = (char*)temp_allocator.alloc(max_str_len))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("alloc memory failed", K(max_str_len));
|
||||
} else if (OB_FAIL(ObCharset::like_range(cs_type,
|
||||
pattern_str,
|
||||
*(escape_str.ptr()),
|
||||
static_cast<char*>(min_str_buf),
|
||||
&min_str_len,
|
||||
static_cast<char*>(max_str_buf),
|
||||
&max_str_len))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("calc like range failed", K(ret), K(pattern_str), K(escape_str), K(cs_type));
|
||||
} else {
|
||||
ObExprStrResAlloc res_alloc(expr, ctx);
|
||||
char *buf = NULL;
|
||||
if (is_start->get_int() == 1) {
|
||||
res_buf = min_str_buf;
|
||||
res_len = min_str_len;
|
||||
} else {
|
||||
res_buf = max_str_buf;
|
||||
res_len = max_str_len;
|
||||
}
|
||||
buf = (char*)res_alloc.alloc(res_len);
|
||||
if (OB_ISNULL(buf)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("alloc memory failed", K(ret), K(min_str_len));
|
||||
} else {
|
||||
MEMCPY(buf, res_buf, res_len);
|
||||
expr_datum.set_string(buf, res_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDecodeLike::calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *types_stack,
|
||||
int64_t param_num,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (param_num != 6) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param num", K(ret), K(param_num));
|
||||
} else {
|
||||
const ObObj &dest_type = types_stack[3].get_param();
|
||||
const ObObj &dest_collation = types_stack[4].get_param();
|
||||
const ObObj &dest_length = types_stack[5].get_param();
|
||||
if (!types_stack[2].is_int() || !types_stack[3].is_int() || !types_stack[4].is_int() || !types_stack[5].is_int()
|
||||
|| !types_stack[1].is_string_type() || !types_stack[0].is_string_type()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument, unexpected obj type", K(ret), K(types_stack[0]), K(types_stack[1]), K(types_stack[2]),
|
||||
K(types_stack[3]), K(types_stack[4]), K(types_stack[5]));
|
||||
} else {
|
||||
ObObjType expected_type = static_cast<ObObjType>(dest_type.get_int());
|
||||
ObCollationType cs_type = static_cast<ObCollationType>(dest_collation.get_int());
|
||||
int64_t length = dest_length.get_int();
|
||||
type.set_type(expected_type);
|
||||
type.set_length(length);
|
||||
type.set_collation_level(CS_LEVEL_COERCIBLE);
|
||||
type.set_collation_type(cs_type);
|
||||
//pattern
|
||||
types_stack[0].set_calc_meta(types_stack[0].get_obj_meta());
|
||||
types_stack[0].set_calc_collation_type(types_stack[0].get_collation_type());
|
||||
types_stack[0].set_calc_collation_level(CS_LEVEL_COERCIBLE);
|
||||
//escape
|
||||
types_stack[1].set_calc_meta(types_stack[1].get_obj_meta());
|
||||
types_stack[1].set_calc_collation_type(types_stack[1].get_collation_type());
|
||||
types_stack[1].set_calc_collation_level(CS_LEVEL_COERCIBLE);
|
||||
//is_start
|
||||
types_stack[2].set_calc_type(ObIntType);
|
||||
//column type
|
||||
types_stack[3].set_calc_type(ObIntType);
|
||||
//column collation
|
||||
types_stack[4].set_calc_type(ObIntType);
|
||||
//column length
|
||||
types_stack[5].set_calc_type(ObIntType);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDecodeLike::cast_like_obj_if_needed(ObEvalCtx &ctx, const ObExpr &pattern_expr, ObDatum *pattern_datum,
|
||||
const ObExpr &dst_expr, ObDatum * &cast_datum) {
|
||||
int ret = OB_SUCCESS;
|
||||
ObCastMode cm = CM_NONE;
|
||||
if (OB_FAIL(ObSQLUtils::get_default_cast_mode(false /*is_explicit_cast*/,
|
||||
0 /*result_flag*/,
|
||||
ctx.exec_ctx_.get_my_session(),
|
||||
cm))) {
|
||||
LOG_WARN("get default cast mode failed", K(ret));
|
||||
} else if (pattern_expr.datum_meta_.type_ == dst_expr.datum_meta_.type_
|
||||
&& pattern_expr.datum_meta_.cs_type_ == dst_expr.datum_meta_.cs_type_) {
|
||||
cast_datum = pattern_datum;
|
||||
} else if (OB_ISNULL(ctx.datum_caster_) && OB_FAIL(ctx.init_datum_caster())) {
|
||||
LOG_WARN("init datum caster failed", K(ret));
|
||||
} else if (OB_FAIL(ctx.datum_caster_->to_type(dst_expr.datum_meta_, pattern_expr, cm, cast_datum, ctx.get_batch_idx()))) {
|
||||
LOG_WARN("fail to dynamic cast", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
48
src/sql/engine/expr/ob_expr_inner_decode_like.h
Normal file
48
src/sql/engine/expr/ob_expr_inner_decode_like.h
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DECODE_LIKE_
|
||||
#define OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DECODE_LIKE_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
//This expression is used to extract like range.
|
||||
//inner_decode_like(pattern, escape, is_start, column_type, column_collation, column_length)
|
||||
//for example: inner_decode_like('123%', '\\', 1, 22 \*ObVarcharType*\, 45 \*CS_TYPE_UTF8MB4_GENERAL_CI*\, 4) = '123\min\min\min...' (length:16)
|
||||
// inner_decode_like('123%', '\\', 0, 22 \*ObVarcharType*\, 45 \*CS_TYPE_UTF8MB4_GENERAL_CI*\, 4) = '123\max\max\max...' (length:16)
|
||||
class ObExprInnerDecodeLike : public ObStringExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprInnerDecodeLike(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprInnerDecodeLike() {};
|
||||
|
||||
virtual int calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *types_stack,
|
||||
int64_t param_num,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_inner_decode_like(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
|
||||
private:
|
||||
static int cast_like_obj_if_needed(ObEvalCtx &ctx, const ObExpr &pattern_expr, ObDatum *pattern_datum,
|
||||
const ObExpr &dst_expr, ObDatum * &cast_datum);
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprInnerDecodeLike) const;
|
||||
};
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
||||
#endif // OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DECODE_LIKE_
|
402
src/sql/engine/expr/ob_expr_inner_double_to_int.cpp
Normal file
402
src/sql/engine/expr/ob_expr_inner_double_to_int.cpp
Normal file
@ -0,0 +1,402 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
* This file contains implementation for _st_asewkb expr.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "ob_expr_inner_double_to_int.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
const int64_t MAX_PRECISE_DOUBLE_INT64 = 9007199254740991; // 2^53 - 1
|
||||
const int64_t MIN_PRECISE_DOUBLE_INT64 = -9007199254740991; // -2^53 + 1
|
||||
const int DOUBLE_BIAS = 1023;
|
||||
const int64_t DOUBLE_EXP_MASK = 0x7ff;
|
||||
const int64_t DOUBLE_DIG_MASK = 0xfffffffffffff;
|
||||
const double MAX_PRECISE_DOUBLE = 9007199254740991.0; // 2^53 - 1
|
||||
const double MIN_PRECISE_DOUBLE = -9007199254740991.0; // -2^53 + 1
|
||||
const double MAX_DOUBLE_TO_INT64 = 9.223372036854776e+18;
|
||||
const double MIN_DOUBLE_TO_INT64 = -9.223372036854776e+18;
|
||||
const double MIN_DOUBLE_TO_UINT64 = 0.;
|
||||
const double MAX_DOUBLE_TO_UINT64 = 1.8446744073709552e+19;
|
||||
const int MAX_DOUBLE_PRINT_SIZE = 512;
|
||||
ObExprInnerDoubleToInt::ObExprInnerDoubleToInt(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_INNER_DOUBLE_TO_INT, N_INNER_DOUBLE_TO_INT, 1,
|
||||
NOT_VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION,
|
||||
INTERNAL_IN_MYSQL_MODE, INTERNAL_IN_ORACLE_MODE)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* The function convert_double_to_int64_range is used to convert a double with potential precision
|
||||
* loss into the corresponding upper and lower bounds of an int64.
|
||||
* For example, the number 9.223372036854776e+18, after being processed by this function,
|
||||
* would be converted to start=9223372036854775296 and end=INT64_MAX.
|
||||
* The conversion logic here cannot directly call ceil or floor because for large integers (greater than 2^53 + 1)
|
||||
* both would return the same value.
|
||||
*/
|
||||
int ObExprInnerDoubleToInt::convert_double_to_int64_range(double d, int64_t &start, int64_t &end)
|
||||
{
|
||||
int64_t v = static_cast<int64_t>(d);
|
||||
if (v >= MIN_PRECISE_DOUBLE_INT64 && v <= MAX_PRECISE_DOUBLE_INT64) {
|
||||
start = v;
|
||||
end = v;
|
||||
} else {
|
||||
uint64_t num = *reinterpret_cast<uint64_t *>(&d);
|
||||
int64_t exp = ((num >> 52) & DOUBLE_EXP_MASK) - DOUBLE_BIAS;
|
||||
int64_t bits = exp - 52;
|
||||
int64_t out = (((int64_t)1 << 52) + (num & DOUBLE_DIG_MASK));
|
||||
int64_t p = (1 << (bits - 1));
|
||||
uint64_t sign = num & 0x8000000000000000;
|
||||
if (exp == 63) {
|
||||
start = 9223372036854775296;
|
||||
end = INT64_MAX;
|
||||
} else if (exp > 63) {
|
||||
start = INT64_MAX;
|
||||
end = INT64_MAX;
|
||||
} else if ((num & 1) == 1) {
|
||||
if (bits == 1) {
|
||||
out = out << bits;
|
||||
start = out;
|
||||
end = out;
|
||||
} else {
|
||||
start = ((out - 1) << bits) + p + 1;
|
||||
end = (out << bits) + p - 1;
|
||||
}
|
||||
} else {
|
||||
start = ((out - 1) << bits) + p;
|
||||
end = ((out) << bits) + p;
|
||||
}
|
||||
if (start < MAX_PRECISE_DOUBLE_INT64 + 1) {
|
||||
start = MAX_PRECISE_DOUBLE_INT64 + 1;
|
||||
}
|
||||
if (sign == 0x8000000000000000) {
|
||||
start = -start;
|
||||
end = -end;
|
||||
std::swap(start, end);
|
||||
}
|
||||
}
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to convert a double to the upper and lower bounds of a uint64.
|
||||
* The conversion logic is similar to convert_double_to_int64_range, but with a different range of values.
|
||||
*/
|
||||
int ObExprInnerDoubleToInt::convert_double_to_uint64_range(double d, uint64_t &start, uint64_t &end)
|
||||
{
|
||||
uint64_t v = static_cast<uint64_t>(d);
|
||||
if (v >= 0 && v <= MAX_PRECISE_DOUBLE_INT64) {
|
||||
start = v;
|
||||
end = v;
|
||||
} else {
|
||||
uint64_t num = *reinterpret_cast<uint64_t *>(&d);
|
||||
int64_t exp = ((num >> 52) & DOUBLE_EXP_MASK) - DOUBLE_BIAS;
|
||||
int64_t bits = exp - 52;
|
||||
uint64_t out = (((uint64_t)1 << 52) + (num & DOUBLE_DIG_MASK));
|
||||
uint64_t p = (1 << (bits - 1));
|
||||
if (exp == 64) {
|
||||
start = 18446744073709550592u;
|
||||
end = UINT64_MAX;
|
||||
} else if (exp > 64) {
|
||||
start = UINT64_MAX;
|
||||
end = UINT64_MAX;
|
||||
} else if ((num & 1) == 1) {
|
||||
if (bits == 1) {
|
||||
out = out << bits;
|
||||
start = out;
|
||||
end = out;
|
||||
} else {
|
||||
start = ((out - 1) << bits) + p + 1;
|
||||
end = (out << bits) + p - 1;
|
||||
}
|
||||
} else {
|
||||
start = ((out - 1) << bits) + p;
|
||||
end = ((out) << bits) + p;
|
||||
}
|
||||
if (start < MAX_PRECISE_DOUBLE_INT64 + 1) {
|
||||
start = MAX_PRECISE_DOUBLE_INT64 + 1;
|
||||
}
|
||||
}
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function's purpose is to generate a double value out_d that is guaranteed to be greater than the original input value d.
|
||||
* The algorithm achieves this by adding 1 to the least significant digit of the double's mantissa; if this causes an overflow, then 1 is added to the exponent part instead.
|
||||
*
|
||||
* To illustrate the effect of this function with an example, suppose the input value is 3.14. After being processed by the function, the resulting value would be 3.1400000000000006.
|
||||
*
|
||||
* Why do we need this auxiliary function?
|
||||
* When converting a double to a decimal, because a decimal has a fractional part and the precision can vary,
|
||||
* it's not possible to obtain an exact value as with converting to an integer. Therefore, we need to generate an imprecise range that ensures the produced range is a superset of the original one.
|
||||
* For instance, for c1 = 3.14, the resulting range would be [3.1399999999999997; 3.1400000000000006].
|
||||
*
|
||||
* Why doesn't the conversion function simply add 1?
|
||||
* For numbers smaller than 2^53, adding 1 is not an issue,
|
||||
* but for large integers, directly adding 1 doesn't cause any change to the double value.
|
||||
* For example, 9.223372036854776e+18 + 1 is equal to 9.223372036854776e+18, showing no change.
|
||||
*/
|
||||
int ObExprInnerDoubleToInt::add_double_bit_1(double d, double &out_d)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t v = static_cast<int64_t>(d);
|
||||
uint64_t num = *reinterpret_cast<uint64_t *>(&d);
|
||||
int64_t exp = ((num >> 52) & DOUBLE_EXP_MASK);
|
||||
int64_t bits = exp - 52;
|
||||
int64_t out = (((int64_t)1 << 52) + (num & 0xfffffffffffff));
|
||||
uint64_t sign = num & 0x8000000000000000;
|
||||
out += 1;
|
||||
if ((out & 0x20000000000000) == 0x20000000000000) {
|
||||
out = out >> 1;
|
||||
exp += 1;
|
||||
}
|
||||
num = sign | (exp << 52) | (out & 0xfffffffffffff);
|
||||
out_d = *reinterpret_cast<double *>(&num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function serves the opposite purpose to add_double_bit_1, yielding a double that is smaller than the input number,
|
||||
* effectively subtracting 1 from the least significant digit of the double's precision.
|
||||
*/
|
||||
int ObExprInnerDoubleToInt::sub_double_bit_1(double d, double &out_d)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t v = static_cast<int64_t>(d);
|
||||
uint64_t num = *reinterpret_cast<uint64_t *>(&d);
|
||||
int64_t exp = ((num >> 52) & DOUBLE_EXP_MASK);
|
||||
int64_t bits = exp - 52;
|
||||
int64_t out = (((int64_t)1 << 52) + (num & 0xfffffffffffff));
|
||||
uint64_t sign = num & 0x8000000000000000;
|
||||
out -= 1;
|
||||
if ((out & 0x10000000000000) == 0) {
|
||||
out = (out << 1) + 1;
|
||||
exp -= 1;
|
||||
}
|
||||
num = sign | (exp << 52) | (out & 0xfffffffffffff);
|
||||
out_d = *reinterpret_cast<double *>(&num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDoubleToInt::double_to_number(double in_val,
|
||||
ObIAllocator &alloc,
|
||||
number::ObNumber &number)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t length = 0;
|
||||
ObScale res_scale; // useless
|
||||
ObPrecision res_precision;
|
||||
ObString str;
|
||||
SMART_VAR(char[MAX_DOUBLE_PRINT_SIZE], buf) {
|
||||
MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE);
|
||||
length = ob_gcvt_opt(in_val, OB_GCVT_ARG_DOUBLE, static_cast<int32_t>(sizeof(buf) - 1),
|
||||
buf, NULL, lib::is_oracle_mode(), TRUE);
|
||||
str.assign_ptr(buf, length);
|
||||
ret = number.from_sci_opt(str.ptr(), str.length(), alloc,
|
||||
&res_precision, &res_scale);
|
||||
if (OB_NUMERIC_OVERFLOW == ret) {
|
||||
int64_t i = 0;
|
||||
while (i < str.length() && isspace(str[i])) {
|
||||
++i;
|
||||
}
|
||||
bool is_neg = (str[i] == '-');
|
||||
int tmp_ret = OB_SUCCESS;
|
||||
const ObPrecision prec = OB_MAX_DECIMAL_PRECISION;
|
||||
const ObScale scale = 0;
|
||||
const number::ObNumber *bound_num = NULL;
|
||||
if (is_neg) {
|
||||
bound_num = &(ObNumberConstValue::MYSQL_MIN[prec][scale]);
|
||||
} else {
|
||||
bound_num = &(ObNumberConstValue::MYSQL_MAX[prec][scale]);
|
||||
}
|
||||
if (OB_ISNULL(bound_num)) {
|
||||
tmp_ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("bound_num is NULL", K(tmp_ret), K(ret), K(is_neg));
|
||||
} else if (OB_SUCCESS != (tmp_ret = number.from(*bound_num, alloc))) {
|
||||
LOG_WARN("copy min number failed", K(ret), K(tmp_ret), KPC(bound_num));
|
||||
} else {
|
||||
ret = OB_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDoubleToInt::eval_inner_double_to_int(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum) {
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum* val_datum = NULL;
|
||||
double val = 0.;
|
||||
double ceil_val = 0.;
|
||||
double floor_val = 0.;
|
||||
bool is_start = (expr.extra_ & 1) == 1;
|
||||
bool is_equal = (expr.extra_ & 2) == 2;
|
||||
bool is_unsigned = (expr.extra_ & 4) == 4;
|
||||
bool is_decimal = (expr.extra_ & 8) == 8;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, val_datum))) {
|
||||
LOG_WARN("fail to eval conv", K(ret), K(expr));
|
||||
} else if (val_datum->is_null()) {
|
||||
expr_datum.set_null();
|
||||
} else if (OB_FALSE_IT(val = val_datum->get_double())) {
|
||||
} else if (is_decimal) {
|
||||
ObNumStackOnceAlloc tmp_alloc;
|
||||
number::ObNumber number;
|
||||
double tmp_d;
|
||||
if (val == DBL_MAX || val == DBL_MIN ||
|
||||
val == -DBL_MAX || val == -DBL_MIN) {
|
||||
// do nothing
|
||||
} else if ((val > 0. && !is_start) ||
|
||||
(val < 0. && is_start)) {
|
||||
if (OB_FAIL(add_double_bit_1(val, tmp_d))) {
|
||||
LOG_WARN("failed to add double bit 1", K(ret));
|
||||
} else {
|
||||
val = tmp_d;
|
||||
}
|
||||
} else if ((val > 0. && is_start) ||
|
||||
(val < 0. && !is_start)) {
|
||||
if (OB_FAIL(sub_double_bit_1(val, tmp_d))) {
|
||||
LOG_WARN("failed to sub double bit 1", K(ret));
|
||||
} else {
|
||||
val = tmp_d;
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(double_to_number(val, tmp_alloc, number))) {
|
||||
LOG_WARN("failed to trans double to number", K(ret));
|
||||
} else {
|
||||
expr_datum.set_number(number);
|
||||
}
|
||||
} else if (!is_unsigned) {
|
||||
int64_t start = 0, end = 0;
|
||||
if (val >= MIN_PRECISE_DOUBLE && val <= MAX_PRECISE_DOUBLE) {
|
||||
ceil_val = ceill(val);
|
||||
floor_val = floorl(val);
|
||||
if (ceil_val == floor_val) {
|
||||
expr_datum.set_int(static_cast<int64_t>(val));
|
||||
} else if (is_equal) {
|
||||
expr_datum.set_int(is_start ? INT64_MAX : INT64_MIN);
|
||||
} else if (is_start) {
|
||||
expr_datum.set_int(static_cast<int64_t>(ceil_val));
|
||||
} else {
|
||||
expr_datum.set_int(static_cast<int64_t>(floor_val));
|
||||
}
|
||||
} else if (val > MAX_DOUBLE_TO_INT64) {
|
||||
if (is_equal) {
|
||||
expr_datum.set_int(is_start ? INT64_MAX : INT64_MIN);
|
||||
} else {
|
||||
expr_datum.set_int(INT64_MAX);
|
||||
}
|
||||
} else if (val < MIN_DOUBLE_TO_INT64) {
|
||||
if (is_equal) {
|
||||
expr_datum.set_int(is_start ? INT64_MAX : INT64_MIN);
|
||||
} else {
|
||||
expr_datum.set_int(INT64_MIN);
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(convert_double_to_int64_range(val, start, end))) {
|
||||
LOG_WARN("failed to convert double to int64 range", K(ret));
|
||||
} else if (is_start) {
|
||||
expr_datum.set_int(start);
|
||||
} else {
|
||||
expr_datum.set_int(end);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint64_t start = 0, end = 0;
|
||||
if (val >= MIN_DOUBLE_TO_UINT64 && val <= MAX_PRECISE_DOUBLE) {
|
||||
ceil_val = ceill(val);
|
||||
floor_val = floorl(val);
|
||||
if (ceil_val == floor_val) {
|
||||
expr_datum.set_uint(static_cast<uint64_t>(val));
|
||||
} else if (is_equal) {
|
||||
expr_datum.set_uint(is_start ? UINT64_MAX : 0);
|
||||
} else if (is_start) {
|
||||
expr_datum.set_uint(static_cast<uint64_t>(ceil_val));
|
||||
} else {
|
||||
expr_datum.set_uint(static_cast<uint64_t>(floor_val));
|
||||
}
|
||||
} else if (val > MAX_DOUBLE_TO_UINT64) {
|
||||
if (is_equal) {
|
||||
expr_datum.set_uint(is_start ? UINT64_MAX : 0);
|
||||
} else {
|
||||
expr_datum.set_uint(UINT64_MAX);
|
||||
}
|
||||
} else if (val < MIN_DOUBLE_TO_UINT64) {
|
||||
if (is_equal) {
|
||||
expr_datum.set_uint(is_start ? UINT64_MAX : 0);
|
||||
} else {
|
||||
expr_datum.set_uint(0);
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(convert_double_to_uint64_range(val, start, end))) {
|
||||
LOG_WARN("failed to convert double to int64 range", K(ret));
|
||||
} else if (is_start) {
|
||||
expr_datum.set_uint(start);
|
||||
} else {
|
||||
expr_datum.set_uint(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDoubleToInt::calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExpr *raw_expr = get_raw_expr();
|
||||
UNUSED(type_ctx);
|
||||
if (OB_ISNULL(raw_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("op raw expr is null or param_count error", K(ret), K(raw_expr));
|
||||
} else {
|
||||
bool is_unsigned = (raw_expr->get_extra() & 4) == 4;
|
||||
bool is_decimal = (raw_expr->get_extra() & 8) == 8;
|
||||
if (is_decimal) {
|
||||
type.set_number();
|
||||
} else if (is_unsigned) {
|
||||
type.set_uint64();
|
||||
} else {
|
||||
type.set_int();
|
||||
}
|
||||
type1.set_calc_type(ObDoubleType);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerDoubleToInt::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(expr_cg_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(1 != rt_expr.arg_cnt_)) {
|
||||
ret = OB_ERR_PARAM_SIZE;
|
||||
LOG_WARN("invalid arg cnt of expr", K(ret), K(rt_expr));
|
||||
} else if (OB_ISNULL(rt_expr.args_[0])) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("the arg of inner double to int is null.", K(ret), K(rt_expr));
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprInnerDoubleToInt::eval_inner_double_to_int;
|
||||
rt_expr.extra_ = raw_expr.get_extra();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
56
src/sql/engine/expr/ob_expr_inner_double_to_int.h
Normal file
56
src/sql/engine/expr/ob_expr_inner_double_to_int.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DOUBLE_TO_INT_
|
||||
#define OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DOUBLE_TO_INT_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
//This expression is used to extract double to int range.
|
||||
//inner_double_to_int(val)
|
||||
//for example: inner_double_to_int(9.223372036854776e+18) = 9223372036854775296
|
||||
// inner_double_to_int(9.223372036854776e+18) = INT64_MAX
|
||||
class ObExprInnerDoubleToInt : public ObFuncExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprInnerDoubleToInt(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprInnerDoubleToInt() {};
|
||||
|
||||
virtual int calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_inner_double_to_int(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
|
||||
static int convert_double_to_int64_range(double d, int64_t &start, int64_t &end);
|
||||
|
||||
static int convert_double_to_uint64_range(double d, uint64_t &start, uint64_t &end);
|
||||
|
||||
static int add_double_bit_1(double d, double &out);
|
||||
|
||||
static int sub_double_bit_1(double d, double &out);
|
||||
|
||||
static int double_to_number(double in_val, ObIAllocator &alloc,
|
||||
number::ObNumber &number);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprInnerDoubleToInt) const;
|
||||
};
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
||||
#endif // OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_INNER_DOUBLE_TO_INT_
|
@ -65,7 +65,7 @@ DEF_SET_LOCAL_SESSION_VARS(ObExprInnerTrim, raw_expr) {
|
||||
int ret = OB_SUCCESS;
|
||||
if (lib::is_mysql_mode()) {
|
||||
SET_LOCAL_SYSVAR_CAPACITY(1);
|
||||
EXPR_ADD_LOCAL_SYSVAR(SYS_VAR_COLLATION_CONNECTION);
|
||||
EXPR_ADD_LOCAL_SYSVAR(share::SYS_VAR_COLLATION_CONNECTION);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -465,6 +465,115 @@ int ObExprIsNot::calc_is_not_nan(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &ex
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerIsTrue::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
ObExprResType &type2,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExpr *raw_expr = get_raw_expr();
|
||||
if (OB_ISNULL(raw_expr) || OB_UNLIKELY(raw_expr->get_param_count() != 2)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("op raw expr is null", K(ret), K(raw_expr));
|
||||
} else if (OB_UNLIKELY(type1.is_ext())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected type", K(type1));
|
||||
} else {
|
||||
type.set_type(ObExtendType);
|
||||
type.set_precision(DEFAULT_PRECISION_FOR_TEMPORAL);
|
||||
type.set_scale(SCALE_UNKNOWN_YET);
|
||||
type.set_result_flag(NOT_NULL_FLAG);
|
||||
type2.set_calc_type(type2.get_type());
|
||||
if (ob_is_numeric_type(type1.get_type())) {
|
||||
type1.set_calc_meta(type1.get_obj_meta());
|
||||
type1.set_calc_accuracy(type1.get_accuracy());
|
||||
} else if (ob_is_json(type1.get_type())) {
|
||||
type1.set_calc_meta(type1.get_obj_meta());
|
||||
type1.set_calc_accuracy(type1.get_accuracy());
|
||||
} else {
|
||||
type1.set_calc_type(ObNumberType);
|
||||
const ObAccuracy &calc_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[0][ObNumberType];
|
||||
type1.set_calc_accuracy(calc_acc);
|
||||
}
|
||||
}
|
||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_NO_RANGE_CHECK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprInnerIsTrue::cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObConstRawExpr *param2 = NULL;
|
||||
ObObjType param1_type = ObMaxType;
|
||||
if (rt_expr.arg_cnt_ != 2) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("inner is true expr should have 2 params", K(ret), K(rt_expr.arg_cnt_));
|
||||
} else if (OB_ISNULL(rt_expr.args_) || OB_ISNULL(rt_expr.args_[0]) || OB_ISNULL(rt_expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("children of inner is true expr is null", K(ret), K(rt_expr.args_));
|
||||
} else if (OB_ISNULL(param2 = static_cast<const ObConstRawExpr *>(raw_expr.get_param_expr(1)))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("const raw expr param is null", K(param2));
|
||||
} else if (OB_UNLIKELY(!param2->get_value().is_int())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("const value is not int type", KPC(param2));
|
||||
} else {
|
||||
param1_type = rt_expr.args_[0]->datum_meta_.type_;
|
||||
bool is_start = param2->get_value().get_int() > 0;
|
||||
switch (param1_type) {
|
||||
case ObTinyIntType:
|
||||
case ObSmallIntType:
|
||||
case ObMediumIntType:
|
||||
case ObInt32Type:
|
||||
case ObIntType:
|
||||
case ObUTinyIntType:
|
||||
case ObUSmallIntType:
|
||||
case ObUMediumIntType:
|
||||
case ObUInt32Type:
|
||||
case ObUInt64Type:
|
||||
case ObBitType: {
|
||||
rt_expr.eval_func_ = is_start ? ObExprInnerIsTrue::int_is_true_start
|
||||
: ObExprInnerIsTrue::int_is_true_end;
|
||||
break;
|
||||
}
|
||||
case ObFloatType:
|
||||
case ObUFloatType:{
|
||||
rt_expr.eval_func_ = is_start ? ObExprInnerIsTrue::float_is_true_start
|
||||
: ObExprInnerIsTrue::float_is_true_end;
|
||||
break;
|
||||
}
|
||||
case ObDoubleType:
|
||||
case ObUDoubleType: {
|
||||
rt_expr.eval_func_ = is_start ? ObExprInnerIsTrue::double_is_true_start
|
||||
: ObExprInnerIsTrue::double_is_true_end;
|
||||
break;
|
||||
}
|
||||
case ObDecimalIntType: {
|
||||
rt_expr.eval_func_ = is_start ? ObExprInnerIsTrue::decimal_int_is_true_start
|
||||
: ObExprInnerIsTrue::decimal_int_is_true_end;
|
||||
break;
|
||||
}
|
||||
case ObJsonType: {
|
||||
rt_expr.eval_func_ = is_start ? ObExprInnerIsTrue::json_is_true_start
|
||||
: ObExprInnerIsTrue::json_is_true_end;
|
||||
break;
|
||||
}
|
||||
case ObMaxType: {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("is expr got unexpected type param", K(ret), K(param1_type));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
rt_expr.eval_func_ = is_start ? ObExprInnerIsTrue::number_is_true_start
|
||||
: ObExprInnerIsTrue::number_is_true_end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ObExprIsBase::is_zero(T number, const uint32_t len)
|
||||
{
|
||||
@ -544,5 +653,51 @@ NUMERIC_CALC_FUNC(number, ObExprIs, false, false, is)
|
||||
NUMERIC_CALC_FUNC(decimal_int, ObExprIs, false, false, is)
|
||||
NUMERIC_CALC_FUNC(json, ObExprIs, false, false, is)
|
||||
|
||||
#define INNER_NUMERIC_CALC_FUNC(type, is_start, str_pos) \
|
||||
int ObExprInnerIsTrue::type##_##is_true##_##str_pos(const ObExpr &expr, ObEvalCtx &ctx, \
|
||||
ObDatum &expr_datum) \
|
||||
{ \
|
||||
int ret = OB_SUCCESS; \
|
||||
ObDatum *param1 = NULL; \
|
||||
void *ptr = NULL; \
|
||||
bool ret_bool = false; \
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, param1))) { \
|
||||
LOG_WARN("eval first param failed", K(ret)); \
|
||||
} else if (param1->is_null()) { \
|
||||
ret_bool = false; \
|
||||
} else { \
|
||||
ret_bool = !is_zero(param1->get_##type(), param1->len_); \
|
||||
} \
|
||||
if (OB_SUCC(ret)) { \
|
||||
if (OB_ISNULL(ptr = expr.get_str_res_mem(ctx, sizeof(ObObj)))) { \
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED; \
|
||||
LOG_WARN("failed to allocate expr result memory"); \
|
||||
} else { \
|
||||
ObObj *res_obj = new(ptr)ObObj(); \
|
||||
if ((ret_bool && is_start) || (!ret_bool && !is_start)) { \
|
||||
res_obj->set_min_value(); \
|
||||
} else { \
|
||||
res_obj->set_max_value(); \
|
||||
} \
|
||||
ret = expr_datum.from_obj(*res_obj); \
|
||||
} \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
INNER_NUMERIC_CALC_FUNC(int, true, start)
|
||||
INNER_NUMERIC_CALC_FUNC(float, true, start)
|
||||
INNER_NUMERIC_CALC_FUNC(double, true, start)
|
||||
INNER_NUMERIC_CALC_FUNC(number, true, start)
|
||||
INNER_NUMERIC_CALC_FUNC(decimal_int, true, start)
|
||||
INNER_NUMERIC_CALC_FUNC(json, true, start)
|
||||
|
||||
INNER_NUMERIC_CALC_FUNC(int, false, end)
|
||||
INNER_NUMERIC_CALC_FUNC(float, false, end)
|
||||
INNER_NUMERIC_CALC_FUNC(double, false, end)
|
||||
INNER_NUMERIC_CALC_FUNC(number, false, end)
|
||||
INNER_NUMERIC_CALC_FUNC(decimal_int, false, end)
|
||||
INNER_NUMERIC_CALC_FUNC(json, false, end)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,52 @@ private:
|
||||
// data members
|
||||
};
|
||||
|
||||
/**
|
||||
* inner_is_true(expr, is_start) is used by extract query range only
|
||||
* if expr is true
|
||||
* inner_is_true(expr, 1) return min_value
|
||||
* inner_is_true(expr, 0) return max_value
|
||||
* if expr is false
|
||||
* inner_is_true(expr, 1) return max_value
|
||||
* inner_is_true(expr, 0) return min_value
|
||||
*/
|
||||
class ObExprInnerIsTrue: public ObExprIsBase
|
||||
{
|
||||
public:
|
||||
explicit ObExprInnerIsTrue(common::ObIAllocator &alloc)
|
||||
: ObExprIsBase(alloc, T_FUNC_SYS_INNER_IS_TRUE, N_INEER_IS_TRUE) {};
|
||||
virtual ~ObExprInnerIsTrue() {};
|
||||
|
||||
int calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
ObExprResType &type2,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
|
||||
static int int_is_true_start(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int int_is_true_end(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int float_is_true_start(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int float_is_true_end(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int double_is_true_start(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int double_is_true_end(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int number_is_true_start(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int number_is_true_end(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int decimal_int_is_true_start(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int decimal_int_is_true_end(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int json_is_true_start(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
static int json_is_true_end(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
private:
|
||||
// types and constants
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprInnerIsTrue);
|
||||
// function members
|
||||
private:
|
||||
// data members
|
||||
};
|
||||
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "share/ob_json_access_utils.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "ob_expr_json_func_helper.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::sql;
|
||||
|
||||
|
@ -479,6 +479,9 @@
|
||||
#include "sql/engine/expr/ob_expr_audit_log_func.h"
|
||||
#include "sql/engine/expr/ob_expr_can_access_trigger.h"
|
||||
#include "sql/engine/expr/ob_expr_split_part.h"
|
||||
#include "sql/engine/expr/ob_expr_inner_decode_like.h"
|
||||
#include "sql/engine/expr/ob_expr_inner_double_to_int.h"
|
||||
#include "sql/engine/expr/ob_expr_inner_decimal_to_year.h"
|
||||
#include "sql/engine/expr/ob_expr_array_overlaps.h"
|
||||
#include "sql/engine/expr/ob_expr_array_contains_all.h"
|
||||
#include "sql/engine/expr/ob_expr_array_distinct.h"
|
||||
@ -489,6 +492,7 @@
|
||||
#include "sql/engine/expr/ob_expr_priv_st_geohash.h"
|
||||
#include "sql/engine/expr/ob_expr_priv_st_makepoint.h"
|
||||
|
||||
|
||||
using namespace oceanbase::common;
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -1191,6 +1195,10 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP(ObExprSm4Encrypt);
|
||||
REG_OP(ObExprSm4Decrypt);
|
||||
REG_OP(ObExprSplitPart);
|
||||
REG_OP(ObExprInnerIsTrue);
|
||||
REG_OP(ObExprInnerDecodeLike);
|
||||
REG_OP(ObExprInnerDoubleToInt);
|
||||
REG_OP(ObExprInnerDecimalToYear);
|
||||
REG_OP(ObExprTokenize);
|
||||
REG_OP(ObExprArrayOverlaps);
|
||||
REG_OP(ObExprArrayContainsAll);
|
||||
@ -1531,6 +1539,9 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP_ORCL(ObExprGetPath);
|
||||
REG_OP_ORCL(ObExprDecodeTraceId);
|
||||
REG_OP_ORCL(ObExprSplitPart);
|
||||
REG_OP_ORCL(ObExprInnerIsTrue);
|
||||
REG_OP_ORCL(ObExprInnerDecodeLike);
|
||||
REG_OP_ORCL(ObExprInnerDoubleToInt);
|
||||
REG_OP_ORCL(ObExprCalcOdpsSize);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "ob_expr_sys_makexml.h"
|
||||
#include "sql/engine/expr/ob_expr_xml_func_helper.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::sql;
|
||||
|
||||
|
@ -489,6 +489,7 @@ public:
|
||||
bool is_ps_protocol() const { return is_ps_protocol_; }
|
||||
void set_original_param_cnt(const int64_t cnt) { original_param_cnt_ = cnt; }
|
||||
int64_t get_original_param_cnt() const { return original_param_cnt_; }
|
||||
bool is_exec_param_readable() const { return param_store_.count() > original_param_cnt_; }
|
||||
void set_orig_question_mark_cnt(const int64_t cnt) { orig_question_mark_cnt_ = cnt; }
|
||||
int64_t get_orig_question_mark_cnt() const { return orig_question_mark_cnt_; }
|
||||
void set_is_ps_rewrite_sql() { is_ps_rewrite_sql_ = true; }
|
||||
|
@ -797,7 +797,7 @@ int ObGranuleSplitter::split_gi_task(ObGranulePumpArgs &args,
|
||||
&& OB_FAIL(ranges.assign(args.query_range_by_runtime_filter_))) {
|
||||
LOG_WARN("failed to assign query range", K(ret), K(tablets));
|
||||
} else if (args.query_range_by_runtime_filter_.empty()
|
||||
&& OB_FAIL(get_query_range(*args.ctx_, tsc->get_query_range(), ranges, ss_ranges,
|
||||
&& OB_FAIL(get_query_range(*args.ctx_, tsc->get_query_range_provider(), ranges, ss_ranges,
|
||||
table_id, op_id, partition_granule,
|
||||
ObGranuleUtil::with_param_down(args.gi_attri_flag_)))) {
|
||||
LOG_WARN("get query range failed", K(ret));
|
||||
@ -850,7 +850,7 @@ int ObGranuleSplitter::split_gi_task(ObGranulePumpArgs &args,
|
||||
}
|
||||
|
||||
int ObGranuleSplitter::get_query_range(ObExecContext &ctx,
|
||||
const ObQueryRange &tsc_pre_query_range,
|
||||
const ObQueryRangeProvider &tsc_pre_query_range,
|
||||
ObIArray<ObNewRange> &ranges,
|
||||
ObIArray<ObNewRange> &ss_ranges,
|
||||
int64_t table_id,
|
||||
|
@ -210,7 +210,7 @@ public :
|
||||
virtual ~ObGranuleSplitter() = default;
|
||||
|
||||
static int get_query_range(ObExecContext &ctx,
|
||||
const ObQueryRange &tsc_pre_query_range,
|
||||
const ObQueryRangeProvider &tsc_pre_query_range,
|
||||
ObIArray<ObNewRange> &ranges,
|
||||
ObIArray<ObNewRange> &ss_ranges,
|
||||
int64_t table_id,
|
||||
|
@ -209,7 +209,7 @@ int ObPXServerAddrUtil::get_external_table_loc(
|
||||
ObExecContext &ctx,
|
||||
uint64_t table_id,
|
||||
uint64_t ref_table_id,
|
||||
const ObQueryRange &pre_query_range,
|
||||
const ObQueryRangeProvider &pre_query_range,
|
||||
ObDfo &dfo,
|
||||
ObDASTableLoc *&table_loc)
|
||||
{
|
||||
@ -491,7 +491,7 @@ int ObPXServerAddrUtil::alloc_by_data_distribution_inner(
|
||||
LOG_WARN("fail to get table loc", K(ret), K(table_location_key), K(ref_table_id), K(DAS_CTX(ctx).get_table_loc_list()));
|
||||
} else if (OB_NOT_NULL(scan_op) && scan_op->is_external_table_) {
|
||||
// create new table loc for a random dfo distribution for external table
|
||||
OZ (get_external_table_loc(ctx, table_location_key, ref_table_id, scan_op->get_query_range(), dfo, table_loc));
|
||||
OZ (get_external_table_loc(ctx, table_location_key, ref_table_id, scan_op->get_query_range_provider(), dfo, table_loc));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1183,7 +1183,7 @@ int ObPXServerAddrUtil::set_dfo_accessed_location(ObExecContext &ctx,
|
||||
LOG_WARN("failed to get phy table location", K(ret));
|
||||
} else if (scan_op->is_external_table_
|
||||
&& OB_FAIL(get_external_table_loc(ctx, table_location_key, ref_table_id,
|
||||
scan_op->get_query_range(), dfo, table_loc))) {
|
||||
scan_op->get_query_range_provider(), dfo, table_loc))) {
|
||||
LOG_WARN("fail to get external table loc", K(ret));
|
||||
} else if (OB_FAIL(set_sqcs_accessed_location(ctx,
|
||||
// dml op has already set sqc.get_location information,
|
||||
|
@ -196,7 +196,7 @@ public:
|
||||
ObExecContext &ctx,
|
||||
uint64_t table_id,
|
||||
uint64_t ref_table_id,
|
||||
const ObQueryRange &pre_query_range,
|
||||
const ObQueryRangeProvider &pre_query_range,
|
||||
ObDfo &dfo,
|
||||
ObDASTableLoc *&table_loc);
|
||||
|
||||
|
@ -110,6 +110,7 @@ OB_DEF_SERIALIZE(ObTableScanCtDef)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool has_lookup = (lookup_ctdef_ != nullptr);
|
||||
bool is_new_query_range = scan_flags_.is_new_query_range();
|
||||
OB_UNIS_ENCODE(pre_query_range_);
|
||||
OB_UNIS_ENCODE(flashback_item_.need_scn_);
|
||||
OB_UNIS_ENCODE(flashback_item_.flashback_query_expr_);
|
||||
@ -137,6 +138,9 @@ OB_DEF_SERIALIZE(ObTableScanCtDef)
|
||||
OB_UNIS_ENCODE(abandoned_always_false_text_ir);
|
||||
OB_UNIS_ENCODE(attach_spec_);
|
||||
OB_UNIS_ENCODE(flags_);
|
||||
if (is_new_query_range) {
|
||||
OB_UNIS_ENCODE(pre_range_graph_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -144,6 +148,7 @@ OB_DEF_SERIALIZE_SIZE(ObTableScanCtDef)
|
||||
{
|
||||
int64_t len = 0;
|
||||
bool has_lookup = (lookup_ctdef_ != nullptr);
|
||||
bool is_new_query_range = scan_flags_.is_new_query_range();
|
||||
OB_UNIS_ADD_LEN(pre_query_range_);
|
||||
OB_UNIS_ADD_LEN(flashback_item_.need_scn_);
|
||||
OB_UNIS_ADD_LEN(flashback_item_.flashback_query_expr_);
|
||||
@ -171,6 +176,9 @@ OB_DEF_SERIALIZE_SIZE(ObTableScanCtDef)
|
||||
OB_UNIS_ADD_LEN(abandoned_always_false_text_ir);
|
||||
OB_UNIS_ADD_LEN(attach_spec_);
|
||||
OB_UNIS_ADD_LEN(flags_);
|
||||
if (is_new_query_range) {
|
||||
OB_UNIS_ADD_LEN(pre_range_graph_);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -222,6 +230,10 @@ OB_DEF_DESERIALIZE(ObTableScanCtDef)
|
||||
OB_UNIS_DECODE(abandoned_always_false_text_ir);
|
||||
OB_UNIS_DECODE(attach_spec_);
|
||||
OB_UNIS_DECODE(flags_);
|
||||
bool is_new_query_range = scan_flags_.is_new_query_range();
|
||||
if (is_new_query_range) {
|
||||
OB_UNIS_DECODE(pre_range_graph_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1358,74 +1370,68 @@ int ObTableScanOp::prepare_single_scan_range(int64_t group_idx)
|
||||
ObIAllocator &range_allocator = (table_rescan_allocator_ != nullptr ?
|
||||
*table_rescan_allocator_ : ctx_.get_allocator());
|
||||
bool is_same_type = true; // use for extract equal pre_query_range
|
||||
if (OB_FAIL(single_equal_scan_check_type(plan_ctx->get_param_store(), is_same_type))) {
|
||||
LOG_WARN("failed to check type about single equal scan", K(ret));
|
||||
} else if (is_same_type && MY_CTDEF.pre_query_range_.get_is_equal_and()) {
|
||||
int64_t column_count = MY_CTDEF.pre_query_range_.get_column_count();
|
||||
size_t range_size = sizeof(ObNewRange) + sizeof(ObObj) * column_count * 2;
|
||||
void *range_buffers = static_cast<char*>(tsc_rtdef_.range_buffers_) + tsc_rtdef_.range_buffer_idx_ * range_size;
|
||||
if (tsc_rtdef_.range_buffer_idx_ < 0 || tsc_rtdef_.range_buffer_idx_ >= tsc_rtdef_.max_group_size_) {
|
||||
ret = OB_ERROR_OUT_OF_RANGE;
|
||||
LOG_WARN("get wrong offset of range_buffers_", K(ret));
|
||||
} else if (OB_FAIL(ObSQLUtils::extract_equal_pre_query_range(
|
||||
MY_CTDEF.pre_query_range_,
|
||||
range_buffers,
|
||||
plan_ctx->get_param_store(),
|
||||
key_ranges))) {
|
||||
LOG_WARN("failed to extract equal pre query ranges", K(ret));
|
||||
}
|
||||
} else {
|
||||
if (OB_UNLIKELY(!need_extract_range())) {
|
||||
// virtual table, do nothing
|
||||
} else if (MY_CTDEF.pre_query_range_.is_contain_geo_filters() &&
|
||||
OB_FAIL(ObSQLUtils::extract_geo_query_range(
|
||||
MY_CTDEF.pre_query_range_,
|
||||
range_allocator,
|
||||
ctx_,
|
||||
key_ranges,
|
||||
MY_INPUT.mbr_filters_,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to extract pre query ranges", K(ret));
|
||||
} else if (!MY_CTDEF.pre_query_range_.is_contain_geo_filters() &&
|
||||
OB_FAIL(ObSQLUtils::extract_pre_query_range(
|
||||
MY_CTDEF.pre_query_range_,
|
||||
range_allocator,
|
||||
ctx_,
|
||||
key_ranges,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to extract pre query ranges", K(ret));
|
||||
} else if (MY_CTDEF.scan_ctdef_.is_external_table_) {
|
||||
uint64_t table_loc_id = MY_SPEC.get_table_loc_id();
|
||||
ObDASTableLoc *tab_loc = DAS_CTX(ctx_).get_table_loc_by_id(table_loc_id, MY_CTDEF.scan_ctdef_.ref_table_id_);
|
||||
const ObString &table_format_or_properties = MY_CTDEF.scan_ctdef_.external_file_format_str_.str_;
|
||||
ObArray<int64_t> partition_ids;
|
||||
if (OB_ISNULL(tab_loc)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("table lock is null", K(ret));
|
||||
} else {
|
||||
for (DASTabletLocListIter iter = tab_loc->tablet_locs_begin(); OB_SUCC(ret)
|
||||
&& iter != tab_loc->tablet_locs_end(); ++iter) {
|
||||
ret = partition_ids.push_back((*iter)->partition_id_);
|
||||
}
|
||||
if (OB_UNLIKELY(!need_extract_range())) {
|
||||
// virtual table, do nothing
|
||||
} else if (MY_CTDEF.get_query_range_provider().is_contain_geo_filters() &&
|
||||
OB_FAIL(ObSQLUtils::extract_geo_query_range(
|
||||
MY_CTDEF.get_query_range_provider(),
|
||||
range_allocator,
|
||||
ctx_,
|
||||
key_ranges,
|
||||
MY_INPUT.mbr_filters_,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to extract pre query ranges", K(ret));
|
||||
} else if (!MY_CTDEF.get_query_range_provider().is_contain_geo_filters() &&
|
||||
MY_CTDEF.get_query_range_provider().is_fast_nlj_range() &&
|
||||
OB_FAIL(MY_CTDEF.get_query_range_provider().get_fast_nlj_tablet_ranges(
|
||||
tsc_rtdef_.fast_final_nlj_range_ctx_,
|
||||
range_allocator,
|
||||
ctx_,
|
||||
plan_ctx->get_param_store(),
|
||||
locate_range_buffer(),
|
||||
key_ranges,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to extract pre fast nlj query range", K(ret));
|
||||
} else if (!MY_CTDEF.get_query_range_provider().is_contain_geo_filters() &&
|
||||
!MY_CTDEF.get_query_range_provider().is_fast_nlj_range() &&
|
||||
OB_FAIL(ObSQLUtils::extract_pre_query_range(
|
||||
MY_CTDEF.get_query_range_provider(),
|
||||
range_allocator,
|
||||
ctx_,
|
||||
key_ranges,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to extract pre query ranges", K(ret));
|
||||
} else if (MY_CTDEF.scan_ctdef_.is_external_table_) {
|
||||
uint64_t table_loc_id = MY_SPEC.get_table_loc_id();
|
||||
ObDASTableLoc *tab_loc = DAS_CTX(ctx_).get_table_loc_by_id(table_loc_id, MY_CTDEF.scan_ctdef_.ref_table_id_);
|
||||
const ObString &table_format_or_properties = MY_CTDEF.scan_ctdef_.external_file_format_str_.str_;
|
||||
ObArray<int64_t> partition_ids;
|
||||
if (OB_ISNULL(tab_loc)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("table lock is null", K(ret));
|
||||
} else {
|
||||
for (DASTabletLocListIter iter = tab_loc->tablet_locs_begin(); OB_SUCC(ret)
|
||||
&& iter != tab_loc->tablet_locs_end(); ++iter) {
|
||||
ret = partition_ids.push_back((*iter)->partition_id_);
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(ObExternalTableUtils::prepare_single_scan_range(
|
||||
ctx_.get_my_session()->get_effective_tenant_id(),
|
||||
MY_CTDEF.scan_ctdef_.ref_table_id_,
|
||||
table_format_or_properties,
|
||||
partition_ids,
|
||||
key_ranges,
|
||||
range_allocator,
|
||||
key_ranges,
|
||||
tab_loc->loc_meta_->is_external_files_on_disk_))) {
|
||||
LOG_WARN("failed to prepare single scan range for external table", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(MY_CTDEF.pre_query_range_.get_ss_tablet_ranges(range_allocator,
|
||||
ctx_,
|
||||
ss_key_ranges,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to final extract index skip query range", K(ret));
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(ObExternalTableUtils::prepare_single_scan_range(
|
||||
ctx_.get_my_session()->get_effective_tenant_id(),
|
||||
MY_CTDEF.scan_ctdef_.ref_table_id_,
|
||||
table_format_or_properties,
|
||||
partition_ids,
|
||||
key_ranges,
|
||||
range_allocator,
|
||||
key_ranges,
|
||||
tab_loc->loc_meta_->is_external_files_on_disk_))) {
|
||||
LOG_WARN("failed to prepare single scan range for external table", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(MY_CTDEF.get_query_range_provider().get_ss_tablet_ranges(range_allocator,
|
||||
ctx_,
|
||||
ss_key_ranges,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to final extract index skip query range", K(ret));
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (!ss_key_ranges.empty()) {
|
||||
@ -1698,8 +1704,8 @@ int ObTableScanOp::inner_open()
|
||||
// here need add plan batch_size, because in vectorized execution,
|
||||
// left batch may greater than OB_MAX_BULK_JOIN_ROWS
|
||||
tsc_rtdef_.max_group_size_ = OB_MAX_BULK_JOIN_ROWS + MY_SPEC.plan_->get_batch_size();
|
||||
if (MY_CTDEF.pre_query_range_.get_is_equal_and()) {
|
||||
int64_t column_count = MY_CTDEF.pre_query_range_.get_column_count();
|
||||
if (MY_CTDEF.get_query_range_provider().is_fast_nlj_range()) {
|
||||
int64_t column_count = MY_CTDEF.get_query_range_provider().get_column_count();
|
||||
size_t range_size = sizeof(ObNewRange) + sizeof(ObObj) * column_count * 2;
|
||||
if (!MY_SPEC.batch_scan_flag_) {
|
||||
tsc_rtdef_.range_buffers_ = ctx_.get_allocator().alloc(range_size);
|
||||
@ -2854,7 +2860,7 @@ int ObTableScanOp::reassign_task_ranges(ObGranuleTaskInfo &info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (MY_SPEC.gi_above_ && !iter_end_) {
|
||||
if (OB_UNLIKELY(MY_SPEC.get_query_range().is_contain_geo_filters())) {
|
||||
if (OB_UNLIKELY(MY_SPEC.get_query_range_provider().is_contain_geo_filters())) {
|
||||
MY_INPUT.key_ranges_.reuse();
|
||||
MY_INPUT.ss_key_ranges_.reuse();
|
||||
MY_INPUT.mbr_filters_.reuse();
|
||||
|
@ -168,6 +168,7 @@ public:
|
||||
allocator_(allocator),
|
||||
calc_part_id_expr_(NULL),
|
||||
global_index_rowkey_exprs_(allocator),
|
||||
pre_range_graph_(allocator),
|
||||
attach_spec_(allocator_, &scan_ctdef_),
|
||||
flags_(0)
|
||||
{ }
|
||||
@ -183,6 +184,11 @@ public:
|
||||
lookup_ctdef_->access_column_ids_ :
|
||||
scan_ctdef_.access_column_ids_;
|
||||
}
|
||||
const ObQueryRangeProvider& get_query_range_provider() const
|
||||
{
|
||||
return scan_flags_.is_new_query_range() ? static_cast<const ObQueryRangeProvider&>(pre_range_graph_)
|
||||
: static_cast<const ObQueryRangeProvider&>(pre_query_range_);
|
||||
}
|
||||
int allocate_dppr_table_loc();
|
||||
ObDASScanCtDef *get_lookup_ctdef();
|
||||
const ObDASScanCtDef *get_lookup_ctdef() const;
|
||||
@ -227,6 +233,7 @@ public:
|
||||
ObExpr *calc_part_id_expr_;
|
||||
ExprFixedArray global_index_rowkey_exprs_;
|
||||
// end for Global Index Lookup
|
||||
ObPreRangeGraph pre_range_graph_;
|
||||
ObDASAttachSpec attach_spec_;
|
||||
union {
|
||||
uint64_t flags_;
|
||||
@ -246,6 +253,7 @@ struct ObTableScanRtDef
|
||||
lookup_rtdef_(nullptr),
|
||||
range_buffers_(nullptr),
|
||||
range_buffer_idx_(0),
|
||||
fast_final_nlj_range_ctx_(),
|
||||
group_size_(0),
|
||||
max_group_size_(0),
|
||||
attach_rtinfo_(nullptr),
|
||||
@ -266,6 +274,7 @@ struct ObTableScanRtDef
|
||||
// for equal_query_range opt
|
||||
void *range_buffers_;
|
||||
int64_t range_buffer_idx_;
|
||||
ObFastFinalNLJRangeCtx fast_final_nlj_range_ctx_;
|
||||
// for equal_query_range opt end
|
||||
int64_t group_size_;
|
||||
int64_t max_group_size_;
|
||||
@ -346,7 +355,7 @@ public:
|
||||
int explain_index_selection_info(char *buf, int64_t buf_len, int64_t &pos) const;
|
||||
|
||||
virtual bool is_table_scan() const override { return true; }
|
||||
inline const ObQueryRange &get_query_range() const { return tsc_ctdef_.pre_query_range_; }
|
||||
inline const ObQueryRangeProvider &get_query_range_provider() const { return tsc_ctdef_.get_query_range_provider(); }
|
||||
inline uint64_t get_table_loc_id() const { return table_loc_id_; }
|
||||
bool use_dist_das() const { return use_dist_das_; }
|
||||
int64_t get_rowkey_cnt() const {
|
||||
@ -524,7 +533,7 @@ protected:
|
||||
int prepare_batch_scan_range();
|
||||
int build_bnlj_params();
|
||||
int single_equal_scan_check_type(const ParamStore ¶m_store, bool& is_same_type);
|
||||
bool need_extract_range() const { return MY_SPEC.tsc_ctdef_.pre_query_range_.has_range(); }
|
||||
bool need_extract_range() const { return MY_SPEC.tsc_ctdef_.get_query_range_provider().has_range(); }
|
||||
int prepare_single_scan_range(int64_t group_idx = 0);
|
||||
int prepare_index_merge_scan_range(int64_t group_idx = 0);
|
||||
int prepare_range_for_each_index(int64_t group_idx, ObIAllocator &allocator, ObDASBaseRtDef *rtdef);
|
||||
@ -682,6 +691,13 @@ protected:
|
||||
int64_t range_buffer_idx_;
|
||||
};
|
||||
|
||||
OB_INLINE void* locate_range_buffer()
|
||||
{
|
||||
int64_t column_count = MY_SPEC.tsc_ctdef_.get_query_range_provider().get_column_count();
|
||||
size_t range_size = sizeof(ObNewRange) + sizeof(ObObj) * column_count * 2;
|
||||
void *range_buffers = static_cast<char*>(tsc_rtdef_.range_buffers_) + tsc_rtdef_.range_buffer_idx_ * range_size;
|
||||
return range_buffers;
|
||||
}
|
||||
private:
|
||||
const ObTableScanSpec& get_tsc_spec() {return MY_SPEC;}
|
||||
const ObTableScanCtDef& get_tsc_ctdef() {return MY_SPEC.tsc_ctdef_;}
|
||||
|
@ -2875,7 +2875,7 @@ bool check_stack_overflow_c()
|
||||
return is_overflow;
|
||||
}
|
||||
|
||||
int ObSQLUtils::extract_pre_query_range(const ObQueryRange &pre_query_range,
|
||||
int ObSQLUtils::extract_pre_query_range(const ObQueryRangeProvider &query_range_provider,
|
||||
ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &key_ranges,
|
||||
@ -2883,55 +2883,65 @@ int ObSQLUtils::extract_pre_query_range(const ObQueryRange &pre_query_range,
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool dummy_all_single_value_ranges = false;
|
||||
if (OB_FAIL(pre_query_range.get_tablet_ranges(allocator, exec_ctx, key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
if (OB_FAIL(query_range_provider.get_tablet_ranges(allocator, exec_ctx, key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSQLUtils::extract_geo_query_range(const ObQueryRange &pre_query_range,
|
||||
ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &key_ranges,
|
||||
ObMbrFilterArray &mbr_filters,
|
||||
const ObDataTypeCastParams &dtc_params)
|
||||
int ObSQLUtils::extract_geo_query_range(const ObQueryRangeProvider &query_range_provider,
|
||||
ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &key_ranges,
|
||||
ObMbrFilterArray &mbr_filters,
|
||||
const ObDataTypeCastParams &dtc_params)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool dummy_all_single_value_ranges = false;
|
||||
if (OB_LIKELY(!pre_query_range.need_deep_copy())) {
|
||||
//对于大多数查询来说,query条件是非常规范和工整的,这种条件我们不需要拷贝进行graph的变化,可以直接提取
|
||||
if (OB_FAIL(pre_query_range.direct_get_tablet_ranges(allocator,
|
||||
exec_ctx,
|
||||
key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("fail to get tablet ranges", K(ret));
|
||||
} else {
|
||||
const MbrFilterArray &pre_filters = pre_query_range.get_mbr_filter();
|
||||
FOREACH_X(it, pre_filters, OB_SUCC(ret) && it != pre_filters.end()) {
|
||||
if (OB_FAIL(mbr_filters.push_back(*it))) {
|
||||
LOG_WARN("store mbr_filters_ failed", K(ret));
|
||||
}
|
||||
}
|
||||
if (query_range_provider.is_new_query_range()) {
|
||||
if (OB_FAIL(query_range_provider.get_tablet_ranges(allocator, exec_ctx, key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params,
|
||||
mbr_filters))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
}
|
||||
} else {
|
||||
ObQueryRange final_query_range(allocator);
|
||||
if (OB_FAIL(final_query_range.deep_copy(pre_query_range))) {
|
||||
// MUST deep copy to make it thread safe
|
||||
LOG_WARN("fail to create final query range", K(ret), K(pre_query_range));
|
||||
} else if (OB_FAIL(final_query_range.final_extract_query_range(exec_ctx, dtc_params))) {
|
||||
LOG_WARN("fail to final extract query range", K(ret), K(final_query_range));
|
||||
} else if (OB_FAIL(final_query_range.get_tablet_ranges(key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("fail to get tablet ranges from query range", K(ret), K(final_query_range));
|
||||
const ObQueryRange &pre_query_range = static_cast<const ObQueryRange&>(query_range_provider);
|
||||
if (OB_LIKELY(!pre_query_range.need_deep_copy())) {
|
||||
//对于大多数查询来说,query条件是非常规范和工整的,这种条件我们不需要拷贝进行graph的变化,可以直接提取
|
||||
if (OB_FAIL(pre_query_range.direct_get_tablet_ranges(allocator,
|
||||
exec_ctx,
|
||||
key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("fail to get tablet ranges", K(ret));
|
||||
} else {
|
||||
const MbrFilterArray &pre_filters = pre_query_range.get_mbr_filter();
|
||||
FOREACH_X(it, pre_filters, OB_SUCC(ret) && it != pre_filters.end()) {
|
||||
if (OB_FAIL(mbr_filters.push_back(*it))) {
|
||||
LOG_WARN("store mbr_filters_ failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const MbrFilterArray &pre_filters = final_query_range.get_mbr_filter();
|
||||
FOREACH_X(it, pre_filters, OB_SUCC(ret) && it != pre_filters.end()) {
|
||||
if (OB_FAIL(mbr_filters.push_back(*it))) {
|
||||
LOG_WARN("store mbr_filters_ failed", K(ret));
|
||||
ObQueryRange final_query_range(allocator);
|
||||
if (OB_FAIL(final_query_range.deep_copy(pre_query_range))) {
|
||||
// MUST deep copy to make it thread safe
|
||||
LOG_WARN("fail to create final query range", K(ret), K(pre_query_range));
|
||||
} else if (OB_FAIL(final_query_range.final_extract_query_range(exec_ctx, dtc_params))) {
|
||||
LOG_WARN("fail to final extract query range", K(ret), K(final_query_range));
|
||||
} else if (OB_FAIL(final_query_range.get_tablet_ranges(key_ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("fail to get tablet ranges from query range", K(ret), K(final_query_range));
|
||||
} else {
|
||||
const MbrFilterArray &pre_filters = final_query_range.get_mbr_filter();
|
||||
FOREACH_X(it, pre_filters, OB_SUCC(ret) && it != pre_filters.end()) {
|
||||
if (OB_FAIL(mbr_filters.push_back(*it))) {
|
||||
LOG_WARN("store mbr_filters_ failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6419,6 +6429,17 @@ bool ObSQLUtils::is_data_version_ge_424_or_433(uint64_t data_version)
|
||||
return ((MOCK_DATA_VERSION_4_2_4_0 <= data_version && data_version < DATA_VERSION_4_3_0_0) || data_version >= DATA_VERSION_4_3_3_0);
|
||||
}
|
||||
|
||||
bool ObSQLUtils::is_min_cluster_version_ge_425_or_435()
|
||||
{
|
||||
uint64_t version = GET_MIN_CLUSTER_VERSION();
|
||||
return ((MOCK_CLUSTER_VERSION_4_2_5_0 <= version && version < CLUSTER_VERSION_4_3_0_0) || version >= CLUSTER_VERSION_4_3_5_0);
|
||||
}
|
||||
|
||||
bool ObSQLUtils::is_opt_feature_version_ge_425_or_435(uint64_t opt_feature_version)
|
||||
{
|
||||
return ((COMPAT_VERSION_4_2_5 <= opt_feature_version && opt_feature_version < COMPAT_VERSION_4_3_0) || opt_feature_version >= COMPAT_VERSION_4_3_5);
|
||||
}
|
||||
|
||||
int ObSQLUtils::get_strong_partition_replica_addr(const ObCandiTabletLoc &phy_part_loc_info,
|
||||
ObAddr &selected_addr)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define _OCEANBASE_SQL_OB_SQL_UTILS_H
|
||||
|
||||
#include "common/ob_range.h"
|
||||
#include "sql/rewrite/ob_query_range_provider.h"
|
||||
#include "common/object/ob_object.h"
|
||||
#include "lib/container/ob_vector.h"
|
||||
#include "lib/container/ob_2d_array.h"
|
||||
@ -456,7 +457,7 @@ public:
|
||||
common::ObExprCtx &expr_ctx);
|
||||
|
||||
// use get_tablet_ranges instead.
|
||||
static int extract_pre_query_range(const ObQueryRange &pre_query_range,
|
||||
static int extract_pre_query_range(const ObQueryRangeProvider &query_range_provider,
|
||||
common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &key_ranges,
|
||||
@ -466,7 +467,7 @@ public:
|
||||
void *range_buffer,
|
||||
const ParamStore ¶m_store,
|
||||
ObQueryRangeArray &key_ranges);
|
||||
static int extract_geo_query_range(const ObQueryRange &pre_query_range,
|
||||
static int extract_geo_query_range(const ObQueryRangeProvider &query_range_provider,
|
||||
ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &key_ranges,
|
||||
@ -776,6 +777,8 @@ public:
|
||||
static bool is_data_version_ge_423_or_431(uint64_t data_version);
|
||||
static bool is_data_version_ge_423_or_432(uint64_t data_version);
|
||||
static bool is_data_version_ge_424_or_433(uint64_t data_version);
|
||||
static bool is_min_cluster_version_ge_425_or_435();
|
||||
static bool is_opt_feature_version_ge_425_or_435(uint64_t opt_feature_version);
|
||||
|
||||
static int get_proxy_can_activate_role(const ObIArray<uint64_t> &role_id_array,
|
||||
const ObIArray<uint64_t> &role_id_option_array,
|
||||
|
@ -316,8 +316,8 @@ int ObAccessPathEstimation::choose_best_est_method(ObOptimizerContext &ctx,
|
||||
if (OB_ISNULL(paths.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret), K(paths.at(i)));
|
||||
} else if (paths.at(i)->pre_query_range_ != NULL &&
|
||||
OB_FAIL(paths.at(i)->pre_query_range_->is_get(is_table_get))) {
|
||||
} else if (paths.at(i)->get_query_range_provider() != NULL &&
|
||||
OB_FAIL(paths.at(i)->get_query_range_provider()->is_get(is_table_get))) {
|
||||
LOG_WARN("check query range is table get", K(ret));
|
||||
}
|
||||
}
|
||||
@ -1076,9 +1076,13 @@ int ObAccessPathEstimation::process_storage_estimation_result(ObIArray<ObBatchEs
|
||||
if (is_reliable) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < result_helpers.count(); ++i) {
|
||||
AccessPath *path = result_helpers.at(i).path_;
|
||||
bool new_range_with_exec_param = (path->get_query_range_provider() != NULL &&
|
||||
path->get_query_range_provider()->is_new_query_range() &&
|
||||
path->get_query_range_provider()->has_exec_param());
|
||||
if (result_helpers.at(i).result_.logical_row_count_ >= 0 &&
|
||||
OB_FAIL(estimate_prefix_range_rowcount(result_helpers.at(i).result_.logical_row_count_,
|
||||
result_helpers.at(i).result_.physical_row_count_,
|
||||
new_range_with_exec_param,
|
||||
path->est_cost_info_))) {
|
||||
LOG_WARN("failed to estimate prefix range rowcount", K(ret));
|
||||
} else if (OB_FAIL(fill_cost_table_scan_info(path->est_cost_info_))) {
|
||||
@ -1166,6 +1170,7 @@ int ObAccessPathEstimation::do_storage_estimation(ObOptimizerContext &ctx,
|
||||
int ObAccessPathEstimation::estimate_prefix_range_rowcount(
|
||||
const double res_logical_row_count,
|
||||
const double res_physical_row_count,
|
||||
bool new_range_with_exec_param,
|
||||
ObCostTableScanInfo &est_cost_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1179,6 +1184,17 @@ int ObAccessPathEstimation::estimate_prefix_range_rowcount(
|
||||
physical_row_count += get_range_count;
|
||||
|
||||
// NLJ or SPF push down prefix filters
|
||||
if (new_range_with_exec_param) {
|
||||
/**
|
||||
* new query range extraction always get (min; max) for range graph with exec param.
|
||||
* for NLJ push down path with expr (c1 = 1 and c2 = ?). old query range generate
|
||||
* (1, min; 1, max), New query range generate (min, min; max, max). This behavior will
|
||||
* cause row estimate with new query range get a larger result.Hence, we need multiple
|
||||
* prefix_filter_sel for push down path with exec param to get a more accurate row count.
|
||||
*/
|
||||
logical_row_count *= est_cost_info.prefix_filter_sel_;
|
||||
physical_row_count *= est_cost_info.prefix_filter_sel_;
|
||||
}
|
||||
logical_row_count *= est_cost_info.pushdown_prefix_filter_sel_;
|
||||
physical_row_count *= est_cost_info.pushdown_prefix_filter_sel_;
|
||||
|
||||
@ -1491,7 +1507,8 @@ int ObAccessPathEstimation::calc_skip_scan_prefix_ndv(AccessPath &ap, double &pr
|
||||
ObJoinOrder *join_order = NULL;
|
||||
ObLogPlan *log_plan = NULL;
|
||||
const ObTableMetaInfo *table_meta_info = NULL;
|
||||
if (OB_ISNULL(ap.pre_query_range_) || !ap.pre_query_range_->is_ss_range()
|
||||
ObQueryRangeProvider *query_range_provider = ap.get_query_range_provider();
|
||||
if (OB_ISNULL(query_range_provider) || !query_range_provider->is_ss_range()
|
||||
|| OptSkipScanState::SS_DISABLE == ap.use_skip_scan_) {
|
||||
/* do nothing */
|
||||
} else if (OB_ISNULL(join_order = ap.parent_) || OB_ISNULL(log_plan = join_order->get_plan())
|
||||
@ -1509,7 +1526,7 @@ int ObAccessPathEstimation::calc_skip_scan_prefix_ndv(AccessPath &ap, double &pr
|
||||
const double temp_rows = log_plan->get_selectivity_ctx().get_current_rows();
|
||||
log_plan->get_selectivity_ctx().init_op_ctx(&join_order->get_output_equal_sets(), prefix_range_row_count);
|
||||
if (OB_FAIL(get_skip_scan_prefix_exprs(ap.est_cost_info_.range_columns_,
|
||||
ap.pre_query_range_->get_skip_scan_offset(),
|
||||
query_range_provider->get_skip_scan_offset(),
|
||||
prefix_exprs))) {
|
||||
LOG_WARN("failed to get skip scan prefix expers", K(ret));
|
||||
} else if (OB_FAIL(ObOptSelectivity::update_table_meta_info(log_plan->get_basic_table_metas(),
|
||||
@ -1517,7 +1534,7 @@ int ObAccessPathEstimation::calc_skip_scan_prefix_ndv(AccessPath &ap, double &pr
|
||||
log_plan->get_selectivity_ctx(),
|
||||
ap.get_table_id(),
|
||||
prefix_range_row_count,
|
||||
ap.pre_query_range_->get_range_exprs(),
|
||||
query_range_provider->get_range_exprs(),
|
||||
log_plan->get_predicate_selectivities()))) {
|
||||
LOG_WARN("failed to update table meta info", K(ret));
|
||||
} else if (OB_FAIL(ObOptSelectivity::calculate_distinct(tmp_metas,
|
||||
|
@ -286,6 +286,7 @@ private:
|
||||
static int estimate_prefix_range_rowcount(
|
||||
const double res_logical_row_count,
|
||||
const double res_physical_row_count,
|
||||
bool new_range_with_exec_param,
|
||||
ObCostTableScanInfo &est_cost_info);
|
||||
|
||||
static int fill_cost_table_scan_info(ObCostTableScanInfo &est_cost_info);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define OCEANBASE_SQL_OPTIMIZER_OB_INDEX_INFO_CACHE_H 1
|
||||
|
||||
#include "sql/rewrite/ob_query_range.h"
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
#include "sql/ob_sql_define.h"
|
||||
|
||||
namespace oceanbase
|
||||
@ -28,6 +29,7 @@ public:
|
||||
QueryRangeInfo() : is_valid_(false),
|
||||
contain_always_false_(false),
|
||||
query_range_(NULL),
|
||||
pre_range_graph_(NULL),
|
||||
ranges_(),
|
||||
ss_ranges_(),
|
||||
equal_prefix_count_(0),
|
||||
@ -35,8 +37,15 @@ public:
|
||||
range_prefix_count_(0),
|
||||
index_column_count_(0),
|
||||
range_columns_(),
|
||||
expr_constraints_() {}
|
||||
expr_constraints_(),
|
||||
index_prefix_(-1) {}
|
||||
const ObQueryRange* get_query_range() const { return query_range_; }
|
||||
const ObPreRangeGraph* get_pre_range_graph() const { return pre_range_graph_; }
|
||||
const ObQueryRangeProvider *get_query_range_provider() const
|
||||
{
|
||||
return pre_range_graph_ != nullptr ? static_cast<const ObQueryRangeProvider *>(pre_range_graph_)
|
||||
: static_cast<const ObQueryRangeProvider *>(query_range_);
|
||||
}
|
||||
const ObQueryRangeArray& get_ranges() const { return ranges_; }
|
||||
const common::ObIArray<ColumnItem> &get_range_columns() const { return range_columns_; }
|
||||
const common::ObIArray<ObExprConstraint> &get_expr_constraints() const
|
||||
@ -53,6 +62,7 @@ public:
|
||||
ObQueryRangeArray& get_ss_ranges() { return ss_ranges_; }
|
||||
const ObQueryRangeArray& get_ss_ranges() const { return ss_ranges_; }
|
||||
void set_query_range(ObQueryRange *query_range) { query_range_ = query_range; }
|
||||
void set_pre_range_graph(ObPreRangeGraph *pre_range_graph) { pre_range_graph_ = pre_range_graph; }
|
||||
common::ObIArray<ColumnItem> &get_range_columns() { return range_columns_; }
|
||||
common::ObIArray<ObExprConstraint> &get_expr_constraints() { return expr_constraints_; }
|
||||
void set_valid() { is_valid_ = true; }
|
||||
@ -87,14 +97,18 @@ public:
|
||||
{ index_column_count_ = index_column_count; };
|
||||
void set_contain_always_false(const bool contain_always_false)
|
||||
{ contain_always_false_ = contain_always_false; }
|
||||
void set_index_prefix(int64_t index_prefix)
|
||||
{ index_prefix_ = index_prefix; }
|
||||
int64_t get_index_prefix() const { return index_prefix_; }
|
||||
|
||||
TO_STRING_KV(K_(is_valid), K_(contain_always_false), K_(range_columns), K_(equal_prefix_count),
|
||||
K_(equal_prefix_null_count), K_(range_prefix_count),
|
||||
K_(index_column_count), K_(expr_constraints));
|
||||
K_(index_column_count), K_(expr_constraints), K_(index_prefix));
|
||||
private:
|
||||
bool is_valid_;
|
||||
bool contain_always_false_;
|
||||
ObQueryRange *query_range_;
|
||||
ObPreRangeGraph *pre_range_graph_;
|
||||
ObQueryRangeArray ranges_;
|
||||
ObQueryRangeArray ss_ranges_; // for index skip scan, postfix range
|
||||
int64_t equal_prefix_count_;
|
||||
@ -103,6 +117,7 @@ private:
|
||||
int64_t index_column_count_; // index column count without adding primary key
|
||||
common::ObArray<ColumnItem> range_columns_;
|
||||
common::ObArray<ObExprConstraint> expr_constraints_;
|
||||
int64_t index_prefix_;
|
||||
DISALLOW_COPY_AND_ASSIGN(QueryRangeInfo);
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "share/stat/ob_opt_stat_manager.h"
|
||||
#include "sql/rewrite/ob_predicate_deduce.h"
|
||||
#include "share/vector_index/ob_vector_index_util.h"
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
using namespace oceanbase;
|
||||
using namespace sql;
|
||||
using namespace oceanbase::common;
|
||||
@ -87,17 +88,18 @@ int ObJoinOrder::fill_query_range_info(const QueryRangeInfo &range_info,
|
||||
ObSEArray<ObRawExpr*, 4> cur_const_exprs;
|
||||
ObSEArray<ObRawExpr*, 16> columns;
|
||||
bool has_exec_param = false;
|
||||
if (OB_ISNULL(range_info.get_query_range())) {
|
||||
const ObQueryRangeProvider *provider = range_info.get_query_range_provider();
|
||||
if (OB_ISNULL(provider)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected NULL", K(ret), K(range_info.get_query_range()));
|
||||
} else if (OB_FAIL(check_has_exec_param(*range_info.get_query_range(), has_exec_param))) {
|
||||
LOG_WARN("unexpected NULL", K(ret), K(provider));
|
||||
} else if (OB_FAIL(check_has_exec_param(*provider, has_exec_param))) {
|
||||
LOG_WARN("failed to check has exec param", K(ret));
|
||||
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(range_info.get_query_range()->get_range_exprs(),
|
||||
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(provider->get_range_exprs(),
|
||||
columns))) {
|
||||
LOG_WARN("failed to extract column exprs", K(ret));
|
||||
} else if (columns.empty() || !has_exec_param) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(ObOptimizerUtil::compute_const_exprs(range_info.get_query_range()->get_range_exprs(),
|
||||
} else if (OB_FAIL(ObOptimizerUtil::compute_const_exprs(provider->get_range_exprs(),
|
||||
cur_const_exprs))) {
|
||||
// for inner path, const expr is computed without pushdown filter.
|
||||
// need compute const expr by range_exprs.
|
||||
@ -982,7 +984,7 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
ObSqlSchemaGuard *schema_guard = NULL;
|
||||
ObExecContext *exec_ctx = NULL;
|
||||
ObQueryRange *query_range = NULL;
|
||||
ObQueryRangeProvider *query_range_provider = NULL;
|
||||
const share::schema::ObTableSchema *index_schema = NULL;
|
||||
ObQueryRangeArray &ranges = range_info.get_ranges();
|
||||
ObQueryRangeArray &ss_ranges = range_info.get_ss_ranges();
|
||||
@ -1026,6 +1028,7 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
|
||||
int64_t range_prefix_count = 0;
|
||||
bool contain_always_false = false;
|
||||
bool has_exec_param = false;
|
||||
int64_t out_index_prefix = -1;
|
||||
bool is_domain_index = (is_geo_index || is_multi_index);
|
||||
|
||||
common::ObSEArray<ObRawExpr *, 4> agent_table_filter;
|
||||
@ -1040,35 +1043,36 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
|
||||
: helper.filters_,
|
||||
range_info.get_expr_constraints(),
|
||||
table_id,
|
||||
query_range,
|
||||
index_id))) {
|
||||
query_range_provider,
|
||||
index_id,
|
||||
out_index_prefix))) {
|
||||
LOG_WARN("failed to extract query range", K(ret), K(index_id));
|
||||
} else if (is_geo_index && OB_FAIL(extract_geo_preliminary_query_range(range_columns,
|
||||
is_oracle_inner_index_table
|
||||
? agent_table_filter
|
||||
: helper.filters_,
|
||||
domain_columnInfo_map,
|
||||
query_range))) {
|
||||
query_range_provider))) {
|
||||
LOG_WARN("failed to extract query range", K(ret), K(index_id));
|
||||
} else if (is_multi_index
|
||||
&& OB_FAIL(extract_multivalue_preliminary_query_range(range_columns,
|
||||
is_oracle_inner_index_table ?
|
||||
agent_table_filter : helper.filters_,
|
||||
query_range))) {
|
||||
query_range_provider))) {
|
||||
LOG_WARN("failed to extract query range", K(ret), K(index_id));
|
||||
} else if (OB_ISNULL(query_range)) {
|
||||
} else if (OB_ISNULL(query_range_provider)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(query_range), K(ret));
|
||||
} else if (OB_FAIL(query_range->get_tablet_ranges(*allocator_,
|
||||
*exec_ctx,
|
||||
ranges,
|
||||
all_single_value_range,
|
||||
dtc_params))) {
|
||||
LOG_WARN("get unexpected null", K(query_range_provider), K(ret));
|
||||
} else if (OB_FAIL(query_range_provider->get_tablet_ranges(*allocator_,
|
||||
*exec_ctx,
|
||||
ranges,
|
||||
all_single_value_range,
|
||||
dtc_params))) {
|
||||
LOG_WARN("failed to final extract query range", K(ret));
|
||||
} else if (OB_FAIL(query_range->get_ss_tablet_ranges(*allocator_,
|
||||
*exec_ctx,
|
||||
ss_ranges,
|
||||
dtc_params))) {
|
||||
} else if (OB_FAIL(query_range_provider->get_ss_tablet_ranges(*allocator_,
|
||||
*exec_ctx,
|
||||
ss_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("failed to final extract index skip query range", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::check_prefix_ranges_count(range_info.get_ranges(),
|
||||
equal_prefix_count,
|
||||
@ -1076,7 +1080,7 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
|
||||
range_prefix_count,
|
||||
contain_always_false))) {
|
||||
LOG_WARN("failed to compute query range prefix count", K(ret));
|
||||
} else if (OB_FAIL(check_has_exec_param(*query_range, has_exec_param))) {
|
||||
} else if (OB_FAIL(check_has_exec_param(*query_range_provider, has_exec_param))) {
|
||||
LOG_WARN("failed to check has exec param", K(ret));
|
||||
} else if (!has_exec_param) {
|
||||
//没有exec param就使用真实query range计算equal prefix count
|
||||
@ -1084,30 +1088,35 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id,
|
||||
range_info.set_equal_prefix_count(equal_prefix_count);
|
||||
range_info.set_range_prefix_count(range_prefix_count);
|
||||
range_info.set_contain_always_false(contain_always_false);
|
||||
} else if (OB_FAIL(get_preliminary_prefix_info(*query_range, range_info))) {
|
||||
} else if (OB_FAIL(get_preliminary_prefix_info(*query_range_provider, range_info))) {
|
||||
LOG_WARN("failed to get preliminary prefix info", K(ret));
|
||||
}
|
||||
range_info.set_valid();
|
||||
range_info.set_query_range(query_range);
|
||||
range_info.set_equal_prefix_null_count(equal_prefix_null_count);
|
||||
range_info.set_index_column_count(index_schema->is_index_table() ?
|
||||
index_schema->get_index_column_num() :
|
||||
index_schema->get_rowkey_column_num());
|
||||
if (OB_FAIL(ret)) {
|
||||
if (NULL != query_range) {
|
||||
query_range->~ObQueryRange();
|
||||
query_range = NULL;
|
||||
if (OB_SUCC(ret)) {
|
||||
range_info.set_valid();
|
||||
if (query_range_provider->is_new_query_range()) {
|
||||
range_info.set_pre_range_graph(static_cast<ObPreRangeGraph*>(query_range_provider));
|
||||
} else {
|
||||
range_info.set_query_range(static_cast<ObQueryRange*>(query_range_provider));
|
||||
}
|
||||
} else {
|
||||
range_info.set_equal_prefix_null_count(equal_prefix_null_count);
|
||||
range_info.set_index_column_count(index_schema->is_index_table() ?
|
||||
index_schema->get_index_column_num() :
|
||||
index_schema->get_rowkey_column_num());
|
||||
range_info.set_index_prefix(out_index_prefix);
|
||||
LOG_TRACE("succeed to get query range", K(ranges), K(ss_ranges), K(helper.filters_),
|
||||
K(*query_range), K(range_columns), K(query_range->get_range_exprs()),
|
||||
K(table_id), K(index_id));
|
||||
KPC(query_range_provider), K(range_columns),
|
||||
K(query_range_provider->get_range_exprs()), K(table_id), K(index_id));
|
||||
} else {
|
||||
if (NULL != query_range_provider) {
|
||||
query_range_provider->~ObQueryRangeProvider();
|
||||
query_range_provider = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::check_has_exec_param(const ObQueryRange &query_range,
|
||||
int ObJoinOrder::check_has_exec_param(const ObQueryRangeProvider &query_range,
|
||||
bool &has_exec_param)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1125,22 +1134,18 @@ int ObJoinOrder::check_has_exec_param(const ObQueryRange &query_range,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::get_preliminary_prefix_info(ObQueryRange &query_range,
|
||||
int ObJoinOrder::get_preliminary_prefix_info(ObQueryRangeProvider &query_range_provider,
|
||||
QueryRangeInfo &range_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t equal_prefix_count = 0;
|
||||
int64_t range_prefix_count = 0;
|
||||
bool contain_always_false = false;
|
||||
const ObKeyPart *key_part_head = query_range.get_table_grapth().key_part_head_;
|
||||
if (OB_ISNULL(key_part_head)) {
|
||||
ret = OB_NOT_INIT;
|
||||
LOG_WARN("table_graph.key_part_head_ is not inited.", K(ret));
|
||||
if (OB_FAIL(query_range_provider.get_prefix_info(equal_prefix_count,
|
||||
range_prefix_count,
|
||||
contain_always_false))) {
|
||||
LOG_WARN("failed to get prefix info");
|
||||
} else {
|
||||
get_prefix_info(key_part_head,
|
||||
equal_prefix_count,
|
||||
range_prefix_count,
|
||||
contain_always_false);
|
||||
range_info.set_equal_prefix_count(equal_prefix_count);
|
||||
range_info.set_range_prefix_count(range_prefix_count);
|
||||
range_info.set_contain_always_false(contain_always_false);
|
||||
@ -1150,35 +1155,6 @@ int ObJoinOrder::get_preliminary_prefix_info(ObQueryRange &query_range,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObJoinOrder::get_prefix_info(const ObKeyPart *key_part,
|
||||
int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false)
|
||||
{
|
||||
if (OB_NOT_NULL(key_part)) {
|
||||
equal_prefix_count = OB_USER_MAX_ROWKEY_COLUMN_NUMBER;
|
||||
range_prefix_count = OB_USER_MAX_ROWKEY_COLUMN_NUMBER;
|
||||
for ( /*do nothing*/ ; NULL != key_part; key_part = key_part->or_next_) {
|
||||
int64_t cur_equal_prefix_count = 0;
|
||||
int64_t cur_range_prefix_count = 0;
|
||||
if (key_part->is_equal_condition()) {
|
||||
get_prefix_info(key_part->and_next_,
|
||||
cur_equal_prefix_count,
|
||||
cur_range_prefix_count,
|
||||
contain_always_false);
|
||||
++cur_equal_prefix_count;
|
||||
++cur_range_prefix_count;
|
||||
} else if (key_part->is_range_condition()) {
|
||||
++cur_range_prefix_count;
|
||||
} else if (key_part->is_always_false()) {
|
||||
contain_always_false = true;
|
||||
}
|
||||
equal_prefix_count = std::min(cur_equal_prefix_count, equal_prefix_count);
|
||||
range_prefix_count = std::min(cur_range_prefix_count, range_prefix_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ObJoinOrder::add_table_by_heuristics(const uint64_t table_id,
|
||||
const uint64_t ref_table_id,
|
||||
const ObIndexInfoCache &index_info_cache,
|
||||
@ -1750,6 +1726,7 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
|
||||
ap->interesting_order_info_ = index_info_entry->get_interesting_order_info();
|
||||
ap->for_update_ = table_item->for_update_;
|
||||
ap->use_skip_scan_ = use_skip_scan;
|
||||
ap->index_prefix_ = index_info_entry->get_range_info().get_index_prefix();
|
||||
ap->use_column_store_ = use_column_store;
|
||||
ap->est_cost_info_.use_column_store_ = use_column_store;
|
||||
|
||||
@ -1760,7 +1737,7 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
|
||||
LOG_WARN("failed to init sample info", K(ret));
|
||||
} else if (OB_FAIL(add_access_filters(ap,
|
||||
ordering_info.get_index_keys(),
|
||||
range_info.get_query_range()->get_range_exprs(),
|
||||
(nullptr == range_info.get_query_range_provider()) ? nullptr : &range_info.get_query_range_provider()->get_range_exprs(),
|
||||
helper))) {
|
||||
LOG_WARN("failed to add access filters", K(*ap), K(ordering_info.get_index_keys()), K(ret));
|
||||
} else if (OB_FAIL(get_plan()->get_stmt()->get_column_items(table_id, ap->est_cost_info_.access_column_items_))) {
|
||||
@ -1775,6 +1752,7 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
|
||||
LOG_WARN("failed to create index keys expression array", K(index_id), K(ret));
|
||||
} else if (ordering_info.get_index_keys().count() > 0) {
|
||||
ap->pre_query_range_ = const_cast<ObQueryRange *>(range_info.get_query_range());
|
||||
ap->pre_range_graph_ = const_cast<ObPreRangeGraph*>(range_info.get_pre_range_graph());
|
||||
if (OB_FAIL(ap->index_keys_.assign(ordering_info.get_index_keys()))) {
|
||||
LOG_WARN("failed to get index keys", K(ret));
|
||||
} else if (OB_FAIL(ap->est_cost_info_.range_columns_.assign(range_info.get_range_columns()))) {
|
||||
@ -1795,7 +1773,7 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(fill_filters(ap->filter_,
|
||||
ap->pre_query_range_,
|
||||
ap->get_query_range_provider(),
|
||||
ap->est_cost_info_,
|
||||
is_nl_with_extended_range,
|
||||
ObSqlSchemaGuard::is_link_table(get_plan()->get_stmt(), table_id),
|
||||
@ -2295,7 +2273,7 @@ int ObJoinOrder::get_direction_in_order_by(const ObIArray<OrderItem> &order_by,
|
||||
|
||||
int ObJoinOrder::add_access_filters(AccessPath *path,
|
||||
const ObIArray<ObRawExpr *> &index_keys,
|
||||
const ObIArray<ObRawExpr *> &range_exprs,
|
||||
const ObIArray<ObRawExpr *> *range_exprs,
|
||||
PathHelper &helper)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -2313,7 +2291,7 @@ int ObJoinOrder::add_access_filters(AccessPath *path,
|
||||
if (ObOptimizerUtil::is_expr_equivalent(deduced_expr_info.deduced_expr_, restrict_infos.at(i),
|
||||
get_plan()->get_equal_sets())) {
|
||||
found = true;
|
||||
if (ObOptimizerUtil::find_equal_expr(range_exprs, restrict_infos.at(i))) {
|
||||
if (range_exprs != nullptr && ObOptimizerUtil::find_equal_expr(*range_exprs, restrict_infos.at(i))) {
|
||||
if (OB_FAIL(path->filter_.push_back(restrict_infos.at(i)))) {
|
||||
LOG_WARN("push back error", K(ret));
|
||||
} else if (OB_FAIL(append(helper.const_param_constraints_, deduced_expr_info.const_param_constraints_))) {
|
||||
@ -3117,7 +3095,7 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id,
|
||||
int ret = OB_SUCCESS;
|
||||
use_skip_scan = OptSkipScanState::SS_UNSET;
|
||||
IndexInfoEntry *index_info_entry = NULL;
|
||||
const ObQueryRange *query_range = NULL;
|
||||
const ObQueryRangeProvider *query_range_provider = NULL;
|
||||
ObQueryCtx *query_ctx = NULL;
|
||||
bool hint_force_skip_scan = false;
|
||||
bool hint_force_no_skip_scan = false;
|
||||
@ -3133,8 +3111,8 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id,
|
||||
} else if (OB_ISNULL(index_info_entry)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("index info entry should not be null", K(ret));
|
||||
} else if (OB_ISNULL(query_range = index_info_entry->get_range_info().get_query_range()) ||
|
||||
!query_range->is_ss_range()) {
|
||||
} else if (OB_ISNULL(query_range_provider = index_info_entry->get_range_info().get_query_range_provider()) ||
|
||||
!query_range_provider->is_ss_range()) {
|
||||
use_skip_scan = OptSkipScanState::SS_DISABLE;
|
||||
} else if (OB_FAIL(get_plan()->get_log_plan_hint().check_use_skip_scan(table_id,
|
||||
index_id,
|
||||
@ -3157,7 +3135,7 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id,
|
||||
if (OB_SUCC(ret) && OptSkipScanState::SS_DISABLE != use_skip_scan) {
|
||||
// OptColumnMeta for prefix columns may be not added. It's needed to calculate prefix NDV
|
||||
const ObIArray<ColumnItem> &column_items = index_info_entry->get_range_info().get_range_columns();
|
||||
const int64_t ss_offset = query_range->get_skip_scan_offset();
|
||||
const int64_t ss_offset = query_range_provider->get_skip_scan_offset();
|
||||
const OptSelectivityCtx &ctx = get_plan()->get_selectivity_ctx();
|
||||
OptTableMeta *table_meta = NULL;
|
||||
if (OB_UNLIKELY(column_items.count() < ss_offset) ||
|
||||
@ -4092,44 +4070,96 @@ int ObJoinOrder::extract_preliminary_query_range(const ObIArray<ColumnItem> &ran
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
ObIArray<ObExprConstraint> &expr_constraints,
|
||||
int64_t table_id,
|
||||
ObQueryRange *&query_range,
|
||||
int64_t index_id)
|
||||
ObQueryRangeProvider *&query_range,
|
||||
int64_t index_id,
|
||||
int64_t &out_index_prefix)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
const ParamStore *params = NULL;
|
||||
ObSQLSessionInfo *session_info = NULL;
|
||||
int64_t index_prefix = -1;
|
||||
bool enable_better_inlist = false;
|
||||
bool enable_index_prefix_cost = false;
|
||||
ObSEArray<ObRawExpr*, 4> range_predicates;
|
||||
ObSEArray<uint64_t, 4> total_range_counts;
|
||||
const LogTableHint *log_table_hint = NULL;
|
||||
out_index_prefix = -1;
|
||||
if (OB_ISNULL(get_plan()) ||
|
||||
OB_ISNULL(opt_ctx = &get_plan()->get_optimizer_context()) ||
|
||||
OB_ISNULL(allocator_) ||
|
||||
OB_ISNULL(params = opt_ctx->get_params()) ||
|
||||
OB_ISNULL(session_info = opt_ctx->get_session_info())) {
|
||||
OB_ISNULL(session_info = opt_ctx->get_session_info())||
|
||||
OB_ISNULL(get_plan()->get_stmt())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("get unexpected null", K(get_plan()), K(opt_ctx),
|
||||
K(allocator_), K(params), K(ret));
|
||||
} else if (OB_FAIL(check_enable_better_inlist(table_id, enable_better_inlist, enable_index_prefix_cost))) {
|
||||
LOG_WARN("failed to check better inlist enabled", K(ret));
|
||||
} else if (enable_better_inlist &&
|
||||
OB_FAIL(get_candi_range_expr(range_columns,
|
||||
predicates,
|
||||
range_predicates))) {
|
||||
LOG_WARN("failed to get candi range expr", K(ret));
|
||||
} else if (!enable_better_inlist &&
|
||||
OB_FAIL(range_predicates.assign(predicates))) {
|
||||
LOG_WARN("failed to assign exprs", K(ret));
|
||||
} else if (OB_FAIL(get_plan()->get_log_plan_hint().get_index_prefix(table_id,
|
||||
index_id,
|
||||
out_index_prefix))) {
|
||||
LOG_WARN("failed to get index prefix", K(table_id), K(index_id), K(out_index_prefix), K(ret));
|
||||
} else if (opt_ctx->enable_new_query_range()) {
|
||||
void *ptr = allocator_->alloc(sizeof(ObPreRangeGraph));
|
||||
ObPreRangeGraph *pre_range_graph = NULL;
|
||||
if (OB_ISNULL(ptr)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for pre range graph", K(ret));
|
||||
} else {
|
||||
pre_range_graph = new(ptr)ObPreRangeGraph(*allocator_);
|
||||
if (OB_FAIL(pre_range_graph->preliminary_extract_query_range(range_columns, range_predicates,
|
||||
opt_ctx->get_exec_ctx(),
|
||||
&expr_constraints,
|
||||
params, false, true,
|
||||
out_index_prefix))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
} else if (FALSE_IT(log_table_hint = get_plan()->get_log_plan_hint().get_index_hint(table_id))) {
|
||||
} else if (NULL != log_table_hint && log_table_hint->is_use_index_hint()) {
|
||||
// do nothing
|
||||
} else if (!enable_index_prefix_cost) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(pre_range_graph->get_total_range_sizes(total_range_counts))) {
|
||||
LOG_WARN("failed to get total range sizes", K(ret));
|
||||
} else if (total_range_counts.empty()) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(get_better_index_prefix(pre_range_graph->get_range_exprs(),
|
||||
pre_range_graph->get_range_expr_max_offsets(),
|
||||
total_range_counts,
|
||||
out_index_prefix))) {
|
||||
LOG_WARN("failed to get better index prefix", K(ret));
|
||||
} else if (-1 == out_index_prefix) {
|
||||
// do nothing
|
||||
} else if (OB_FALSE_IT(pre_range_graph->reset())) {
|
||||
} else if (OB_FAIL(pre_range_graph->preliminary_extract_query_range(range_columns, range_predicates,
|
||||
opt_ctx->get_exec_ctx(),
|
||||
&expr_constraints,
|
||||
params, false, true,
|
||||
out_index_prefix))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
query_range = pre_range_graph;
|
||||
} else {
|
||||
if (NULL != pre_range_graph) {
|
||||
pre_range_graph->~ObPreRangeGraph();
|
||||
pre_range_graph = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
void *tmp_ptr = allocator_->alloc(sizeof(ObQueryRange));
|
||||
ObQueryRange *tmp_qr = NULL;
|
||||
ObSEArray<ObRawExpr*, 4> range_predicates;
|
||||
bool enable_better_inlist = false;
|
||||
if (OB_ISNULL(tmp_ptr)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for query range", K(ret));
|
||||
} else if (OB_FAIL(check_enable_better_inlist(table_id, enable_better_inlist))) {
|
||||
LOG_WARN("failed to check better inlist enabled", K(ret));
|
||||
} else if (enable_better_inlist &&
|
||||
OB_FAIL(get_candi_range_expr(range_columns,
|
||||
predicates,
|
||||
range_predicates))) {
|
||||
LOG_WARN("failed to get candi range expr", K(ret));
|
||||
} else if (!enable_better_inlist &&
|
||||
OB_FAIL(range_predicates.assign(predicates))) {
|
||||
LOG_WARN("failed to assign exprs", K(ret));
|
||||
} else if (OB_FAIL(get_plan()->get_log_plan_hint().get_index_prefix(table_id,
|
||||
index_id,
|
||||
index_prefix))) {
|
||||
LOG_WARN("failed to get index prefix", K(table_id), K(index_id), K(index_prefix), K(ret));
|
||||
} else {
|
||||
tmp_qr = new(tmp_ptr)ObQueryRange(*allocator_);
|
||||
const ObDataTypeCastParams dtc_params =
|
||||
@ -4145,7 +4175,7 @@ int ObJoinOrder::extract_preliminary_query_range(const ObIArray<ColumnItem> &ran
|
||||
&expr_constraints,
|
||||
params, false, true,
|
||||
is_in_range_optimization_enabled,
|
||||
index_prefix))) {
|
||||
out_index_prefix))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
}
|
||||
}
|
||||
@ -4161,10 +4191,14 @@ int ObJoinOrder::extract_preliminary_query_range(const ObIArray<ColumnItem> &ran
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::check_enable_better_inlist(int64_t table_id, bool &enable)
|
||||
int ObJoinOrder::check_enable_better_inlist(int64_t table_id,
|
||||
bool &enable_better_inlist,
|
||||
bool &enable_index_prefix_cost)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
enable = false;
|
||||
bool enable = false;
|
||||
enable_better_inlist = false;
|
||||
enable_index_prefix_cost = false;
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
ObQueryCtx *query_ctx = NULL;
|
||||
ObSQLSessionInfo *session_info = NULL;
|
||||
@ -4172,7 +4206,8 @@ int ObJoinOrder::check_enable_better_inlist(int64_t table_id, bool &enable)
|
||||
if (OB_ISNULL(get_plan()) ||
|
||||
OB_ISNULL(opt_ctx = &get_plan()->get_optimizer_context()) ||
|
||||
OB_ISNULL(session_info = opt_ctx->get_session_info()) ||
|
||||
OB_ISNULL(query_ctx = get_plan()->get_optimizer_context().get_query_ctx())) {
|
||||
OB_ISNULL(query_ctx = get_plan()->get_optimizer_context().get_query_ctx()) ||
|
||||
OB_ISNULL(get_plan()->get_stmt())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("get unexpected null", K(get_plan()), K(opt_ctx), K(session_info), K(query_ctx), K(ret));
|
||||
} else if (!session_info->is_user_session()) {
|
||||
@ -4187,13 +4222,22 @@ int ObJoinOrder::check_enable_better_inlist(int64_t table_id, bool &enable)
|
||||
} else if (table_meta->use_default_stat()) {
|
||||
enable = false;
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && enable) {
|
||||
if (ObSQLUtils::is_opt_feature_version_ge_425_or_435(
|
||||
get_plan()->get_stmt()->get_query_ctx()->optimizer_features_enable_version_)) {
|
||||
enable_index_prefix_cost = true;
|
||||
} else {
|
||||
enable_better_inlist = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::extract_geo_preliminary_query_range(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
const ColumnIdInfoMap &column_schema_info,
|
||||
ObQueryRange *&query_range)
|
||||
ObQueryRangeProvider *&query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
@ -4205,6 +4249,30 @@ int ObJoinOrder::extract_geo_preliminary_query_range(const ObIArray<ColumnItem>
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("get unexpected null", K(get_plan()), K(opt_ctx),
|
||||
K(allocator_), K(params), K(ret));
|
||||
} else if (opt_ctx->enable_new_query_range()) {
|
||||
void *ptr = allocator_->alloc(sizeof(ObPreRangeGraph));
|
||||
ObPreRangeGraph *pre_range_graph = NULL;
|
||||
if (OB_ISNULL(ptr)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for pre range graph", K(ret));
|
||||
} else {
|
||||
pre_range_graph = new(ptr)ObPreRangeGraph(*allocator_);
|
||||
if (OB_FAIL(pre_range_graph->preliminary_extract_query_range(range_columns, predicates,
|
||||
opt_ctx->get_exec_ctx(),
|
||||
nullptr,
|
||||
params, false, true,
|
||||
-1, &column_schema_info))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
query_range = pre_range_graph;
|
||||
} else {
|
||||
if (NULL != pre_range_graph) {
|
||||
pre_range_graph->~ObPreRangeGraph();
|
||||
pre_range_graph = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
void *tmp_ptr = allocator_->alloc(sizeof(ObQueryRange));
|
||||
ObQueryRange *tmp_qr = NULL;
|
||||
@ -4248,7 +4316,7 @@ int ObJoinOrder::extract_geo_preliminary_query_range(const ObIArray<ColumnItem>
|
||||
|
||||
int ObJoinOrder::extract_multivalue_preliminary_query_range(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
ObQueryRange *&query_range)
|
||||
ObQueryRangeProvider *&query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
@ -4260,6 +4328,30 @@ int ObJoinOrder::extract_multivalue_preliminary_query_range(const ObIArray<Colum
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("get unexpected null", K(get_plan()), K(opt_ctx),
|
||||
K(allocator_), K(params), K(ret));
|
||||
} else if (opt_ctx->enable_new_query_range()) {
|
||||
void *ptr = allocator_->alloc(sizeof(ObPreRangeGraph));
|
||||
ObPreRangeGraph *pre_range_graph = NULL;
|
||||
if (OB_ISNULL(ptr)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for pre range graph", K(ret));
|
||||
} else {
|
||||
pre_range_graph = new(ptr)ObPreRangeGraph(*allocator_);
|
||||
if (OB_FAIL(pre_range_graph->preliminary_extract_query_range(range_columns, predicates,
|
||||
opt_ctx->get_exec_ctx(),
|
||||
nullptr,
|
||||
params, false, true,
|
||||
-1, NULL))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
query_range = pre_range_graph;
|
||||
} else {
|
||||
if (NULL != pre_range_graph) {
|
||||
pre_range_graph->~ObPreRangeGraph();
|
||||
pre_range_graph = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
void *tmp_ptr = allocator_->alloc(sizeof(ObQueryRange));
|
||||
ObQueryRange *tmp_qr = NULL;
|
||||
@ -4428,29 +4520,46 @@ int ObJoinOrder::calculate_range_expr_cost(ObIArray<CandiRangeExprs*> &sorted_pr
|
||||
double &cost)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
double range_sel = 1;
|
||||
ObSEArray<ObRawExpr*, 4> filters;
|
||||
if (OB_FAIL(get_range_filter(sorted_predicates,
|
||||
range_exprs,
|
||||
filters))) {
|
||||
LOG_WARN("failed to get range filter", K(ret));
|
||||
} else if (OB_FAIL(calculate_range_and_filter_expr_cost(range_exprs,
|
||||
filters,
|
||||
range_column_count,
|
||||
range_count,
|
||||
cost))) {
|
||||
LOG_WARN("failed to calculate range expr cost", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::calculate_range_and_filter_expr_cost(ObIArray<ObRawExpr*> &range_exprs,
|
||||
ObIArray<ObRawExpr*> &filter_exprs,
|
||||
int64_t range_column_count,
|
||||
int64_t range_count,
|
||||
double &cost)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
double range_sel = 1;
|
||||
if (OB_ISNULL(get_plan())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null plan", K(ret));
|
||||
} else if (OB_FAIL(get_range_filter(sorted_predicates,
|
||||
range_exprs,
|
||||
filters))) {
|
||||
LOG_WARN("failed to get range filter", K(ret));
|
||||
} else if (OB_FAIL(ObOptSelectivity::calculate_selectivity(get_plan()->get_basic_table_metas(),
|
||||
get_plan()->get_selectivity_ctx(),
|
||||
range_exprs,
|
||||
range_sel,
|
||||
get_plan()->get_predicate_selectivities()))) {
|
||||
get_plan()->get_selectivity_ctx(),
|
||||
range_exprs,
|
||||
range_sel,
|
||||
get_plan()->get_predicate_selectivities()))) {
|
||||
LOG_WARN("failed to calculate selectivity", K(ret));
|
||||
} else if (OB_FAIL(ObOptEstCost::calc_range_cost(table_meta_info_,
|
||||
filters,
|
||||
range_column_count,
|
||||
range_count,
|
||||
range_sel,
|
||||
cost,
|
||||
get_plan()->get_optimizer_context()))) {
|
||||
LOG_WARN("failed to estimate range scan cost", K(ret));
|
||||
filter_exprs,
|
||||
range_column_count,
|
||||
range_count,
|
||||
range_sel,
|
||||
cost,
|
||||
get_plan()->get_optimizer_context()))) {
|
||||
LOG_WARN("failed to estimate range scan cost", K(ret));
|
||||
} else {
|
||||
LOG_TRACE("query range cost:", K(range_column_count), K(range_count), K(range_sel), K(cost));
|
||||
LOG_TRACE("candi range exprs:", K(range_exprs));
|
||||
@ -5940,6 +6049,8 @@ int AccessPath::assign(const AccessPath &other, common::ObIAllocator *allocator)
|
||||
use_skip_scan_ = other.use_skip_scan_;
|
||||
use_column_store_ = other.use_column_store_;
|
||||
is_valid_inner_path_ = other.is_valid_inner_path_;
|
||||
pre_query_range_ = NULL;
|
||||
pre_range_graph_ = NULL;
|
||||
can_batch_rescan_ = other.can_batch_rescan_;
|
||||
can_das_dynamic_part_pruning_ = other.can_das_dynamic_part_pruning_;
|
||||
|
||||
@ -5954,9 +6065,21 @@ int AccessPath::assign(const AccessPath &other, common::ObIAllocator *allocator)
|
||||
LOG_WARN("Failed to assign re_est_param", K(ret));
|
||||
} else if (OB_FAIL(est_records_.assign(other.est_records_))) {
|
||||
LOG_WARN("Failed to assign re_est_param", K(ret));
|
||||
} else if (NULL == other.pre_query_range_) {
|
||||
pre_query_range_ = NULL;
|
||||
} else {
|
||||
} else if (other.pre_range_graph_ != NULL) {
|
||||
ObPreRangeGraph *range_graph = static_cast<ObPreRangeGraph*>(allocator->alloc(sizeof(ObPreRangeGraph)));
|
||||
if (OB_ISNULL(range_graph)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("failed to allocate memory for pre range graph");
|
||||
} else {
|
||||
range_graph = new(range_graph)ObPreRangeGraph(*allocator);
|
||||
if (OB_FAIL(range_graph->deep_copy(*other.pre_range_graph_))) {
|
||||
range_graph->~ObPreRangeGraph();
|
||||
range_graph = NULL;
|
||||
} else {
|
||||
pre_range_graph_ = range_graph;
|
||||
}
|
||||
}
|
||||
} else if (other.pre_query_range_ != NULL) {
|
||||
ObQueryRange *query_range = static_cast<ObQueryRange*>(allocator->alloc(sizeof(ObQueryRange)));
|
||||
if (OB_ISNULL(query_range)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
@ -13360,7 +13483,7 @@ int ObJoinOrder::get_simple_index_info(const uint64_t table_id,
|
||||
* table_filters: filters that can be evaluated after index back
|
||||
*/
|
||||
int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
|
||||
const ObQueryRange *query_range,
|
||||
const ObQueryRangeProvider *query_range_provider,
|
||||
ObCostTableScanInfo &est_cost_info,
|
||||
bool &is_nl_with_extended_range,
|
||||
bool is_link,
|
||||
@ -13368,7 +13491,7 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_nl_with_extended_range = false;
|
||||
if (NULL == query_range) {
|
||||
if (NULL == query_range_provider) {
|
||||
//如果没有抽出query range,那么所有的filter都是table filter
|
||||
ret = est_cost_info.table_filters_.assign(all_filters);
|
||||
} else {
|
||||
@ -13379,6 +13502,7 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
|
||||
ObBitSet<> prefix_column_bs;
|
||||
ObBitSet<> ex_prefix_column_bs;
|
||||
ObSEArray<ObColDesc, 16> index_column_descs;
|
||||
const ObIArray<ObRawExpr*> &unprecise_range_exprs = query_range_provider->get_unprecise_range_exprs();
|
||||
if (OB_ISNULL(get_plan()) ||
|
||||
OB_ISNULL(schema_guard = get_plan()->get_optimizer_context().get_sql_schema_guard())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -13407,9 +13531,10 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
|
||||
}
|
||||
//
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(est_cost_info.prefix_filters_.assign(query_range->get_range_exprs()))) {
|
||||
if (OB_FAIL(est_cost_info.prefix_filters_.assign(query_range_provider->get_range_exprs()))) {
|
||||
LOG_WARN("failed to assign exprs", K(ret));
|
||||
} else if (use_skip_scan && OB_FAIL(est_cost_info.ss_postfix_range_filters_.assign(query_range->get_ss_range_exprs()))) {
|
||||
} else if (use_skip_scan &&
|
||||
OB_FAIL(est_cost_info.ss_postfix_range_filters_.assign(query_range_provider->get_ss_range_exprs()))) {
|
||||
LOG_WARN("failed to assign exprs", K(ret));
|
||||
}
|
||||
}
|
||||
@ -13481,7 +13606,9 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
|
||||
} else if (!expr_column_bs.is_subset(index_column_bs)) {
|
||||
ret = est_cost_info.table_filters_.push_back(filter);
|
||||
} else if (OB_FAIL(can_extract_unprecise_range(est_cost_info.table_id_, filter,
|
||||
ex_prefix_column_bs, can_extract))) {
|
||||
ex_prefix_column_bs,
|
||||
unprecise_range_exprs,
|
||||
can_extract))) {
|
||||
LOG_WARN("failed to extract column ids", K(ret));
|
||||
} else if (can_extract) {
|
||||
ret = est_cost_info.pushdown_prefix_filters_.push_back(filter);
|
||||
@ -13542,6 +13669,7 @@ int ObJoinOrder::fill_filters(const ObIArray<ObRawExpr*> &all_filters,
|
||||
int ObJoinOrder::can_extract_unprecise_range(const uint64_t table_id,
|
||||
const ObRawExpr *filter,
|
||||
const ObBitSet<> &ex_prefix_column_bs,
|
||||
const ObIArray<ObRawExpr*> &unprecise_exprs,
|
||||
bool &can_extract)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -13551,6 +13679,9 @@ int ObJoinOrder::can_extract_unprecise_range(const uint64_t table_id,
|
||||
if (OB_ISNULL(filter)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null expr", K(ret));
|
||||
} else if (ObOptimizerUtil::find_equal_expr(unprecise_exprs, filter) &&
|
||||
filter->has_flag(CNT_DYNAMIC_PARAM)) {
|
||||
can_extract = true;
|
||||
} else if (T_OP_EQ == filter->get_expr_type() || T_OP_NSEQ == filter->get_expr_type()) {
|
||||
const ObRawExpr *l_expr = filter->get_param_expr(0);
|
||||
const ObRawExpr *r_expr = filter->get_param_expr(1);
|
||||
@ -15082,7 +15213,7 @@ int ObJoinOrder::increase_diverse_path_count(AccessPath *ap)
|
||||
if (OB_ISNULL(ap)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("access path is null", K(ret));
|
||||
} else if (NULL == ap->pre_query_range_ ||
|
||||
} else if (NULL == ap->get_query_range_provider() ||
|
||||
(ap->get_cost_table_scan_info().ranges_.count() == 1
|
||||
&& ap->get_cost_table_scan_info().ranges_.at(0).is_whole_range())) {
|
||||
// ap is whole range
|
||||
@ -17509,3 +17640,65 @@ int ObJoinOrder::get_matched_inv_index_tid(ObMatchFunRawExpr *match_expr,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::get_better_index_prefix(const ObIArray<ObRawExpr*> &range_exprs,
|
||||
const ObIArray<int64_t> &range_expr_max_offsets,
|
||||
const ObIArray<uint64_t> &total_range_counts,
|
||||
int64_t &better_index_prefix)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObRawExpr*, 4> used_range_exprs;
|
||||
ObSEArray<ObRawExpr*, 4> used_filters;
|
||||
double range_sel = 1;
|
||||
double cost = 1;
|
||||
double min_cost = DBL_MAX;
|
||||
int64_t min_cost_offset = -1;
|
||||
uint64_t min_cost_range_count = 0;
|
||||
better_index_prefix = -1;
|
||||
if (OB_UNLIKELY(range_exprs.count() != range_expr_max_offsets.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected range exprs", K(ret));
|
||||
} else if (OB_ISNULL(get_plan())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null plan", K(ret));
|
||||
}
|
||||
for (int64_t offset = total_range_counts.count() - 1; OB_SUCC(ret) && offset >= 0; --offset) {
|
||||
used_range_exprs.reuse();
|
||||
used_filters.reuse();
|
||||
range_sel = 1;
|
||||
uint64_t range_count = offset == -1 ? 1 : total_range_counts.at(offset);
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < range_exprs.count(); ++i) {
|
||||
if (range_expr_max_offsets.at(i) <= offset) {
|
||||
if (OB_FAIL(used_range_exprs.push_back(range_exprs.at(i)))) {
|
||||
LOG_WARN("failed to push back array", K(ret));
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(used_filters.push_back(range_exprs.at(i)))) {
|
||||
LOG_WARN("failed to push back array", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(calculate_range_and_filter_expr_cost(used_range_exprs,
|
||||
used_filters,
|
||||
total_range_counts.count(),
|
||||
range_count,
|
||||
cost))) {
|
||||
LOG_WARN("failed to calculate range and filter expr cost", K(ret));
|
||||
} else if (total_range_counts.count() - 1 == offset) {
|
||||
min_cost_offset = offset;
|
||||
min_cost = cost;
|
||||
min_cost_range_count = range_count;
|
||||
} else if ( cost < min_cost) {
|
||||
min_cost_offset = offset;
|
||||
min_cost_range_count = range_count;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (total_range_counts.at(total_range_counts.count() - 1) - min_cost_range_count > 500) {
|
||||
better_index_prefix = min_cost_offset + 1;
|
||||
LOG_TRACE("choose better index prefix", K(better_index_prefix));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "sql/optimizer/ob_fd_item.h"
|
||||
#include "sql/optimizer/ob_logical_operator.h"
|
||||
#include "sql/optimizer/ob_log_plan.h"
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
|
||||
using oceanbase::common::ObString;
|
||||
namespace test
|
||||
@ -538,6 +539,7 @@ struct EstimateCostInfo {
|
||||
table_partition_info_(NULL),
|
||||
index_keys_(),
|
||||
pre_query_range_(NULL),
|
||||
pre_range_graph_(NULL),
|
||||
is_get_(false),
|
||||
order_direction_(direction),
|
||||
is_hash_index_(false),
|
||||
@ -551,6 +553,7 @@ struct EstimateCostInfo {
|
||||
use_skip_scan_(OptSkipScanState::SS_UNSET),
|
||||
use_column_store_(false),
|
||||
is_valid_inner_path_(false),
|
||||
index_prefix_(-1),
|
||||
can_batch_rescan_(false),
|
||||
can_das_dynamic_part_pruning_(-1),
|
||||
is_index_merge_(false),
|
||||
@ -635,6 +638,16 @@ struct EstimateCostInfo {
|
||||
{
|
||||
return 1 == est_cost_info_.ranges_.count() && est_cost_info_.ranges_.at(0).is_false_range();
|
||||
}
|
||||
ObQueryRangeProvider *get_query_range_provider()
|
||||
{
|
||||
return pre_range_graph_ != nullptr ? static_cast<ObQueryRangeProvider *>(pre_range_graph_)
|
||||
: static_cast<ObQueryRangeProvider *>(pre_query_range_);
|
||||
}
|
||||
const ObQueryRangeProvider *get_query_range_provider() const
|
||||
{
|
||||
return pre_range_graph_ != nullptr ? static_cast<const ObQueryRangeProvider *>(pre_range_graph_)
|
||||
: static_cast<const ObQueryRangeProvider *>(pre_query_range_);
|
||||
}
|
||||
|
||||
int compute_access_path_batch_rescan();
|
||||
bool is_rescan_path() const { return est_cost_info_.is_rescan_; }
|
||||
@ -678,6 +691,7 @@ struct EstimateCostInfo {
|
||||
ObTablePartitionInfo *table_partition_info_;
|
||||
common::ObSEArray<ObRawExpr*, 4, common::ModulePageAllocator, true> index_keys_; // index keys
|
||||
ObQueryRange* pre_query_range_; // pre_query_range for each access path
|
||||
ObPreRangeGraph* pre_range_graph_; // pre_query_graph for each access path
|
||||
bool is_get_;
|
||||
ObOrderDirection order_direction_;//序的方向(升序or倒序)
|
||||
bool is_hash_index_; // is hash index (virtual table and is index)
|
||||
@ -692,6 +706,7 @@ struct EstimateCostInfo {
|
||||
bool use_column_store_;
|
||||
// mark this access path is inner path and contribute query range
|
||||
bool is_valid_inner_path_;
|
||||
int64_t index_prefix_;
|
||||
bool can_batch_rescan_;
|
||||
int64_t can_das_dynamic_part_pruning_;
|
||||
bool is_index_merge_; // whether used for index merge
|
||||
@ -1766,10 +1781,13 @@ struct NullAwareAntiJoinInfo {
|
||||
const common::ObIArray<ObRawExpr*> &predicates,
|
||||
ObIArray<ObExprConstraint> &expr_constraints,
|
||||
int64_t table_id,
|
||||
ObQueryRange* &range,
|
||||
int64_t index_id);
|
||||
ObQueryRangeProvider* &range,
|
||||
int64_t index_id,
|
||||
int64_t &out_index_prefix);
|
||||
|
||||
int check_enable_better_inlist(int64_t table_id, bool &enable);
|
||||
int check_enable_better_inlist(int64_t table_id,
|
||||
bool &enable_better_inlist,
|
||||
bool &enable_index_prefix_cost);
|
||||
|
||||
int get_candi_range_expr(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
@ -1781,6 +1799,17 @@ struct NullAwareAntiJoinInfo {
|
||||
int64_t range_count,
|
||||
double &cost);
|
||||
|
||||
int calculate_range_and_filter_expr_cost(ObIArray<ObRawExpr*> &range_exprs,
|
||||
ObIArray<ObRawExpr*> &filter_exprs,
|
||||
int64_t range_column_count,
|
||||
int64_t range_count,
|
||||
double &cost);
|
||||
|
||||
int get_better_index_prefix(const ObIArray<ObRawExpr*> &range_exprs,
|
||||
const ObIArray<int64_t> &range_expr_max_offsets,
|
||||
const ObIArray<uint64_t> &total_range_counts,
|
||||
int64_t &better_index_prefix);
|
||||
|
||||
int sort_predicate_by_index_column(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
ObIArray<CandiRangeExprs*> &sort_exprs,
|
||||
@ -1798,11 +1827,11 @@ struct NullAwareAntiJoinInfo {
|
||||
int extract_geo_preliminary_query_range(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
const ColumnIdInfoMap &column_schema_info,
|
||||
ObQueryRange *&query_range);
|
||||
ObQueryRangeProvider *&query_range);
|
||||
|
||||
int extract_multivalue_preliminary_query_range(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &predicates,
|
||||
ObQueryRange *&query_range);
|
||||
ObQueryRangeProvider *&query_range);
|
||||
|
||||
int extract_geo_schema_info(const uint64_t table_id,
|
||||
const uint64_t index_id,
|
||||
@ -2360,7 +2389,7 @@ struct NullAwareAntiJoinInfo {
|
||||
private:
|
||||
int add_access_filters(AccessPath *path,
|
||||
const common::ObIArray<ObRawExpr*> &index_keys,
|
||||
const common::ObIArray<ObRawExpr*> &range_exprs,
|
||||
const common::ObIArray<ObRawExpr*> *range_exprs,
|
||||
PathHelper &helper);
|
||||
|
||||
int set_nl_filters(JoinPath *join_path,
|
||||
@ -2384,15 +2413,10 @@ struct NullAwareAntiJoinInfo {
|
||||
QueryRangeInfo &range_info,
|
||||
PathHelper &helper);
|
||||
|
||||
int check_has_exec_param(const ObQueryRange &query_range,
|
||||
int check_has_exec_param(const ObQueryRangeProvider &query_range,
|
||||
bool &has_exec_param);
|
||||
|
||||
int get_preliminary_prefix_info(ObQueryRange &query_range,QueryRangeInfo &range_info);
|
||||
|
||||
void get_prefix_info(const ObKeyPart *key_part,
|
||||
int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false);
|
||||
int get_preliminary_prefix_info(ObQueryRangeProvider &query_range,QueryRangeInfo &range_info);
|
||||
|
||||
// @brief check if an index is relevant to the conditions
|
||||
int is_relevant_index(const uint64_t table_id,
|
||||
@ -2532,7 +2556,7 @@ struct NullAwareAntiJoinInfo {
|
||||
int revise_output_rows_after_creating_path(PathHelper &helper,
|
||||
ObIArray<AccessPath *> &access_paths);
|
||||
int fill_filters(const common::ObIArray<ObRawExpr *> &all_filters,
|
||||
const ObQueryRange* query_range,
|
||||
const ObQueryRangeProvider* query_range,
|
||||
ObCostTableScanInfo &est_scan_cost_info,
|
||||
bool &is_nl_with_extended_range,
|
||||
bool is_link = false,
|
||||
@ -2541,6 +2565,7 @@ struct NullAwareAntiJoinInfo {
|
||||
int can_extract_unprecise_range(const uint64_t table_id,
|
||||
const ObRawExpr *filter,
|
||||
const ObBitSet<> &ex_prefix_column_bs,
|
||||
const ObIArray<ObRawExpr*> &unprecise_exprs,
|
||||
bool &can_extract);
|
||||
|
||||
int estimate_rowcount_for_access_path(ObIArray<AccessPath*> &all_paths,
|
||||
|
@ -2899,8 +2899,10 @@ int ObLogPlan::allocate_access_path(AccessPath *ap,
|
||||
scan->set_session_id(table_schema->get_session_id());
|
||||
}
|
||||
scan->set_pre_query_range(ap->pre_query_range_);
|
||||
scan->set_pre_range_graph(ap->pre_range_graph_);
|
||||
scan->set_skip_scan(OptSkipScanState::SS_DISABLE != ap->use_skip_scan_);
|
||||
scan->set_table_type(table_schema->get_table_type());
|
||||
scan->set_index_prefix(ap->index_prefix_);
|
||||
if (!ap->is_inner_path_ &&
|
||||
OB_FAIL(scan->set_query_ranges(ap->get_cost_table_scan_info().ranges_,
|
||||
ap->get_cost_table_scan_info().ss_ranges_))) {
|
||||
@ -8920,8 +8922,8 @@ int ObLogPlan::get_subplan_filter_correlated_equal_keys(const ObLogicalOperator
|
||||
LOG_WARN("failed to append filter exprs", K(ret));
|
||||
} else if (log_op_def::LOG_TABLE_SCAN == top->get_type()) {
|
||||
const ObLogTableScan *table_scan = static_cast<const ObLogTableScan *>(top);
|
||||
if (NULL != table_scan->get_pre_query_range() &&
|
||||
OB_FAIL(append(filters, table_scan->get_pre_query_range()->get_range_exprs()))) {
|
||||
if (NULL != table_scan->get_pre_graph() &&
|
||||
OB_FAIL(append(filters, table_scan->get_pre_graph()->get_range_exprs()))) {
|
||||
LOG_WARN("failed to append conditions", K(ret));
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,9 @@ const char *ObLogTableScan::get_name() const
|
||||
const char *name = NULL;
|
||||
int ret = OB_SUCCESS;
|
||||
SampleInfo::SampleMethod sample_method = get_sample_info().method_;
|
||||
if (NULL != pre_query_range_) {
|
||||
if (OB_FAIL(get_pre_query_range()->is_get(is_get))) {
|
||||
const ObQueryRangeProvider *pre_range = get_pre_graph();
|
||||
if (NULL != pre_range) {
|
||||
if (OB_FAIL(pre_range->is_get(is_get))) {
|
||||
// is_get always return true
|
||||
LOG_WARN("failed to get is_get", K(ret));
|
||||
} else if (range_conds_.count() > 0) {
|
||||
@ -1382,6 +1383,7 @@ int ObLogTableScan::pick_out_query_range_exprs()
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
ObSqlSchemaGuard *schema_guard = NULL;
|
||||
const share::schema::ObTableSchema *index_schema = NULL;
|
||||
const ObQueryRangeProvider *pre_range = get_pre_graph();
|
||||
/*
|
||||
* virtual table may have hash index,
|
||||
* for hash index, if it is a get, we should still extract the range condition
|
||||
@ -1400,8 +1402,8 @@ int ObLogTableScan::pick_out_query_range_exprs()
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(is_table_get(is_get))) {
|
||||
LOG_WARN("failed to check is table get", K(ret));
|
||||
} else if ((index_schema->is_ordered() || is_get) && NULL != pre_query_range_) {
|
||||
const ObIArray<ObRawExpr *> &range_exprs = pre_query_range_->get_range_exprs();
|
||||
} else if ((index_schema->is_ordered() || is_get) && NULL != pre_range) {
|
||||
const ObIArray<ObRawExpr *> &range_exprs = pre_range->get_range_exprs();
|
||||
ObArray<ObRawExpr *> filter_exprs;
|
||||
if (OB_FAIL(filter_exprs.assign(filter_exprs_))) {
|
||||
LOG_WARN("assign filter exprs failed", K(ret));
|
||||
@ -2217,7 +2219,7 @@ int ObLogTableScan::print_range_annotation(char *buf,
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && is_skip_scan()) {
|
||||
int64_t skip_scan_offset = get_pre_query_range()->get_skip_scan_offset();
|
||||
int64_t skip_scan_offset = get_pre_graph()->get_skip_scan_offset();
|
||||
if (OB_FAIL(BUF_PRINTF("\n prefix_columns_cnt = %ld , skip_scan_range", skip_scan_offset))) {
|
||||
LOG_WARN("BUF_PRINTF fails", K(ret));
|
||||
} else if (ss_ranges_.empty() && OB_FAIL(BUF_PRINTF("(MIN ; MAX)"))) {
|
||||
@ -2241,6 +2243,16 @@ int ObLogTableScan::print_range_annotation(char *buf,
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && EXPLAIN_EXTENDED == type) {
|
||||
if (pre_range_graph_ != nullptr && pre_range_graph_->is_fast_nlj_range()) {
|
||||
if (OB_FAIL(BUF_PRINTF(", "))) {
|
||||
LOG_WARN("BUF_PRINTF fails", K(ret));
|
||||
} else if (OB_FAIL(BUF_PRINTF(" is_fast_range = true"))) {
|
||||
LOG_WARN("BUF_PRINTF fails", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2295,7 +2307,7 @@ int ObLogTableScan::print_outline_data(PlanText &plan_text)
|
||||
TableItem *table_item = NULL;
|
||||
ObString qb_name;
|
||||
const ObString *index_name = NULL;
|
||||
int64_t index_prefix = -1;
|
||||
int64_t index_prefix = index_prefix_;
|
||||
ObItemType index_type = T_INDEX_HINT;
|
||||
const ObDMLStmt *stmt = NULL;
|
||||
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) {
|
||||
@ -2323,10 +2335,6 @@ int ObLogTableScan::print_outline_data(PlanText &plan_text)
|
||||
} else {
|
||||
index_name = &get_index_name();
|
||||
}
|
||||
} else if (OB_FAIL(get_plan()->get_log_plan_hint().get_index_prefix(table_id_,
|
||||
index_table_id_,
|
||||
index_prefix))) {
|
||||
LOG_WARN("failed to get index prefix", K(table_id_), K(index_table_id_), K(index_prefix), K(ret));
|
||||
} else if (ref_table_id_ == index_table_id_ && index_prefix < 0) {
|
||||
index_type = T_FULL_HINT;
|
||||
index_name = &ObIndexHint::PRIMARY_KEY;
|
||||
@ -2568,8 +2576,9 @@ int ObLogTableScan::allocate_granule_post(AllocGIContext &ctx)
|
||||
int ObLogTableScan::is_table_get(bool &is_get) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (pre_query_range_ != NULL) {
|
||||
if (OB_FAIL(pre_query_range_->is_get(is_get))) {
|
||||
const ObQueryRangeProvider *pre_range = get_pre_graph();
|
||||
if (pre_range != NULL) {
|
||||
if (OB_FAIL(pre_range->is_get(is_get))) {
|
||||
LOG_WARN("check query range is table get", K(ret));
|
||||
}
|
||||
}
|
||||
|
@ -177,6 +177,7 @@ public:
|
||||
for_update_(false),
|
||||
for_update_wait_us_(-1), /* default infinite */
|
||||
pre_query_range_(NULL),
|
||||
pre_range_graph_(NULL),
|
||||
part_ids_(NULL),
|
||||
filter_before_index_back_(),
|
||||
table_partition_info_(NULL),
|
||||
@ -225,6 +226,7 @@ public:
|
||||
multivalue_type_(-1),
|
||||
is_tsc_with_vid_(false),
|
||||
rowkey_vid_tid_(common::OB_INVALID_ID),
|
||||
index_prefix_(-1),
|
||||
mr_mv_scan_(common::ObQueryFlag::NormalMode)
|
||||
{
|
||||
}
|
||||
@ -309,6 +311,18 @@ public:
|
||||
inline const ObQueryRange *get_pre_query_range() const
|
||||
{ return pre_query_range_; }
|
||||
|
||||
inline const ObPreRangeGraph *get_pre_range_graph() const
|
||||
{ return pre_range_graph_; }
|
||||
|
||||
inline const ObQueryRangeProvider *get_pre_graph() const
|
||||
{
|
||||
return pre_range_graph_ != nullptr ? static_cast<const ObQueryRangeProvider *>(pre_range_graph_)
|
||||
: static_cast<const ObQueryRangeProvider *>(pre_query_range_);
|
||||
}
|
||||
|
||||
inline bool is_new_query_range() const
|
||||
{ return pre_range_graph_ != nullptr; }
|
||||
|
||||
/**
|
||||
* Get range columns
|
||||
*/
|
||||
@ -374,6 +388,9 @@ public:
|
||||
inline void set_pre_query_range(const ObQueryRange *query_range)
|
||||
{ pre_query_range_ = query_range; }
|
||||
|
||||
inline void set_pre_range_graph(const ObPreRangeGraph *range_graph)
|
||||
{ pre_range_graph_ = range_graph; }
|
||||
|
||||
/**
|
||||
* Set range columns
|
||||
*/
|
||||
@ -494,18 +511,28 @@ public:
|
||||
inline void set_index_name(common::ObString &index_name)
|
||||
{ index_name_= index_name; }
|
||||
|
||||
inline void set_index_prefix(int64_t index_prefix)
|
||||
{ index_prefix_ = index_prefix; }
|
||||
|
||||
inline ObTablePartitionInfo *get_table_partition_info() { return table_partition_info_; }
|
||||
inline const ObTablePartitionInfo *get_table_partition_info() const { return table_partition_info_; }
|
||||
inline void set_table_partition_info(ObTablePartitionInfo *table_partition_info) { table_partition_info_ = table_partition_info; }
|
||||
|
||||
bool is_index_scan() const { return ref_table_id_ != index_table_id_; }
|
||||
bool is_table_whole_range_scan() const { return !is_index_scan() && (NULL == pre_query_range_ ||
|
||||
(1 == ranges_.count() && ranges_.at(0).is_whole_range())); }
|
||||
bool is_table_whole_range_scan() const
|
||||
{
|
||||
return !is_index_scan() &&
|
||||
((NULL == pre_query_range_ && NULL == pre_range_graph_) ||
|
||||
(1 == ranges_.count() && ranges_.at(0).is_whole_range()));
|
||||
}
|
||||
void set_skip_scan(bool is_skip_scan) { is_skip_scan_ = is_skip_scan; }
|
||||
bool is_skip_scan() const { return is_skip_scan_; }
|
||||
virtual bool is_table_scan() const override { return true; }
|
||||
bool is_whole_range_scan() const {return NULL == pre_query_range_
|
||||
|| (1 == ranges_.count() && ranges_.at(0).is_whole_range()); }
|
||||
bool is_whole_range_scan() const
|
||||
{
|
||||
return (NULL == pre_query_range_ && NULL == pre_range_graph_) ||
|
||||
(1 == ranges_.count() && ranges_.at(0).is_whole_range());
|
||||
}
|
||||
ObOrderDirection get_scan_direction() const { return scan_direction_; }
|
||||
void set_index_back(bool index_back) { index_back_ = index_back; }
|
||||
bool get_index_back() const { return index_back_; }
|
||||
@ -766,6 +793,7 @@ protected: // memeber variables
|
||||
// query range after preliminary extract, which will be stored in physical plan
|
||||
// for future use
|
||||
const ObQueryRange *pre_query_range_;
|
||||
const ObPreRangeGraph *pre_range_graph_;
|
||||
const common::ObIArray<int64_t> *part_ids_;
|
||||
common::ObSEArray<ObRawExpr *, 8, common::ModulePageAllocator, true> range_conds_;
|
||||
|
||||
@ -903,6 +931,7 @@ protected: // memeber variables
|
||||
uint64_t rowkey_vid_tid_;
|
||||
// end for table scan with vid
|
||||
|
||||
int64_t index_prefix_;
|
||||
common::ObQueryFlag::MRMVScanMode mr_mv_scan_; // used for major refresh mview fast refresh and real-time mview
|
||||
|
||||
// disallow copy and assign
|
||||
|
@ -5051,11 +5051,11 @@ int ObLogicalOperator::check_can_extract_query_range_by_rf(
|
||||
// maybe temp table access op, can not extract query range
|
||||
can_extract_query_range = false;
|
||||
} else if (FALSE_IT(scan_op = static_cast<ObLogTableScan*>(scan_node))) {
|
||||
} else if (OB_ISNULL(scan_op->get_pre_query_range()) ) {
|
||||
} else if (OB_ISNULL(scan_op->get_pre_graph()) ) {
|
||||
// for virtual table, the pre_query_range may be null,
|
||||
// can not extract query range by runtime filter
|
||||
can_extract_query_range = false;
|
||||
} else if (!scan_op->get_pre_query_range()->is_precise_whole_range()) {
|
||||
} else if (!scan_op->get_pre_graph()->is_precise_whole_range()) {
|
||||
// already has query range which is not whole range,
|
||||
// do not extract query range by runtime filter
|
||||
can_extract_query_range = false;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "share/schema/ob_part_mgr_util.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr_util.h"
|
||||
#include "sql/rewrite/ob_query_range.h"
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
#include "sql/optimizer/ob_opt_est_utils.h"
|
||||
#include "sql/optimizer/ob_optimizer.h"
|
||||
#include "sql/optimizer/ob_optimizer_util.h"
|
||||
@ -1609,7 +1610,7 @@ int ObOptSelectivity::get_column_range_sel(const OptTableMetas &table_metas,
|
||||
const ObDMLStmt *stmt = ctx.get_stmt();
|
||||
uint64_t tid = col_expr.get_table_id();
|
||||
uint64_t cid = col_expr.get_column_id();
|
||||
ObQueryRange query_range;
|
||||
ObArenaAllocator allocator("ObSelRange", OB_MALLOC_NORMAL_BLOCK_SIZE, ctx.get_session_info()->get_effective_tenant_id());
|
||||
ObQueryRangeArray ranges;
|
||||
ObSEArray<ColumnItem, 1> column_items;
|
||||
bool use_hist = false;
|
||||
@ -1620,7 +1621,7 @@ int ObOptSelectivity::get_column_range_sel(const OptTableMetas &table_metas,
|
||||
} else if (OB_FAIL(check_column_in_current_level_stmt(stmt, col_expr))) {
|
||||
LOG_WARN("failed to check if column is in current level stmt", K(col_expr), K(ret));
|
||||
} else if (OB_FAIL(get_column_query_range(ctx, tid, cid, quals,
|
||||
column_items, query_range, ranges))) {
|
||||
column_items, allocator, ranges))) {
|
||||
LOG_WARN("failed to get column query range", K(ret));
|
||||
} else {
|
||||
selectivity = 0.0;
|
||||
@ -1706,7 +1707,7 @@ int ObOptSelectivity::get_column_range_min_max(const OptSelectivityCtx &ctx,
|
||||
const ObDMLStmt *stmt = ctx.get_stmt();
|
||||
uint64_t tid = 0;
|
||||
uint64_t cid = 0;
|
||||
ObQueryRange query_range;
|
||||
ObArenaAllocator allocator("ObSelRange", OB_MALLOC_NORMAL_BLOCK_SIZE, ctx.get_session_info()->get_effective_tenant_id());
|
||||
ObQueryRangeArray ranges;
|
||||
ObSEArray<ColumnItem, 1> column_items;
|
||||
if (OB_ISNULL(stmt) || OB_ISNULL(col_expr) ||
|
||||
@ -1717,7 +1718,7 @@ int ObOptSelectivity::get_column_range_min_max(const OptSelectivityCtx &ctx,
|
||||
} else if (OB_FAIL(check_column_in_current_level_stmt(stmt, *col_expr))) {
|
||||
LOG_WARN("failed to check if column is in current level stmt", KPC(col_expr), K(ret));
|
||||
} else if (OB_FAIL(get_column_query_range(ctx, tid, cid, quals,
|
||||
column_items, query_range, ranges))) {
|
||||
column_items, allocator, ranges))) {
|
||||
LOG_WARN("failed to get column query range", K(ret));
|
||||
} else if (OB_ISNULL(column_items.at(0).expr_) ||
|
||||
OB_UNLIKELY(ranges.empty())) {
|
||||
@ -2756,50 +2757,63 @@ int ObOptSelectivity::get_column_query_range(const OptSelectivityCtx &ctx,
|
||||
const uint64_t column_id,
|
||||
const ObIArray<ObRawExpr *> &quals,
|
||||
ObIArray<ColumnItem> &column_items,
|
||||
ObQueryRange &query_range,
|
||||
ObIAllocator &alloc,
|
||||
ObQueryRangeArray &ranges)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObLogPlan *log_plan = ctx.get_plan();
|
||||
const ParamStore *params = ctx.get_params();
|
||||
ObExecContext *exec_ctx = ctx.get_opt_ctx().get_exec_ctx();
|
||||
ObIAllocator &allocator = ctx.get_allocator();
|
||||
ObSQLSessionInfo *session_info = ctx.get_session_info();
|
||||
ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(ctx.get_session_info());
|
||||
const ColumnItem* column_item = NULL;
|
||||
bool dummy_all_single_value_ranges = true;
|
||||
bool is_in_range_optimization_enabled = false;
|
||||
if (OB_ISNULL(log_plan) || OB_ISNULL(exec_ctx) ||
|
||||
if (OB_ISNULL(log_plan) || OB_ISNULL(exec_ctx) || OB_ISNULL(session_info) ||
|
||||
OB_ISNULL(column_item = log_plan->get_column_item_by_id(table_id, column_id)) ||
|
||||
OB_ISNULL(ctx.get_stmt()) || OB_ISNULL(ctx.get_stmt()->get_query_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret), K(log_plan), K(exec_ctx), K(column_item));
|
||||
LOG_WARN("get unexpected null", K(ret), K(log_plan), K(exec_ctx), K(session_info), K(column_item));
|
||||
} else if (OB_FAIL(column_items.push_back(*column_item))) {
|
||||
LOG_WARN("failed to push back column item", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::is_in_range_optimization_enabled(ctx.get_stmt()->get_query_ctx()->get_global_hint(),
|
||||
ctx.get_session_info(),
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to check in range optimization enabled", K(ret));
|
||||
} else if (OB_FAIL(query_range.preliminary_extract_query_range(column_items,
|
||||
quals,
|
||||
dtc_params,
|
||||
ctx.get_opt_ctx().get_exec_ctx(),
|
||||
ctx.get_opt_ctx().get_query_ctx(),
|
||||
NULL,
|
||||
params,
|
||||
false,
|
||||
true,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
} else if (!query_range.need_deep_copy()) {
|
||||
if (OB_FAIL(query_range.direct_get_tablet_ranges(allocator, *exec_ctx, ranges,
|
||||
dummy_all_single_value_ranges, dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
} else if (ctx.get_opt_ctx().enable_new_query_range()) {
|
||||
ObPreRangeGraph pre_range_graph(alloc);
|
||||
if (OB_FAIL(pre_range_graph.preliminary_extract_query_range(column_items, quals, exec_ctx,
|
||||
NULL, params, false, true))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(column_items), K(quals));
|
||||
} else if (OB_FAIL(pre_range_graph.get_tablet_ranges(alloc, *exec_ctx, ranges,
|
||||
dummy_all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges");
|
||||
}
|
||||
} else if (OB_FAIL(query_range.final_extract_query_range(*exec_ctx, dtc_params))) {
|
||||
LOG_WARN("failed to final extract query range", K(ret));
|
||||
} else if (OB_FAIL(query_range.get_tablet_ranges(ranges, dummy_all_single_value_ranges, dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
} else {
|
||||
ObQueryRange query_range(alloc);
|
||||
bool is_in_range_optimization_enabled = false;
|
||||
if (OB_FAIL(ObOptimizerUtil::is_in_range_optimization_enabled(ctx.get_stmt()->get_query_ctx()->get_global_hint(),
|
||||
ctx.get_session_info(),
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to check in range optimization enabled", K(ret));
|
||||
} else if (OB_FAIL(query_range.preliminary_extract_query_range(column_items,
|
||||
quals,
|
||||
dtc_params,
|
||||
ctx.get_opt_ctx().get_exec_ctx(),
|
||||
ctx.get_opt_ctx().get_query_ctx(),
|
||||
NULL,
|
||||
params,
|
||||
false,
|
||||
true,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
} else if (!query_range.need_deep_copy()) {
|
||||
if (OB_FAIL(query_range.direct_get_tablet_ranges(alloc, *exec_ctx, ranges,
|
||||
dummy_all_single_value_ranges, dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(query_range.final_extract_query_range(*exec_ctx, dtc_params))) {
|
||||
LOG_WARN("failed to final extract query range", K(ret));
|
||||
} else if (OB_FAIL(query_range.get_tablet_ranges(ranges, dummy_all_single_value_ranges, dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -944,7 +944,7 @@ public:
|
||||
const uint64_t column_id,
|
||||
const ObIArray<ObRawExpr *> &quals,
|
||||
ObIArray<ColumnItem> &column_items,
|
||||
ObQueryRange &query_range,
|
||||
ObIAllocator &alloc,
|
||||
ObQueryRangeArray &ranges);
|
||||
|
||||
// @brief 检测OR中 expr 对于第 index 个子表达式的互斥性, 只检测 c1 = v 的情况,
|
||||
|
@ -679,6 +679,11 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession
|
||||
if (!session.is_inner() && stmt.get_query_ctx()->get_injected_random_status()) {
|
||||
ctx_.set_generate_random_plan(true);
|
||||
}
|
||||
if (session.is_enable_new_query_range() &&
|
||||
ObSQLUtils::is_min_cluster_version_ge_425_or_435() &&
|
||||
ObSQLUtils::is_opt_feature_version_ge_425_or_435(query_ctx->optimizer_features_enable_version_)) {
|
||||
ctx_.set_enable_new_query_range(true);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -260,6 +260,7 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
|
||||
use_column_store_replica_(false),
|
||||
push_join_pred_into_view_enabled_(true),
|
||||
table_access_policy_(ObTableAccessPolicy::AUTO),
|
||||
enable_new_query_range_(false),
|
||||
partition_wise_plan_enabled_(true),
|
||||
enable_px_ordered_coord_(false)
|
||||
{ }
|
||||
@ -684,6 +685,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
|
||||
inline void set_push_join_pred_into_view_enabled(bool enabled) { push_join_pred_into_view_enabled_ = enabled; }
|
||||
inline void set_table_access_policy(ObTableAccessPolicy policy) { table_access_policy_ = policy; }
|
||||
inline ObTableAccessPolicy get_table_acces_policy() const { return table_access_policy_; }
|
||||
inline void set_enable_new_query_range(bool v) { enable_new_query_range_ = v; }
|
||||
inline bool enable_new_query_range() const { return enable_new_query_range_; }
|
||||
private:
|
||||
ObSQLSessionInfo *session_info_;
|
||||
ObExecContext *exec_ctx_;
|
||||
@ -786,6 +789,7 @@ private:
|
||||
bool use_column_store_replica_;
|
||||
bool push_join_pred_into_view_enabled_;
|
||||
ObTableAccessPolicy table_access_policy_;
|
||||
bool enable_new_query_range_;
|
||||
bool partition_wise_plan_enabled_;
|
||||
bool enable_px_ordered_coord_;
|
||||
};
|
||||
|
@ -6375,7 +6375,7 @@ bool ObOptimizerUtil::is_lossless_type_conv(const ObExprResType &child_type, con
|
||||
return is_lossless;
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr *expr, bool &is_lossless)
|
||||
int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr *expr, bool &is_lossless, bool is_query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_lossless = false;
|
||||
@ -6427,6 +6427,18 @@ int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr *expr, bool &is_los
|
||||
ObAccuracy lossless_acc = child_type.get_accuracy();
|
||||
if (lossless_acc.get_scale() == dst_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
} else if (!is_query_range) {
|
||||
} else if (-1 == dst_acc.get_precision() && -1 == dst_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
} else if (dst_acc.get_precision() >= lossless_acc.get_precision() &&
|
||||
dst_acc.get_scale() >= lossless_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
}
|
||||
} else if (ObDoubleTC == dst_tc && is_query_range) {
|
||||
ObAccuracy lossless_acc = child_type.get_accuracy();
|
||||
if (-1 == dst_acc.get_precision() && -1 == dst_acc.get_scale() &&
|
||||
-1 == lossless_acc.get_precision() && -1 == lossless_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
}
|
||||
}
|
||||
} else if (ObDateTimeType == child_type.get_type()) {
|
||||
@ -6445,16 +6457,6 @@ int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr *expr, bool &is_los
|
||||
}
|
||||
}
|
||||
} else if (ObYearTC == child_tc) {
|
||||
if (ObNumberTC == dst_tc || ObDecimalIntTC == dst_tc) {
|
||||
ObAccuracy lossless_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[ObCompatibilityMode::MYSQL_MODE][child_type.get_type()];
|
||||
if (dst_acc.get_precision() - dst_acc.get_scale() >= lossless_acc.get_precision() - lossless_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
}
|
||||
} else if (ObDoubleTC == dst_tc) {
|
||||
if (-1 == dst_acc.get_precision() && -1 == dst_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
}
|
||||
}
|
||||
} else if (ObVarcharType == child_type.get_type()) {
|
||||
// varchar, varbinnary
|
||||
} else if (ObCharType == child_type.get_type()) {
|
||||
@ -6535,6 +6537,13 @@ int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr *expr, bool &is_los
|
||||
is_lossless = true;
|
||||
}
|
||||
}
|
||||
} else if (ObDateTimeTC == child_tc) {
|
||||
if (is_query_range && ObTimestampNanoType == dst_type.get_type()) {
|
||||
if (dst_type.get_accuracy().get_precision() >=
|
||||
child_type.get_accuracy().get_precision()) {
|
||||
is_lossless = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("lossless column cast", K(child_type), K(child_tc), K(dst_type), K(dst_tc),
|
||||
@ -6544,7 +6553,8 @@ int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr *expr, bool &is_los
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::get_expr_without_lossless_cast(const ObRawExpr* ori_expr,
|
||||
const ObRawExpr*& expr)
|
||||
const ObRawExpr*& expr,
|
||||
bool is_query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_lossless = false;
|
||||
@ -6556,7 +6566,7 @@ int ObOptimizerUtil::get_expr_without_lossless_cast(const ObRawExpr* ori_expr,
|
||||
if (OB_FAIL(get_expr_without_lossless_cast(ori_expr->get_param_expr(2), expr))) {
|
||||
LOG_WARN("failed to check is lossless column cast", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(is_lossless_column_cast(ori_expr, is_lossless))) {
|
||||
} else if (OB_FAIL(is_lossless_column_cast(ori_expr, is_lossless, is_query_range))) {
|
||||
LOG_WARN("failed to check is lossless column cast", K(ret));
|
||||
} else if (is_lossless) {
|
||||
expr = ori_expr->get_param_expr(0);
|
||||
@ -6565,7 +6575,8 @@ int ObOptimizerUtil::get_expr_without_lossless_cast(const ObRawExpr* ori_expr,
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::get_expr_without_lossless_cast(ObRawExpr* ori_expr,
|
||||
ObRawExpr*& expr)
|
||||
ObRawExpr*& expr,
|
||||
bool is_query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_lossless = false;
|
||||
@ -6573,7 +6584,95 @@ int ObOptimizerUtil::get_expr_without_lossless_cast(ObRawExpr* ori_expr,
|
||||
if (OB_ISNULL(ori_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(is_lossless_column_cast(ori_expr, is_lossless))) {
|
||||
} else if (OB_FAIL(is_lossless_column_cast(ori_expr, is_lossless, is_query_range))) {
|
||||
LOG_WARN("failed to check is lossless column cast", K(ret));
|
||||
} else if (is_lossless) {
|
||||
expr = ori_expr->get_param_expr(0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::get_column_expr_without_nvl(ObRawExpr* ori_expr, ObRawExpr*& expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObOpRawExpr *op_expr = NULL;
|
||||
ObRawExpr *l_expr = NULL;
|
||||
ObRawExpr *r_expr = NULL;
|
||||
expr = ori_expr;
|
||||
if (OB_ISNULL(ori_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (T_FUN_SYS_NVL != ori_expr->get_expr_type()) {
|
||||
// do nothing
|
||||
} else if (OB_FALSE_IT(op_expr = static_cast<ObOpRawExpr*>(expr))) {
|
||||
} else if (OB_ISNULL(l_expr = op_expr->get_param_expr(0))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(get_expr_without_lossless_cast(l_expr, l_expr, true))) {
|
||||
LOG_WARN("get expr without lossless cast", K(ret));
|
||||
} else if (l_expr->is_column_ref_expr()) {
|
||||
expr = l_expr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::is_lossless_or_unprecise_column_cast(const ObRawExpr *expr, bool &is_lossless)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObRawExpr *child_expr = NULL;
|
||||
is_lossless = false;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (T_FUN_SYS_CAST != expr->get_expr_type()) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(is_lossless_column_cast(expr, is_lossless, true))) {
|
||||
LOG_WARN("failed to check is lossless column cast", K(ret));
|
||||
} else if (is_lossless ||
|
||||
expr->is_const_expr()) {
|
||||
// do nothing
|
||||
} else if (OB_ISNULL(child_expr = expr->get_param_expr(0))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else {
|
||||
ObExprResType child_type = child_expr->get_result_type();
|
||||
ObObjTypeClass child_tc = child_type.get_type_class();
|
||||
ObExprResType dst_type = expr->get_result_type();
|
||||
ObObjTypeClass dst_tc = dst_type.get_type_class();
|
||||
ObAccuracy dst_acc = dst_type.get_accuracy();
|
||||
if (!is_oracle_mode()) {
|
||||
if (ObIntTC == child_tc ) {
|
||||
if (dst_tc == ObDoubleTC && dst_acc.get_precision() == -1 &&
|
||||
dst_acc.get_scale() == -1) {
|
||||
is_lossless = true;
|
||||
}
|
||||
} else if (ObYearTC == child_tc) {
|
||||
if (ObNumberTC == dst_tc) {
|
||||
is_lossless = true;
|
||||
} else if (ObDoubleTC == dst_tc) {
|
||||
if (-1 == dst_acc.get_precision() && -1 == dst_acc.get_scale()) {
|
||||
is_lossless = true;
|
||||
}
|
||||
}
|
||||
} else if (ObNumberTC == child_tc) {
|
||||
if (ObDoubleTC == dst_tc || ObFloatTC == dst_tc) {
|
||||
is_lossless = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::get_expr_without_unprecise_and_lossless_cast(ObRawExpr* ori_expr, ObRawExpr*& expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_lossless = false;
|
||||
expr = ori_expr;
|
||||
if (OB_ISNULL(ori_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(is_lossless_or_unprecise_column_cast(ori_expr, is_lossless))) {
|
||||
LOG_WARN("failed to check is lossless column cast", K(ret));
|
||||
} else if (is_lossless) {
|
||||
expr = ori_expr->get_param_expr(0);
|
||||
|
@ -1122,13 +1122,17 @@ public:
|
||||
const EqualSets &equal_sets,
|
||||
const ObIArray<ObRawExpr *> &const_exprs,
|
||||
bool &is_match);
|
||||
|
||||
static int is_lossless_column_cast(const ObRawExpr *expr, bool &is_lossless);
|
||||
static int is_lossless_column_cast(const ObRawExpr *expr, bool &is_lossless, bool is_query_range = false);
|
||||
static bool is_lossless_type_conv(const ObExprResType &child_type, const ObExprResType &dst_type);
|
||||
static int is_lossless_column_conv(const ObRawExpr *expr, bool &is_lossless);
|
||||
static int get_expr_without_lossless_cast(const ObRawExpr* ori_expr, const ObRawExpr*& expr);
|
||||
static int get_expr_without_lossless_cast(ObRawExpr* ori_expr, ObRawExpr*& expr);
|
||||
|
||||
static int get_expr_without_lossless_cast(const ObRawExpr* ori_expr, const ObRawExpr*& expr, bool is_query_range = false);
|
||||
static int get_expr_without_lossless_cast(ObRawExpr* ori_expr, ObRawExpr*& expr, bool is_query_range = false);
|
||||
/**
|
||||
* This interface is specifically designed for query range, used to retrieve the column c1 that can extract the range from nvl(c1, 1) = 1.
|
||||
*/
|
||||
static int get_column_expr_without_nvl(ObRawExpr* ori_expr, ObRawExpr*& expr);
|
||||
static int get_expr_without_unprecise_and_lossless_cast(ObRawExpr* ori_expr, ObRawExpr*& expr);
|
||||
static int is_lossless_or_unprecise_column_cast(const ObRawExpr *expr, bool &is_lossless);
|
||||
static int gen_set_target_list(ObIAllocator *allocator,
|
||||
ObSQLSessionInfo *session_info,
|
||||
ObRawExprFactory *expr_factory,
|
||||
|
@ -7826,38 +7826,60 @@ int ObSelectLogPlan::adjust_late_materialization_plan_structure(ObLogicalOperato
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObDataTypeCastParams dtc_params =
|
||||
ObBasicSessionInfo::create_dtc_params(optimizer_context_.get_session_info());
|
||||
ObQueryRange *query_range = static_cast<ObQueryRange*>(get_allocator().alloc(sizeof(ObQueryRange)));
|
||||
const ParamStore *params = get_optimizer_context().get_params();
|
||||
if (OB_ISNULL(query_range)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for query range", K(ret));
|
||||
} else if (OB_ISNULL(params)) {
|
||||
if (OB_ISNULL(params)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else {
|
||||
query_range = new(query_range)ObQueryRange(get_allocator());
|
||||
bool is_in_range_optimization_enabled = false;
|
||||
if (OB_FAIL(ObOptimizerUtil::is_in_range_optimization_enabled(optimizer_context_.get_global_hint(),
|
||||
optimizer_context_.get_session_info(),
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to check in range optimization enabled", K(ret));
|
||||
} else if (OB_FAIL(query_range->preliminary_extract_query_range(range_columns,
|
||||
join_conditions,
|
||||
dtc_params,
|
||||
optimizer_context_.get_exec_ctx(),
|
||||
optimizer_context_.get_query_ctx(),
|
||||
NULL,
|
||||
params,
|
||||
false,
|
||||
true,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
} else if (OB_FAIL(table_scan->set_range_columns(range_columns))) {
|
||||
LOG_WARN("failed to set range columns", K(ret));
|
||||
} else if (OB_FAIL(table_scan->set_range_columns(range_columns))) {
|
||||
LOG_WARN("failed to set range columns", K(ret));
|
||||
} else if (optimizer_context_.enable_new_query_range()) {
|
||||
ObPreRangeGraph *pre_range_graph = static_cast<ObPreRangeGraph*>(get_allocator().alloc(sizeof(ObPreRangeGraph)));
|
||||
if (OB_ISNULL(pre_range_graph)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for pre range graph", K(ret));
|
||||
} else {
|
||||
table_scan->set_pre_query_range(query_range);
|
||||
pre_range_graph = new(pre_range_graph)ObPreRangeGraph(get_allocator());
|
||||
if (OB_FAIL(pre_range_graph->preliminary_extract_query_range(range_columns,
|
||||
join_conditions,
|
||||
optimizer_context_.get_exec_ctx(),
|
||||
NULL,
|
||||
params,
|
||||
false,
|
||||
true))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
} else {
|
||||
table_scan->set_pre_range_graph(pre_range_graph);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ObQueryRange *query_range = static_cast<ObQueryRange*>(get_allocator().alloc(sizeof(ObQueryRange)));
|
||||
if (OB_ISNULL(query_range)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for query range", K(ret));
|
||||
} else {
|
||||
query_range = new(query_range)ObQueryRange(get_allocator());
|
||||
bool is_in_range_optimization_enabled = false;
|
||||
if (OB_FAIL(ObOptimizerUtil::is_in_range_optimization_enabled(optimizer_context_.get_global_hint(),
|
||||
optimizer_context_.get_session_info(),
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to check in range optimization enabled", K(ret));
|
||||
} else if (OB_FAIL(query_range->preliminary_extract_query_range(range_columns,
|
||||
join_conditions,
|
||||
dtc_params,
|
||||
optimizer_context_.get_exec_ctx(),
|
||||
optimizer_context_.get_query_ctx(),
|
||||
NULL,
|
||||
params,
|
||||
false,
|
||||
true,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to preliminary extract query range", K(ret));
|
||||
} else {
|
||||
table_scan->set_pre_query_range(query_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(table_scan->set_table_scan_filters(join_conditions))) {
|
||||
@ -8202,8 +8224,8 @@ int ObSelectLogPlan::if_index_back_plan_need_late_materialization(ObLogSort *chi
|
||||
} else if (OB_FAIL(append(temp_exprs, table_scan->get_filter_exprs())) ||
|
||||
OB_FAIL(append(temp_exprs, table_keys))) {
|
||||
LOG_WARN("failed to append exprs", K(ret));
|
||||
} else if (NULL != table_scan->get_pre_query_range() &&
|
||||
OB_FAIL(append(temp_exprs, table_scan->get_pre_query_range()->get_range_exprs()))) {
|
||||
} else if (NULL != table_scan->get_pre_graph() &&
|
||||
OB_FAIL(append(temp_exprs, table_scan->get_pre_graph()->get_range_exprs()))) {
|
||||
LOG_WARN("failed to append exprs", K(ret));
|
||||
} else if (OB_ISNULL(schema_guard = get_optimizer_context().get_sql_schema_guard())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -8267,8 +8289,8 @@ int ObSelectLogPlan::if_column_store_plan_need_late_materialization(ObLogSort *c
|
||||
LOG_WARN("failed to append exprs", K(ret));
|
||||
} else if (OB_FAIL(append(temp_exprs, table_scan->get_filter_exprs()))) {
|
||||
LOG_WARN("failed to append exprs", K(ret));
|
||||
} else if (NULL != table_scan->get_pre_query_range() &&
|
||||
OB_FAIL(append(temp_exprs, table_scan->get_pre_query_range()->get_range_exprs()))) {
|
||||
} else if (NULL != table_scan->get_pre_graph() &&
|
||||
OB_FAIL(append(temp_exprs, table_scan->get_pre_graph()->get_range_exprs()))) {
|
||||
LOG_WARN("failed to append exprs", K(ret));
|
||||
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(temp_exprs, temp_col_exprs))) {
|
||||
LOG_WARN("extract column exprs failed", K(ret));
|
||||
|
@ -383,6 +383,13 @@ ObPartLocCalcNode *ObPartLocCalcNode::create_part_calc_node(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ObPartLocCalcNode::PRE_RANGE_GRAPH: {
|
||||
ptr = allocator.alloc(sizeof(ObPLPreRangeGraphNode));
|
||||
if (NULL != ptr) {
|
||||
ret_node = new(ptr) ObPLPreRangeGraphNode(allocator);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ObPartLocCalcNode::FUNC_VALUE: {
|
||||
ptr = allocator.alloc(sizeof(ObPLFuncValueNode));
|
||||
if (NULL != ptr) {
|
||||
@ -444,6 +451,13 @@ int ObPartLocCalcNode::create_part_calc_node(common::ObIAllocator &allocator,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ObPartLocCalcNode::PRE_RANGE_GRAPH: {
|
||||
ptr = allocator.alloc(sizeof(ObPLPreRangeGraphNode));
|
||||
if (NULL != ptr) {
|
||||
ret_node = new(ptr) ObPLPreRangeGraphNode(allocator);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ObPartLocCalcNode::FUNC_VALUE: {
|
||||
ptr = allocator.alloc(sizeof(ObPLFuncValueNode));
|
||||
if (NULL != ptr) {
|
||||
@ -601,6 +615,29 @@ int ObPLQueryRangeNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*>
|
||||
return calc_nodes.push_back(this);
|
||||
}
|
||||
|
||||
int ObPLPreRangeGraphNode::deep_copy(
|
||||
ObIAllocator &allocator,
|
||||
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
||||
ObPartLocCalcNode *&other) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(other = create_part_calc_node(allocator, calc_nodes, PRE_RANGE_GRAPH))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("Allocate calc node failed", K(ret));
|
||||
} else {
|
||||
ObPLPreRangeGraphNode *node = static_cast<ObPLPreRangeGraphNode*>(other);
|
||||
if (OB_FAIL(node->pre_range_graph_.deep_copy(pre_range_graph_))) {
|
||||
LOG_WARN("Failed to deep copy pre query range", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLPreRangeGraphNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes)
|
||||
{
|
||||
return calc_nodes.push_back(this);
|
||||
}
|
||||
|
||||
int ObPLFuncValueNode::deep_copy(
|
||||
ObIAllocator &allocator,
|
||||
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
||||
@ -1298,12 +1335,16 @@ int ObTableLocation::init(
|
||||
LOG_WARN("fail to record_in_dml_partition_info", K(ret));
|
||||
} else if (!is_in_hit_) {
|
||||
bool is_in_range_optimization_enabled = false;
|
||||
bool use_new_query_range = (session_info->is_enable_new_query_range()
|
||||
&& ObSQLUtils::is_opt_feature_version_ge_425_or_435(stmt.get_query_ctx()->optimizer_features_enable_version_)
|
||||
&& ObSQLUtils::is_min_cluster_version_ge_425_or_435());
|
||||
if (OB_FAIL(ObOptimizerUtil::is_in_range_optimization_enabled(stmt.get_query_ctx()->get_global_hint(),
|
||||
session_info,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("failed to check in range optimization enabled", K(ret));
|
||||
} else if (OB_FAIL(record_not_insert_dml_partition_info(stmt, exec_ctx, table_schema, filter_exprs, dtc_params,
|
||||
is_in_range_optimization_enabled))) {
|
||||
is_in_range_optimization_enabled,
|
||||
use_new_query_range))) {
|
||||
LOG_WARN("Fail to record select or update partition info", K(stmt_type_), K(ret));
|
||||
} else if (OB_FAIL(get_not_insert_dml_part_sort_expr(stmt, sort_exprs))) {
|
||||
LOG_WARN("Failed to get not insert dml sort key with parts", K(ret));
|
||||
@ -2059,7 +2100,8 @@ int ObTableLocation::set_location_calc_node(const ObDMLStmt &stmt,
|
||||
ObPartLocCalcNode *&gen_col_node,
|
||||
bool &get_all,
|
||||
bool &is_range_get,
|
||||
const bool is_in_range_optimization_enabled)
|
||||
const bool is_in_range_optimization_enabled,
|
||||
const bool use_new_query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ColumnItem, 5> part_columns;
|
||||
@ -2091,20 +2133,28 @@ int ObTableLocation::set_location_calc_node(const ObDMLStmt &stmt,
|
||||
dtc_params,
|
||||
exec_ctx,
|
||||
query_ctx,
|
||||
is_in_range_optimization_enabled))) {
|
||||
is_in_range_optimization_enabled,
|
||||
use_new_query_range))) {
|
||||
LOG_WARN("Failed to get location calc node", K(ret));
|
||||
} else if (gen_cols.count() > 0) {
|
||||
//analyze information with dependented column of generated column
|
||||
bool always_true =false;
|
||||
if (OB_FAIL(get_query_range_node(part_level,
|
||||
gen_cols,
|
||||
filter_exprs,
|
||||
always_true,
|
||||
gen_col_node,
|
||||
dtc_params,
|
||||
exec_ctx,
|
||||
query_ctx,
|
||||
is_in_range_optimization_enabled))) {
|
||||
if (use_new_query_range && OB_FAIL(get_pre_range_graph_node(part_level,
|
||||
gen_cols,
|
||||
filter_exprs,
|
||||
always_true,
|
||||
gen_col_node,
|
||||
exec_ctx))) {
|
||||
LOG_WARN("Get query range node error", K(ret));
|
||||
} else if (!use_new_query_range && OB_FAIL(get_query_range_node(part_level,
|
||||
gen_cols,
|
||||
filter_exprs,
|
||||
always_true,
|
||||
gen_col_node,
|
||||
dtc_params,
|
||||
exec_ctx,
|
||||
query_ctx,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("Get query range node error", K(ret));
|
||||
} else if (always_true) {
|
||||
gen_col_node = NULL;
|
||||
@ -2375,7 +2425,8 @@ int ObTableLocation::record_not_insert_dml_partition_info(
|
||||
const ObTableSchema *table_schema,
|
||||
const ObIArray<ObRawExpr*> &filter_exprs,
|
||||
const ObDataTypeCastParams &dtc_params,
|
||||
const bool is_in_range_optimization_enabled)
|
||||
const bool is_in_range_optimization_enabled,
|
||||
const bool use_new_query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(set_location_calc_node(stmt,
|
||||
@ -2390,7 +2441,8 @@ int ObTableLocation::record_not_insert_dml_partition_info(
|
||||
gen_col_node_,
|
||||
part_get_all_,
|
||||
is_part_range_get_,
|
||||
is_in_range_optimization_enabled))) {
|
||||
is_in_range_optimization_enabled,
|
||||
use_new_query_range))) {
|
||||
LOG_WARN("failed to set location calc node for first-level partition", K(ret));
|
||||
} else if (PARTITION_LEVEL_TWO == part_level_
|
||||
&& OB_FAIL(set_location_calc_node(stmt,
|
||||
@ -2405,7 +2457,8 @@ int ObTableLocation::record_not_insert_dml_partition_info(
|
||||
sub_gen_col_node_,
|
||||
subpart_get_all_,
|
||||
is_subpart_range_get_,
|
||||
is_in_range_optimization_enabled))) {
|
||||
is_in_range_optimization_enabled,
|
||||
use_new_query_range))) {
|
||||
LOG_WARN("failed to set location calc node for second-level partition", K(ret));
|
||||
}
|
||||
|
||||
@ -2437,6 +2490,10 @@ int ObTableLocation::get_not_insert_dml_part_sort_expr(const ObDMLStmt &stmt,
|
||||
if (static_cast<ObPLQueryRangeNode*>(calc_node_)->pre_query_range_.is_precise_get()) {
|
||||
part_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
||||
}
|
||||
} else if (calc_node_->is_pre_range_graph_node()) {
|
||||
if (static_cast<ObPLPreRangeGraphNode*>(calc_node_)->pre_range_graph_.is_precise_get()) {
|
||||
part_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
||||
}
|
||||
} else { }
|
||||
}
|
||||
} else { }
|
||||
@ -2490,7 +2547,8 @@ int ObTableLocation::get_location_calc_node(const ObPartitionLevel part_level,
|
||||
const ObDataTypeCastParams &dtc_params,
|
||||
ObExecContext *exec_ctx,
|
||||
ObQueryCtx *query_ctx,
|
||||
const bool is_in_range_optimization_enabled)
|
||||
const bool is_in_range_optimization_enabled,
|
||||
const bool use_new_query_range)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
uint64_t column_id = OB_INVALID_ID;
|
||||
@ -2512,22 +2570,40 @@ int ObTableLocation::get_location_calc_node(const ObPartitionLevel part_level,
|
||||
} else if (only_range_node) {
|
||||
bool always_true = false;
|
||||
ObPartLocCalcNode *calc_node = NULL;
|
||||
if (OB_FAIL(get_query_range_node(part_level,
|
||||
partition_columns,
|
||||
filter_exprs,
|
||||
always_true,
|
||||
calc_node,
|
||||
dtc_params,
|
||||
exec_ctx,
|
||||
query_ctx,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("Get query range node error", K(ret));
|
||||
} else if (always_true) {
|
||||
get_all = true;
|
||||
if (use_new_query_range) {
|
||||
if (OB_FAIL(get_pre_range_graph_node(part_level,
|
||||
partition_columns,
|
||||
filter_exprs,
|
||||
always_true,
|
||||
calc_node,
|
||||
exec_ctx))) {
|
||||
LOG_WARN("Get query range node error", K(ret));
|
||||
} else if (always_true) {
|
||||
get_all = true;
|
||||
} else {
|
||||
res_node = calc_node;
|
||||
if (OB_NOT_NULL(calc_node)) {
|
||||
is_range_get = static_cast<ObPLPreRangeGraphNode*>(calc_node)->pre_range_graph_.is_precise_get();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res_node = calc_node;
|
||||
if (OB_NOT_NULL(calc_node)) {
|
||||
is_range_get = static_cast<ObPLQueryRangeNode*>(calc_node)->pre_query_range_.is_precise_get();
|
||||
if (OB_FAIL(get_query_range_node(part_level,
|
||||
partition_columns,
|
||||
filter_exprs,
|
||||
always_true,
|
||||
calc_node,
|
||||
dtc_params,
|
||||
exec_ctx,
|
||||
query_ctx,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("Get query range node error", K(ret));
|
||||
} else if (always_true) {
|
||||
get_all = true;
|
||||
} else {
|
||||
res_node = calc_node;
|
||||
if (OB_NOT_NULL(calc_node)) {
|
||||
is_range_get = static_cast<ObPLQueryRangeNode*>(calc_node)->pre_query_range_.is_precise_get();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -2562,12 +2638,20 @@ int ObTableLocation::get_location_calc_node(const ObPartitionLevel part_level,
|
||||
ObPartLocCalcNode *column_node = NULL;
|
||||
if (normal_filters.count() > 0) {
|
||||
column_always_true = false;
|
||||
if (OB_FAIL(get_query_range_node(part_level, partition_columns, filter_exprs, column_always_true,
|
||||
column_node, dtc_params, exec_ctx, query_ctx,
|
||||
is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("Failed to get query range node", K(ret));
|
||||
} else if (OB_NOT_NULL(column_node)) {
|
||||
is_column_range_get = static_cast<ObPLQueryRangeNode*>(column_node)->pre_query_range_.is_precise_get();
|
||||
if (use_new_query_range) {
|
||||
if (OB_FAIL(get_pre_range_graph_node(part_level, partition_columns, filter_exprs,
|
||||
column_always_true, column_node, exec_ctx))) {
|
||||
LOG_WARN("Failed to get query range node", K(ret));
|
||||
} else if (OB_NOT_NULL(column_node)) {
|
||||
is_column_range_get = static_cast<ObPLPreRangeGraphNode*>(column_node)->pre_range_graph_.is_precise_get();
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(get_query_range_node(part_level, partition_columns, filter_exprs, column_always_true,
|
||||
column_node, dtc_params, exec_ctx, query_ctx, is_in_range_optimization_enabled))) {
|
||||
LOG_WARN("Failed to get query range node", K(ret));
|
||||
} else if (OB_NOT_NULL(column_node)) {
|
||||
is_column_range_get = static_cast<ObPLQueryRangeNode*>(column_node)->pre_query_range_.is_precise_get();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
@ -2629,6 +2713,41 @@ int ObTableLocation::get_query_range_node(const ObPartitionLevel part_level,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableLocation::get_pre_range_graph_node(const ObPartitionLevel part_level,
|
||||
const ColumnIArray &partition_columns,
|
||||
const ObIArray<ObRawExpr*> &filter_exprs,
|
||||
bool &always_true,
|
||||
ObPartLocCalcNode *&calc_node,
|
||||
ObExecContext *exec_ctx)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool phy_rowid_for_table_loc = (part_level == part_level_);
|
||||
if (filter_exprs.empty()) {
|
||||
always_true = true;
|
||||
} else if (OB_ISNULL(calc_node = ObPartLocCalcNode::create_part_calc_node(
|
||||
allocator_, calc_nodes_, ObPartLocCalcNode::PRE_RANGE_GRAPH))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("Allocate memory failed", K(ret));
|
||||
} else {
|
||||
ObPLPreRangeGraphNode *node = static_cast<ObPLPreRangeGraphNode*>(calc_node);
|
||||
if (OB_FAIL(node->pre_range_graph_.preliminary_extract_query_range(partition_columns,
|
||||
filter_exprs,
|
||||
exec_ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
phy_rowid_for_table_loc,
|
||||
false))) {
|
||||
LOG_WARN("Failed to pre extract query range", K(ret));
|
||||
} else if (node->pre_range_graph_.is_precise_whole_range()) {
|
||||
//pre query range is whole range, indicate that there are no partition condition in filters,
|
||||
//so you need to get all part ids
|
||||
always_true = true;
|
||||
calc_node = NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableLocation::analyze_filter(const ObIArray<ColumnItem> &partition_columns,
|
||||
const ObRawExpr *partition_expr,
|
||||
uint64_t column_id,
|
||||
@ -3144,9 +3263,16 @@ int ObTableLocation::calc_partition_ids_by_calc_node(ObExecContext &exec_ctx,
|
||||
if (NULL != gen_col_node && NULL != se_gen_col_expr) {
|
||||
//partition key is generated column and dependent column condition is not empty
|
||||
//so you need to calc partition id by dependent column condition
|
||||
if (!gen_col_node->is_query_range_node()) {
|
||||
if (!gen_col_node->is_query_range_node() && !gen_col_node->is_pre_range_graph_node()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("column dependented by generated column calc node should be query range node", K(ret));
|
||||
} else if (gen_col_node->is_pre_range_graph_node()) {
|
||||
if (OB_FAIL(calc_pre_range_graph_partition_ids(exec_ctx, tablet_mapper, params,
|
||||
static_cast<const ObPLPreRangeGraphNode*>(gen_col_node),
|
||||
gen_tablet_ids, gen_part_ids, gen_col_all_part, dtc_params,
|
||||
part_ids, se_gen_col_expr))) {
|
||||
LOG_WARN("Failed to calcl partition ids by gen col node", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(calc_query_range_partition_ids(exec_ctx, tablet_mapper, params,
|
||||
static_cast<const ObPLQueryRangeNode*>(gen_col_node),
|
||||
gen_tablet_ids, gen_part_ids, gen_col_all_part, dtc_params,
|
||||
@ -3242,6 +3368,13 @@ int ObTableLocation::calc_partition_ids_by_calc_node(ObExecContext &exec_ctx,
|
||||
dtc_params, part_ids, NULL))) {
|
||||
LOG_WARN("Failed to calc and partition ids", K(ret));
|
||||
}
|
||||
} else if (ObPartLocCalcNode::PRE_RANGE_GRAPH == calc_node->get_node_type()) {
|
||||
if (OB_FAIL(calc_pre_range_graph_partition_ids(exec_ctx, tablet_mapper, params,
|
||||
static_cast<const ObPLPreRangeGraphNode*>(calc_node),
|
||||
tablet_ids, partition_ids, all_part,
|
||||
dtc_params, part_ids, NULL))) {
|
||||
LOG_WARN("Failed to calc and partition ids", K(ret));
|
||||
}
|
||||
} else if (ObPartLocCalcNode::FUNC_VALUE == calc_node->get_node_type()) {
|
||||
if (OB_FAIL(calc_func_value_partition_ids(exec_ctx, tablet_mapper, params,
|
||||
static_cast<const ObPLFuncValueNode*>(calc_node),
|
||||
@ -3423,6 +3556,56 @@ int ObTableLocation::calc_query_range_partition_ids(ObExecContext &exec_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableLocation::calc_pre_range_graph_partition_ids(ObExecContext &exec_ctx,
|
||||
ObDASTabletMapper &tablet_mapper,
|
||||
const ParamStore ¶ms,
|
||||
const ObPLPreRangeGraphNode *calc_node,
|
||||
ObIArray<ObTabletID> &tablet_ids,
|
||||
ObIArray<ObObjectID> &partition_ids,
|
||||
bool &all_part,
|
||||
const ObDataTypeCastParams &dtc_params,
|
||||
const ObIArray<ObObjectID> *part_ids,
|
||||
const ObTempExpr *se_gen_col_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(calc_node)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("Calc node should not be NULL", K(ret));
|
||||
} else {
|
||||
all_part = false;
|
||||
ObQueryRangeArray query_ranges;
|
||||
ObArenaAllocator allocator(CURRENT_CONTEXT->get_malloc_allocator());
|
||||
allocator.set_label("CalcQRPartIds");
|
||||
bool is_all_single_value_ranges = true;
|
||||
if (OB_FAIL(calc_node->pre_range_graph_.get_tablet_ranges(allocator, exec_ctx, query_ranges,
|
||||
is_all_single_value_ranges, dtc_params))) {
|
||||
LOG_WARN("get tablet ranges failed", K(ret));
|
||||
} else if (OB_UNLIKELY(query_ranges.count() == 0)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Query ranges' count should not be 0",
|
||||
"query range count", query_ranges.count(), K(ret));
|
||||
} else {
|
||||
bool is_empty = true;
|
||||
if (OB_FAIL(is_all_ranges_empty(query_ranges, is_empty))) {
|
||||
LOG_WARN("fail to check all ranges", K(query_ranges));
|
||||
} else if (!is_empty) {
|
||||
if (OB_FAIL(calc_partition_ids_by_ranges(exec_ctx,
|
||||
tablet_mapper,
|
||||
query_ranges,
|
||||
is_all_single_value_ranges,
|
||||
tablet_ids,
|
||||
partition_ids,
|
||||
all_part,
|
||||
part_ids,
|
||||
se_gen_col_expr))) {
|
||||
LOG_WARN("Failed to get partition ids", K(ret), K(loc_meta_.table_loc_id_));
|
||||
}
|
||||
} else { } //do nothing. partition ids will be empty
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableLocation::calc_func_value_partition_ids(
|
||||
ObExecContext &exec_ctx,
|
||||
ObDASTabletMapper &tablet_mapper,
|
||||
@ -4616,6 +4799,7 @@ OB_DEF_DESERIALIZE(ObPLOrNode)
|
||||
OB_SERIALIZE_MEMBER(ObPLFuncValueNode::ParamValuePair, param_idx_, obj_value_);
|
||||
OB_SERIALIZE_MEMBER(ObPartLocCalcNode, node_type_);
|
||||
OB_SERIALIZE_MEMBER((ObPLQueryRangeNode, ObPartLocCalcNode), pre_query_range_);
|
||||
OB_SERIALIZE_MEMBER((ObPLPreRangeGraphNode, ObPartLocCalcNode), pre_range_graph_);
|
||||
|
||||
OB_DEF_SERIALIZE(ObPLFuncValueNode)
|
||||
{
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "lib/hash/ob_pointer_hashmap.h"
|
||||
#include "sql/rewrite/ob_query_range.h"
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
#include "sql/das/ob_das_define.h"
|
||||
#include "sql/engine/expr/ob_sql_expression.h"
|
||||
#include "sql/engine/expr/ob_sql_expression_factory.h"
|
||||
@ -128,6 +129,7 @@ public:
|
||||
QUERY_RANGE,
|
||||
FUNC_VALUE,
|
||||
COLUMN_VALUE,
|
||||
PRE_RANGE_GRAPH
|
||||
};
|
||||
|
||||
ObPartLocCalcNode (common::ObIAllocator &allocator): node_type_(INVALID), allocator_(allocator)
|
||||
@ -142,6 +144,7 @@ public:
|
||||
inline bool is_query_range_node() const { return QUERY_RANGE == node_type_; }
|
||||
inline bool is_func_value_node() const { return FUNC_VALUE == node_type_; }
|
||||
inline bool is_column_value_node() const { return COLUMN_VALUE == node_type_; }
|
||||
inline bool is_pre_range_graph_node() const { return PRE_RANGE_GRAPH == node_type_; }
|
||||
|
||||
static ObPartLocCalcNode *create_part_calc_node(common::ObIAllocator &allocator,
|
||||
common::ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
||||
@ -219,6 +222,22 @@ public:
|
||||
ObQueryRange pre_query_range_;
|
||||
};
|
||||
|
||||
struct ObPLPreRangeGraphNode : public ObPartLocCalcNode
|
||||
{
|
||||
OB_UNIS_VERSION_V(1);
|
||||
public:
|
||||
ObPLPreRangeGraphNode(common::ObIAllocator &allocator)
|
||||
: ObPartLocCalcNode(allocator), pre_range_graph_(allocator)
|
||||
{ set_node_type(PRE_RANGE_GRAPH); }
|
||||
virtual ~ObPLPreRangeGraphNode()
|
||||
{ pre_range_graph_.reset(); }
|
||||
virtual int deep_copy(common::ObIAllocator &allocator,
|
||||
common::ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
||||
ObPartLocCalcNode *&other) const;
|
||||
virtual int add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes);
|
||||
ObPreRangeGraph pre_range_graph_;
|
||||
};
|
||||
|
||||
struct ObPLFuncValueNode : public ObPartLocCalcNode
|
||||
{
|
||||
OB_UNIS_VERSION_V(1);
|
||||
@ -862,6 +881,17 @@ private:
|
||||
const common::ObIArray<common::ObObjectID> *part_ids,
|
||||
const ObTempExpr *temp_expr) const;
|
||||
|
||||
int calc_pre_range_graph_partition_ids(ObExecContext &exec_ctx,
|
||||
ObDASTabletMapper &tablet_mapper,
|
||||
const ParamStore ¶ms,
|
||||
const ObPLPreRangeGraphNode *calc_node,
|
||||
ObIArray<ObTabletID> &tablet_ids,
|
||||
ObIArray<ObObjectID> &partition_ids,
|
||||
bool &all_part,
|
||||
const ObDataTypeCastParams &dtc_params,
|
||||
const ObIArray<ObObjectID> *part_ids,
|
||||
const ObTempExpr *se_gen_col_expr) const;
|
||||
|
||||
int calc_func_value_partition_ids(ObExecContext &exec_ctx,
|
||||
ObDASTabletMapper &tablet_mapper,
|
||||
const ParamStore ¶ms,
|
||||
@ -953,7 +983,8 @@ private:
|
||||
const share::schema::ObTableSchema *table_schema,
|
||||
const common::ObIArray<ObRawExpr*> &filter_exprs,
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
const bool is_in_range_optimization_enabled);
|
||||
const bool is_in_range_optimization_enabled,
|
||||
const bool use_new_query_range);
|
||||
|
||||
int add_se_value_expr(const ObRawExpr *value_expr,
|
||||
RowDesc &value_row_desc,
|
||||
@ -983,7 +1014,8 @@ private:
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
ObExecContext *exec_ctx,
|
||||
ObQueryCtx *query_ctx,
|
||||
const bool is_in_range_optimization_enabled);
|
||||
const bool is_in_range_optimization_enabled,
|
||||
const bool use_new_query_range);
|
||||
|
||||
int analyze_filter(const common::ObIArray<ColumnItem> &partition_columns,
|
||||
const ObRawExpr *partition_expr,
|
||||
@ -1005,6 +1037,13 @@ private:
|
||||
ObQueryCtx *query_ctx,
|
||||
const bool is_in_range_optimization_enabled);
|
||||
|
||||
int get_pre_range_graph_node(const ObPartitionLevel part_level,
|
||||
const ColumnIArray &partition_columns,
|
||||
const ObIArray<ObRawExpr*> &filter_exprs,
|
||||
bool &always_true,
|
||||
ObPartLocCalcNode *&calc_node,
|
||||
ObExecContext *exec_ctx);
|
||||
|
||||
int extract_eq_op(ObExecContext *exec_ctx,
|
||||
const ObRawExpr *l_expr,
|
||||
const ObRawExpr *r_expr,
|
||||
@ -1091,7 +1130,8 @@ private:
|
||||
ObPartLocCalcNode *&gen_col_node,
|
||||
bool &get_all,
|
||||
bool &is_range_get,
|
||||
const bool is_in_range_optimization_enabled);
|
||||
const bool is_in_range_optimization_enabled,
|
||||
const bool use_new_query_range);
|
||||
|
||||
int calc_partition_ids_by_in_expr(
|
||||
ObExecContext &exec_ctx,
|
||||
@ -1178,7 +1218,6 @@ private:
|
||||
ObTempExpr *se_sub_gen_col_expr_;
|
||||
|
||||
common::ObFixedArray<common::ObObjectID, common::ObIAllocator> part_hint_ids_;
|
||||
ObQueryRange pre_query_range_; // query range for the table scan
|
||||
ObObjType part_col_type_;
|
||||
ObCollationType part_collation_type_;
|
||||
ObObjType subpart_col_type_;
|
||||
|
@ -92,13 +92,13 @@ int ObAdaptiveAutoDop::calculate_tsc_auto_dop(const ObOpSpec &spec, int64_t &tab
|
||||
bool is_oracle_agent_table =
|
||||
share::is_oracle_mapping_real_virtual_table(tsc_spec.get_ref_table_id());
|
||||
ObQueryRangeArray key_ranges;
|
||||
const ObQueryRange &query_range = tsc_spec.get_query_range();
|
||||
const ObQueryRangeProvider &query_range_provider = tsc_spec.get_query_range_provider();
|
||||
|
||||
if (is_oracle_agent_table || cost_tsc_info.get_is_spatial_index()) {
|
||||
// step1: calculate query range.
|
||||
} else if (query_range.has_range()
|
||||
} else if (query_range_provider.has_range()
|
||||
&& OB_FAIL(ObSQLUtils::extract_pre_query_range(
|
||||
query_range, ctx_.get_allocator(), ctx_, key_ranges,
|
||||
query_range_provider, ctx_.get_allocator(), ctx_, key_ranges,
|
||||
ObBasicSessionInfo::create_dtc_params(ctx_.get_my_session())))) {
|
||||
LOG_WARN("failed to extract pre query ranges", K(ret));
|
||||
// step2: build est tasks.
|
||||
|
@ -1646,6 +1646,7 @@ int64_t ObConstRawExpr::to_string(char* buf, const int64_t buf_len) const
|
||||
N_EXPR_INFO, info_,
|
||||
N_REL_ID, rel_ids_,
|
||||
N_VALUE, value_,
|
||||
"is_dynamic_questionmark", is_dynamic_eval_questionmark_,
|
||||
K_(expr_hash));
|
||||
if (!literal_prefix_.empty()) {
|
||||
J_COMMA();
|
||||
|
3699
src/sql/rewrite/ob_expr_range_converter.cpp
Normal file
3699
src/sql/rewrite/ob_expr_range_converter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
230
src/sql/rewrite/ob_expr_range_converter.h
Normal file
230
src/sql/rewrite/ob_expr_range_converter.h
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
#ifndef OCEANBASE_SQL_REWRITE_OB_RANGE_NODE_GENERATOR_H_
|
||||
#define OCEANBASE_SQL_REWRITE_OB_RANGE_NODE_GENERATOR_H_
|
||||
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
|
||||
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
|
||||
typedef ObSEArray<const ObRawExpr*, 4> TmpExprArray;
|
||||
|
||||
class ObExprRangeConverter
|
||||
{
|
||||
public:
|
||||
ObExprRangeConverter(ObIAllocator &allocator, ObQueryRangeCtx &ctx)
|
||||
: allocator_(allocator),
|
||||
ctx_(ctx),
|
||||
mem_used_(allocator.used())
|
||||
{}
|
||||
|
||||
int convert_expr_to_range_node(const ObRawExpr *expr,
|
||||
ObRangeNode *&range_node,
|
||||
int64_t expr_depth,
|
||||
bool &is_precise);
|
||||
int generate_always_true_or_false_node(bool is_true, ObRangeNode *&range_node);
|
||||
int convert_const_expr(const ObRawExpr *expr, ObRangeNode *&range_node);
|
||||
int convert_basic_cmp_expr(const ObRawExpr *expr,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int get_basic_range_node(const ObRawExpr *l_expr,
|
||||
const ObRawExpr *r_expr,
|
||||
ObItemType cmp_type,
|
||||
const ObExprResType &result_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int convert_is_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
|
||||
int convert_between_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int convert_not_between_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int convert_not_equal_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int convert_like_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int convert_in_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
|
||||
|
||||
int fill_range_node_for_basic_cmp(ObItemType cmp_type,
|
||||
const int64_t key_idx,
|
||||
const int64_t val_idx,
|
||||
ObRangeNode &range_node) const;
|
||||
int fill_range_node_for_basic_row_cmp(ObItemType cmp_type,
|
||||
const ObIArray<int64_t> &key_idxs,
|
||||
const ObIArray<int64_t> &val_idxs,
|
||||
ObRangeNode &range_node) const;
|
||||
int fill_range_node_for_like(const int64_t key_idx,
|
||||
const int64_t start_val_idx,
|
||||
const int64_t end_val_idx,
|
||||
ObRangeNode &range_node) const;
|
||||
|
||||
int check_expr_precise(const ObRawExpr &const_expr,
|
||||
const ObExprCalcType &calc_type,
|
||||
const ObExprResType &column_res_type);
|
||||
|
||||
inline int64_t get_mem_used() const { return mem_used_; }
|
||||
|
||||
static int64_t get_expr_category(ObItemType type);
|
||||
|
||||
int sort_range_exprs(const ObIArray<ObRawExpr*> &range_exprs,
|
||||
ObIArray<ObRawExpr*> &out_range_exprs);
|
||||
private:
|
||||
ObExprRangeConverter();
|
||||
int alloc_range_node(ObRangeNode *&range_node);
|
||||
int generate_deduce_const_expr(ObRawExpr *expr, int64_t &start_val, int64_t &end_val);
|
||||
int gen_column_cmp_node(const ObRawExpr &l_expr,
|
||||
const ObRawExpr &r_expr,
|
||||
ObItemType cmp_type,
|
||||
const ObExprResType &result_type,
|
||||
int64_t expr_depth,
|
||||
bool null_safe,
|
||||
ObRangeNode *&range_node);
|
||||
int gen_row_column_cmp_node(const ObIArray<const ObColumnRefRawExpr*> &l_exprs,
|
||||
const ObIArray<const ObRawExpr*> &r_exprs,
|
||||
ObItemType cmp_type,
|
||||
const ObIArray<const ObExprCalcType*> &calc_types,
|
||||
int64_t expr_depth,
|
||||
int64_t row_dim,
|
||||
bool null_safe,
|
||||
ObRangeNode *&range_node);
|
||||
int get_rowid_node(const ObRawExpr &l_expr,
|
||||
const ObRawExpr &r_expr,
|
||||
ObItemType cmp_type,
|
||||
ObRangeNode *&range_node);
|
||||
int get_extract_rowid_range_infos(const ObRawExpr &calc_urowid_expr,
|
||||
ObIArray<const ObColumnRefRawExpr*> &pk_columns,
|
||||
bool &is_physical_rowid,
|
||||
uint64_t &part_column_id);
|
||||
int get_single_in_range_node(const ObColumnRefRawExpr *column_expr,
|
||||
const ObRawExpr *r_expr,
|
||||
const ObExprResType &res_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int get_row_in_range_ndoe(const ObRawExpr &l_expr,
|
||||
const ObRawExpr &r_expr,
|
||||
const ObExprResType &res_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int get_single_rowid_in_range_node(const ObRawExpr &rowid_expr,
|
||||
const ObRawExpr &row_expr,
|
||||
ObRangeNode *&range_node);
|
||||
int convert_not_in_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int get_single_not_in_range_node(const ObColumnRefRawExpr *column_expr,
|
||||
const ObRawExpr *r_expr,
|
||||
const ObExprResType &res_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int get_nvl_cmp_node(const ObRawExpr &l_expr,
|
||||
const ObRawExpr &r_expr,
|
||||
ObItemType cmp_type,
|
||||
const ObExprResType &result_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int gen_is_null_range_node(const ObRawExpr *l_expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
|
||||
int check_escape_valid(const ObRawExpr *escape, char &escape_ch, bool &is_valid);
|
||||
int build_decode_like_expr(ObRawExpr *pattern, ObRawExpr *escape, char escape_ch,
|
||||
ObRangeColumnMeta *column_meta, int64_t &start_val_idx, int64_t &end_val_idx);
|
||||
int get_calculable_expr_val(const ObRawExpr *expr, ObObj &val, bool &is_valid, const bool ignore_error = true);
|
||||
int check_calculable_expr_valid(const ObRawExpr *expr, bool &is_valid, const bool ignore_error = true);
|
||||
int add_precise_constraint(const ObRawExpr *expr, bool is_precise);
|
||||
int add_prefix_pattern_constraint(const ObRawExpr *expr);
|
||||
int get_final_expr_idx(const ObRawExpr *expr,
|
||||
const ObRangeColumnMeta *column_meta,
|
||||
int64_t &idx);
|
||||
int get_final_in_array_idx(InParam *&in_param, int64_t &idx);
|
||||
bool is_range_key(const uint64_t column_id, int64_t &key_idx);
|
||||
ObRangeColumnMeta* get_column_meta(int64_t idx);
|
||||
int try_wrap_lob_with_substr(const ObRawExpr *expr,
|
||||
const ObRangeColumnMeta *column_meta,
|
||||
const ObRawExpr *&out_expr);
|
||||
int set_column_flags(int64_t key_idx, ObItemType type);
|
||||
static int get_domain_extra_item(const common::ObDomainOpType op_type,
|
||||
const ObRawExpr *expr,
|
||||
const ObConstRawExpr *&extra_item);
|
||||
int convert_geo_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int get_geo_range_node(const ObColumnRefRawExpr *column_expr,
|
||||
common::ObDomainOpType geo_type,
|
||||
const ObRawExpr* wkb_expr,
|
||||
const ObRawExpr *distance_expr,
|
||||
ObRangeNode *&range_node);
|
||||
int fill_range_node_for_geo_node(const int64_t key_idx,
|
||||
common::ObDomainOpType geo_type,
|
||||
uint32_t srid,
|
||||
const int64_t start_val_idx,
|
||||
const int64_t end_val_idx,
|
||||
ObRangeNode &range_node) const;
|
||||
int get_implicit_cast_range(const ObRawExpr &l_expr,
|
||||
const ObRawExpr &r_expr,
|
||||
ObItemType cmp_type,
|
||||
const ObExprResType &result_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int gen_implicit_cast_range(const ObColumnRefRawExpr *column_expr,
|
||||
const ObRawExpr *const_expr,
|
||||
ObItemType cmp_type,
|
||||
const ObExprResType &result_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int build_double_to_int_expr(const ObRawExpr *double_expr,
|
||||
bool is_start,
|
||||
ObItemType cmp_type,
|
||||
bool is_unsigned,
|
||||
bool is_decimal,
|
||||
const ObRawExpr *&out_expr);
|
||||
int get_row_cmp_node(const ObRawExpr &l_expr,
|
||||
const ObRawExpr &r_expr,
|
||||
ObItemType cmp_type,
|
||||
const ObExprResType &result_type,
|
||||
int64_t expr_depth,
|
||||
ObRangeNode *&range_node);
|
||||
int gen_row_implicit_cast_range(const ObIArray<const ObColumnRefRawExpr*> &column_exprs,
|
||||
const ObIArray<const ObRawExpr*> &const_exprs,
|
||||
ObItemType cmp_type,
|
||||
const ObIArray<const ObExprCalcType*> &calc_types,
|
||||
ObIArray<int64_t> &implicit_cast_idxs,
|
||||
int64_t expr_depth,
|
||||
int64_t row_dim,
|
||||
ObRangeNode *&range_node);
|
||||
int build_decimal_to_year_expr(const ObRawExpr *decimal_expr,
|
||||
bool is_start,
|
||||
ObItemType cmp_type,
|
||||
const ObRawExpr *&out_expr);
|
||||
|
||||
int build_implicit_cast_range_expr(const ObColumnRefRawExpr *column_expr,
|
||||
const ObRawExpr *const_expr,
|
||||
ObItemType cmp_type,
|
||||
bool is_start,
|
||||
const ObRawExpr *&out_expr);
|
||||
int can_extract_implicit_cast_range(const ObColumnRefRawExpr &column_expr,
|
||||
const ObRawExpr &const_expr,
|
||||
bool &can_extract);
|
||||
int check_can_use_range_get(const ObRawExpr &const_expr,
|
||||
const ObRangeColumnMeta &column_meta);
|
||||
int set_extract_implicit_is_precise(const ObColumnRefRawExpr &column_expr,
|
||||
const ObRawExpr &const_expr,
|
||||
ObItemType cmp_type,
|
||||
bool &is_precise);
|
||||
int convert_domain_expr(const ObRawExpr *expr, int64_t expr_depth, ObRangeNode *&range_node);
|
||||
int need_extract_domain_range(const ObOpRawExpr &domain_expr, bool& need_extract);
|
||||
int check_decimal_int_range_cmp_valid(const ObRawExpr *const_expr, bool &is_valid);
|
||||
private:
|
||||
ObIAllocator &allocator_;
|
||||
ObQueryRangeCtx &ctx_;
|
||||
const int64_t mem_used_;
|
||||
};
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
#endif // OCEANBASE_SQL_REWRITE_OB_QUERY_RANGE_DEFINE_H_
|
@ -79,6 +79,7 @@ ObQueryRange::ObQueryRange()
|
||||
key_part_store_(allocator_),
|
||||
range_exprs_(allocator_),
|
||||
ss_range_exprs_(allocator_),
|
||||
unprecise_range_exprs_(allocator_),
|
||||
mbr_filters_(allocator_),
|
||||
has_exec_param_(false),
|
||||
is_equal_and_(false),
|
||||
@ -104,6 +105,7 @@ ObQueryRange::ObQueryRange(ObIAllocator &alloc)
|
||||
key_part_store_(allocator_),
|
||||
range_exprs_(allocator_),
|
||||
ss_range_exprs_(allocator_),
|
||||
unprecise_range_exprs_(allocator_),
|
||||
mbr_filters_(allocator_),
|
||||
has_exec_param_(false),
|
||||
is_equal_and_(false),
|
||||
@ -147,6 +149,7 @@ void ObQueryRange::reset()
|
||||
table_graph_.reset();
|
||||
range_exprs_.reset();
|
||||
ss_range_exprs_.reset();
|
||||
unprecise_range_exprs_.reset();
|
||||
inner_allocator_.reset();
|
||||
has_exec_param_ = false;
|
||||
is_equal_and_ = false;
|
||||
@ -1302,6 +1305,7 @@ int ObQueryRange::fill_range_exprs(const int64_t max_precise_pos,
|
||||
} else {
|
||||
ObSEArray<ObRawExpr*, 4> range_exprs;
|
||||
ObSEArray<ObRawExpr*, 4> ss_range_exprs;
|
||||
ObSEArray<ObRawExpr*, 4> unprecise_range_exprs;
|
||||
bool precise = true;
|
||||
bool ss_precise = true;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < query_range_ctx_->precise_range_exprs_.count(); ++i) {
|
||||
@ -1330,6 +1334,8 @@ int ObQueryRange::fill_range_exprs(const int64_t max_precise_pos,
|
||||
LOG_WARN("failed to assign range exprs", K(ret));
|
||||
} else if (OB_FAIL(ss_range_exprs_.assign(ss_range_exprs))) {
|
||||
LOG_WARN("failed to assign skip scan range exprs", K(ret));
|
||||
} else if (OB_FAIL(unprecise_range_exprs_.assign(unprecise_range_exprs))) {
|
||||
LOG_WARN("failed to assign unprecise range exprs", K(ret));
|
||||
} else {
|
||||
LOG_DEBUG("finish fill range exprs", K(max_precise_pos), K(range_exprs));
|
||||
LOG_DEBUG("finish fill skip scan range exprs", K(ss_offset), K(ss_max_precise_pos), K(ss_range_exprs));
|
||||
@ -7518,6 +7524,25 @@ int ObQueryRange::get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
ObIArray<common::ObSpatialMBR> &mbr_filters) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(mbr_filters);
|
||||
if (OB_FAIL(get_tablet_ranges(allocator,
|
||||
exec_ctx,
|
||||
ranges,
|
||||
all_single_value_ranges,
|
||||
dtc_params))) {
|
||||
LOG_WARN("failed to get tablet ranges", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::get_ss_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ss_ranges,
|
||||
@ -7543,6 +7568,26 @@ int ObQueryRange::get_ss_tablet_ranges(common::ObIAllocator &allocator,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::get_fast_nlj_tablet_ranges(ObFastFinalNLJRangeCtx &fast_nlj_range_ctx,
|
||||
common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
const ParamStore ¶m_store,
|
||||
void *range_buffer,
|
||||
ObQueryRangeArray &ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const
|
||||
{
|
||||
int ret = OB_NOT_SUPPORTED;
|
||||
UNUSED(fast_nlj_range_ctx);
|
||||
UNUSED(allocator);
|
||||
UNUSED(exec_ctx);
|
||||
UNUSED(param_store);
|
||||
UNUSED(range_buffer);
|
||||
UNUSED(ranges);
|
||||
UNUSED(dtc_params);
|
||||
LOG_WARN("old qeury range not support this interface");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::ObSearchState::tailor_final_range(int64_t column_count)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -9121,6 +9166,8 @@ OB_NOINLINE int ObQueryRange::deep_copy(const ObQueryRange &other,
|
||||
LOG_WARN("assign range exprs failed", K(ret));
|
||||
} else if (OB_FAIL(ss_range_exprs_.assign(other.ss_range_exprs_))) {
|
||||
LOG_WARN("assign range exprs failed", K(ret));
|
||||
} else if (OB_FAIL(unprecise_range_exprs_.assign(other.unprecise_range_exprs_))) {
|
||||
LOG_WARN("assign unprecise range exprs failed", K(ret));
|
||||
} else if (OB_FAIL(table_graph_.assign(other_graph))) {
|
||||
LOG_WARN("Deep copy range columns failed", K(ret));
|
||||
} else if (OB_FAIL(equal_offs_.assign(other.equal_offs_))) {
|
||||
@ -9737,7 +9784,7 @@ DEF_TO_STRING(ObQueryRange::ObRangeExprItem)
|
||||
return pos;
|
||||
}
|
||||
|
||||
common::ObDomainOpType ObQueryRange::get_geo_relation(ObItemType type) const
|
||||
common::ObDomainOpType ObQueryRange::get_geo_relation(ObItemType type)
|
||||
{
|
||||
common::ObDomainOpType rel_type = common::ObDomainOpType::T_INVALID;
|
||||
switch (type) {
|
||||
@ -9760,6 +9807,14 @@ common::ObDomainOpType ObQueryRange::get_geo_relation(ObItemType type) const
|
||||
rel_type = common::ObDomainOpType::T_GEO_COVEREDBY;
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_ST_CROSSES : {
|
||||
rel_type = common::ObDomainOpType::T_GEO_INTERSECTS;
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_ST_OVERLAPS : {
|
||||
rel_type = common::ObDomainOpType::T_GEO_INTERSECTS;
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_SDO_RELATE : {
|
||||
rel_type = common::ObDomainOpType::T_GEO_RELATE;
|
||||
break;
|
||||
@ -9770,7 +9825,7 @@ common::ObDomainOpType ObQueryRange::get_geo_relation(ObItemType type) const
|
||||
return rel_type;
|
||||
}
|
||||
|
||||
common::ObDomainOpType ObQueryRange::get_domain_op_type(ObItemType type) const
|
||||
common::ObDomainOpType ObQueryRange::get_domain_op_type(ObItemType type)
|
||||
{
|
||||
common::ObDomainOpType rel_type = common::ObDomainOpType::T_INVALID;
|
||||
switch (type) {
|
||||
@ -10271,7 +10326,6 @@ int ObQueryRange::get_geo_range(const common::ObObj &wkb, const common::ObDomain
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -10294,5 +10348,57 @@ int ObQueryRange::set_columnId_map(uint64_t columnId, const ObGeoColumnInfo &col
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::get_prefix_info(int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(get_table_grapth().key_part_head_)) {
|
||||
ret = OB_NOT_INIT;
|
||||
LOG_WARN("table_graph.key_part_head_ is not inited.", K(ret));
|
||||
} else {
|
||||
inner_get_prefix_info(get_table_grapth().key_part_head_,
|
||||
equal_prefix_count,
|
||||
range_prefix_count,
|
||||
contain_always_false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObQueryRange::inner_get_prefix_info(const ObKeyPart *key_part,
|
||||
int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false) const
|
||||
{
|
||||
if (OB_NOT_NULL(key_part)) {
|
||||
equal_prefix_count = OB_USER_MAX_ROWKEY_COLUMN_NUMBER;
|
||||
range_prefix_count = OB_USER_MAX_ROWKEY_COLUMN_NUMBER;
|
||||
for ( /*do nothing*/ ; NULL != key_part; key_part = key_part->or_next_) {
|
||||
int64_t cur_equal_prefix_count = 0;
|
||||
int64_t cur_range_prefix_count = 0;
|
||||
if (key_part->is_equal_condition()) {
|
||||
inner_get_prefix_info(key_part->and_next_,
|
||||
cur_equal_prefix_count,
|
||||
cur_range_prefix_count,
|
||||
contain_always_false);
|
||||
++cur_equal_prefix_count;
|
||||
++cur_range_prefix_count;
|
||||
} else if (key_part->is_range_condition()) {
|
||||
++cur_range_prefix_count;
|
||||
} else if (key_part->is_always_false()) {
|
||||
contain_always_false = true;
|
||||
}
|
||||
equal_prefix_count = std::min(cur_equal_prefix_count, equal_prefix_count);
|
||||
range_prefix_count = std::min(cur_range_prefix_count, range_prefix_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ObQueryRange::get_total_range_sizes(common::ObIArray<uint64_t> &total_range_sizes) const
|
||||
{
|
||||
UNUSED(total_range_sizes);
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
@ -376,6 +376,8 @@ public:
|
||||
|
||||
void reset();
|
||||
|
||||
virtual inline bool is_new_query_range() const { return false; }
|
||||
|
||||
// preliminary_extract_query_range will preliminary extract query range
|
||||
// from query conditions, which is only occurred in generating the physical plan.
|
||||
// During this stage, some consts are not really known, for example,
|
||||
@ -440,15 +442,28 @@ public:
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
int get_ss_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ss_ranges,
|
||||
const ObDataTypeCastParams &dtc_params) const;
|
||||
int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
virtual int get_ss_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ss_ranges,
|
||||
const ObDataTypeCastParams &dtc_params) const;
|
||||
virtual int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
virtual int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
ObIArray<common::ObSpatialMBR> &mbr_filters) const;
|
||||
virtual int get_fast_nlj_tablet_ranges(ObFastFinalNLJRangeCtx &fast_nlj_range_ctx,
|
||||
common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
const ParamStore ¶m_store,
|
||||
void *range_buffer,
|
||||
ObQueryRangeArray &ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
// deep copy query range except the pointer of phy_plan_
|
||||
int deep_copy(const ObQueryRange &other, const bool copy_for_final = false);
|
||||
// necessary condition:
|
||||
@ -458,7 +473,7 @@ public:
|
||||
// or maybe all ranges are get-conditions after final extraction.
|
||||
|
||||
// USE only in test.
|
||||
bool is_precise_whole_range() const
|
||||
virtual bool is_precise_whole_range() const
|
||||
{
|
||||
bool bret = false;
|
||||
if (NULL == table_graph_.key_part_head_) {
|
||||
@ -470,13 +485,14 @@ public:
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
int is_get(bool &is_get) const;
|
||||
virtual int is_get(bool &is_get) const;
|
||||
int is_get(int64_t column_count, bool &is_get) const;
|
||||
bool is_precise_get() const { return table_graph_.is_precise_get_; }
|
||||
common::ObDomainOpType get_geo_relation(ObItemType type) const;
|
||||
common::ObDomainOpType get_domain_op_type(ObItemType type) const;
|
||||
const common::ObIArray<ObRawExpr*> &get_range_exprs() const { return range_exprs_; }
|
||||
const common::ObIArray<ObRawExpr*> &get_ss_range_exprs() const { return ss_range_exprs_; }
|
||||
virtual bool is_precise_get() const { return table_graph_.is_precise_get_; }
|
||||
static common::ObDomainOpType get_geo_relation(ObItemType type);
|
||||
static common::ObDomainOpType get_domain_op_type(ObItemType type);
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_range_exprs() const { return range_exprs_; }
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_ss_range_exprs() const { return ss_range_exprs_; }
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_unprecise_range_exprs() const { return unprecise_range_exprs_; }
|
||||
int check_graph_type(ObKeyPart &key_part_head);
|
||||
int check_skip_scan_range(ObKeyPart *key_part_head,
|
||||
const bool is_standard_range,
|
||||
@ -484,15 +500,15 @@ public:
|
||||
ObKeyPart *&ss_head,
|
||||
int64_t &skip_scan_offset,
|
||||
int64_t &ss_max_precise_pos);
|
||||
int reset_skip_scan_range();
|
||||
virtual int reset_skip_scan_range();
|
||||
bool is_precise_get(const ObKeyPart &key_part_head,
|
||||
int64_t &max_precise_pos,
|
||||
bool ignore_head = false);
|
||||
int fill_range_exprs(const int64_t max_precise_pos,
|
||||
const int64_t ss_offset,
|
||||
const int64_t ss_max_precise_pos);
|
||||
bool is_ss_range() const { return table_graph_.skip_scan_offset_ > -1; }
|
||||
int64_t get_skip_scan_offset() const { return table_graph_.skip_scan_offset_; }
|
||||
virtual bool is_ss_range() const { return table_graph_.skip_scan_offset_ > -1; }
|
||||
virtual int64_t get_skip_scan_offset() const { return table_graph_.skip_scan_offset_; }
|
||||
|
||||
static bool can_be_extract_range(ObItemType cmp_type, const ObExprResType &col_type,
|
||||
const ObExprCalcType &res_type, common::ObObjType data_type,
|
||||
@ -505,8 +521,8 @@ public:
|
||||
// need copy from ObTableScan operator to physical operator context to extract query range
|
||||
|
||||
bool need_deep_copy() const { return !table_graph_.is_standard_range_; }
|
||||
inline bool has_range() const { return column_count_ > 0; }
|
||||
inline int64_t get_column_count() const { return column_count_; }
|
||||
virtual inline bool has_range() const { return column_count_ > 0; }
|
||||
virtual inline int64_t get_column_count() const { return column_count_; }
|
||||
const ObRangeGraph &get_table_grapth() const { return table_graph_; }
|
||||
int get_result_value(common::ObObj &val, ObExecContext &exec_ctx, ObIAllocator *allocator) const;
|
||||
int get_result_value_with_rowid(const ObKeyPart &key_part,
|
||||
@ -514,7 +530,7 @@ public:
|
||||
ObExecContext &exec_ctx,
|
||||
bool &is_inconsistent_rowid,
|
||||
ObIAllocator *allocator = NULL) const;
|
||||
bool inline has_exec_param() const { return has_exec_param_; }
|
||||
virtual bool inline has_exec_param() const { return has_exec_param_; }
|
||||
bool inline get_is_equal_and() const { return is_equal_and_; }
|
||||
void inline set_is_equal_and(int64_t is_equal_and) { is_equal_and_ = is_equal_and; }
|
||||
const common::ObIArray<ObEqualOff> &get_raw_equal_offs() const { return equal_offs_; }
|
||||
@ -528,7 +544,15 @@ public:
|
||||
int set_columnId_map(uint64_t columnId, const ObGeoColumnInfo &column_info);
|
||||
MbrFilterArray &ut_get_mbr_filter() { return mbr_filters_; }
|
||||
ColumnIdInfoMap &ut_get_columnId_map() { return columnId_map_; }
|
||||
bool is_contain_geo_filters() const { return contain_geo_filters_; }
|
||||
virtual bool is_contain_geo_filters() const { return contain_geo_filters_; }
|
||||
virtual int get_prefix_info(int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false) const;
|
||||
void inner_get_prefix_info(const ObKeyPart *key_part,
|
||||
int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false) const;
|
||||
virtual bool is_fast_nlj_range() const { return false; }
|
||||
private:
|
||||
|
||||
int init_query_range_ctx(common::ObIAllocator &allocator,
|
||||
@ -1002,11 +1026,12 @@ private:
|
||||
int check_inner_row_cmp_type(const ObRawExpr *l_expr,
|
||||
const ObRawExpr *r_expr,
|
||||
bool &use_ori_cmp_type);
|
||||
|
||||
virtual int get_total_range_sizes(common::ObIArray<uint64_t> &total_range_sizes) const;
|
||||
private:
|
||||
static const int64_t RANGE_BUCKET_SIZE = 1000;
|
||||
static const int64_t MAX_RANGE_SIZE_OLD = 10000;
|
||||
static const int64_t MAX_RANGE_SIZE_NEW = 100000;
|
||||
static const int64_t MAX_NOT_IN_SIZE = 10; //do not extract range for not in row over this size
|
||||
static const int64_t MAX_JSON_ARRAY_CHANGE_TO_OR_SIZE = 10;
|
||||
typedef common::ObObjStore<ObKeyPart*, common::ObIAllocator&> KeyPartStore;
|
||||
private:
|
||||
@ -1028,6 +1053,7 @@ private:
|
||||
//this flag used by optimizer, so don't need to serialize it
|
||||
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> range_exprs_;
|
||||
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> ss_range_exprs_;
|
||||
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> unprecise_range_exprs_;
|
||||
MbrFilterArray mbr_filters_;
|
||||
bool has_exec_param_;
|
||||
bool is_equal_and_;
|
||||
|
1119
src/sql/rewrite/ob_query_range_define.cpp
Normal file
1119
src/sql/rewrite/ob_query_range_define.cpp
Normal file
File diff suppressed because it is too large
Load Diff
419
src/sql/rewrite/ob_query_range_define.h
Normal file
419
src/sql/rewrite/ob_query_range_define.h
Normal file
@ -0,0 +1,419 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
#ifndef OCEANBASE_SQL_REWRITE_OB_QUERY_RANGE_DEFINE_H_
|
||||
#define OCEANBASE_SQL_REWRITE_OB_QUERY_RANGE_DEFINE_H_
|
||||
|
||||
#include "lib/list/ob_obj_store.h"
|
||||
#include "lib/allocator/ob_allocator.h"
|
||||
#include "common/object/ob_object.h"
|
||||
#include "sql/engine/expr/ob_expr_frame_info.h"
|
||||
#include "lib/geo/ob_geo_common.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr.h"
|
||||
#include "sql/rewrite/ob_query_range_provider.h"
|
||||
#include "lib/hash/ob_placement_hashmap.h"
|
||||
#include "sql/resolver/dml/ob_dml_stmt.h"
|
||||
|
||||
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExecContext;
|
||||
|
||||
static const int64_t OB_RANGE_MAX_VALUE = INT64_MAX;
|
||||
static const int64_t OB_RANGE_MIN_VALUE = INT64_MAX - 1;
|
||||
static const int64_t OB_RANGE_EMPTY_VALUE = INT64_MAX - 2;
|
||||
static const int64_t OB_RANGE_NULL_VALUE = INT64_MAX - 3;
|
||||
static const int64_t OB_RANGE_EXTEND_VALUE = INT64_MAX - 4;
|
||||
#define PHYSICAL_ROWID_IDX UINT8_MAX
|
||||
|
||||
static const uint32_t OB_FINAL_EXPR_WITH_LOB_TRUNCATE = 1;
|
||||
|
||||
class ObPreRangeGraph;
|
||||
typedef common::ObIArray<ObExprConstraint> ExprConstrantArray;
|
||||
class ObRangeNode
|
||||
{
|
||||
OB_UNIS_VERSION(1);
|
||||
public:
|
||||
ObRangeNode(common::ObIAllocator &allocator)
|
||||
: allocator_(allocator),
|
||||
flags_(0),
|
||||
column_cnt_(0),
|
||||
start_keys_(nullptr),
|
||||
end_keys_(nullptr),
|
||||
min_offset_(-1),
|
||||
max_offset_(-1),
|
||||
in_param_count_(0),
|
||||
node_id_(-1),
|
||||
or_next_(nullptr),
|
||||
and_next_(nullptr) {}
|
||||
~ObRangeNode() { reset(); }
|
||||
void reset();
|
||||
void set_always_true();
|
||||
void set_always_false();
|
||||
int deep_copy(const ObRangeNode &other);
|
||||
DECLARE_TO_STRING;
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObRangeNode);
|
||||
public:
|
||||
common::ObIAllocator &allocator_;
|
||||
union {
|
||||
uint32_t flags_;
|
||||
struct {
|
||||
uint32_t always_true_: 1;
|
||||
uint32_t always_false_: 1;
|
||||
uint32_t include_start_: 1;
|
||||
uint32_t include_end_: 1;
|
||||
uint32_t contain_in_: 1;
|
||||
uint32_t is_phy_rowid_: 1;
|
||||
uint32_t is_domain_node_: 1;
|
||||
uint32_t is_not_in_node_: 1;
|
||||
uint32_t reserved_: 24;
|
||||
};
|
||||
};
|
||||
int64_t column_cnt_;
|
||||
int64_t* start_keys_;
|
||||
int64_t* end_keys_;
|
||||
int64_t min_offset_;
|
||||
int64_t max_offset_;
|
||||
union {
|
||||
int64_t in_param_count_;
|
||||
struct {
|
||||
uint32_t srid_;
|
||||
int32_t domain_releation_type_;
|
||||
} domain_extra_;
|
||||
};
|
||||
int64_t node_id_;
|
||||
//list member
|
||||
ObRangeNode *or_next_;
|
||||
ObRangeNode *and_next_;
|
||||
};
|
||||
|
||||
typedef common::ObFixedArray<int64_t, common::ObIAllocator> InParam;
|
||||
|
||||
struct ObRangeMap
|
||||
{
|
||||
OB_UNIS_VERSION(1);
|
||||
public:
|
||||
struct ExprFinalInfo {
|
||||
ExprFinalInfo()
|
||||
: flags_(0),
|
||||
param_idx_(OB_INVALID_ID)
|
||||
{}
|
||||
union {
|
||||
uint32_t flags_;
|
||||
struct {
|
||||
uint32_t is_param_: 1;
|
||||
uint32_t is_const_: 1;
|
||||
uint32_t is_expr_: 1;
|
||||
uint32_t null_safe_: 1;
|
||||
/**
|
||||
* rowid_idx_ =
|
||||
* 0 : current final info is not rowid
|
||||
* 1-129 : current final info is logical rowid
|
||||
* 255 : current final info is physical rowid
|
||||
*/
|
||||
uint32_t rowid_idx_: 8;
|
||||
uint32_t is_not_first_col_in_row_: 1;
|
||||
uint32_t reserved_: 19;
|
||||
};
|
||||
};
|
||||
union {
|
||||
int64_t param_idx_;
|
||||
common::ObObj* const_val_;
|
||||
ObTempExpr *temp_expr_;
|
||||
};
|
||||
TO_STRING_KV(K_(flags));
|
||||
};
|
||||
public:
|
||||
ObRangeMap(common::ObIAllocator &alloc)
|
||||
: allocator_(alloc),
|
||||
expr_final_infos_(alloc),
|
||||
in_params_(alloc)
|
||||
{}
|
||||
TO_STRING_KV(K_(expr_final_infos));
|
||||
common::ObIAllocator &allocator_;
|
||||
common::ObFixedArray<ExprFinalInfo, common::ObIAllocator> expr_final_infos_;
|
||||
common::ObFixedArray<InParam*, common::ObIAllocator> in_params_;
|
||||
};
|
||||
|
||||
class ObRangeColumnMeta
|
||||
{
|
||||
OB_UNIS_VERSION(1);
|
||||
public:
|
||||
ObRangeColumnMeta()
|
||||
: column_type_()
|
||||
{}
|
||||
|
||||
ObRangeColumnMeta(ObExprResType type)
|
||||
: column_type_(type)
|
||||
{}
|
||||
|
||||
TO_STRING_KV(N_COLUMN_TYPE, column_type_);
|
||||
|
||||
ObExprResType column_type_;
|
||||
};
|
||||
|
||||
struct ObQueryRangeCtx
|
||||
{
|
||||
ObQueryRangeCtx(ObExecContext *exec_ctx)
|
||||
: column_cnt_(0),
|
||||
need_final_extract_(false),
|
||||
cur_is_precise_(false),
|
||||
phy_rowid_for_table_loc_(false),
|
||||
ignore_calc_failure_(false),
|
||||
refresh_max_offset_(false),
|
||||
exec_ctx_(exec_ctx),
|
||||
expr_constraints_(nullptr),
|
||||
params_(nullptr),
|
||||
expr_factory_(nullptr),
|
||||
session_info_(nullptr),
|
||||
geo_column_id_map_(nullptr),
|
||||
max_mem_size_(128*1024*1024),
|
||||
enable_not_in_range_(true),
|
||||
optimizer_features_enable_version_(0),
|
||||
index_prefix_(-1),
|
||||
is_geo_range_(false),
|
||||
can_range_get_(true),
|
||||
contail_geo_filters_(false) {}
|
||||
~ObQueryRangeCtx() {}
|
||||
int init(ObPreRangeGraph *pre_range_graph,
|
||||
const ObIArray<ColumnItem> &range_columns,
|
||||
ExprConstrantArray *expr_constraints,
|
||||
const ParamStore *params,
|
||||
ObRawExprFactory *expr_factory,
|
||||
const bool phy_rowid_for_table_loc,
|
||||
const bool ignore_calc_failure,
|
||||
const int64_t index_prefix,
|
||||
const ColumnIdInfoMap *geo_column_id_map);
|
||||
int64_t column_cnt_;
|
||||
// 131 is the next prime number larger than OB_MAX_ROWKEY_COLUMN_NUMBER
|
||||
common::hash::ObPlacementHashMap<int64_t, int64_t, 131> range_column_map_;
|
||||
bool need_final_extract_;
|
||||
// current expr can generate precise range
|
||||
bool cur_is_precise_;
|
||||
bool phy_rowid_for_table_loc_;
|
||||
bool ignore_calc_failure_;
|
||||
bool refresh_max_offset_;
|
||||
ObExecContext *exec_ctx_;
|
||||
ExprConstrantArray *expr_constraints_;
|
||||
const common::ParamStore *params_;
|
||||
ObRawExprFactory *expr_factory_;
|
||||
ObSQLSessionInfo *session_info_;
|
||||
common::ObSEArray<const ObRawExpr *, 16> final_exprs_;
|
||||
common::ObSEArray<uint32_t, 16> final_exprs_flag_;
|
||||
common::ObSEArray<InParam*, 4> in_params_;
|
||||
common::ObSEArray<int64_t, 16> null_safe_value_idxs_;
|
||||
common::ObSEArray<ObRangeColumnMeta*, 4> column_metas_;
|
||||
common::ObSEArray<std::pair<int64_t, int64_t>, 16> rowid_idxs_;
|
||||
common::ObSEArray<int64_t, 4> column_flags_;
|
||||
common::ObSEArray<int64_t, 16> non_first_in_row_value_idxs_;
|
||||
const ColumnIdInfoMap *geo_column_id_map_;
|
||||
int64_t max_mem_size_;
|
||||
bool enable_not_in_range_;
|
||||
uint64_t optimizer_features_enable_version_;
|
||||
int64_t index_prefix_;
|
||||
bool is_geo_range_;
|
||||
bool can_range_get_;
|
||||
bool contail_geo_filters_;
|
||||
};
|
||||
|
||||
class ObPreRangeGraph : public ObQueryRangeProvider
|
||||
{
|
||||
OB_UNIS_VERSION(1);
|
||||
public:
|
||||
ObPreRangeGraph(ObIAllocator &alloc)
|
||||
: allocator_(alloc),
|
||||
table_id_(OB_INVALID_ID),
|
||||
column_count_(0),
|
||||
range_size_(0),
|
||||
node_count_(0),
|
||||
node_head_(nullptr),
|
||||
is_standard_range_(false),
|
||||
is_precise_get_(false),
|
||||
is_equal_range_(false),
|
||||
is_get_(false),
|
||||
contain_exec_param_(false),
|
||||
column_metas_(alloc),
|
||||
range_map_(alloc),
|
||||
skip_scan_offset_(-1),
|
||||
range_exprs_(alloc),
|
||||
ss_range_exprs_(alloc),
|
||||
unprecise_range_exprs_(alloc),
|
||||
total_range_sizes_(alloc),
|
||||
range_expr_max_offsets_(alloc),
|
||||
flags_(0) {}
|
||||
|
||||
virtual ~ObPreRangeGraph() { reset(); }
|
||||
|
||||
void reset();
|
||||
virtual inline bool is_new_query_range() const { return true; }
|
||||
virtual int deep_copy(const ObPreRangeGraph &other);
|
||||
|
||||
int deep_copy_range_graph(ObRangeNode *src_node);
|
||||
int inner_deep_copy_range_graph(ObRangeNode *range_node,
|
||||
ObIArray<ObRangeNode*> &range_nodes,
|
||||
ObIArray<std::pair<int64_t, int64_t>> &ptr_pairs);
|
||||
int deep_copy_column_metas(const ObIArray<ObRangeColumnMeta*> &src_metas);
|
||||
int deep_copy_range_map(const ObRangeMap &src_range_map);
|
||||
|
||||
virtual int preliminary_extract_query_range(const ObIArray<ColumnItem> &range_columns,
|
||||
const ObIArray<ObRawExpr*> &root_exprs,
|
||||
ObExecContext *exec_ctx,
|
||||
ExprConstrantArray *expr_constraints = NULL,
|
||||
const ParamStore *params = NULL,
|
||||
const bool phy_rowid_for_table_loc = false,
|
||||
const bool ignore_calc_failure = true,
|
||||
const int64_t index_prefix = -1,
|
||||
const ColumnIdInfoMap *geo_column_id_map = NULL);
|
||||
virtual int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
virtual int get_tablet_ranges(ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params);
|
||||
virtual int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
ObIArray<common::ObSpatialMBR> &mbr_filters) const;
|
||||
virtual int get_fast_nlj_tablet_ranges(ObFastFinalNLJRangeCtx &fast_nlj_range_ctx,
|
||||
common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
const ParamStore ¶m_store,
|
||||
void *range_buffer,
|
||||
ObQueryRangeArray &ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
int fill_column_metas(const ObIArray<ColumnItem> &range_columns);
|
||||
virtual int get_ss_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ss_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const;
|
||||
virtual bool is_precise_whole_range() const { return (nullptr == node_head_) || (node_head_->always_true_); }
|
||||
virtual int is_get(bool &is_get) const
|
||||
{
|
||||
is_get = is_get_;
|
||||
return common::OB_SUCCESS;
|
||||
}
|
||||
virtual bool is_precise_get() const { return is_precise_get_; }
|
||||
bool is_standard_range() const { return is_standard_range_; }
|
||||
bool is_equal_range() const { return is_equal_range_; }
|
||||
virtual int64_t get_column_count() const { return column_count_; }
|
||||
virtual bool has_exec_param() const { return contain_exec_param_; }
|
||||
virtual bool is_ss_range() const { return skip_scan_offset_ > -1; }
|
||||
virtual int64_t get_skip_scan_offset() const { return skip_scan_offset_; }
|
||||
virtual int reset_skip_scan_range()
|
||||
{
|
||||
skip_scan_offset_ = -1;
|
||||
return common::OB_SUCCESS;
|
||||
}
|
||||
virtual inline bool has_range() const { return column_count_ > 0; }
|
||||
virtual bool is_contain_geo_filters() const { return contain_geo_filters_; }
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_range_exprs() const { return range_exprs_; }
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_ss_range_exprs() const { return ss_range_exprs_; }
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_unprecise_range_exprs() const { return unprecise_range_exprs_; }
|
||||
virtual int get_prefix_info(int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false) const;
|
||||
virtual int get_total_range_sizes(common::ObIArray<uint64_t> &total_range_sizes) const;
|
||||
|
||||
const ObIArray<uint64_t>& get_range_sizes() const { return total_range_sizes_; }
|
||||
virtual bool is_fast_nlj_range() const { return fast_nlj_range_; }
|
||||
int get_prefix_info(const ObRangeNode *range_node,
|
||||
bool* equals,
|
||||
int64_t &equal_prefix_count) const;
|
||||
int get_new_equal_idx(const ObRangeNode *range_node,
|
||||
bool* equals,
|
||||
ObIArray<int64_t> &new_idx) const;
|
||||
|
||||
ObRangeNode* get_range_head() { return node_head_; }
|
||||
const ObRangeNode* get_range_head() const { return node_head_; }
|
||||
uint64_t get_table_id() const { return table_id_; }
|
||||
uint64_t get_range_size() const { return range_size_; }
|
||||
uint64_t get_node_count() const { return node_count_; }
|
||||
int64_t get_column_cnt() const { return column_count_; }
|
||||
ObIArray<ObRangeColumnMeta*>& get_column_metas() { return column_metas_; }
|
||||
ObRangeColumnMeta* get_column_meta(int64_t idx) { return column_metas_.at(idx); }
|
||||
const ObRangeColumnMeta* get_column_meta(int64_t idx) const { return column_metas_.at(idx); }
|
||||
ObRangeMap& get_range_map() { return range_map_; }
|
||||
const ObRangeMap& get_range_map() const { return range_map_; }
|
||||
void set_table_id(const uint64_t v) { table_id_ = v; }
|
||||
void set_range_size(const uint64_t v) { range_size_ = v; }
|
||||
void set_node_count(const uint64_t v) { node_count_ = v; }
|
||||
void set_range_head(ObRangeNode* head) { node_head_ = head; }
|
||||
void set_is_standard_range(const bool v) { is_standard_range_ = v; }
|
||||
void set_is_precise_get(const bool v) { is_precise_get_ = v; }
|
||||
void set_is_equal_range(const bool v) { is_equal_range_ = v; }
|
||||
void set_is_get(const bool v) { is_get_ = v; }
|
||||
void set_contain_exec_param(const bool v) { contain_exec_param_ = v; }
|
||||
void set_skip_scan_offset(int64_t v) { skip_scan_offset_ = v; }
|
||||
int set_range_exprs(ObIArray<ObRawExpr*> &range_exprs) { return range_exprs_.assign(range_exprs); }
|
||||
int set_ss_range_exprs(ObIArray<ObRawExpr*> &range_exprs) { return ss_range_exprs_.assign(range_exprs); }
|
||||
int set_unprecise_range_exprs(ObIArray<ObRawExpr*> &range_exprs) { return unprecise_range_exprs_.assign(range_exprs); }
|
||||
void set_fast_nlj_range(bool v) { fast_nlj_range_ = v; }
|
||||
|
||||
int serialize_range_graph(ObRangeNode *range_node, char *buf,
|
||||
int64_t buf_len, int64_t &pos) const;
|
||||
int deserialize_range_graph(ObRangeNode *&range_node, const char *buf,
|
||||
int64_t data_len, int64_t &pos);
|
||||
int64_t get_serialize_size_range_graph(const ObRangeNode *range_node) const;
|
||||
DECLARE_TO_STRING;
|
||||
int64_t range_graph_to_string(char *buf, const int64_t buf_len,
|
||||
ObRangeNode *range_node) const;
|
||||
int64_t set_total_range_sizes(uint64_t* total_range_sizes, int64_t count);
|
||||
void set_contain_geo_filters(bool v) { contain_geo_filters_ = v; }
|
||||
int64_t set_range_expr_max_offsets(const ObIArray<int64_t> &max_offsets) { return range_expr_max_offsets_.assign(max_offsets); }
|
||||
const ObIArray<int64_t>& get_range_expr_max_offsets() const { return range_expr_max_offsets_; }
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObPreRangeGraph);
|
||||
private:
|
||||
common::ObIAllocator &allocator_;
|
||||
uint64_t table_id_;
|
||||
int64_t column_count_;
|
||||
uint64_t range_size_;
|
||||
uint64_t node_count_;
|
||||
ObRangeNode *node_head_;
|
||||
// one range for all columns
|
||||
bool is_standard_range_;
|
||||
// one equal range for all columns. e.g. [1,2,3; 1,2,3]
|
||||
bool is_precise_get_;
|
||||
// one or more equal range for partial columns. e.g. (1,2,min; 1,2,max), (3,4,min; 3,4,max)
|
||||
bool is_equal_range_;
|
||||
// one or more equal range for all columns. e.g. [1,2,3; 1,2,3], [4,5,6; 4,5,6]
|
||||
bool is_get_;
|
||||
bool contain_exec_param_;
|
||||
common::ObFixedArray<ObRangeColumnMeta*, common::ObIAllocator> column_metas_;
|
||||
ObRangeMap range_map_;
|
||||
int64_t skip_scan_offset_;
|
||||
// only used by optimizer, don't need to serialize it
|
||||
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> range_exprs_;
|
||||
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> ss_range_exprs_;
|
||||
common::ObFixedArray<ObRawExpr*, common::ObIAllocator> unprecise_range_exprs_;
|
||||
common::ObFixedArray<uint64_t, common::ObIAllocator> total_range_sizes_;
|
||||
common::ObFixedArray<int64_t, common::ObIAllocator> range_expr_max_offsets_;
|
||||
union {
|
||||
uint32_t flags_;
|
||||
struct {
|
||||
uint32_t contain_geo_filters_ : 1;
|
||||
uint32_t fast_nlj_range_ : 1;
|
||||
uint32_t reserved_ : 30;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
#endif // OCEANBASE_SQL_REWRITE_OB_QUERY_RANGE_DEFINE_H_
|
@ -16,7 +16,7 @@
|
||||
#include "lib/container/ob_array.h"
|
||||
#include "lib/container/ob_se_array.h"
|
||||
#include "common/ob_range.h"
|
||||
|
||||
#include "lib/geo/ob_s2adapter.h"
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace common
|
||||
@ -26,24 +26,78 @@ struct ObDataTypeCastParams;
|
||||
namespace sql
|
||||
{
|
||||
struct ColumnItem;
|
||||
class ObRawExpr;
|
||||
typedef common::ObSEArray<common::ObNewRange *, 1> ObQueryRangeArray;
|
||||
typedef common::ObSEArray<common::ObNewRange, 4, common::ModulePageAllocator, true> ObRangesArray;
|
||||
typedef common::ObSEArray<ColumnItem, 16, common::ModulePageAllocator, true> ColumnArray;
|
||||
static const int64_t MAX_NOT_IN_SIZE = 10; //do not extract range for not in row over this size
|
||||
static const int64_t NEW_MAX_NOT_IN_SIZE = 1000; // mysql support 1000 not in range node
|
||||
|
||||
struct ObFastFinalNLJRangeCtx
|
||||
{
|
||||
ObFastFinalNLJRangeCtx()
|
||||
: has_check_valid(false),
|
||||
is_valid(false) {}
|
||||
|
||||
bool has_check_valid;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
class ObQueryRangeProvider
|
||||
{
|
||||
public:
|
||||
virtual ~ObQueryRangeProvider() {}
|
||||
virtual bool is_new_query_range() const = 0;
|
||||
virtual int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const = 0;
|
||||
virtual int get_tablet_ranges(ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) = 0;
|
||||
virtual int get_ss_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ss_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const = 0;
|
||||
virtual int get_tablet_ranges(common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
ObQueryRangeArray &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
ObIArray<common::ObSpatialMBR> &mbr_filters) const = 0;
|
||||
virtual int get_fast_nlj_tablet_ranges(ObFastFinalNLJRangeCtx &fast_nlj_range_ctx,
|
||||
common::ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
const ParamStore ¶m_store,
|
||||
void *range_buffer,
|
||||
ObQueryRangeArray &ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params) const = 0;
|
||||
virtual bool is_precise_whole_range() const = 0;
|
||||
virtual int is_get(bool &is_get) const = 0;
|
||||
virtual bool is_precise_get() const = 0;
|
||||
virtual int64_t get_column_count() const = 0;
|
||||
virtual bool has_exec_param() const = 0;
|
||||
virtual bool is_ss_range() const = 0;
|
||||
virtual int64_t get_skip_scan_offset() const = 0;
|
||||
virtual int reset_skip_scan_range() = 0;
|
||||
virtual bool has_range() const = 0;
|
||||
virtual bool is_contain_geo_filters() const = 0;
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_range_exprs() const = 0;
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_ss_range_exprs() const = 0;
|
||||
virtual const common::ObIArray<ObRawExpr*> &get_unprecise_range_exprs() const = 0;
|
||||
virtual int get_prefix_info(int64_t &equal_prefix_count,
|
||||
int64_t &range_prefix_count,
|
||||
bool &contain_always_false) const = 0;
|
||||
|
||||
// to string
|
||||
virtual int64_t to_string(char *buf, const int64_t buf_len) const = 0;
|
||||
virtual int get_total_range_sizes(common::ObIArray<uint64_t> &total_range_sizes) const = 0;
|
||||
virtual bool is_fast_nlj_range() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif //OCEANBASE_SQL_REWRITE_QUERY_RANGE_PROVIDER_
|
||||
//// end of header file
|
||||
|
||||
|
||||
|
||||
|
2518
src/sql/rewrite/ob_range_generator.cpp
Normal file
2518
src/sql/rewrite/ob_range_generator.cpp
Normal file
File diff suppressed because it is too large
Load Diff
220
src/sql/rewrite/ob_range_generator.h
Normal file
220
src/sql/rewrite/ob_range_generator.h
Normal file
@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
#ifndef OCEANBASE_SQL_REWRITE_OB_RANGE_GENERATOR_H_
|
||||
#define OCEANBASE_SQL_REWRITE_OB_RANGE_GENERATOR_H_
|
||||
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
#include "sql/rewrite/ob_expr_range_converter.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
|
||||
struct ObTmpRange : public common::ObDLinkBase<ObTmpRange>
|
||||
{
|
||||
ObTmpRange(common::ObIAllocator &allocator)
|
||||
: start_(NULL),
|
||||
end_(NULL),
|
||||
include_start_(false),
|
||||
include_end_(false),
|
||||
always_true_(false),
|
||||
always_false_(false),
|
||||
min_offset_(0),
|
||||
max_offset_(0),
|
||||
column_cnt_(0),
|
||||
is_phy_rowid_(false),
|
||||
allocator_(allocator)
|
||||
{
|
||||
}
|
||||
int copy(ObTmpRange &other);
|
||||
int init_tmp_range(int64_t column_count);
|
||||
void set_always_true();
|
||||
void set_always_false();
|
||||
int intersect(ObTmpRange &other, bool &need_delay);
|
||||
int formalize();
|
||||
int refine_final_range();
|
||||
DECLARE_TO_STRING;
|
||||
// int tailor_final_range(int64_t column_count);
|
||||
common::ObObj *start_;
|
||||
common::ObObj *end_;
|
||||
bool include_start_;
|
||||
bool include_end_;
|
||||
bool always_true_;
|
||||
bool always_false_;
|
||||
int min_offset_;
|
||||
int max_offset_;
|
||||
int column_cnt_;
|
||||
bool is_phy_rowid_;
|
||||
common::ObIAllocator &allocator_;
|
||||
};
|
||||
|
||||
typedef ObDList<ObTmpRange> TmpRangeList;
|
||||
|
||||
struct ObTmpInParam
|
||||
{
|
||||
ObTmpInParam(common::ObIAllocator &allocator)
|
||||
: always_false_(false),
|
||||
always_true_(false),
|
||||
in_param_(allocator) {}
|
||||
|
||||
TO_STRING_KV(K_(always_false), K_(always_true), K(in_param_));
|
||||
bool always_false_;
|
||||
bool always_true_;
|
||||
ObFixedArray<ObObj*, ObIAllocator> in_param_;
|
||||
};
|
||||
|
||||
struct ObTmpGeoParam
|
||||
{
|
||||
ObTmpGeoParam(common::ObIAllocator &allocator)
|
||||
: always_true_(false),
|
||||
start_keys_(allocator),
|
||||
end_keys_(allocator) {}
|
||||
|
||||
TO_STRING_KV(K(always_true_), K(start_keys_), K(end_keys_));
|
||||
bool always_true_;
|
||||
ObFixedArray<uint64_t, ObIAllocator> start_keys_;
|
||||
ObFixedArray<uint64_t, ObIAllocator> end_keys_;
|
||||
};
|
||||
|
||||
class ObRangeGenerator
|
||||
{
|
||||
public:
|
||||
ObRangeGenerator(ObIAllocator &allocator,
|
||||
ObExecContext &exec_ctx,
|
||||
const ObPreRangeGraph *pre_range_graph,
|
||||
ObIArray<common::ObNewRange *> &ranges,
|
||||
bool &all_single_value_ranges,
|
||||
const common::ObDataTypeCastParams &dtc_params,
|
||||
ObIArray<common::ObSpatialMBR> &mbr_filters)
|
||||
: allocator_(allocator),
|
||||
exec_ctx_(exec_ctx),
|
||||
pre_range_graph_(pre_range_graph),
|
||||
ranges_(ranges),
|
||||
all_single_value_ranges_(all_single_value_ranges),
|
||||
dtc_params_(dtc_params),
|
||||
range_map_(pre_range_graph->get_range_map()),
|
||||
always_true_range_(nullptr),
|
||||
always_false_range_(nullptr),
|
||||
all_tmp_ranges_(allocator),
|
||||
tmp_range_lists_(nullptr),
|
||||
all_tmp_node_caches_(allocator),
|
||||
always_false_tmp_range_(nullptr),
|
||||
mbr_filters_(mbr_filters),
|
||||
is_generate_ss_range_(false),
|
||||
cur_datetime_(0)
|
||||
{
|
||||
if (OB_NOT_NULL(exec_ctx_.get_physical_plan_ctx())) {
|
||||
cur_datetime_ = exec_ctx_.get_physical_plan_ctx()->get_cur_time().get_datetime();
|
||||
}
|
||||
}
|
||||
|
||||
int generate_ranges();
|
||||
int generate_ss_ranges();
|
||||
static int generate_fast_nlj_range(const ObPreRangeGraph &pre_range_graph,
|
||||
const ParamStore ¶m_store,
|
||||
ObIAllocator &allocator,
|
||||
void *range_buffer);
|
||||
static int check_can_final_fast_nlj_range(const ObPreRangeGraph &pre_range_graph,
|
||||
const ParamStore ¶m_store,
|
||||
bool &is_valid);
|
||||
static int get_spatial_relationship_by_mask(const ObObj& extra, ObDomainOpType& op_type);
|
||||
static bool is_geo_type(const ObDomainOpType& op_type);
|
||||
private:
|
||||
int generate_tmp_range(ObTmpRange *&tmp_range, const int64_t column_cnt);
|
||||
int generate_one_range(ObTmpRange &tmp_range);
|
||||
int generate_precise_get_range(const ObRangeNode &node);
|
||||
int generate_standard_ranges(const ObRangeNode *node);
|
||||
int formalize_standard_range(const ObRangeNode *node, ObTmpRange &range);
|
||||
int generate_complex_ranges(const ObRangeNode *node);
|
||||
int formalize_complex_range(const ObRangeNode *node);
|
||||
int generate_one_complex_range();
|
||||
int final_range_node(const ObRangeNode *node, ObTmpRange *&range, bool need_cache);
|
||||
int final_in_range_node(const ObRangeNode *node, const int64_t in_idx, ObTmpRange *&range);
|
||||
int get_result_value(const int64_t param_idx, ObObj &val, bool &is_valid, ObExecContext &exec_ctx) const;
|
||||
|
||||
int cast_value_type(ObTmpRange &range);
|
||||
int try_cast_value(const ObRangeColumnMeta &meta,
|
||||
ObObj &value,
|
||||
int64_t &cmp,
|
||||
common::ObCmpOp cmp_op);
|
||||
int generate_contain_exec_param_range();
|
||||
int merge_and_remove_ranges();
|
||||
int try_intersect_delayed_range(ObTmpRange &range);
|
||||
int create_new_range(ObNewRange *&range, int64_t column_cnt);
|
||||
static inline bool is_const_expr_or_null(int64_t idx) { return idx < OB_RANGE_EXTEND_VALUE || OB_RANGE_NULL_VALUE == idx; }
|
||||
int final_not_in_range_node(const ObRangeNode &node,
|
||||
const int64_t not_in_idx,
|
||||
ObTmpInParam *in_param,
|
||||
ObTmpRange *&range);
|
||||
int generate_tmp_not_in_param(const ObRangeNode &node,
|
||||
ObTmpInParam *&in_param);
|
||||
int generate_tmp_geo_param(const ObRangeNode &node,
|
||||
ObTmpGeoParam *&tmp_geo_param);
|
||||
int get_intersects_tmp_geo_param(uint32_t input_srid,
|
||||
const common::ObString &wkb,
|
||||
const common::ObDomainOpType op_type,
|
||||
const double &distance,
|
||||
ObTmpGeoParam *geo_param);
|
||||
int get_coveredby_tmp_geo_param(uint32_t input_srid,
|
||||
const common::ObString &wkb,
|
||||
const common::ObDomainOpType op_type,
|
||||
ObTmpGeoParam *geo_param);
|
||||
int final_geo_range_node(const ObRangeNode &node,
|
||||
const uint64_t start,
|
||||
const uint64_t end,
|
||||
ObTmpRange *&range);
|
||||
int check_need_merge_range_nodes(const ObRangeNode *node,
|
||||
bool &need_merge);
|
||||
|
||||
int cast_double_to_fixed_double(const ObRangeColumnMeta &meta,
|
||||
const ObObj& in_value,
|
||||
ObObj &out_value);
|
||||
|
||||
int refine_real_range(const ObAccuracy &accuracy, double &value);
|
||||
int final_json_member_of_range_node(const ObRangeNode *node, ObTmpRange *&range, bool need_cache);
|
||||
int fill_domain_range_node(const ObRangeNode &node,
|
||||
const ObObj& start_val,
|
||||
const ObObj& end_val,
|
||||
ObTmpRange *range);
|
||||
int generate_tmp_json_array_param(const ObRangeNode &node,
|
||||
ObTmpInParam *&in_param);
|
||||
int final_domain_range_node(const ObRangeNode &node,
|
||||
const int64_t in_idx,
|
||||
ObTmpInParam *in_param,
|
||||
ObTmpRange *&range);
|
||||
private:
|
||||
ObRangeGenerator();
|
||||
static const int64_t RANGE_BUCKET_SIZE = 1000;
|
||||
private:
|
||||
ObIAllocator &allocator_;
|
||||
ObExecContext &exec_ctx_;
|
||||
const ObPreRangeGraph *pre_range_graph_;
|
||||
ObIArray<common::ObNewRange *> &ranges_;
|
||||
bool &all_single_value_ranges_;
|
||||
const common::ObDataTypeCastParams &dtc_params_;
|
||||
const ObRangeMap &range_map_;
|
||||
common::ObNewRange *always_true_range_;
|
||||
common::ObNewRange *always_false_range_;
|
||||
ObFixedArray<ObTmpRange*, ObIAllocator> all_tmp_ranges_;
|
||||
TmpRangeList* tmp_range_lists_;
|
||||
ObFixedArray<void*, ObIAllocator> all_tmp_node_caches_;
|
||||
ObTmpRange *always_false_tmp_range_;
|
||||
ObIArray<common::ObSpatialMBR> &mbr_filters_;
|
||||
bool is_generate_ss_range_;
|
||||
int64_t cur_datetime_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
#endif // OCEANBASE_SQL_REWRITE_OB_RANGE_GENERATOR_H_
|
1723
src/sql/rewrite/ob_range_graph_generator.cpp
Normal file
1723
src/sql/rewrite/ob_range_graph_generator.cpp
Normal file
File diff suppressed because it is too large
Load Diff
204
src/sql/rewrite/ob_range_graph_generator.h
Normal file
204
src/sql/rewrite/ob_range_graph_generator.h
Normal file
@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
#ifndef OCEANBASE_SQL_REWRITE_OB_RANGE_GRAPH_GENERATOR_H_
|
||||
#define OCEANBASE_SQL_REWRITE_OB_RANGE_GRAPH_GENERATOR_H_
|
||||
|
||||
#include "sql/rewrite/ob_query_range_define.h"
|
||||
#include "sql/rewrite/ob_expr_range_converter.h"
|
||||
|
||||
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
|
||||
struct ObPriciseExprItem
|
||||
{
|
||||
ObPriciseExprItem()
|
||||
: expr_(nullptr), max_offset_(-1) {}
|
||||
ObPriciseExprItem(ObRawExpr *expr, int64_t max_offset)
|
||||
: expr_(expr), max_offset_(max_offset) {}
|
||||
TO_STRING_KV(KPC(expr_), K(max_offset_));
|
||||
const ObRawExpr *expr_;
|
||||
int64_t max_offset_;
|
||||
};
|
||||
|
||||
struct RangeNodeCmp
|
||||
{
|
||||
inline bool operator()(const ObRangeNode *left, const ObRangeNode *right)
|
||||
{
|
||||
bool bret = false;
|
||||
if (left != nullptr && right != nullptr) {
|
||||
if (left->always_false_ || right->always_false_) {
|
||||
bret = !right->always_false_;
|
||||
} else if (left->always_true_ || right->always_true_) {
|
||||
bret = !right->always_true_;
|
||||
} else {
|
||||
bret = left->min_offset_ < right->min_offset_;
|
||||
}
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
};
|
||||
|
||||
struct RangeNodeConnectInfo
|
||||
{
|
||||
RangeNodeConnectInfo()
|
||||
: inited_(false),
|
||||
data_(nullptr),
|
||||
node_count_(0),
|
||||
per_node_info_len_(0) {
|
||||
}
|
||||
bool inited_;
|
||||
uint8_t* data_;
|
||||
uint64_t node_count_;
|
||||
uint64_t per_node_info_len_;
|
||||
};
|
||||
|
||||
class ObRangeGraphGenerator
|
||||
{
|
||||
public:
|
||||
ObRangeGraphGenerator(ObIAllocator &allocator,
|
||||
ObQueryRangeCtx &ctx,
|
||||
ObPreRangeGraph *pre_range_graph,
|
||||
int64_t column_cnt)
|
||||
: allocator_(allocator),
|
||||
ctx_(ctx),
|
||||
pre_range_graph_(pre_range_graph),
|
||||
max_precise_offset_(column_cnt),
|
||||
ss_max_precise_offset_(column_cnt)
|
||||
{}
|
||||
|
||||
int generate_range_graph(const ObIArray<ObRawExpr*> &exprs,
|
||||
ObExprRangeConverter &range_node_generator);
|
||||
static int and_range_nodes(ObIArray<ObRangeNode*> &range_nodes,
|
||||
const int64_t column_cnt,
|
||||
ObRangeNode *&range_node);
|
||||
static int or_range_nodes(ObExprRangeConverter &range_node_generator,
|
||||
ObIArray<ObRangeNode*> &range_nodes,
|
||||
const int64_t column_cnt,
|
||||
ObRangeNode *&range_node);
|
||||
private:
|
||||
int generate_range_node(ObRawExpr* expr,
|
||||
ObExprRangeConverter &range_node_generator,
|
||||
ObRangeNode *&range_node,
|
||||
int64_t expr_depth,
|
||||
bool &is_precise,
|
||||
int64_t &max_offset);
|
||||
int generate_and_range_node(ObRawExpr *and_expr,
|
||||
ObExprRangeConverter &range_node_generator,
|
||||
ObRangeNode *&range_node,
|
||||
int64_t expr_depth,
|
||||
bool &is_precise,
|
||||
int64_t &max_offset);
|
||||
|
||||
static void set_new_start_key(ObRangeNode &l_node, ObRangeNode &r_node, const int64_t column_cnt, int64_t start_offset);
|
||||
static void set_new_end_key(ObRangeNode &l_node, ObRangeNode &r_node, const int64_t column_cnt, int64_t start_offset);
|
||||
|
||||
int generate_or_range_node(ObRawExpr *or_expr,
|
||||
ObExprRangeConverter &range_node_generator,
|
||||
ObRangeNode *&range_node,
|
||||
int64_t expr_depth,
|
||||
bool &is_precise,
|
||||
int64_t &max_offset);
|
||||
|
||||
static int and_two_range_node(ObRangeNode *&l_node,
|
||||
ObRangeNode *&r_node,
|
||||
const int64_t column_cnt,
|
||||
bool &is_merge);
|
||||
|
||||
static int or_two_range_node(ObRangeNode *&l_node,
|
||||
ObRangeNode *&r_node,
|
||||
const int64_t column_cnt);
|
||||
|
||||
static int and_link_range_node(ObRangeNode *&l_node, ObRangeNode *&r_node);
|
||||
static int get_and_tails(ObRangeNode *range_node, ObIArray<ObRangeNode*> &and_tails);
|
||||
|
||||
int formalize_final_range_node(ObRangeNode *&range_node);
|
||||
int collect_graph_infos(ObRangeNode *range_node,
|
||||
uint64_t *total_range_sizes,
|
||||
uint64_t *range_sizes,
|
||||
bool &start_from_zero,
|
||||
int64_t &min_offset);
|
||||
int check_skip_scan_valid(ObRangeNode *range_node,
|
||||
ObRangeNode *&ss_head);
|
||||
static int generate_node_id(ObRangeNode *range_node, uint64_t &node_count);
|
||||
|
||||
int check_graph_type(ObRangeNode *range_node);
|
||||
|
||||
bool is_precise_get(ObRangeNode *range_node) const;
|
||||
bool is_standard_range(ObRangeNode *range_node) const;
|
||||
int get_max_precise_pos(ObRangeNode *range_node, int64_t &max_precise_pos, int64_t start_pos = 0) const;
|
||||
int inner_get_max_precise_pos(const ObRangeNode *range_node, bool* equals, int64_t &max_offset, int64_t start_pos) const;
|
||||
int remove_useless_range_node(ObRangeNode *range_node, int64_t start_pos = 0) const;
|
||||
int is_strict_equal_graph(const ObRangeNode *range_node, bool &is_strict_equal, bool &is_get) const;
|
||||
int inner_is_strict_equal_graph(const ObRangeNode *range_node,
|
||||
bool* equals,
|
||||
int64_t &max_offset,
|
||||
int64_t &max_node_offset,
|
||||
bool &is_strict_equal) const;
|
||||
int get_new_equal_idx(const ObRangeNode *range_node, bool* equals, ObIArray<int64_t> &new_idx) const;
|
||||
bool is_strict_equal_node(const ObRangeNode *range_node) const;
|
||||
bool is_equal_node(const ObRangeNode *range_node) const;
|
||||
|
||||
int fill_range_exprs(ObIArray<ObPriciseExprItem> &pricise_exprs,
|
||||
ObIArray<ObPriciseExprItem> &unpricise_exprs);
|
||||
int generate_expr_final_info();
|
||||
|
||||
inline void update_max_precise_offset(int64_t offset) { max_precise_offset_ = std::min(max_precise_offset_, offset); }
|
||||
inline void update_ss_max_precise_offset(int64_t offset) { ss_max_precise_offset_ = std::min(ss_max_precise_offset_, offset); }
|
||||
inline bool is_const_expr_or_null(int64_t idx) const
|
||||
{
|
||||
return idx < OB_RANGE_EXTEND_VALUE || OB_RANGE_NULL_VALUE == idx;
|
||||
}
|
||||
int relink_standard_range_if_needed(ObRangeNode *&range_node);
|
||||
static int crop_final_range_node(ObRangeNode *&range_node, int64_t crop_offset);
|
||||
static int crop_final_range_node(ObRangeNode *&range_node, int64_t crop_offset,
|
||||
RangeNodeConnectInfo &connect_info,
|
||||
common::hash::ObHashMap<uint64_t, ObRangeNode*> &refined_ranges,
|
||||
common::hash::ObHashSet<uint64_t> &shared_ranges);
|
||||
static int check_crop_range_node_valid(ObRangeNode *range_node,
|
||||
ObRangeNode *next_range_node,
|
||||
RangeNodeConnectInfo &connect_info);
|
||||
static int reset_node_id(ObRangeNode *range_node);
|
||||
static int generate_range_node_connect_info(ObIAllocator &allocator,
|
||||
ObRangeNode *range_node,
|
||||
uint64_t node_count,
|
||||
RangeNodeConnectInfo &connect_info);
|
||||
static int collect_range_node_connect_info(ObRangeNode *range_node,
|
||||
RangeNodeConnectInfo &connect_info);
|
||||
|
||||
static int get_max_offset(const ObRangeNode *range_node, int64_t &max_offset);
|
||||
|
||||
static int get_start_from_zero(const ObRangeNode *range_node, bool &start_from_zero);
|
||||
|
||||
static int check_can_fast_nlj_range_extraction(const ObRangeNode *range_node,
|
||||
const ObRangeMap &range_map,
|
||||
bool is_equal_range,
|
||||
bool &fast_nlj_range);
|
||||
|
||||
static int formalize_one_range_node(ObRangeNode &range_node);
|
||||
private:
|
||||
ObRangeGraphGenerator();
|
||||
private:
|
||||
ObIAllocator &allocator_;
|
||||
ObQueryRangeCtx &ctx_;
|
||||
ObPreRangeGraph *pre_range_graph_;
|
||||
int64_t max_precise_offset_;
|
||||
int64_t ss_max_precise_offset_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
#endif // OCEANBASE_SQL_REWRITE_OB_RANGE_GRAPH_GENERATOR_H_
|
@ -39,8 +39,10 @@
|
||||
#include "sql/parser/ob_parser.h"
|
||||
#include "sql/rewrite/ob_transform_pre_process.h"
|
||||
#include "sql/rewrite/ob_expand_aggregate_utils.h"
|
||||
#include "sql/ob_sql_utils.h"
|
||||
#include "share/stat/ob_opt_stat_manager.h"
|
||||
|
||||
|
||||
namespace oceanbase {
|
||||
using namespace common;
|
||||
using namespace share::schema;
|
||||
@ -3043,9 +3045,13 @@ int ObTransformUtils::get_simple_filter_column(const ObDMLStmt *stmt,
|
||||
OB_ISNULL(right = expr->get_param_expr(1))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexcept null param expr", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::get_expr_without_lossless_cast(left, left)) ||
|
||||
OB_FAIL(ObOptimizerUtil::get_expr_without_lossless_cast(right, right))) {
|
||||
} else if (OB_FAIL(ObOptimizerUtil::get_expr_without_unprecise_and_lossless_cast(left, left)) ||
|
||||
OB_FAIL(ObOptimizerUtil::get_expr_without_unprecise_and_lossless_cast(right, right))) {
|
||||
LOG_WARN("failed to get expr without lossless cast", K(ret));
|
||||
} else if (IS_BASIC_CMP_OP(expr->get_expr_type()) &&
|
||||
(OB_FAIL(ObOptimizerUtil::get_column_expr_without_nvl(left, left)) ||
|
||||
OB_FAIL(ObOptimizerUtil::get_column_expr_without_nvl(right, right)))) {
|
||||
LOG_WARN("failed to get column expr without nvl", K(ret));
|
||||
} else if (left->is_column_ref_expr() &&
|
||||
table_id == static_cast<ObColumnRefRawExpr*>(left)->get_table_id()) {
|
||||
if (right->get_relation_ids().has_member(stmt->get_table_bit_index(table_id))) {
|
||||
@ -3485,27 +3491,50 @@ int ObTransformUtils::check_index_extract_query_range(const ObDMLStmt *stmt,
|
||||
ObRawExpr *condition_expr = NULL;
|
||||
ObArenaAllocator alloc(ObMemAttr(MTL_ID(), "RewriteMinMax"));
|
||||
void *tmp_ptr = NULL;
|
||||
ObQueryRange *query_range = NULL;
|
||||
const ParamStore *params = NULL;
|
||||
ObQueryCtx *query_ctx = NULL;
|
||||
ObSQLSessionInfo *session = NULL;
|
||||
if (OB_ISNULL(stmt) || OB_ISNULL(ctx) || OB_ISNULL(ctx->exec_ctx_)
|
||||
|| OB_ISNULL(ctx->exec_ctx_->get_physical_plan_ctx())
|
||||
|| OB_ISNULL(query_ctx = stmt->get_query_ctx())) {
|
||||
|| OB_ISNULL(query_ctx = stmt->get_query_ctx())
|
||||
|| OB_ISNULL(session = ctx->session_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("params have null", K(ret), K(stmt), K(ctx));
|
||||
} else if (OB_FAIL(get_range_column_items_by_ids(stmt,
|
||||
table_id,
|
||||
index_cols,
|
||||
range_columns))) {
|
||||
LOG_WARN("failed to get index column items by index cols", K(ret));
|
||||
} else if (session->is_enable_new_query_range() &&
|
||||
ObSQLUtils::is_min_cluster_version_ge_425_or_435() &&
|
||||
ObSQLUtils::is_opt_feature_version_ge_425_or_435(query_ctx->optimizer_features_enable_version_)) {
|
||||
ObPreRangeGraph *pre_range_graph = NULL;
|
||||
params = &ctx->exec_ctx_->get_physical_plan_ctx()->get_param_store();
|
||||
if (OB_ISNULL(tmp_ptr = alloc.alloc(sizeof(ObPreRangeGraph))) ||
|
||||
OB_ISNULL(pre_range_graph = new(tmp_ptr)ObPreRangeGraph(alloc))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for pre range graph", K(ret));
|
||||
} else if (OB_FAIL(pre_range_graph->preliminary_extract_query_range(range_columns,
|
||||
predicate_exprs,
|
||||
ctx->exec_ctx_,
|
||||
NULL,
|
||||
params))) {
|
||||
LOG_WARN("failed to extract query range", K(ret));
|
||||
} else if (pre_range_graph->get_range_exprs().count() != predicate_exprs.count()) {
|
||||
is_match = false;
|
||||
}
|
||||
if (OB_NOT_NULL(pre_range_graph)) {
|
||||
pre_range_graph->~ObPreRangeGraph();
|
||||
pre_range_graph = NULL;
|
||||
}
|
||||
} else {
|
||||
ObQueryRange *query_range = NULL;
|
||||
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(ctx->session_info_);
|
||||
params = &ctx->exec_ctx_->get_physical_plan_ctx()->get_param_store();
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_ISNULL(tmp_ptr = alloc.alloc(sizeof(ObQueryRange)))
|
||||
|| OB_ISNULL(query_range = new(tmp_ptr)ObQueryRange(alloc))) {
|
||||
if (OB_ISNULL(tmp_ptr = alloc.alloc(sizeof(ObQueryRange))) ||
|
||||
OB_ISNULL(query_range = new(tmp_ptr)ObQueryRange(alloc))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed to allocate memory for query range", K(ret));
|
||||
} else if (OB_FAIL(get_range_column_items_by_ids(stmt,
|
||||
table_id,
|
||||
index_cols,
|
||||
range_columns))) {
|
||||
LOG_WARN("failed to get index column items by index cols", K(ret));
|
||||
} else if (OB_FAIL(query_range->preliminary_extract_query_range(range_columns,
|
||||
predicate_exprs,
|
||||
dtc_params,
|
||||
|
@ -5700,8 +5700,8 @@ int ObBasicSessionInfo::get_auto_increment_cache_size(int64_t &auto_increment_ca
|
||||
int ObBasicSessionInfo::get_optimizer_features_enable_version(uint64_t &version) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
// if OPTIMIZER_FEATURES_ENABLE is set as '', use LASTED_COMPAT_VERSION
|
||||
version = LASTED_COMPAT_VERSION;
|
||||
// if OPTIMIZER_FEATURES_ENABLE is set as '', use COMPAT_VERSION_4_2_1 where this variable is introduced.
|
||||
version = COMPAT_VERSION_4_2_1;
|
||||
ObString version_str;
|
||||
uint64_t tmp_version = 0;
|
||||
if (OB_FAIL(get_string_sys_var(SYS_VAR_OPTIMIZER_FEATURES_ENABLE, version_str))) {
|
||||
@ -5709,7 +5709,7 @@ int ObBasicSessionInfo::get_optimizer_features_enable_version(uint64_t &version)
|
||||
} else if (version_str.empty()
|
||||
|| OB_FAIL(ObClusterVersion::get_version(version_str, tmp_version))
|
||||
|| !ObGlobalHint::is_valid_opt_features_version(tmp_version)) {
|
||||
LOG_WARN("fail invalid optimizer features version", K(ret), K(version_str), K(tmp_version));
|
||||
LOG_TRACE("fail invalid optimizer features version", K(ret), K(version_str), K(tmp_version));
|
||||
ret = OB_SUCCESS;
|
||||
} else {
|
||||
version = tmp_version;
|
||||
|
@ -659,6 +659,17 @@ int ObSQLSessionInfo::get_spm_mode(int64_t &spm_mode)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObSQLSessionInfo::is_enable_new_query_range() const
|
||||
{
|
||||
bool bret = false;
|
||||
int64_t tenant_id = get_effective_tenant_id();
|
||||
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
|
||||
if (tenant_config.is_valid()) {
|
||||
bret = tenant_config->_enable_new_query_range_extraction;
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
void ObSQLSessionInfo::destroy(bool skip_sys_var)
|
||||
{
|
||||
if (is_inited_) {
|
||||
|
@ -1315,6 +1315,7 @@ public:
|
||||
bool is_spf_mlj_group_rescan_enabled() const;
|
||||
int is_preserve_order_for_pagination_enabled(bool &enabled) const;
|
||||
int get_spm_mode(int64_t &spm_mode);
|
||||
bool is_enable_new_query_range() const;
|
||||
|
||||
ObSessionDDLInfo &get_ddl_info() { return ddl_info_; }
|
||||
const ObSessionDDLInfo &get_ddl_info() const { return ddl_info_; }
|
||||
|
@ -42,10 +42,10 @@ Query Plan
|
||||
==========================================================
|
||||
|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)|
|
||||
----------------------------------------------------------
|
||||
|0 |SORT | |5 |35 |
|
||||
|0 |SORT | |5 |36 |
|
||||
|1 |└─NESTED-LOOP JOIN | |5 |35 |
|
||||
|2 | ├─COLUMN TABLE FULL SCAN|t4 |2 |3 |
|
||||
|3 | └─TABLE RANGE SCAN |t3 |3 |16 |
|
||||
|3 | └─TABLE RANGE SCAN |t3 |10 |16 |
|
||||
==========================================================
|
||||
Outputs & filters:
|
||||
-------------------------------------
|
||||
|
@ -352,6 +352,7 @@ _enable_kv_feature
|
||||
_enable_log_cache
|
||||
_enable_memleak_light_backtrace
|
||||
_enable_newsort
|
||||
_enable_new_query_range_extraction
|
||||
_enable_new_sql_nio
|
||||
_enable_nlj_spf_use_rich_format
|
||||
_enable_optimizer_qualify_filter
|
||||
|
@ -626,7 +626,7 @@ Outputs & filters:
|
||||
0 - output([t1.a], [t1.b], [t1.c]), filter([t1.a > 0], [t1.a < 100]), rowset=16
|
||||
access([t1.b], [t1.a], [t1.c]), partitions(p0)
|
||||
is_index_back=false, is_global_index=false, filter_before_indexback[false,false],
|
||||
range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(100,100,MAX,MAX ; 100,MAX,100,MIN),
|
||||
range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(100,100,MAX,MAX ; 100,MAX,MAX,MAX),
|
||||
range_cond([t1.b = 100], [t1.c > 100])
|
||||
explain select a, b, c from t1 where b = 100 and a > 0 and a < 100 and c = 200;
|
||||
Query Plan
|
||||
@ -1539,42 +1539,44 @@ Outputs & filters:
|
||||
range_cond([t1.b = 100], [t1.c < 100], [t1.c > 100])
|
||||
explain select a, b, c from t1 where b = 100 or (b = 200 and c = 300) order by c desc limit 0, 100;
|
||||
Query Plan
|
||||
============================================================
|
||||
|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|
|
||||
------------------------------------------------------------
|
||||
|0 |LIMIT | |1 |5 |
|
||||
|1 |└─TOP-N SORT | |1 |5 |
|
||||
|2 | └─TABLE FULL SCAN|t1(idx_b_c_a)|1 |5 |
|
||||
============================================================
|
||||
=============================================================
|
||||
|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|
|
||||
-------------------------------------------------------------
|
||||
|0 |LIMIT | |1 |5 |
|
||||
|1 |└─TOP-N SORT | |1 |5 |
|
||||
|2 | └─TABLE RANGE SCAN|t1(idx_b_c_a)|1 |5 |
|
||||
=============================================================
|
||||
Outputs & filters:
|
||||
-------------------------------------
|
||||
0 - output([t1.a], [t1.b], [t1.c]), filter(nil), rowset=16
|
||||
limit(100), offset(0)
|
||||
1 - output([t1.a], [t1.b], [t1.c]), filter(nil), rowset=16
|
||||
sort_keys([t1.c, DESC]), topn(100 + 0)
|
||||
2 - output([t1.b], [t1.c], [t1.a]), filter([t1.b = 100 OR t1.b = 200 AND t1.c = 300]), rowset=16
|
||||
2 - output([t1.b], [t1.c], [t1.a]), filter(nil), rowset=16
|
||||
access([t1.b], [t1.c], [t1.a]), partitions(p0)
|
||||
is_index_back=false, is_global_index=false, filter_before_indexback[false],
|
||||
range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(100,MIN,MIN,MIN ; 100,MAX,MAX,MAX), (200,300,MIN,MIN ; 200,300,MAX,MAX)
|
||||
is_index_back=false, is_global_index=false,
|
||||
range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(100,MIN,MIN,MIN ; 100,MAX,MAX,MAX), (200,300,MIN,MIN ; 200,300,MAX,MAX),
|
||||
range_cond([t1.b = 100 OR t1.b = 200 AND t1.c = 300])
|
||||
explain select a, b, c from t1 where (b = 200 and c = 300) or (b = 100) order by c desc limit 0, 100;
|
||||
Query Plan
|
||||
============================================================
|
||||
|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|
|
||||
------------------------------------------------------------
|
||||
|0 |LIMIT | |1 |5 |
|
||||
|1 |└─TOP-N SORT | |1 |5 |
|
||||
|2 | └─TABLE FULL SCAN|t1(idx_b_c_a)|1 |5 |
|
||||
============================================================
|
||||
=============================================================
|
||||
|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|
|
||||
-------------------------------------------------------------
|
||||
|0 |LIMIT | |1 |5 |
|
||||
|1 |└─TOP-N SORT | |1 |5 |
|
||||
|2 | └─TABLE RANGE SCAN|t1(idx_b_c_a)|1 |5 |
|
||||
=============================================================
|
||||
Outputs & filters:
|
||||
-------------------------------------
|
||||
0 - output([t1.a], [t1.b], [t1.c]), filter(nil), rowset=16
|
||||
limit(100), offset(0)
|
||||
1 - output([t1.a], [t1.b], [t1.c]), filter(nil), rowset=16
|
||||
sort_keys([t1.c, DESC]), topn(100 + 0)
|
||||
2 - output([t1.b], [t1.c], [t1.a]), filter([t1.b = 200 AND t1.c = 300 OR t1.b = 100]), rowset=16
|
||||
2 - output([t1.b], [t1.c], [t1.a]), filter(nil), rowset=16
|
||||
access([t1.b], [t1.c], [t1.a]), partitions(p0)
|
||||
is_index_back=false, is_global_index=false, filter_before_indexback[false],
|
||||
range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(200,300,MIN,MIN ; 200,300,MAX,MAX), (100,MIN,MIN,MIN ; 100,MAX,MAX,MAX)
|
||||
is_index_back=false, is_global_index=false,
|
||||
range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(100,MIN,MIN,MIN ; 100,MAX,MAX,MAX), (200,300,MIN,MIN ; 200,300,MAX,MAX),
|
||||
range_cond([t1.b = 200 AND t1.c = 300 OR t1.b = 100])
|
||||
explain select a1, a2, b, min(c), max(c) from t4 group by a1, a2, b;
|
||||
Query Plan
|
||||
=========================================================
|
||||
|
@ -258,7 +258,7 @@ Outputs & filters:
|
||||
0 - output([t1.c1], [t1.c2], [t1.c3]), filter([t1.c1 < 4]), rowset=16
|
||||
access([t1.c1], [t1.c2], [t1.c3]), partitions(p0)
|
||||
is_index_back=true, is_global_index=false, filter_before_indexback[true],
|
||||
range_key([t1.c2], [t1.c1]), range(1,MAX ; MAX,4),
|
||||
range_key([t1.c2], [t1.c1]), range(1,MAX ; MAX,MAX),
|
||||
range_cond([t1.c2 > 1])
|
||||
select /*+index(t1 idx)*/ c1, c2, c3 from t1 where c2 > 1 and c1 < 4;
|
||||
+----+------+------+
|
||||
|
@ -55,6 +55,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -86,6 +87,7 @@
|
||||
"value": {
|
||||
"DECIMAL":"1"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -119,6 +121,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -183,6 +186,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -216,6 +220,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -249,6 +254,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -313,6 +319,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -371,6 +378,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -402,6 +410,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -433,6 +442,7 @@
|
||||
"value": {
|
||||
"BIGINT":3
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -500,6 +510,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -558,6 +569,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -589,6 +601,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -620,6 +633,7 @@
|
||||
"value": {
|
||||
"BIGINT":3
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -715,6 +729,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -777,6 +792,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -870,6 +886,7 @@
|
||||
"value": {
|
||||
"BIGINT":100
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -932,6 +949,7 @@
|
||||
"value": {
|
||||
"BIGINT":0
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1027,6 +1045,7 @@
|
||||
"value": {
|
||||
"BIGINT":100
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1116,6 +1135,7 @@
|
||||
"value": {
|
||||
"BIGINT":0
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1178,6 +1198,7 @@
|
||||
"value": {
|
||||
"BIGINT":100
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1296,6 +1317,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
"when": [
|
||||
@ -1330,6 +1352,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -1363,6 +1386,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1398,6 +1422,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -1431,6 +1456,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1496,6 +1522,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
"when": [
|
||||
@ -1555,6 +1582,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -1586,6 +1614,7 @@
|
||||
"value": {
|
||||
"BIGINT":0
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1624,6 +1653,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -1774,6 +1804,7 @@
|
||||
"value": {
|
||||
"DECIMAL":"3.14"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -2104,6 +2135,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -2376,6 +2408,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
[18] @@auto_increment_increment
|
||||
@ -2440,6 +2473,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"SYSCONST"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -2471,6 +2505,7 @@
|
||||
"value": {
|
||||
"BIGINT":0
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -2666,6 +2701,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -2697,6 +2733,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -2789,6 +2826,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -3189,6 +3227,7 @@
|
||||
"value": {
|
||||
"BIGINT":3
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -3301,6 +3340,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -3570,6 +3610,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -3601,6 +3642,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -3632,6 +3674,7 @@
|
||||
"value": {
|
||||
"BIGINT":3
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -3663,6 +3706,7 @@
|
||||
"value": {
|
||||
"BIGINT":4
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -3805,6 +3849,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -3916,6 +3961,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4009,6 +4055,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -4040,6 +4087,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4232,6 +4280,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -4263,6 +4312,7 @@
|
||||
"value": {
|
||||
"BIGINT":2
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4434,6 +4484,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -4465,6 +4516,7 @@
|
||||
"value": {
|
||||
"BIGINT":10
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4579,6 +4631,7 @@
|
||||
"value": {
|
||||
"BIGINT":30
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4732,6 +4785,7 @@
|
||||
"value": {
|
||||
"BIGINT":1
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -4817,6 +4871,7 @@
|
||||
"value": {
|
||||
"UNKNOWN":0
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4881,6 +4936,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -4997,6 +5053,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -5157,6 +5214,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
},
|
||||
{
|
||||
@ -5188,6 +5246,7 @@
|
||||
"value": {
|
||||
"BIGINT":45
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -5229,6 +5288,7 @@
|
||||
"value": {
|
||||
"BIGINT":46
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -5270,6 +5330,7 @@
|
||||
"value": {
|
||||
"BIGINT":-4290838506
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -5311,6 +5372,7 @@
|
||||
"value": {
|
||||
"BIGINT":-4290838506
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
@ -5509,6 +5571,7 @@
|
||||
"collation":"utf8mb4_general_ci",
|
||||
"coercibility":"COERCIBLE"
|
||||
},
|
||||
"is_dynamic_questionmark":false,
|
||||
"expr_hash":0
|
||||
}
|
||||
],
|
||||
|
Loading…
x
Reference in New Issue
Block a user