提交 f51c7afe 编写于 作者: H Hongqin-Li 提交者: wangzelin.wzl

Fix the conversion rules from string/datetime to enum/set

上级 44f28e92
......@@ -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;
}
......
......@@ -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
......@@ -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;
......
......@@ -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
}
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册