提交 1ec7b00f 编写于 作者: O obdev 提交者: wangzelin.wzl

bugfix cherry-pick to opensource release

上级 601c09e2
......@@ -947,6 +947,31 @@ int ObAggregateProcessor::init_one_group(const int64_t group_id)
eval_ctx_,
need_rewind))) {
LOG_WARN("init GroupConcatExtraResult failed", K(ret));
} else if (aggr_info.separator_expr_ != NULL) {
ObDatum* separator_result = NULL;
if (OB_UNLIKELY(!aggr_info.separator_expr_->obj_meta_.is_string_type())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr node is null", K(ret), KPC(aggr_info.separator_expr_));
} else if (OB_FAIL(aggr_info.separator_expr_->eval(eval_ctx_, separator_result))) {
LOG_WARN("eval failed", K(ret));
} else {
// parse separator in prepare
int64_t pos = sizeof(ObDatum);
int64_t len = pos + (separator_result->null_ ? 0 : separator_result->len_);
char* buf = (char*)aggr_alloc_.alloc(len);
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fall to alloc buff", K(len), K(ret));
} else {
ObDatum** separator_datum = const_cast<ObDatum**>(&result->get_separator_datum());
*separator_datum = new (buf) ObDatum;
if (OB_FAIL((*separator_datum)->deep_copy(*separator_result, buf, len, pos))) {
LOG_WARN("failed to deep copy datum", K(ret), K(pos), K(len));
} else {
LOG_DEBUG("succ to calc separator", K(ret), KP(*separator_datum));
}
}
}
}
}
break;
......@@ -1299,31 +1324,6 @@ int ObAggregateProcessor::prepare_aggr_result(const ObChunkDatumStore::StoredRow
LOG_WARN("fail to add row", K(ret));
} else if (param_exprs != NULL && OB_FAIL(extra->add_row(*param_exprs, eval_ctx_))) {
LOG_WARN("fail to add row", K(ret));
} else if (aggr_info.separator_expr_ != NULL) {
ObDatum* separator_result = NULL;
if (OB_UNLIKELY(!aggr_info.separator_expr_->obj_meta_.is_string_type())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr node is null", K(ret), KPC(aggr_info.separator_expr_));
} else if (OB_FAIL(aggr_info.separator_expr_->eval(eval_ctx_, separator_result))) {
LOG_WARN("eval failed", K(ret));
} else {
// parse separator in prepare
int64_t pos = sizeof(ObDatum);
int64_t len = pos + (separator_result->null_ ? 0 : separator_result->len_);
char* buf = (char*)aggr_alloc_.alloc(len);
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fall to alloc buff", K(len), K(ret));
} else {
ObDatum** separator_datum = const_cast<ObDatum**>(&aggr_info.separator_datum_);
*separator_datum = new (buf) ObDatum;
if (OB_FAIL((*separator_datum)->deep_copy(*separator_result, buf, len, pos))) {
LOG_WARN("failed to deep copy datum", K(ret), K(pos), K(len));
} else {
LOG_DEBUG("succ to calc separator", K(ret), KP(*separator_datum));
}
}
}
} else {
LOG_DEBUG("succ to add row", K(stored_row), KPC(extra));
}
......@@ -1699,11 +1699,11 @@ int ObAggregateProcessor::collect_aggr_result(AggrCell& aggr_cell, const ObExpr*
LOG_WARN("finish_add_row failed", KPC(extra), K(ret));
} else {
if (aggr_info.separator_expr_ != NULL) {
if (OB_ISNULL(aggr_info.separator_datum_)) {
if (OB_ISNULL(extra->get_separator_datum())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("seperator is nullptr", K(ret));
} else {
sep_str = aggr_info.separator_datum_->get_string();
sep_str = extra->get_separator_datum()->get_string();
}
} else {
if (share::is_oracle_mode()) {
......
......@@ -46,7 +46,6 @@ public:
sort_collations_(),
sort_cmp_funcs_(),
separator_expr_(NULL),
separator_datum_(nullptr),
linear_inter_expr_(NULL)
{}
virtual ~ObAggrInfo();
......@@ -98,7 +97,6 @@ public:
ObSortCollations sort_collations_;
ObSortFuncs sort_cmp_funcs_;
ObExpr* separator_expr_;
ObDatum* separator_datum_;
// used for median/percentile_cont aggr
ObExpr* linear_inter_expr_;
......@@ -160,7 +158,7 @@ public:
class GroupConcatExtraResult : public ExtraResult {
public:
explicit GroupConcatExtraResult(common::ObIAllocator& alloc)
: ExtraResult(alloc), row_count_(0), iter_idx_(0), sort_op_(NULL)
: ExtraResult(alloc), row_count_(0), iter_idx_(0), sort_op_(NULL), separator_datum_(NULL)
{}
virtual ~GroupConcatExtraResult();
void reuse_self();
......@@ -208,6 +206,7 @@ public:
{
return row_count_;
}
ObDatum *&get_separator_datum() { return separator_datum_; }
DECLARE_VIRTUAL_TO_STRING;
private:
......@@ -218,6 +217,7 @@ public:
ObChunkDatumStore::Iterator row_store_iter_;
ObSortOpImpl* sort_op_;
ObDatum *separator_datum_;
};
class AggrCell {
......
......@@ -760,6 +760,9 @@ int ObExprLike::like_varchar(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& expr_d
escape_val.assign_ptr("\\", 1);
} else {
escape_val = escape.get_string();
if (escape_val.empty()) {
escape_val.assign_ptr("\\", 1);
}
}
if (OB_SUCC(ret)) {
if (do_optimization && like_id != OB_INVALID_ID && (!text_val.empty()) && (!pattern_val.empty())) {
......
......@@ -29,7 +29,22 @@ ObExprLog::ObExprLog(ObIAllocator& alloc) : ObExprOperator(alloc, T_FUN_SYS_LOG,
int ObExprLog::calc_result_type2(
ObExprResType& type, ObExprResType& type1, ObExprResType& type2, ObExprTypeCtx& type_ctx) const
{
return calc_trig_function_result_type2(type, type1, type2, type_ctx);
int ret = OB_SUCCESS;
if (lib::is_mysql_mode()) {
if (NOT_ROW_DIMENSION != row_dimension_) {
ret = OB_ERR_INVALID_TYPE_FOR_OP; // arithmetic not support row
} else if (ObMaxType == type1.get_type() || ObMaxType == type2.get_type()) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
} else {
type.set_double();
type1.set_calc_type(type.get_type());
type2.set_calc_type(type.get_type());
ObExprOperator::calc_result_flag2(type, type1, type2);
}
} else if (OB_FAIL(calc_trig_function_result_type2(type, type1, type2, type_ctx))) {
LOG_WARN("failed to calc_trig_function_result_type2", K(ret));
} else {/*do nothing*/}
return ret;
}
int ObExprLog::calc_result2(ObObj& result, const ObObj& obj1, const ObObj& obj2, ObExprCtx& expr_ctx) const
......@@ -55,12 +70,26 @@ int ObExprLog::calc_result2(ObObj& result, const ObObj& obj1, const ObObj& obj2,
// binary_double, result type is double
double double_base = obj1.get_double();
double double_x = obj2.get_double();
double result_double = std::log(double_x) / std::log(double_base);
if (isinf(result_double) || isnan(result_double)) {
ret = OB_OPERATE_OVERFLOW;
if (lib::is_mysql_mode() && (double_base <= 0 || double_x <= 0)) {
LOG_USER_WARN(OB_EER_INVALID_ARGUMENT_FOR_LOGARITHM);
result.set_null();
} else {
result.set_double(result_double);
double result_double = std::log(double_x) / std::log(double_base);
if (isinf(result_double) || isnan(result_double)) {
if (lib::is_mysql_mode()) {
LOG_USER_WARN(OB_EER_INVALID_ARGUMENT_FOR_LOGARITHM);
result.set_null();
} else {
ret = OB_OPERATE_OVERFLOW;
}
} else {
result.set_double(result_double);
}
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get invalid calc type, expected number/double", K(get_type_name(obj1.get_type())),
K(get_type_name(obj2.get_type())), K(ret));
}
return ret;
}
......@@ -74,8 +103,18 @@ int calc_log_expr_double(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res_datum)
LOG_WARN("eval arg failed", K(ret), K(expr));
} else if (base->is_null() || x->is_null()) {
res_datum.set_null();
} else if (OB_FAIL(ObExprPow::safe_set_double(res_datum, std::log(x->get_double()) / std::log(base->get_double())))) {
LOG_WARN("set double failed", K(ret), K(base->get_double()), K(x->get_double()));
} else if (lib::is_mysql_mode() && (x->get_double() <= 0 || base->get_double() <= 0)) {
LOG_USER_WARN(OB_EER_INVALID_ARGUMENT_FOR_LOGARITHM);
res_datum.set_null();
} else if (OB_FAIL(ObExprPow::safe_set_double(res_datum,
std::log(x->get_double()) / std::log(base->get_double())))) {
if (lib::is_mysql_mode() && OB_OPERATE_OVERFLOW == ret) {
ret = OB_SUCCESS;
LOG_USER_WARN(OB_EER_INVALID_ARGUMENT_FOR_LOGARITHM);
res_datum.set_null();
} else {
LOG_WARN("set double failed", K(ret), K(base->get_double()), K(x->get_double()));
}
}
return ret;
}
......
......@@ -645,6 +645,7 @@ void ObExprOperatorFactory::register_expr_operators()
REG_OP(ObExprAtan2);
REG_OP(ObExprToOutfileRow);
REG_OP(ObExprFormat);
REG_OP(ObExprLog);
// register oracle system function
REG_OP_ORCL(ObExprSysConnectByPath);
REG_OP_ORCL(ObExprTimestampNvl);
......
......@@ -30,3 +30,4 @@ flex -Cfa -B -8 -o ../../../src/sql/parser/sql_parser_mysql_mode_lex.c ../../../
sed "/Setup the input buffer state to scan the given bytes/,/}/{/int i/d}" -i sql_parser_mysql_mode_lex.c
sed "/Setup the input buffer state to scan the given bytes/,/}/{/for ( i = 0; i < _yybytes_len; ++i )/d}" -i sql_parser_mysql_mode_lex.c
sed "/Setup the input buffer state to scan the given bytes/,/}/{s/\tbuf\[i\] = yybytes\[i\]/memcpy(buf, yybytes, _yybytes_len)/g}" -i sql_parser_mysql_mode_lex.c
sed "/YY_EXIT_FAILURE/,/}/{s/yyconst char\* msg , yyscan_t yyscanner/yyconst char* msg , yyscan_t yyscanner __attribute__((unused))/g}" -i sql_parser_mysql_mode_lex.c
\ No newline at end of file
......@@ -262,6 +262,7 @@ static const NonReservedKeyword Mysql_none_reserved_keywords[] = {{"access", ACC
{"linestring", LINESTRING},
{"list", LIST_},
{"listagg", LISTAGG},
{"ln", LN},
{"local", LOCAL},
{"locality", LOCALITY},
{"location", LOCATION},
......@@ -269,6 +270,7 @@ static const NonReservedKeyword Mysql_none_reserved_keywords[] = {{"access", ACC
{"locks", LOCKS},
{"logfile", LOGFILE},
{"logonly_replica_num", LOGONLY_REPLICA_NUM},
{"log", LOG},
{"logs", LOGS},
{"major", MAJOR},
{"manual", MANUAL},
......
......@@ -1085,6 +1085,7 @@ typedef enum ObItemType {
T_SFU_INT,
T_SFU_DECIMAL,
T_SFU_DOUBLE,
T_FOR_UPDATE,
T_DEFAULT_INT,
T_DEFAULT_NULL,
......
......@@ -54,8 +54,8 @@ bool ObParser::is_single_stmt(const ObString& stmt)
// In multi-stmt mode(delimiter #) eg: create t1; create t2; create t3
// in the case of is_ret_first_stmt(false), queries will return the following stmts:
// queries[0]: create t1; create t2; create t3;
// queries[1]: create t2; create t3;
// queries[0]: create t1;
// queries[1]: create t2;
// queries[2]: create t3;
// in the case of is_ret_first_stmt(true) and it will return one element
// queries[0]: create t1;
......@@ -92,39 +92,45 @@ int ObParser::split_multiple_stmt(
}
int tmp_ret = OB_SUCCESS;
while (remain > 0 && OB_SUCC(ret) && !parse_stat.parse_fail_) {
bool need_continue = true;
while (remain > 0 && OB_SUCC(ret) && !parse_stat.parse_fail_ && need_continue) {
ObArenaAllocator allocator(CURRENT_CONTEXT.get_malloc_allocator());
allocator.set_label("SplitMultiStmt");
ObIAllocator* bak_allocator = allocator_;
allocator_ = &allocator;
ObString part(remain, stmt.ptr() + offset);
if (OB_SUCC(tmp_ret = parse(part, parse_result, parse_mode))) {
// length: length of the remainer statements
// size: length of the single statement
int64_t str_len = 0;
//for save memory allocate in parser, we need try find the single stmt length in advance
while (stmt[str_len + offset] != ';' && str_len < remain) {
++ str_len;
}
str_len = str_len == remain ? str_len : str_len + 1;
ObString part(str_len, stmt.ptr() + offset);
ObString remain_part(remain, stmt.ptr() + offset);
//first try parse part str, because it's have less length and need less memory
if (OB_FAIL(tmp_ret = parse(part, parse_result, parse_mode))) {
//if parser part str failed, then try parse all remain part, avoid parse many times:
//bug: https://work.aone.alibaba-inc.com/issue/34642901
tmp_ret = OB_SUCCESS;
tmp_ret = parse(remain_part, parse_result, parse_mode);
}
if (OB_SUCC(tmp_ret)) {
int32_t single_stmt_length = parse_result.end_col_;
if ((!is_ret_first_stmt) && (';' == *(stmt.ptr() + offset + parse_result.end_col_ - 1))) {
--single_stmt_length;
}
if (is_ret_first_stmt) {
ObString first_query(single_stmt_length, stmt.ptr());
ret = queries.push_back(first_query);
break; // only return the first stmt, so ignore the remaining stmts
need_continue = false; // only return the first stmt, so ignore the remaining stmts
} else {
ObString query(single_stmt_length, static_cast<int32_t>(remain), stmt.ptr() + offset);
ObString query(single_stmt_length,stmt.ptr() + offset);
ret = queries.push_back(query);
}
remain -= parse_result.end_col_;
offset += parse_result.end_col_;
if (remain < 0 || offset > stmt.length()) {
LOG_ERROR("split_multiple_stmt data error", K(remain), K(offset), K(stmt.length()), K(ret));
LOG_ERROR("split_multiple_stmt data error",
K(remain), K(offset), K(stmt.length()), K(ret));
}
} else {
int32_t single_stmt_length = parse_result.end_col_;
if (';' == *(stmt.ptr() + offset + parse_result.end_col_ - 1)) {
--single_stmt_length;
}
ObString query(single_stmt_length, static_cast<int32_t>(remain), stmt.ptr() + offset);
ObString query(static_cast<int32_t>(remain), stmt.ptr() + offset);
ret = queries.push_back(query);
if (OB_SUCCESS == ret) {
parse_stat.parse_fail_ = true;
......
......@@ -96,7 +96,8 @@
%left AND AND_OP
%left BETWEEN CASE WHEN THEN ELSE
%nonassoc LOWER_THAN_COMP
%left COMP_EQ COMP_NSEQ COMP_GE COMP_GT COMP_LE COMP_LT COMP_NE IS LIKE IN REGEXP
%left COMP_EQ COM P_NSEQ COMP_GE COMP_GT COMP_LE COMP_LT COMP_NE IS LIKE IN REGEXP
%nonassoc STRING_VALUE
%right ESCAPE /*for conflict for escape*/
%left '|'
%left '&'
......@@ -108,8 +109,9 @@
%left CNNOP
%left NEG '~'
%nonassoc LOWER_PARENS
//%nonassoc STRING_VALUE
%left '(' ')'
%nonassoc HIGHER_PARENS TRANSACTION/*for simple_expr conflict*/
%nonassoc HIGHER_PARENS TRANSACTION /*for simple_expr conflict*/
%left '.'
%right NOT NOT2
%right BINARY COLLATE
......@@ -232,7 +234,7 @@ END_P SET_VAR DELIMITER
LAG LANGUAGE LAST LAST_VALUE LEAD LEADER LEAVES LESS LEAK LEAK_MOD LEAK_RATE LINESTRING LIST_
LISTAGG LOCAL LOCALITY LOCATION LOCKED LOCKS LOGFILE LOGONLY_REPLICA_NUM LOGS LOCK_ LOGICAL_READS
LEVEL
LEVEL LN LOG
MAJOR MANUAL MASTER MASTER_AUTO_POSITION MASTER_CONNECT_RETRY MASTER_DELAY MASTER_HEARTBEAT_PERIOD
MASTER_HOST MASTER_LOG_FILE MASTER_LOG_POS MASTER_PASSWORD MASTER_PORT MASTER_RETRY_COUNT
......@@ -397,14 +399,14 @@ END_P SET_VAR DELIMITER
%type <node> opt_index_name opt_key_or_index opt_index_options opt_primary opt_all
%type <node> charset_key database_key charset_name charset_name_or_default collation_name databases_or_schemas trans_param_name trans_param_value
%type <node> set_names_stmt set_charset_stmt
%type <node> charset_introducer opt_charset_introducer complex_string_literal literal number_literal now_or_signed_literal signed_literal
%type <node> charset_introducer complex_string_literal literal number_literal now_or_signed_literal signed_literal
%type <node> create_tablegroup_stmt drop_tablegroup_stmt alter_tablegroup_stmt default_tablegroup
%type <node> set_transaction_stmt transaction_characteristics transaction_access_mode isolation_level
%type <node> lock_tables_stmt unlock_tables_stmt lock_type lock_table_list lock_table opt_local
%type <node> purge_stmt
%type <node> tenant_name_list opt_tenant_list tenant_list_tuple cache_type flush_scope opt_zone_list
%type <node> into_opt into_clause field_opt field_term field_term_list line_opt line_term line_term_list into_var_list into_var
%type <node> string_list text_string
%type <node> string_list text_string string_val_list
%type <node> balance_task_type opt_balance_task_type
%type <node> list_expr list_partition_element list_partition_expr list_partition_list list_partition_option opt_list_partition_list opt_list_subpartition_list list_subpartition_list list_subpartition_element drop_partition_name_list
%type <node> primary_zone_name locality_name change_tenant_name_or_tenant_id distribute_method opt_distribute_method
......@@ -711,30 +713,25 @@ column_name
}
;
opt_charset_introducer:
/*empty*/
{
$$ = NULL;
}
| charset_introducer
{
$$ = $1;
};
/* literal string with */
complex_string_literal:
opt_charset_introducer STRING_VALUE
STRING_VALUE %prec LOWER_THAN_COMP
{
malloc_non_terminal_node($$, result->malloc_pool_, T_VARCHAR, 2, NULL, $1);
$$->str_value_ = $1->str_value_;
$$->str_len_ = $1->str_len_;
$$->raw_text_ = $1->raw_text_;
$$->text_len_ = $1->text_len_;
@$.first_column = @1.first_column;
@$.last_column = @1.last_column;
}
| charset_introducer STRING_VALUE
{
malloc_non_terminal_node($$, result->malloc_pool_, T_VARCHAR, 2, $1, $2);
$$->str_value_ = $2->str_value_;
$$->str_len_ = $2->str_len_;
$$->raw_text_ = $2->raw_text_;
$$->text_len_ = $2->text_len_;
if (NULL == $1)
{
@$.first_column = @2.first_column;
@$.last_column = @2.last_column;
}
}
| charset_introducer HEX_STRING_VALUE
{
......@@ -1013,7 +1010,19 @@ bit_expr IN in_expr
//In the resolver, if only two children are found, the escape parameter will be set to '\'
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 2, $1, $3);
}
| bit_expr LIKE simple_expr ESCAPE simple_expr %prec LIKE
| bit_expr LIKE STRING_VALUE string_val_list %prec LOWER_THAN_COMP
{
//在resolver时,如果发现只有两个children,会将escape 参数设置为‘\’
ParseNode *str_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $3, $4);
ParseNode *string_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, string_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 2, $1, concat_node);
}
| bit_expr LIKE simple_expr ESCAPE simple_expr %prec LIKE
{
// If escape is an empty string '', the default value'\' is used
if (OB_UNLIKELY(T_VARCHAR == $5->type_ && 0 == $5->str_len_)) {
......@@ -1026,12 +1035,74 @@ bit_expr IN in_expr
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 3, $1, $3, $5);
}
}
| bit_expr LIKE STRING_VALUE string_val_list ESCAPE simple_expr %prec LIKE
{
// 如果escape 为空串 '', 则使用默认值'\'
ParseNode *str_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $3, $4);
ParseNode *string_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, string_list_node);
if (OB_UNLIKELY(T_VARCHAR == $6->type_ && 0 == $6->str_len_)) {
ParseNode *node = NULL;
malloc_terminal_node(node, result->malloc_pool_, T_VARCHAR);
node->str_value_ = "\\";
node->str_len_ = 1;
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 3, $1, concat_node, node);
} else {
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 3, $1, concat_node, $6);
}
}
| bit_expr LIKE simple_expr ESCAPE STRING_VALUE string_val_list %prec LIKE
{
ParseNode *escape_node = NULL;
malloc_non_terminal_node(escape_node, result->malloc_pool_, T_LINK_NODE, 2, $5, $6);
ParseNode *escape_list_node = NULL;
merge_nodes(escape_list_node, result, T_EXPR_LIST, escape_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, escape_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 3, $1, $3, concat_node);
}
| bit_expr LIKE STRING_VALUE string_val_list ESCAPE STRING_VALUE string_val_list %prec LIKE
{
ParseNode *str_node = NULL;
ParseNode *escape_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $3, $4);
malloc_non_terminal_node(escape_node, result->malloc_pool_, T_LINK_NODE, 2, $6, $7);
ParseNode *string_list_node = NULL;
ParseNode *escape_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
merge_nodes(escape_list_node, result, T_EXPR_LIST, escape_node);
ParseNode *concat_node1 = NULL;
ParseNode *concat_node2 = NULL;
make_name_node(concat_node1, result->malloc_pool_, "concat");
make_name_node(concat_node2, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node1, result->malloc_pool_, T_FUN_SYS, 2, concat_node1, string_list_node);
malloc_non_terminal_node(concat_node2, result->malloc_pool_, T_FUN_SYS, 2, concat_node2, escape_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_LIKE, 3, $1, concat_node1, concat_node2);
}
| bit_expr not LIKE simple_expr
{
(void)($2);
//In the resolver, if only two children are found, the escape parameter will be set to '\'
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 2, $1, $4);
}
| bit_expr not LIKE STRING_VALUE string_val_list %prec LOWER_THAN_COMP
{
(void)($2);
//在resolver时,如果发现只有两个children,会将escape 参数设置为‘\’
ParseNode *str_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $4, $5);
ParseNode *string_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, string_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 2, $1, concat_node);
}
| bit_expr not LIKE simple_expr ESCAPE simple_expr %prec LIKE
{
(void)($2);
......@@ -1046,19 +1117,104 @@ bit_expr IN in_expr
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 3, $1, $4, $6);
}
}
| bit_expr not LIKE STRING_VALUE string_val_list ESCAPE simple_expr %prec LIKE
{
(void)($2);
ParseNode *str_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $4, $5);
ParseNode *string_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, string_list_node);
// 如果escape 为空串 '', 则使用默认值'\'
if (OB_UNLIKELY(T_VARCHAR == $7->type_ && 0 == $7->str_len_)) {
ParseNode *node = NULL;
malloc_terminal_node(node, result->malloc_pool_, T_VARCHAR);
node->str_value_ = "\\";
node->str_len_ = 1;
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 3, $1, concat_node, node);
} else {
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 3, $1, concat_node, $7);
}
}
| bit_expr not LIKE simple_expr ESCAPE STRING_VALUE string_val_list %prec LIKE
{
(void)($2);
ParseNode *escape_node = NULL;
malloc_non_terminal_node(escape_node, result->malloc_pool_, T_LINK_NODE, 2, $6, $7);
ParseNode *escape_list_node = NULL;
merge_nodes(escape_list_node, result, T_EXPR_LIST, escape_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, escape_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 3, $1, $4, concat_node);
}
| bit_expr not LIKE STRING_VALUE string_val_list ESCAPE STRING_VALUE string_val_list %prec LIKE
{
(void)($2);
ParseNode *str_node = NULL;
ParseNode *escape_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $4, $5);
malloc_non_terminal_node(escape_node, result->malloc_pool_, T_LINK_NODE, 2, $7, $8);
ParseNode *string_list_node = NULL;
ParseNode *escape_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
merge_nodes(escape_list_node, result, T_EXPR_LIST, escape_node);
ParseNode *concat_node1 = NULL;
ParseNode *concat_node2 = NULL;
make_name_node(concat_node1, result->malloc_pool_, "concat");
make_name_node(concat_node2, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node1, result->malloc_pool_, T_FUN_SYS, 2, concat_node1, string_list_node);
malloc_non_terminal_node(concat_node2, result->malloc_pool_, T_FUN_SYS, 2, concat_node2, escape_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_LIKE, 3, $1, concat_node1, concat_node2);
}
| bit_expr REGEXP bit_expr
{
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_REGEXP, 2, $1, $3);
}
| bit_expr REGEXP STRING_VALUE string_val_list %prec LOWER_THAN_COMP
{
ParseNode *str_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $3, $4);
ParseNode *string_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, string_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_REGEXP, 2, $1, concat_node);
}
| bit_expr not REGEXP bit_expr
{
(void)($2);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_REGEXP, 2, $1, $4);
}
| bit_expr not REGEXP STRING_VALUE string_val_list %prec LOWER_THAN_COMP
{
(void)($2);
ParseNode *str_node = NULL;
malloc_non_terminal_node(str_node, result->malloc_pool_, T_LINK_NODE, 2, $4, $5);
ParseNode *string_list_node = NULL;
merge_nodes(string_list_node, result, T_EXPR_LIST, str_node);
ParseNode *concat_node = NULL;
make_name_node(concat_node, result->malloc_pool_, "concat");
malloc_non_terminal_node(concat_node, result->malloc_pool_, T_FUN_SYS, 2, concat_node, string_list_node);
malloc_non_terminal_node($$, result->malloc_pool_, T_OP_NOT_REGEXP, 2, $1, concat_node);
}
| bit_expr %prec LOWER_THAN_COMP
{ $$ = $1; }
;
string_val_list:
STRING_VALUE
{
$$ = $1;
}
| string_val_list STRING_VALUE
{
malloc_non_terminal_node($$, result->malloc_pool_, T_LINK_NODE, 2, $1, $2);
};
bit_expr:
bit_expr '|' bit_expr %prec '|'
{
......@@ -2231,6 +2387,47 @@ MOD '(' expr ',' expr ')'
make_name_node($$, result->malloc_pool_, "char");
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, params_node);
}
| LOG '(' expr ',' expr ')'
{
ParseNode *params = NULL;
malloc_non_terminal_node(params, result->malloc_pool_, T_EXPR_LIST, 2, $3, $5);
make_name_node($$, result->malloc_pool_, "log");
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, params);
}
| LOG '(' expr ')'
{
ParseNode *param_node = NULL;
malloc_terminal_node(param_node, result->malloc_pool_, T_SFU_DOUBLE);
int64_t len = strlen("2.718281828459045");
param_node->str_value_ = parse_strndup("2.718281828459045", len, result->malloc_pool_);
if (OB_UNLIKELY(NULL == param_node->str_value_)) {
yyerror(NULL, result, "No more space for mallocing string\n");
YYABORT_NO_MEMORY;
}
param_node->str_len_ = len;
ParseNode *param_list_node = NULL;
malloc_non_terminal_node(param_list_node, result->malloc_pool_, T_LINK_NODE, 2, param_node, $3);
merge_nodes(param_list_node, result, T_EXPR_LIST, param_list_node);
make_name_node($$, result->malloc_pool_, "log");
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, param_list_node);
}
| LN '(' expr ')'
{
ParseNode *param_node = NULL;
malloc_terminal_node(param_node, result->malloc_pool_, T_SFU_DOUBLE);
int64_t len = strlen("2.718281828459045");
param_node->str_value_ = parse_strndup("2.718281828459045", len, result->malloc_pool_);
if (OB_UNLIKELY(NULL == param_node->str_value_)) {
yyerror(NULL, result, "No more space for mallocing string\n");
YYABORT_NO_MEMORY;
}
param_node->str_len_ = len;
ParseNode *param_list_node = NULL;
malloc_non_terminal_node(param_list_node, result->malloc_pool_, T_LINK_NODE, 2, param_node, $3);
merge_nodes(param_list_node, result, T_EXPR_LIST, param_list_node);
make_name_node($$, result->malloc_pool_, "log");
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, param_list_node);
}
| function_name '(' opt_expr_as_list ')'
{
if (NULL != $3)
......@@ -12611,10 +12808,12 @@ ACCOUNT
| LINESTRING
| LIST_
| LISTAGG
| LN
| LOCAL
| LOCALITY
| LOCKED
| LOCKS
| LOG
| LOGFILE
| LOGONLY_REPLICA_NUM
| LOGS
......
此差异已折叠。
......@@ -269,7 +269,9 @@ bool ObSqlParameterization::is_tree_not_param(const ParseNode* tree)
ret_bool = true;
} else if (T_FUN_SYS_CUR_DATE == tree->type_) {
ret_bool = true;
} else if (T_SFU_INT == tree->type_ || T_SFU_DECIMAL == tree->type_) {
} else if (T_SFU_INT == tree->type_ ||
T_SFU_DECIMAL == tree->type_ ||
T_SFU_DOUBLE == tree->type_) {
ret_bool = true;
} else if (T_CYCLE_NODE == tree->type_) {
ret_bool = true;
......
......@@ -250,6 +250,14 @@ int ObRawExprResolverImpl::do_recursive_resolve(const ParseNode* node, ObRawExpr
}
break;
}
case T_SFU_DOUBLE: {
ParseNode *tmp_node = const_cast<ParseNode *>(node);
tmp_node->type_ = T_DOUBLE;
if (OB_FAIL(process_datatype_or_questionmark(*tmp_node, expr))) {
LOG_WARN("fail to process datetype or questionmark", K(ret), K(tmp_node));
} else {/*do nothing*/}
break;
}
case T_CAST_ARGUMENT: {
ObConstRawExpr* c_expr = NULL;
if (OB_FAIL(ctx_.expr_factory_.create_raw_expr(T_INT, c_expr))) {
......
......@@ -4152,6 +4152,8 @@ int ObQueryRange::get_like_range(
}
} else if (OB_FAIL(escape.get_string(escape_str))) {
LOG_WARN("failed to get escape string", K(escape), K(ret));
} else if (escape_str.empty()) {
escape_str.assign_ptr("\\", 1);
} else { /* do nothing */
}
if (OB_FAIL(ret)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册