fix some window func bugs

This commit is contained in:
wangt1xiuyi 2023-08-14 07:18:41 +00:00 committed by ob-robot
parent ef9887b33b
commit e067fa2e07
14 changed files with 261 additions and 17 deletions

View File

@ -984,7 +984,12 @@
#define ER_WINDOW_NO_CHILD_PARTITIONING 3581
#define ER_WINDOW_NO_INHERIT_FRAME 3582
#define ER_WINDOW_NO_REDEFINE_ORDER_BY 3583
#define ER_WINDOW_FRAME_ILLEGAL 3586
#define ER_WINDOW_RANGE_FRAME_ORDER_TYPE 3587
#define ER_WINDOW_RANGE_FRAME_TEMPORAL_TYPE 3588
#define ER_WINDOW_RANGE_FRAME_NUMERIC_TYPE 3589
#define ER_WINDOW_RANGE_BOUND_NOT_CONSTANT 3590
#define ER_WINDOW_ILLEGAL_ORDER_BY 3592
#define ER_WINDOW_ROWS_INTERVAL_USE 3596

File diff suppressed because one or more lines are too long

View File

@ -1147,6 +1147,11 @@ DEFINE_ORACLE_ERROR(OB_ERR_DEFAULT_NOT_ALLOWED, -5504, -1, "HY000", "Virtual col
DEFINE_ORACLE_ERROR(OB_ERR_MODIFY_REALCOL_TO_GENCOL, -5505, -1, "HY000", "Real column cannot have an expression", 54026, "Real column cannot have an expression");
DEFINE_ORACLE_ERROR(OB_ERR_MODIFY_TYPE_OF_GENCOL, -5506, -1, "HY000", "cannot modify data-type of virtual column", 54027, "cannot modify data-type of virtual column");
DEFINE_ERROR_EXT(OB_ERR_WINDOW_FRAME_ILLEGAL, -5507, ER_WINDOW_FRAME_ILLEGAL, "HY000", "frame start or end is negative or NULL or of non-integral type", "Window '%.*s': frame start or end is negative or NULL or of non-integral type");
DEFINE_ERROR_EXT(OB_ERR_WINDOW_RANGE_FRAME_TEMPORAL_TYPE, -5508, ER_WINDOW_RANGE_FRAME_TEMPORAL_TYPE, "HY000", "Window with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.", "Window '%.*s' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.");
DEFINE_ERROR_EXT(OB_ERR_WINDOW_RANGE_FRAME_NUMERIC_TYPE, -5509, ER_WINDOW_RANGE_FRAME_NUMERIC_TYPE, "HY000", "Window with RANGE frame has ORDER BY expression of numeric type. INTERVAL bound value not allowed.", "Window '%.*s' with RANGE frame has ORDER BY expression of numeric type. INTERVAL bound value not allowed.");
DEFINE_ERROR_EXT(OB_ERR_WINDOW_RANGE_BOUND_NOT_CONSTANT, -5510, ER_WINDOW_RANGE_BOUND_NOT_CONSTANT, "HY000", "Window has a non-constant frame bound.", "Window '%.*s' has a non-constant frame bound.");
DEFINE_ERROR_EXT(OB_ERR_SP_ALREADY_EXISTS, -5541, ER_SP_ALREADY_EXISTS, "42000", "procedure/function already exists", "%s %.*s already exists");
DEFINE_ERROR_EXT(OB_ERR_SP_DOES_NOT_EXIST, -5542, ER_SP_DOES_NOT_EXIST, "42000", "procedure/function does not exist", "%s %.*s.%.*s does not exist");
DEFINE_PLS_ERROR_EXT(OB_ERR_SP_UNDECLARED_VAR, -5543, ER_SP_UNDECLARED_VAR, "42000", "Undeclared variable", "Undeclared variable: %.*s", 201, "identifier must be declared", "identifier '%.*s' must be declared");

View File

@ -859,6 +859,10 @@ constexpr int OB_ERR_VIEW_SELECT_CONTAIN_INTO = -5503;
constexpr int OB_ERR_DEFAULT_NOT_ALLOWED = -5504;
constexpr int OB_ERR_MODIFY_REALCOL_TO_GENCOL = -5505;
constexpr int OB_ERR_MODIFY_TYPE_OF_GENCOL = -5506;
constexpr int OB_ERR_WINDOW_FRAME_ILLEGAL = -5507;
constexpr int OB_ERR_WINDOW_RANGE_FRAME_TEMPORAL_TYPE = -5508;
constexpr int OB_ERR_WINDOW_RANGE_FRAME_NUMERIC_TYPE = -5509;
constexpr int OB_ERR_WINDOW_RANGE_BOUND_NOT_CONSTANT = -5510;
constexpr int OB_ERR_SP_ALREADY_EXISTS = -5541;
constexpr int OB_ERR_SP_DOES_NOT_EXIST = -5542;
constexpr int OB_ERR_SP_UNDECLARED_VAR = -5543;
@ -2805,6 +2809,10 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219;
#define OB_ERR_DEFAULT_NOT_ALLOWED__USER_ERROR_MSG "Virtual column cannot have a default value"
#define OB_ERR_MODIFY_REALCOL_TO_GENCOL__USER_ERROR_MSG "Real column cannot have an expression"
#define OB_ERR_MODIFY_TYPE_OF_GENCOL__USER_ERROR_MSG "cannot modify data-type of virtual column"
#define OB_ERR_WINDOW_FRAME_ILLEGAL__USER_ERROR_MSG "Window '%.*s': frame start or end is negative or NULL or of non-integral type"
#define OB_ERR_WINDOW_RANGE_FRAME_TEMPORAL_TYPE__USER_ERROR_MSG "Window '%.*s' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed."
#define OB_ERR_WINDOW_RANGE_FRAME_NUMERIC_TYPE__USER_ERROR_MSG "Window '%.*s' with RANGE frame has ORDER BY expression of numeric type. INTERVAL bound value not allowed."
#define OB_ERR_WINDOW_RANGE_BOUND_NOT_CONSTANT__USER_ERROR_MSG "Window '%.*s' has a non-constant frame bound."
#define OB_ERR_SP_ALREADY_EXISTS__USER_ERROR_MSG "%s %.*s already exists"
#define OB_ERR_SP_DOES_NOT_EXIST__USER_ERROR_MSG "%s %.*s.%.*s does not exist"
#define OB_ERR_SP_UNDECLARED_VAR__USER_ERROR_MSG "Undeclared variable: %.*s"
@ -4920,6 +4928,10 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219;
#define OB_ERR_DEFAULT_NOT_ALLOWED__ORA_USER_ERROR_MSG "ORA-54025: Virtual column cannot have a default value"
#define OB_ERR_MODIFY_REALCOL_TO_GENCOL__ORA_USER_ERROR_MSG "ORA-54026: Real column cannot have an expression"
#define OB_ERR_MODIFY_TYPE_OF_GENCOL__ORA_USER_ERROR_MSG "ORA-54027: cannot modify data-type of virtual column"
#define OB_ERR_WINDOW_FRAME_ILLEGAL__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5507, Window '%.*s': frame start or end is negative or NULL or of non-integral type"
#define OB_ERR_WINDOW_RANGE_FRAME_TEMPORAL_TYPE__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5508, Window '%.*s' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed."
#define OB_ERR_WINDOW_RANGE_FRAME_NUMERIC_TYPE__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5509, Window '%.*s' with RANGE frame has ORDER BY expression of numeric type. INTERVAL bound value not allowed."
#define OB_ERR_WINDOW_RANGE_BOUND_NOT_CONSTANT__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5510, Window '%.*s' has a non-constant frame bound."
#define OB_ERR_SP_ALREADY_EXISTS__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5541, %s %.*s already exists"
#define OB_ERR_SP_DOES_NOT_EXIST__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5542, %s %.*s.%.*s does not exist"
#define OB_ERR_SP_UNDECLARED_VAR__ORA_USER_ERROR_MSG "PLS-00201: identifier '%.*s' must be declared"
@ -6005,7 +6017,7 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219;
#define OB_ERR_DATA_TOO_LONG_MSG_FMT_V2__ORA_USER_ERROR_MSG "ORA-12899: value too large for column %.*s (actual: %ld, maximum: %ld)"
#define OB_ERR_INVALID_DATE_MSG_FMT_V2__ORA_USER_ERROR_MSG "ORA-01861: Incorrect datetime value for column '%.*s' at row %ld"
extern int g_all_ob_errnos[2111];
extern int g_all_ob_errnos[2115];
const char *ob_error_name(const int oberr);
const char* ob_error_cause(const int oberr);

View File

@ -444,10 +444,12 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
ObEvalCtx &eval_ctx,
bool &is_null,
int64_t &value,
const bool need_number/* = false*/)
const bool need_number/* = false*/,
const bool need_check_valid/* = false*/)
{
int ret = OB_SUCCESS;
ObDatum *result = NULL;
bool is_valid_param = true;
is_null = false;
value = 0;
if (OB_FAIL(expr.eval(eval_ctx, result))) {
@ -457,12 +459,14 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
LOG_WARN("params is not number type", K(expr), K(ret));
} else if (result->is_null()) {
is_null = true;
is_valid_param = !need_check_valid;
} else if (need_number || expr.obj_meta_.is_number()) {
//we restrict the bucket_num in range [0, (1<<63)-1]
number::ObNumber result_nmb;
number::ObCompactNumber &cnum = const_cast<number::ObCompactNumber &>(
result->get_number());
result_nmb.assign(cnum.desc_.desc_, cnum.digits_ + 0);
is_valid_param = !need_check_valid || !result_nmb.is_negative();
if (OB_FAIL(result_nmb.extract_valid_int64_with_trunc(value))) {
LOG_WARN("extract_valid_int64_with_trunc failed", K(ret));
}
@ -470,11 +474,13 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
switch (expr.obj_meta_.get_type_class()) {
case ObIntTC: {
value = result->get_int();
is_valid_param = !need_check_valid || value >= 0;
break;
}
case ObUIntTC: {
const uint64_t tmp_value = result->get_uint();
if (tmp_value > INT64_MAX) {
is_valid_param = !need_check_valid || static_cast<int64_t>(tmp_value) >= 0;
if (tmp_value > INT64_MAX && is_valid_param) {
ret = OB_DATA_OUT_OF_RANGE;
LOG_WARN("int64 out of range", K(ret), K(tmp_value), K(INT64_MAX));
} else {
@ -484,6 +490,7 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
}
case ObFloatTC: {
const float tmp_value = result->get_float();
is_valid_param = !need_check_valid || tmp_value >= 0;
if (tmp_value > INT64_MAX) {
ret = OB_DATA_OUT_OF_RANGE;
LOG_WARN("int64 out of range", K(ret), K(tmp_value), K(INT64_MAX));
@ -494,6 +501,7 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
}
case ObDoubleTC: {
const double tmp_value = result->get_double();
is_valid_param = !need_check_valid || tmp_value >= 0;
if (tmp_value > INT64_MAX) {
ret = OB_DATA_OUT_OF_RANGE;
LOG_WARN("int64 out of range", K(ret), K(tmp_value), K(INT64_MAX));
@ -504,7 +512,8 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
}
case ObBitTC: {
const uint64_t tmp_value = result->get_bit();
if (tmp_value > INT64_MAX) {
is_valid_param = !need_check_valid || static_cast<int64_t>(tmp_value) >= 0;
if (tmp_value > INT64_MAX && is_valid_param) {
ret = OB_DATA_OUT_OF_RANGE;
LOG_WARN("int64 out of range", K(ret), K(tmp_value), K(INT64_MAX));
} else {
@ -518,6 +527,10 @@ int ObWindowFunctionOp::get_param_int_value(ObExpr &expr,
}
}
}
if (OB_SUCC(ret) && !is_valid_param) {
ret = OB_ERR_WINDOW_FRAME_ILLEGAL;
LOG_WARN("frame start or end is negative, NULL or of non-integral type", K(ret), K(value), KPC(result));
}
return ret;
}
@ -758,8 +771,14 @@ int ObWindowFunctionOp::NonAggrCellNtile::eval(RowsReader &row_reader,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("argument is NULL", K(ret));
} else if (OB_FAIL(ObWindowFunctionOp::get_param_int_value(*param,
op_.eval_ctx_, is_null, bucket_num))) {
LOG_WARN("get_param_int_value failed", K(ret));
op_.eval_ctx_, is_null, bucket_num, false, lib::is_mysql_mode()))) {
if (ret == OB_ERR_WINDOW_FRAME_ILLEGAL) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Incorrect arguments to ntile", K(ret));
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "ntile");
} else {
LOG_WARN("get_param_int_value failed", K(ret));
}
} else if (is_null) {
// return NULL when backets_num is NULL
val.set_null();
@ -2818,7 +2837,10 @@ int ObWindowFunctionOp::get_pos(RowsReader &row_reader,
if (OB_ISNULL(between_value_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("between_value_expr is unexpected", KPC(between_value_expr), K(ret));
} else if (OB_FAIL(get_param_int_value(*between_value_expr, eval_ctx_, is_null, interval))) {
} else if (OB_UNLIKELY(lib::is_mysql_mode() && is_rows && !between_value_expr->obj_meta_.is_integer_type())) {
ret = OB_ERR_WINDOW_FRAME_ILLEGAL;
LOG_WARN("frame start or end is negative, NULL or of non-integral type", K(ret), K(between_value_expr->obj_meta_));
} else if (OB_FAIL(get_param_int_value(*between_value_expr, eval_ctx_, is_null, interval, false, lib::is_mysql_mode()))) {
LOG_WARN("get_param_int_value failed", K(ret), KPC(between_value_expr));
} else if (is_null) {
got_null_val = true;
@ -2831,7 +2853,17 @@ int ObWindowFunctionOp::get_pos(RowsReader &row_reader,
if (OB_FAIL(ret)) {
} else if (is_rows) {
// range or rows with expr
pos = is_preceding ? row_idx - interval : row_idx + interval;
if (OB_UNLIKELY(!is_preceding && static_cast<uint64>(row_idx + interval) > INT64_MAX)) {
if (lib::is_mysql_mode()) {
ret = OB_ERR_WINDOW_FRAME_ILLEGAL;
LOG_WARN("frame start or end is negative, NULL or of non-integral type", K(ret), K(row_idx + interval));
} else {
ret = OB_DATA_OUT_OF_RANGE;
LOG_WARN("int64 out of range", K(ret), K(row_idx + interval));
}
} else {
pos = is_preceding ? row_idx - interval : row_idx + interval;
}
} else if (wf_cell.wf_info_.sort_exprs_.count() == 0) {
//Only when order by is const, sort_exprs_.count() == 0
ObDatum *cmp_result = NULL;
@ -2886,6 +2918,12 @@ int ObWindowFunctionOp::get_pos(RowsReader &row_reader,
LOG_WARN("NULL ptr", K(ret), K(bound_expr));
} else if (OB_FAIL(bound_expr->eval(eval_ctx_, cmp_val))) {
LOG_WARN("calc compare value failed", K(ret));
} else if (lib::is_mysql_mode() &&
!is_nmb_literal &&
ob_is_temporal_type(bound_expr->datum_meta_.get_type())) {
if (OB_FAIL(check_interval_valid(*bound_expr))) {
LOG_WARN("failed to check interval valid", K(ret));
}
}
ObSortFuncs &sort_cmp_funcs = wf_cell.wf_info_.sort_cmp_funcs_;
ObDatumCmpFuncType cmp_func = sort_cmp_funcs.at(0).cmp_func_;
@ -3896,5 +3934,41 @@ int ObWindowFunctionOp::final_next_batch(const int64_t max_row_cnt)
return ret;
}
int ObWindowFunctionOp::check_interval_valid(ObExpr &expr)
{
int ret = OB_SUCCESS;
if (expr.type_ == T_FUN_SYS_DATE_ADD ||
expr.type_ == T_FUN_SYS_DATE_SUB) {
bool is_valid = true;
ObDatum *date = NULL;
ObDatum *interval = NULL;
ObDatum *unit = NULL;
if (OB_FAIL(expr.eval_param_value(eval_ctx_, date, interval, unit))) {
LOG_WARN("eval param value failed");
} else if (OB_UNLIKELY(date->is_null() || interval->is_null())) {
is_valid = false;
} else {
ObString interval_val = interval->get_string();
int64_t unit_value = unit->get_int();
ObDateUnitType unit_val = static_cast<ObDateUnitType>(unit_value);
ObInterval interval_time;
if (OB_FAIL(ObTimeConverter::str_to_ob_interval(interval_val, unit_val, interval_time))) {
if (OB_UNLIKELY(OB_INVALID_DATE_VALUE == ret)) {
ret = OB_SUCCESS;
} else {
LOG_WARN("failed to convert string to ob interval", K(ret));
}
} else {
is_valid = !(DT_MODE_NEG & interval_time.mode_);
}
}
if (OB_SUCC(ret) && !is_valid) {
ret = OB_ERR_WINDOW_FRAME_ILLEGAL;
LOG_WARN("frame start or end is negative, NULL or of non-integral type", K(ret), KPC(interval), KPC(unit));
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -822,7 +822,8 @@ protected:
// shanting attention!
inline int64_t get_part_end_idx() const { return input_rows_.cur_->count() - 1; }
static int get_param_int_value(ObExpr &expr, ObEvalCtx &eval_ctx, bool &is_null, int64_t &value,
const bool need_number_type = false);
const bool need_number_type = false,
const bool need_check_valid = false);
int parallel_winbuf_process();
int get_whole_msg(bool is_end, ObWinbufWholeMsg &whole,
const ObRADatumStore::StoredRow *row = NULL);
@ -897,6 +898,7 @@ protected:
const ObChunkDatumStore::StoredRow *row_, uint64_t &hash_value);
int detect_aggr_status();
bool skip_calc(const int64_t wf_idx);
int check_interval_valid(ObExpr &expr);
private:
// disallow copy

View File

@ -1951,7 +1951,7 @@ COUNT '(' opt_all '*' ')' OVER new_generalized_window_clause
$$->type_ = T_WIN_FUN_LAG;
malloc_non_terminal_node($$, result->malloc_pool_, T_WINDOW_FUNCTION, 2, $$, $4);
}
| NTH_VALUE '(' expr ',' expr ')' opt_from_first_or_last opt_respect_or_ignore_nulls OVER new_generalized_window_clause
| NTH_VALUE '(' expr ',' simple_expr ')' opt_from_first_or_last opt_respect_or_ignore_nulls OVER new_generalized_window_clause
{
malloc_non_terminal_node($$, result->malloc_pool_, T_WIN_FUN_NTH_VALUE, 4, $3, $5, $7, $8);
malloc_non_terminal_node($$, result->malloc_pool_, T_WINDOW_FUNCTION, 2, $$, $10);
@ -2159,11 +2159,22 @@ PRECEDING
;
win_interval:
expr
INTNUM
{
malloc_non_terminal_node($$, result->malloc_pool_, T_WIN_INTERVAL, 1, $1);
$$->value_ = 1;
}
| DECIMAL_VAL
{
malloc_non_terminal_node($$, result->malloc_pool_, T_WIN_INTERVAL, 1, $1);
$$->value_ = 1;
}
| UNBOUNDED
{
get_non_reserved_node($$, result->malloc_pool_, @1.first_column, @1.last_column);
malloc_non_terminal_node($$, result->malloc_pool_, T_WIN_INTERVAL, 1, $$);
$$->value_ = 1;
}
| INTERVAL expr date_unit
{
malloc_non_terminal_node($$, result->malloc_pool_, T_WIN_INTERVAL, 2, $2, $3);

View File

@ -4899,7 +4899,8 @@ int ObSelectResolver::resolve_column_ref_expr(
LOG_WARN("session info is null");
} else if (OB_FALSE_IT(const_cast<ObQualifiedName&>(q_name).current_resolve_level_ = current_level_)) {
} else if (q_name.parents_expr_info_.has_member(IS_AGG)) {
} else if (q_name.parents_expr_info_.has_member(IS_AGG) &&
!q_name.parents_expr_info_.has_member(IS_WINDOW_FUNC)) {
const_cast<ObQualifiedName&>(q_name).parent_aggr_level_ = current_level_;
} else {
const_cast<ObQualifiedName&>(q_name).parent_aggr_level_ = parent_aggr_level_;

View File

@ -56,7 +56,10 @@ public:
virtual ObSelectStmt *get_child_stmt() { return get_select_stmt(); }
virtual bool is_select_resolver() const { return true; }
inline bool can_produce_aggr() const
{ return T_FIELD_LIST_SCOPE == current_scope_ || T_HAVING_SCOPE == current_scope_ || T_ORDER_SCOPE == current_scope_; }
{ return T_FIELD_LIST_SCOPE == current_scope_ ||
T_HAVING_SCOPE == current_scope_ ||
T_ORDER_SCOPE == current_scope_ ||
T_NAMED_WINDOWS_SCOPE == current_scope_; }
int add_aggr_expr(ObAggFunRawExpr *&final_aggr_expr);
int add_unsettled_column(ObRawExpr *column_expr);
void set_in_set_query(bool in_set_query) { in_set_query_ = in_set_query; }

View File

@ -5087,6 +5087,9 @@ int ObWindow::assign(const ObWindow &other)
LOG_WARN("failed to assign order items", K(ret));
} else if (OB_FAIL(ObFrame::assign(other))) {
LOG_WARN("failed to assign frame", K(ret));
} else {
win_name_ = other.win_name_;
has_frame_orig_ = other.has_frame_orig_;
}
}
return ret;

View File

@ -4305,7 +4305,7 @@ public:
ObRawExpr *date_unit_expr_;
ObRawExpr *exprs_[BOUND_EXPR_MAX];
TO_STRING_KV(K_(type), K_(is_preceding), K_(is_nmb_literal), KP_(interval_expr),
TO_STRING_KV(K_(type), K_(is_preceding), K_(is_nmb_literal), KPC_(interval_expr),
K_(date_unit_expr));
};

View File

@ -2429,6 +2429,20 @@ int ObRawExprDeduceType::visit(ObWinFunRawExpr &expr)
} else {
func_params.at(0) = cast_expr;
}
} else if (OB_UNLIKELY(lib::is_mysql_mode() &&
(!func_params.at(0)->is_const_expr() ||
!func_params.at(0)->get_result_type().is_integer_type()))) {
if (func_params.at(0)->get_expr_type() == T_FUN_SYS_FLOOR &&
func_params.at(0)->get_param_count() >= 1 &&
func_params.at(0)->get_param_expr(0) != NULL &&
func_params.at(0)->get_param_expr(0)->get_expr_type() == T_REF_QUERY &&
func_params.at(0)->get_param_expr(0)->get_result_type().is_integer_type()) {
//do nothing
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Incorrect arguments to ntile", K(ret), KPC(func_params.at(0)));
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "ntile");
}
}
} else if (T_WIN_FUN_NTH_VALUE == expr.get_func_type()) {
// nth_value函数的返回类型可以为null. lead和lag也是
@ -2600,6 +2614,31 @@ int ObRawExprDeduceType::visit(ObWinFunRawExpr &expr)
LOG_WARN("interval is not numberic", K(ret), KPC(expr.lower_.interval_expr_));
}
}
if (OB_SUCC(ret) &&
lib::is_mysql_mode() &&
expr.get_window_type() == WINDOW_RANGE &&
(expr.upper_.interval_expr_ != NULL || expr.lower_.interval_expr_ != NULL)) {
if (expr.get_order_items().empty()) {
//do nothing
} else if (OB_UNLIKELY(expr.get_order_items().count() != 1)) {
ret = OB_ERR_INVALID_WINDOW_FUNC_USE;
LOG_WARN("invalid window specification", K(ret), K(expr.get_order_items()));
} else if (OB_UNLIKELY(((expr.upper_.interval_expr_ != NULL && !expr.upper_.is_nmb_literal_) ||
(expr.lower_.interval_expr_ != NULL && !expr.lower_.is_nmb_literal_)) &&
expr.get_order_items().at(0).expr_->get_result_type().is_numeric_type())) {
ret = OB_ERR_WINDOW_RANGE_FRAME_NUMERIC_TYPE;
LOG_WARN("Window with RANGE frame has ORDER BY expression of numeric type. INTERVAL bound value not allowed.", K(ret));
ObString tmp_name = expr.get_win_name().empty() ? ObString("<unnamed window>") : expr.get_win_name();
LOG_USER_ERROR(OB_ERR_WINDOW_RANGE_FRAME_NUMERIC_TYPE, tmp_name.length(), tmp_name.ptr());
} else if (OB_UNLIKELY(((expr.upper_.interval_expr_ != NULL && expr.upper_.is_nmb_literal_) ||
(expr.lower_.interval_expr_ != NULL && expr.lower_.is_nmb_literal_)) &&
expr.get_order_items().at(0).expr_->get_result_type().is_temporal_type())) {
ret = OB_ERR_WINDOW_RANGE_FRAME_TEMPORAL_TYPE;
LOG_WARN("Window with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.", K(ret));
ObString tmp_name = expr.get_win_name().empty() ? ObString("<unnamed window>") : expr.get_win_name();
LOG_USER_ERROR(OB_ERR_WINDOW_RANGE_FRAME_TEMPORAL_TYPE, tmp_name.length(), tmp_name.ptr());
}
}
LOG_DEBUG("finish add cast for window function", K(result_number_type), K(expr.lower_), K(expr.upper_));
}

View File

@ -3850,7 +3850,14 @@ int ObRawExprPrinter::print_window_clause(ObWinFunRawExpr *expr)
} else if (BoundType::BOUND_CURRENT_ROW == expr->get_upper().type_) {
DATA_PRINTF(" CURRENT ROW ");
} else if (BoundType::BOUND_INTERVAL == expr->get_upper().type_) {
if (!expr->get_upper().is_nmb_literal_) {
DATA_PRINTF(" INTERVAL ");
}
PRINT_EXPR(expr->get_upper().interval_expr_);
if (!expr->get_upper().is_nmb_literal_) {
DATA_PRINTF(" ");
PRINT_EXPR(expr->get_upper().date_unit_expr_);
}
if (expr->get_upper().is_preceding_) {
DATA_PRINTF(" PRECEDING ");
} else {
@ -3868,7 +3875,14 @@ int ObRawExprPrinter::print_window_clause(ObWinFunRawExpr *expr)
} else if (BoundType::BOUND_CURRENT_ROW == expr->get_lower().type_) {
DATA_PRINTF(" CURRENT ROW ");
} else if (BoundType::BOUND_INTERVAL == expr->get_lower().type_) {
if (!expr->get_lower().is_nmb_literal_) {
DATA_PRINTF(" INTERVAL ");
}
PRINT_EXPR(expr->get_lower().interval_expr_);
if (!expr->get_lower().is_nmb_literal_) {
DATA_PRINTF(" ");
PRINT_EXPR(expr->get_lower().date_unit_expr_);
}
if (expr->get_lower().is_preceding_) {
DATA_PRINTF(" PRECEDING ");
} else {

View File

@ -6419,6 +6419,12 @@ int ObRawExprResolverImpl::process_window_function_node(const ParseNode *node, O
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(func_params.push_back(n_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(n_expr->extract_info())) {
LOG_WARN("faield to extract info", K(ret));
} else if (OB_UNLIKELY(lib::is_mysql_mode() && !n_expr->is_const_expr())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments to nth_value", K(ret));
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "nth_value");
} else {
win_func->set_is_from_first(NULL == func_node->children_[2] || T_FIRST == func_node->children_[2]->type_);
win_func->set_is_ignore_null(!(NULL == func_node->children_[3] || T_RESPECT == func_node->children_[3]->type_));
@ -6535,10 +6541,16 @@ int ObRawExprResolverImpl::process_window_function_node(const ParseNode *node, O
break;
}
}
if(OB_SUCC(ret) && NULL == named_win) {
if (OB_SUCC(ret) && NULL == named_win) {
ret = OB_ERR_WINDOW_NAME_IS_NOT_DEFINE;
LOG_WARN("name win not exist", K(name), K(ret), K(named_windows));
LOG_USER_ERROR(OB_ERR_WINDOW_NAME_IS_NOT_DEFINE, name.length(), name.ptr());
} else if (OB_UNLIKELY(ctx_.current_scope_ == T_NAMED_WINDOWS_SCOPE &&
named_win->has_frame_orig())) {
ret = OB_EER_WINDOW_NO_INHERIT_FRAME;
LOG_WARN("Named window cann't be modified by another framing property", K(ret));
ObString tmp_name = named_win->get_win_name().empty() ? ObString("<unnamed window>") : named_win->get_win_name();
LOG_USER_ERROR(OB_EER_WINDOW_NO_INHERIT_FRAME, tmp_name.length(), tmp_name.ptr());
}
}
}
@ -6676,6 +6688,13 @@ int ObRawExprResolverImpl::process_window_function_node(const ParseNode *node, O
if (OB_SUCC(ret) && NULL != frame_node) {
if (OB_FAIL(process_frame_node(frame_node, frame))) {
LOG_WARN("process window node failed", K(ret));
} else if (lib::is_mysql_mode() &&
OB_UNLIKELY((frame.get_upper().interval_expr_ != NULL && !frame.get_upper().interval_expr_->is_const_expr()) ||
(frame.get_lower().interval_expr_ != NULL && !frame.get_lower().interval_expr_->is_const_expr()))) {
ret = OB_ERR_WINDOW_RANGE_BOUND_NOT_CONSTANT;
LOG_WARN("Window has a non-constant frame bound.", K(ret), KPC(frame.get_upper().interval_expr_), KPC(frame.get_lower().interval_expr_));
ObString tmp_name = named_win == NULL ? ObString("<unnamed window>") : named_win->get_win_name();
LOG_USER_ERROR(OB_ERR_WINDOW_RANGE_BOUND_NOT_CONSTANT, tmp_name.length(), tmp_name.ptr());
}
}
if (OB_SUCC(ret)) {
@ -6914,6 +6933,8 @@ int ObRawExprResolverImpl::process_interval_node(const ParseNode *node,
} else if (OB_ISNULL(interval_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret), K(interval_expr));
} else if (OB_FAIL(interval_expr->extract_info())) {
LOG_WARN("fail to extract info", K(interval_expr), K(ret));
} else if (!is_nmb_literal) {
// date type
ParseNode *date_unit_node = node->children_[1];
@ -6922,8 +6943,10 @@ int ObRawExprResolverImpl::process_interval_node(const ParseNode *node,
} else if (OB_ISNULL(date_unit_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret), K(date_unit_expr));
} else if (OB_FAIL(date_unit_expr->extract_info())) {
LOG_WARN("fail to extract info", K(interval_expr), K(ret));
} else if (!date_unit_expr->is_const_raw_expr()) {
ret = OB_ERR_UNEXPECTED;
ret = OB_INVALID_ARGUMENT;
LOG_WARN("not const expr error", K(ret), K(date_unit_expr->get_expr_type()));
} else {/*do nothing*/}
}