提交 a2b5b777 编写于 作者: A al0 提交者: LINGuanRen

implement of any value expr in mysql mode

上级 d467ca3d
......@@ -335,6 +335,7 @@
#define N_INDEX_FILTER_EXPRS "index_filter_exprs"
#define N_OPERATOR_MONITOR_INFO "op_info"
#define N_PLAN_MONITOR_INFO "plan_info"
#define N_ANY_VAL "any_value"
// common comparison operator
#define N_LESS_THAN "<"
#define N_GREATER_THAN ">"
......
......@@ -164,6 +164,8 @@ ob_set_subtarget(ob_sql engine
engine/expr/ob_expr.cpp
engine/expr/ob_expr_frame_info.cpp
engine/expr/ob_expr_user_can_access_obj.cpp
engine/expr/ob_expr_any_value.h
engine/expr/ob_expr_any_value.cpp
engine/pdml/ob_batch_row_cache.cpp
engine/pdml/ob_pdml_data_driver.cpp
engine/pdml/ob_px_multi_part_modify.cpp
......@@ -950,6 +952,8 @@ ob_set_subtarget(ob_sql resolver
resolver/dml/ob_update_stmt.cpp
resolver/dml/ob_view_table_resolver.cpp
resolver/dml/ob_multi_table_insert_resolver.cpp
resolver/dml/ob_any_value_checker.h
resolver/dml/ob_any_value_checker.cpp
resolver/expr/ob_expr_relation_analyzer.cpp
resolver/expr/ob_raw_expr.cpp
resolver/expr/ob_expr.cpp
......
/*
* Copyright 2014-2021 Alibaba Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* ob_expr_any_value.cpp is for any_value function
*
* Date: 2021/7/9
*
* Authors:
* ailing.lcq<ailing.lcq@alibaba-inc.com>
*
*/
#include "sql/engine/expr/ob_expr_any_value.h"
using namespace oceanbase::common;
namespace oceanbase {
namespace sql {
ObExprAnyValue::ObExprAnyValue(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_ANY_VALUE, N_ANY_VAL, 1, NOT_ROW_DIMENSION)
{}
ObExprAnyValue::~ObExprAnyValue()
{}
int ObExprAnyValue::calc_result_type1(ObExprResType &type, ObExprResType &arg, common::ObExprTypeCtx &) const
{
int ret = OB_SUCCESS;
type = arg;
return ret;
}
int ObExprAnyValue::calc_result1(common::ObObj &result, const common::ObObj &arg, common::ObExprCtx &expr_ctx) const
{
UNUSED(expr_ctx);
int ret = OB_SUCCESS;
result = arg;
return ret;
}
int ObExprAnyValue::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const
{
UNUSED(raw_expr);
UNUSED(expr_cg_ctx);
rt_expr.eval_func_ = ObExprAnyValue::eval_any_value;
return OB_SUCCESS;
}
int ObExprAnyValue::eval_any_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
{
int ret = OB_SUCCESS;
ObDatum *arg = NULL;
if (OB_FAIL(expr.eval_param_value(ctx, arg))) {
SERVER_LOG(WARN, "expr evaluate parameter failed", K(ret));
} else {
expr_datum.set_datum(*arg);
}
return ret;
}
} // namespace sql
} // namespace oceanbase
/*
* Copyright 2014-2021 Alibaba Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* ob_expr_any_value.h is for any_value function
*
* Date: 2021/7/9
*
* Authors:
* ailing.lcq<ailing.lcq@alibaba-inc.com>
*
*/
#ifndef _OB_EXPR_ANY_VALUE_H_
#define _OB_EXPR_ANY_VALUE_H_
#include "sql/engine/expr/ob_expr_operator.h"
namespace oceanbase {
namespace sql {
class ObExprAnyValue : public ObFuncExprOperator {
public:
explicit ObExprAnyValue(common::ObIAllocator &alloc);
virtual ~ObExprAnyValue();
virtual int calc_result_type1(
ObExprResType &type, ObExprResType &arg, common::ObExprTypeCtx &type_ctx) const override;
virtual int calc_result1(common::ObObj &result, const common::ObObj &arg, common::ObExprCtx &expr_ctx) const override;
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override;
static int eval_any_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
private:
DISALLOW_COPY_AND_ASSIGN(ObExprAnyValue) const;
};
} // namespace sql
} // namespace oceanbase
#endif /* _OB_EXPR_ANY_VALUE_H_ */
// select any_value();
\ No newline at end of file
......@@ -186,6 +186,7 @@
#include "ob_expr_convert_tz.h"
#include "ob_expr_degrees.h"
#include "ob_expr_weight_string.h"
#include "ob_expr_any_value.h"
namespace oceanbase {
using namespace common;
......@@ -671,7 +672,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
ObExprPeriodAdd::calc_periodadd, /* 409 */
NULL, /* 410 */
NULL, /* 411 */
NULL, /* 412 */
ObExprAnyValue::eval_any_value, /* 412 */
NULL, /* 413 */
ObExprDegrees::calc_degrees_expr, /* 414 */
NULL, /* 415 */
......
......@@ -270,6 +270,7 @@
#include "sql/engine/expr/ob_expr_convert_tz.h"
#include "sql/engine/expr/ob_expr_degrees.h"
#include "sql/engine/expr/ob_expr_weight_string.h"
#include "sql/engine/expr/ob_expr_any_value.h"
using namespace oceanbase::common;
namespace oceanbase {
......@@ -610,6 +611,7 @@ void ObExprOperatorFactory::register_expr_operators()
REG_OP(ObExprTruncate);
REG_OP(ObExprDllUdf);
REG_OP(ObExprExp);
REG_OP(ObExprAnyValue);
/* subquery comparison experator */
REG_OP(ObExprSubQueryRef);
REG_OP(ObExprSubQueryEqual);
......
......@@ -426,6 +426,7 @@ typedef enum ObItemType {
T_FUN_SYS_QUARTER = 711,
T_FUN_SYS_BIT_LENGTH = 712,
T_FUN_SYS_PI = 713,
T_FUN_SYS_ANY_VALUE = 714,
T_FUN_SYS_DEGREES = 715,
T_FUN_SYS_EXPORT_SET = 721,
......
......@@ -371,6 +371,7 @@ const char* get_type_name(int type)
case T_FUN_SYS_QUARTER : return "T_FUN_SYS_QUARTER";
case T_FUN_SYS_BIT_LENGTH : return "T_FUN_SYS_BIT_LENGTH";
case T_FUN_SYS_PI : return "T_FUN_SYS_PI";
case T_FUN_SYS_ANY_VALUE : return "T_FUN_SYS_ANY_VALUE";
case T_FUN_SYS_DEGREES : return "T_FUN_SYS_DEGREES";
case T_FUN_SYS_EXPORT_SET : return "T_FUN_SYS_EXPORT_SET";
case T_FUN_SYS_INET6NTOA : return "T_FUN_SYS_INET6NTOA";
......
/**
* Copyright 2014-2021 Alibaba Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*
* Date: 2021/07/14
*
* ob_any_value_checker.h is for checking any_value expr in mysql's only_full_group_by mode compatible
*
* Authors:
* ailing.lcq<ailing.lcq@alibaba-inc.com>
*/
#define USING_LOG_PREFIX SQL_RESV
#include "sql/resolver/dml/ob_any_value_checker.h"
#include "sql/rewrite/ob_transform_utils.h"
#include "lib/oblog/ob_log_module.h"
//#include "lib/utility/ob_macro_utils.h"
namespace oceanbase {
namespace sql {
int ObAnyValueChecker::visit(ObSysFunRawExpr &expr)
{
if (T_FUN_SYS_ANY_VALUE == expr.get_expr_type()) {
set_skip_expr(&expr);
}
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObColumnRefRawExpr &expr)
{
if (undefined_column_ == &expr) {
is_pass_ = false;
}
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObConstRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObVarRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObQueryRefRawExpr &expr)
{
int ret = OB_SUCCESS;
const ObSelectStmt *ref_stmt = expr.get_ref_stmt();
if (OB_FAIL(check_select_stmt(ref_stmt))) {
LOG_WARN("failed to check select stmt", K(ret));
}
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObOpRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObCaseOpRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObAggFunRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObSetOpRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObAliasRefRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObFunMatchAgainst &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObWinFunRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::visit(ObPseudoColumnRawExpr &expr)
{
UNUSED(expr);
return OB_SUCCESS;
}
int ObAnyValueChecker::check_select_stmt(const ObSelectStmt *ref_stmt)
{
int ret = OB_SUCCESS;
bool ref_query = false;
LOG_DEBUG("check any value start stmt", K(ret));
if (OB_ISNULL(ref_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("ref_stmt should not be NULL", K(ret));
} else if (OB_FAIL(
ObTransformUtils::is_ref_outer_block_relation(ref_stmt, ref_stmt->get_current_level(), ref_query))) {
LOG_WARN("failed to get ref stmt", K(ret));
} else if (!ref_query) {
// non ref query
} else {
int32_t ignore_scope = 0;
if (ref_stmt->is_order_siblings()) {
ignore_scope |= RelExprCheckerBase::ORDER_SCOPE;
}
ObArray<ObRawExpr *> relation_expr_pointers;
if (OB_FAIL(ref_stmt->get_relation_exprs(relation_expr_pointers, ignore_scope))) {
LOG_WARN("get stmt relation exprs fail", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < relation_expr_pointers.count(); ++i) {
ObRawExpr *expr = relation_expr_pointers.at(i);
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr in relation_expr_pointers is null", K(i), K(relation_expr_pointers));
} else if (OB_FAIL(expr->preorder_accept(*this))) {
LOG_WARN("fail to check group by", K(i), K(ret));
}
}
if (OB_SUCC(ret)) {
const ObIArray<ObSelectStmt *> &child_stmts = ref_stmt->get_set_query();
for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
ret = check_select_stmt(child_stmts.at(i));
}
}
}
LOG_DEBUG("check any value end stmt", K(ret));
return ret;
}
int ObAnyValueChecker::check_any_value(const ObRawExpr *expr, const ObColumnRefRawExpr *undefined_column)
{
int ret = OB_SUCCESS;
undefined_column_ = undefined_column;
ObRawExpr *expr_ = const_cast<ObRawExpr *>(expr);
if (OB_ISNULL(expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null");
} else if (OB_FAIL(expr_->preorder_accept(*this))) {
LOG_WARN("check any value expr fail", K(ret));
}
return ret;
}
bool ObAnyValueChecker::is_pass_after_check()
{
return is_pass_;
}
} // namespace sql
} // namespace oceanbase
\ No newline at end of file
/**
* Copyright 2014-2021 Alibaba Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*
* Date: 2021/07/14
*
* ob_any_value_checker.h is for checking any_value expr in mysql's only_full_group_by mode compatible
*
* Authors:
* ailing.lcq<ailing.lcq@alibaba-inc.com>
*/
#ifndef OCEANBASE_SRC_SQL_RESOLVER_DML_OB_ANY_VALUE_CHECKER_H_
#define OCEANBASE_SRC_SQL_RESOLVER_DML_OB_ANY_VALUE_CHECKER_H_
#include "sql/resolver/expr/ob_raw_expr.h"
#include "sql/resolver/dml/ob_select_stmt.h"
namespace oceanbase {
namespace sql {
class ObAnyValueChecker : public ObRawExprVisitor {
public:
ObAnyValueChecker() : ObRawExprVisitor(), skip_expr_(nullptr), is_pass_(true)
{}
virtual ~ObAnyValueChecker()
{}
/// interface of ObRawExprVisitor
virtual int visit(ObConstRawExpr &expr);
virtual int visit(ObVarRawExpr &expr);
virtual int visit(ObQueryRefRawExpr &expr);
virtual int visit(ObColumnRefRawExpr &expr);
virtual int visit(ObOpRawExpr &expr);
virtual int visit(ObCaseOpRawExpr &expr);
virtual int visit(ObAggFunRawExpr &expr);
virtual int visit(ObSysFunRawExpr &expr);
virtual int visit(ObSetOpRawExpr &expr);
virtual int visit(ObAliasRefRawExpr &expr);
virtual int visit(ObFunMatchAgainst &expr);
virtual int visit(ObWinFunRawExpr &expr);
virtual int visit(ObPseudoColumnRawExpr &expr);
// set expr skip
virtual bool skip_child(ObRawExpr &expr)
{
return skip_expr_ == &expr;
}
int check_select_stmt(const ObSelectStmt *ref_stmt);
int check_any_value(const ObRawExpr *expr, const ObColumnRefRawExpr *undefined_column);
bool is_pass_after_check();
private:
void set_skip_expr(ObRawExpr *expr)
{
skip_expr_ = expr;
}
const ObColumnRefRawExpr *undefined_column_;
ObRawExpr *skip_expr_;
bool is_pass_;
// disallow copy
DISALLOW_COPY_AND_ASSIGN(ObAnyValueChecker);
};
} // namespace sql
} // namespace oceanbase
#endif // OCEANBASE_SRC_SQL_RESOLVER_DML_OB_ANY_VALUE_CHECKER_H_
......@@ -13,6 +13,7 @@
#define USING_LOG_PREFIX SQL_RESV
#include "sql/resolver/dml/ob_standard_group_checker.h"
#include "sql/resolver/expr/ob_raw_expr.h"
#include "sql/resolver/dml/ob_any_value_checker.h"
namespace oceanbase {
using namespace common;
namespace sql {
......@@ -96,7 +97,8 @@ int ObStandardGroupChecker::check_only_full_group_by()
// not check aggregate function or column in aggregate function, such as select count(c1) from t1 group by c2;
// but if expr has column outside of aggregate function, we only check the column not in aggregate function
// such as: select c1+count(c2) from t1 group by c1;
const ObUnsettledExprItem& unsettled_expr = unsettled_exprs_.at(i);
const ObUnsettledExprItem &unsettled_expr = unsettled_exprs_.at(i);
common::ObArray<const ObColumnRefRawExpr *> undefined_columns;
for (int64_t j = unsettled_expr.start_idx_;
OB_SUCC(ret) && j < unsettled_expr.start_idx_ + unsettled_expr.dependent_column_cnt_;
++j) {
......@@ -110,13 +112,22 @@ int ObStandardGroupChecker::check_only_full_group_by()
} else if (OB_FAIL(check_unsettled_column(unsettled_column, undefined_column))) {
LOG_WARN("check unsettled column failed", K(ret));
} else if (undefined_column != NULL) {
break;
//当前stmt中存在undefined的列,根据only full group
//by语义,如果一个表达式中所有列都是defined,那么该表达式是defined
//如果所有列不能保证defined,需要看看表达式本身是否是defined
//例如:select c1+c2 from t1 group by c1, c1+c2
// c1是defined列,c2不是,c1+c2整体是defined,所以这条语句满足only full group by
undefined_columns.push_back(undefined_column);
undefined_column = NULL;
}
}
if (OB_SUCC(ret) && undefined_column != NULL) {
// has undefined column, must check expr whether defined in group by
if (OB_FAIL(check_unsettled_expr(unsettled_expr.expr_, *undefined_column))) {
LOG_WARN("check unsettled expr failed", K(ret));
if (OB_SUCC(ret) && 0 != undefined_columns.size()) {
// has undefined column, must check expr whether defined in group by or in any_value
for (int64_t i = 0; OB_SUCC(ret) && i < undefined_columns.size(); ++i) {
if (OB_FAIL(check_unsettled_expr(unsettled_expr.expr_, *(undefined_columns.at(i))))) {
LOG_WARN("check unsettled expr failed", K(ret));
break;
}
}
}
if (OB_SUCC(ret) && !unsettled_expr.expr_->has_flag(CNT_AGG)) {
......@@ -180,9 +191,6 @@ int ObStandardGroupChecker::check_unsettled_expr(
// but if expr has column outside of aggregate function, we only check the column not in aggregate function
// such as: select c1+count(c2) from t1 group by c1;
ret = OB_ERR_WRONG_FIELD_WITH_GROUP;
ObString column_name = concat_qualified_name(
undefined_column.get_database_name(), undefined_column.get_table_name(), undefined_column.get_column_name());
LOG_USER_ERROR(OB_ERR_WRONG_FIELD_WITH_GROUP, column_name.length(), column_name.ptr());
LOG_DEBUG("column not in group by", K(*unsettled_expr), K(undefined_column));
} else if (OB_HASH_EXIST == (ret = settled_columns_.exist_refactored(reinterpret_cast<int64_t>(unsettled_expr)))) {
// this expr satisfy the only full group by semantic constraints
......@@ -201,13 +209,30 @@ int ObStandardGroupChecker::check_unsettled_expr(
}
if (OB_SUCC(ret) && !is_defined) {
ret = OB_ERR_WRONG_FIELD_WITH_GROUP;
ObString column_name = concat_qualified_name(
undefined_column.get_database_name(), undefined_column.get_table_name(), undefined_column.get_column_name());
LOG_USER_ERROR(OB_ERR_WRONG_FIELD_WITH_GROUP, column_name.length(), column_name.ptr());
}
} else {
LOG_WARN("check unsettled expr failed", K(ret));
}
if (OB_ERR_WRONG_FIELD_WITH_GROUP == ret || OB_ERR_MIX_OF_GROUP_FUNC_AND_FIELDS == ret) {
int tmp_ret = ret;
ObAnyValueChecker any_value_checker;
if (OB_FAIL(any_value_checker.check_any_value(unsettled_expr, &undefined_column))) {
LOG_WARN("check any value expr fail", K(ret));
} else {
if (any_value_checker.is_pass_after_check()) {
ret = OB_SUCCESS;
} else {
ret = tmp_ret;
if (OB_ERR_WRONG_FIELD_WITH_GROUP == ret) {
ObString column_name = concat_qualified_name(undefined_column.get_database_name(),
undefined_column.get_table_name(),
undefined_column.get_column_name());
LOG_USER_ERROR(OB_ERR_WRONG_FIELD_WITH_GROUP, column_name.length(), column_name.ptr());
}
}
}
}
return ret;
}
} // namespace sql
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册