Files
oceanbase/src/sql/optimizer/ob_opt_est_utils.h
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

188 lines
8.0 KiB
C++

/**
* 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_OPTIMIZER_OB_OPT_EST_UTILS_
#define OCEANBASE_SQL_OPTIMIZER_OB_OPT_EST_UTILS_
#include "sql/resolver/expr/ob_raw_expr.h"
namespace oceanbase
{
namespace share
{
namespace schema
{
class ObSchemaGetterGuard;
}
}
namespace sql
{
class ObLogPlan;
class ObSQLSessionInfo;
class ObOptimizerContext;
struct RangeExprs
{
RangeExprs()
: column_expr_(NULL),
range_exprs_()
{ }
TO_STRING_KV(K_(column_expr), K_(range_exprs));
ObColumnRefRawExpr *column_expr_;
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> range_exprs_;
};
class ObOptEstUtils
{
public:
//check if op is monotonic, some type may not considered.
static bool is_monotonic_op(const ObItemType type);
//@brief expr is cmp_op , has is_range_cond flag or is simple op_and,op_or
//such as, c1 > 1 and c1 < 2, c1 between 1 and 1000, c1 > 100 or c1 < 10000
//@param in qual
//@param out is_range
static int is_range_expr(const ObRawExpr *qual, bool &is_simple_filter, const int64_t level = 0);
//extract column exprs with simple operator check.
//level must be initialized with 0(default value)
static int extract_column_exprs_with_op_check(const ObRawExpr *raw_expr,
common::ObIArray<const ObColumnRefRawExpr*> &column_exprs,
bool &only_monotonic_op,
const int64_t level = 0);
//@brief according different column, generate one or more range_exprs, push them into column_exprs_array.
//@brief the item in range_exprs mush be is_range_expr() -> see notes below.
//@param qual the expr need be dealed with
//@param out can_be_extracted, if the expr can be extracted range here
//@param out column_exprs_array, if generate new range_expr, pushed it into this array
static int extract_simple_cond_filters(ObRawExpr &qual,
bool &can_be_extracted,
common::ObIArray<RangeExprs> &column_exprs_array);
//is_calculable_expr:is PARAM with param idx[0, param_count) or const value, or calculable
static bool is_calculable_expr(const ObRawExpr &expr, const int64_t param_count);
//get the expr's value.
//@@param get_value[out]:is_calculable_expr:true, otherwise:false
//@@param value[out]:the value of calculable expr
static int get_expr_value(const ParamStore *params,
const ObRawExpr &expr,
ObExecContext *exec_ctx,
common::ObIAllocator &allocator,
bool &get_value,
common::ObObj &value);
//whether the value of calculable expr is null.
static int if_expr_value_null(const ParamStore *params,
const ObRawExpr &expr,
ObExecContext *exec_ctx,
common::ObIAllocator &allocator,
bool &is_null);
// whether the like condition's patten start with '%' or '_' and not start with escape sign
static int if_expr_start_with_patten_sign(const ParamStore *params,
const ObRawExpr *expr,
const ObRawExpr *esp_expr,
ObExecContext *exec_ctx,
ObIAllocator &allocator,
bool &is_start_with);
//whether the value of first_expr and second_expr is equal.
//if someone of the exprs is not calculable, equal return false;
//@@param null_safe, if think NULL equal NULL, null_safe should be true, otherwise false.
static int if_expr_value_equal(ObOptimizerContext &context,
const ObDMLStmt *stmt,
const ObRawExpr &first_expr,
const ObRawExpr &second_expr,
const bool null_safe,
bool &equal);
static int columns_has_unique_subset(const ObIArray<uint64_t> &full,
const ObRowkeyInfo &sub,
bool &is_subset);
};
class ObOptEstObjToScalar
{
public:
// Functionality: convert objs to scalars(double).
// One Optimization : Limited precision of double type cannot distinguish long strs using
// a static base of 256 (max distinguishable length is 6). We need to firstly truncate the
// common headers, then use a dynamic base to convert strings.
//
// Choice of dynamic base : find min and max of all chars of all given strs beyond the already
// found common prefix length, use (max - min) as base
//
// When to use this optimization : all given objs (2 to 4, min and max may be NULL) are string
// or min or max.
//
// If this optimization is not used, use old method to convert objs.
// dongyun.zdy
static int convert_objs_to_scalars(const common::ObObj *min,
const common::ObObj *max,
const common::ObObj *start,
const common::ObObj *end,
common::ObObj *min_out,
common::ObObj *max_out,
common::ObObj *start_out,
common::ObObj *end_out);
/////////////Start convert obj to scalar related function//////
// @param obj
// @return
static double convert_obj_to_scalar(const common::ObObj* obj);
// double type cannot represent min (max can be represented using Double.INF).
// wrap conversion result as obj, so it can represent min, max, etc.
static int convert_obj_to_scalar_obj(const common::ObObj* obj, common::ObObj* out);
static int convert_obj_to_double(const common::ObObj *obj, double &num);
static int convert_string_to_scalar_for_number(const common::ObString &str, double &scala);
private:
static int add_to_string_conversion_array(const common::ObObj &strobj,
common::ObIArray<common::ObString> &arr,
uint64_t &convertable_map,
int64_t pos);
// 1, find common prefix length of strings
// 2, find dynamic base and offset of strings
// 3, use dynamic base and offset to convert strings to scalars
static int convert_strings_to_scalar(const common::ObIArray<common::ObString> &origin_strs,
common::ObIArray<double> &scalars);
static double convert_string_to_scalar(const common::ObString &str,
int64_t prefix_len = 0,
uint8_t offset = 0,
double base = 256.0);
static int find_common_prefix_len(const common::ObIArray<common::ObString> &strs,
int64_t &length);
static inline void expand_range(uint8_t &min, uint8_t &max, uint8_t rmin, uint8_t rmax)
{
if (rmin < min) {
min = rmin;
}
if (rmax > max) {
max = rmax;
}
}
static int find_string_scalar_offset_base(const common::ObIArray<common::ObString> &strs,
int64_t prefix_len,
uint8_t &offset,
double &base);
};
}
}
#endif