From f51c7afe861065a4a872348c14b3e37b8087a7b3 Mon Sep 17 00:00:00 2001 From: Hongqin-Li Date: Thu, 23 Sep 2021 13:18:58 +0800 Subject: [PATCH] Fix the conversion rules from string/datetime to enum/set --- deps/oblib/src/lib/string/ob_string.h | 6 ++- src/clog/ob_log_file_pool.cpp | 58 +++++++++++++++++++++++- src/clog/ob_log_file_pool.h | 1 + src/share/object/ob_obj_cast.cpp | 42 +++++++----------- src/sql/engine/expr/ob_datum_cast.cpp | 63 ++++++++++++++------------- 5 files changed, 110 insertions(+), 60 deletions(-) diff --git a/deps/oblib/src/lib/string/ob_string.h b/deps/oblib/src/lib/string/ob_string.h index bc9c1c716e..037353aca0 100644 --- a/deps/oblib/src/lib/string/ob_string.h +++ b/deps/oblib/src/lib/string/ob_string.h @@ -609,7 +609,11 @@ public: if (OB_ISNULL(ptr_) || data_length_ == 0) { ret = false; } else { - for (int i = 0; i < data_length_; ++i) { + int i = 0; + if (data_length_ >= 2 && ptr_[0] == '-') { + i += 1; + } + for (; i < data_length_; ++i) { if (!isdigit(ptr_[i])) { ret = false; } diff --git a/src/clog/ob_log_file_pool.cpp b/src/clog/ob_log_file_pool.cpp index 3807c5625a..e543bdaba9 100644 --- a/src/clog/ob_log_file_pool.cpp +++ b/src/clog/ob_log_file_pool.cpp @@ -193,11 +193,37 @@ int ObLogWriteFilePool::get_file_id_range(file_id_t& min_file_id, file_id_t& max if (!is_inited_) { ret = OB_NOT_INIT; } else { + bool need_scan_dir = false; min_file_id = ATOMIC_LOAD(&min_file_id_); max_file_id = ATOMIC_LOAD(&max_file_id_); if (OB_INVALID_FILE_ID == min_file_id || OB_INVALID_FILE_ID == max_file_id) { - ret = log_dir_->get_file_id_range(min_file_id, max_file_id); - if (OB_SUCC(ret)) { + need_scan_dir = true; + } else { + bool b_exist = false; + const char *dir = get_dir_name(); + // check min file id + if (!need_scan_dir && OB_FAIL(check_file_existence(dir, min_file_id, b_exist))) { + need_scan_dir = true; + CLOG_LOG(WARN, "failed to check file existence", K(ret), K(dir), K(min_file_id)); + } else if (!need_scan_dir && !b_exist) { + need_scan_dir = true; + CLOG_LOG(WARN, "min file does not exist", K(min_file_id), K(b_exist)); + } + + // check max file id + if (!need_scan_dir && OB_FAIL(check_file_existence(dir, max_file_id, b_exist))) { + need_scan_dir = true; + CLOG_LOG(WARN, "failed to check file existence", K(ret), K(dir), K(max_file_id)); + } else if (!need_scan_dir && !b_exist) { + need_scan_dir = true; + CLOG_LOG(WARN, "max file does not exist", K(max_file_id), K(b_exist)); + } + } + + if (need_scan_dir) { + if (OB_SUCC(log_dir_->get_file_id_range(min_file_id, max_file_id))) { + update_min_file_id(min_file_id); + update_max_file_id(max_file_id); CLOG_LOG(INFO, "get min/max file id from IO", K(min_file_id), K(max_file_id), K(lbt())); } } @@ -580,5 +606,33 @@ int ObLogWriteFilePool::rename_file( } return ret; } + +int ObLogWriteFilePool::check_file_existence(const char* dir, const file_id_t file_id, bool& b_exist) +{ + int ret = OB_SUCCESS; + b_exist = false; + char full_path[common::MAX_PATH_SIZE] = {0}; + if (OB_ISNULL(dir) || OB_UNLIKELY(0 == STRLEN(dir)) || OB_UNLIKELY(!is_valid_file_id(file_id))) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "invalid args", K(ret), K(dir), K(file_id)); + } else { + int pret = ::snprintf(full_path, sizeof(full_path), "%s/%u", dir, file_id); + if (OB_UNLIKELY(pret <= 0 || pret >= sizeof(full_path))) { + ret = OB_BUF_NOT_ENOUGH; + CLOG_LOG(WARN, "file name too long", K(ret), K(dir), K(file_id)); + } else if (0 != ::access(full_path, F_OK)) { + if (errno == ENOENT) { + ret = OB_SUCCESS; + b_exist = false; + } else { + ret = OB_IO_ERROR; + CLOG_LOG(WARN, "failed to access file", K(ret), K(dir), K(file_id), KERRMSG); + } + } else { + b_exist = true; + } + } + return ret; +} } // end namespace clog } // end namespace oceanbase diff --git a/src/clog/ob_log_file_pool.h b/src/clog/ob_log_file_pool.h index ab5a20b6e9..7f39777f35 100644 --- a/src/clog/ob_log_file_pool.h +++ b/src/clog/ob_log_file_pool.h @@ -90,6 +90,7 @@ protected: int fsync_dir(const int dir_fd); int get_dir_name(const char* fname, char* dir_name, const int64_t len); int rename_file(const int src_dir_fd, const char* srcfile, const int dest_dir_fd, const char* destfile); + int check_file_existence(const char* dir, const file_id_t file_id, bool& b_exist); private: static const int TASK_NUM = 1024; diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index db2104cd0f..42a6d34321 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -4006,7 +4006,8 @@ static int string_enum(const ObExpectType& expect_type, ObObjCastParams& params, int32_t no_sp_len = 0; ObString no_sp_val; ObString in_str; - if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObStringTC != in.get_type_class()) || + if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || + OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || OB_ISNULL(type_infos = expect_type.get_type_infos())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); @@ -4022,35 +4023,22 @@ static int string_enum(const ObExpectType& expect_type, ObObjCastParams& params, if (OB_FAIL(find_type(*type_infos, cs_type, no_sp_val, pos))) { LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(no_sp_val), K(in_str), K(pos), K(ret)); } else if (OB_UNLIKELY(pos < 0)) { - if (CM_IS_WARN_ON_FAIL(cast_mode)) { - params.warning_ = OB_ERR_DATA_TRUNCATED; - value = 0; - LOG_INFO("input value out of range, and set out value zero", K(in), K(expect_type)); - } else { + if (!in_str.is_numeric()) { ret = OB_ERR_DATA_TRUNCATED; - LOG_WARN("input value out of range", K(in), K(expect_type), K(ret)); - // Bug30666903: check implicit cast logic to handle number cases - if (in_str.is_numeric()) { - int err = 0; - value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err); - if (err == 0) { - ret = OB_SUCCESS; - uint32_t val_cnt = type_infos->count(); - if (OB_UNLIKELY(val_cnt <= 0)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect val_cnt", K(in), K(out), K(expect_type), K(ret)); - } else if (value > val_cnt) { - value = 0; - ret = OB_ERR_DATA_TRUNCATED; - LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret)); - } - if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { - params.warning_ = OB_ERR_DATA_TRUNCATED; - ret = OB_SUCCESS; - } - } + } else { + int err = 0; + int64_t val_cnt = type_infos->count(); + value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err); + if (err != 0 || value > val_cnt) { + value = 0; + ret = OB_ERR_DATA_TRUNCATED; + LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret), K(err)); } } + if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { + params.warning_ = OB_ERR_DATA_TRUNCATED; + ret = OB_SUCCESS; + } } else { value = pos + 1; // enum start from 1 } diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index ea3d6aeede..e4a6239432 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -1003,6 +1003,7 @@ int common_check_convert_string(const ObExpr& expr, ObEvalCtx& ctx, const ObStri LOG_WARN("fail to hextoraw_string for blob", K(ret), K(in_str)); } } else { + ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in_str), K(out_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to blob type"); } @@ -4607,35 +4608,23 @@ int string_to_enum(ObIAllocator& alloc, const ObString& orig_in_str, const ObCol } else if (OB_FAIL(find_type(str_values, cs_type, no_sp_val, pos))) { LOG_WARN("fail to find type", K(str_values), K(cs_type), K(no_sp_val), K(in_str), K(pos), K(ret)); } else if (OB_UNLIKELY(pos < 0)) { - if (CM_IS_WARN_ON_FAIL(cast_mode)) { - value = 0; - warning = OB_ERR_DATA_TRUNCATED; - LOG_INFO("input value out of range, and set out value zero", K(no_sp_val), K(str_values), K(warning), K(expr)); - } else { + // Bug30666903: check implicit cast logic to handle number cases + if (!in_str.is_numeric()) { ret = OB_ERR_DATA_TRUNCATED; - LOG_WARN("input value out of range", K(no_sp_val), K(str_values), K(expr), K(ret)); - // Bug30666903: check implicit cast logic to handle number cases - if (in_str.is_numeric()) { - int err = 0; - value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err); - if (err == 0) { - ret = OB_SUCCESS; - uint32_t val_cnt = str_values.count(); - if (OB_UNLIKELY(val_cnt <= 0)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect val_cnt", K(val_cnt), K(ret)); - } else if (value > val_cnt) { - value = 0; - ret = OB_ERR_DATA_TRUNCATED; - LOG_WARN("input value out of range", K(val_cnt), K(ret)); - } - if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { - warning = OB_ERR_DATA_TRUNCATED; - ret = OB_SUCCESS; - } - } + } else { + int err = 0; + int64_t val_cnt = str_values.count(); + value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err); + if (err != 0 || value > val_cnt) { + value = 0; + ret = OB_ERR_DATA_TRUNCATED; + LOG_WARN("input value out of range", K(val_cnt), K(ret), K(err)); } } + if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { + warning = ret; + ret = OB_SUCCESS; + } } else { value = pos + 1; // enum start from 1 } @@ -4777,8 +4766,15 @@ CAST_ENUMSET_FUNC_NAME(datetime, enum) char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); - if (OB_FAIL(common_datetime_string( - expr.args_[0]->datum_meta_.type_, ObVarcharType, 0, false, in_val, ctx, buf, sizeof(buf), len))) { + if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, + ObVarcharType, + expr.args_[0]->datum_meta_.scale_, + false, + in_val, + ctx, + buf, + sizeof(buf), + len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString in_str(len, buf); @@ -4805,8 +4801,15 @@ CAST_ENUMSET_FUNC_NAME(datetime, set) char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); - if (OB_FAIL(common_datetime_string( - expr.args_[0]->datum_meta_.type_, ObVarcharType, 0, false, in_val, ctx, buf, sizeof(buf), len))) { + if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, + ObVarcharType, + expr.args_[0]->datum_meta_.scale_, + false, + in_val, + ctx, + buf, + sizeof(buf), + len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString in_str(len, buf); -- GitLab