support json type

This commit is contained in:
xj0
2022-02-08 14:58:13 +08:00
committed by LINxiansheng
parent 4b25bac8d0
commit e5f59ea074
241 changed files with 46116 additions and 749 deletions

View File

@ -276,7 +276,23 @@ int ObExprCast::calc_result_type2(
if (is_explicit_cast && !lib::is_oracle_mode() && ObCharType == dst_type.get_type()) {
// cast(x as binary(10)), in parser,binary->T_CHAR+bianry, but, result type should be varchar, so set it.
type.set_type(ObVarcharType);
} else {
} else if (lib::is_mysql_mode() && ObFloatType == dst_type.get_type()) {
// Compatible with mysql. If the precision p is not specified, produces a result of type FLOAT.
// If p is provided and 0 <= p <= 24, the result is of type FLOAT. If 25 <= p <= 53,
// the result is of type DOUBLE. If p < 0 or p > 53, an error is returned
// however, ob use -1 as default precision, so it is a valid value
type.set_collation_type(dst_type.get_collation_type());
ObPrecision float_precision = dst_type.get_precision();
if (float_precision < -1 || float_precision > OB_MAX_DOUBLE_FLOAT_PRECISION) {
ret = OB_ERR_TOO_BIG_PRECISION;
LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, float_precision, "CAST", OB_MAX_DOUBLE_FLOAT_PRECISION);
} else if (float_precision <= OB_MAX_FLOAT_PRECISION) {
type.set_type(ObFloatType);
} else {
type.set_type(ObDoubleType);
}
}
else {
type.set_type(dst_type.get_type());
type.set_collation_type(dst_type.get_collation_type());
}
@ -292,13 +308,13 @@ int ObExprCast::calc_result_type2(
ObCollationType collation_nation = session->get_nls_collation_nation();
type1.set_calc_type(get_calc_cast_type(type1.get_type(), dst_type.get_type()));
int32_t length = 0;
if (ob_is_string_type(dst_type.get_type()) || ob_is_raw(dst_type.get_type())) {
if (ob_is_string_type(dst_type.get_type()) || ob_is_raw(dst_type.get_type()) || ob_is_json(dst_type.get_type())) {
type.set_collation_level(is_explicit_cast ? CS_LEVEL_IMPLICIT : type1.get_collation_level());
int32_t len = dst_type.get_length();
int16_t length_semantics =
(dst_type.is_string_or_lob_locator_type()
? dst_type.get_length_semantics()
: (OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics()
int16_t length_semantics =
((dst_type.is_string_or_lob_locator_type() || dst_type.is_json())
? dst_type.get_length_semantics()
: (OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics()
: LS_BYTE));
if (len > 0) { // cast(1 as char(10))
type.set_full_length(len, length_semantics);
@ -430,6 +446,8 @@ int ObExprCast::get_cast_type(const ObExprResType param_type2, ObExprResType& ds
dst_type.set_length(parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX]);
} else if (ob_is_extend(obj_type)) {
ret = OB_NOT_SUPPORTED;
} else if (lib::is_mysql_mode() && ob_is_json(obj_type)) {
dst_type.set_collation_type(CS_TYPE_UTF8MB4_BIN);
} else {
dst_type.set_precision(parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX]);
dst_type.set_scale(parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX]);
@ -476,7 +494,7 @@ int ObExprCast::calc_result2(ObObj& result, const ObObj& obj1, const ObObj& obj2
accuracy.set_full_length(node.int32_values_[1], result_type_.get_length_semantics(), share::is_oracle_mode());
} else if (ObRawTC == dest_tc) {
accuracy.set_length(node.int32_values_[1]);
} else if (ObTextTC == dest_tc || ObLobTC == dest_tc) {
} else if (ObTextTC == dest_tc || ObLobTC == dest_tc || ObJsonTC == dest_tc) {
// TODO texttc should use default length
accuracy.set_length(
node.int32_values_[1] < 0 ? ObAccuracy::DDL_DEFAULT_ACCURACY[dest_type].get_length() : node.int32_values_[1]);
@ -539,27 +557,50 @@ int ObExprCast::calc_result2(ObObj& result, const ObObj& obj1, const ObObj& obj2
result_type_.get_collation_type());
const ObObj* res_obj = NULL;
ObObj buf_obj1;
if (OB_FAIL(ObObjCaster::to_type(dest_type, cast_ctx, obj1_round, buf_obj1, res_obj))) {
LOG_WARN("cast failed", K(ret), K(obj1_round), K(dest_type));
} else if (OB_ISNULL(res_obj)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(obj1_round), K(dest_type));
} else if (OB_FAIL(obj_accuracy_check(
cast_ctx, accuracy, result_type_.get_collation_type(), *res_obj, buf_obj1, res_obj))) {
if (ob_is_string_type(dest_type) && OB_ERR_DATA_TOO_LONG == ret) {
if ((obj1_round.is_character_type() || obj1_round.is_clob()) && compatbility_mode) {
ret = OB_SUCCESS;
} else {
ret = OB_ERR_TRUNCATED_WRONG_VALUE;
}
bool is_bool = false;
ObItemType item_type_obj1 = T_NULL;
if (OB_SUCC(ret) && lib::is_mysql_mode() && (ObIntTC == src_tc || src_tc == ObStringTC)
&& ObJsonType == dest_type) {
// mysql bool to jsonbool or enumset to json
if (OB_FAIL(get_param_is_boolean(expr_ctx, obj1, is_bool))) {
LOG_WARN("get src is_boolean type failed, bool may be cast as json int", K(ret), K(obj1));
} else if (OB_FAIL(get_param_type(expr_ctx, obj1, item_type_obj1))) {
LOG_WARN("get param type failed", K(ret), K(obj1));
}
LOG_WARN("failed to check accuracy",
}
if (OB_SUCC(ret)) {
if (is_bool) {
ret = ObObjCaster::bool_to_json(dest_type, cast_ctx, obj1_round, buf_obj1, res_obj);
} else if (OB_UNLIKELY(item_type_obj1 == T_FUN_SET_TO_STR)) {
ret = ObObjCaster::enumset_to_json(dest_type, cast_ctx, obj1_round, buf_obj1, res_obj);
} else {
ret = ObObjCaster::to_type(dest_type, cast_ctx, obj1_round, buf_obj1, res_obj);
}
if (OB_FAIL(ret)) {
LOG_WARN("cast failed", K(ret), K(obj1_round), K(dest_type));
} else if (OB_ISNULL(res_obj)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(obj1_round), K(dest_type));
} else if (OB_FAIL(
obj_accuracy_check(cast_ctx, accuracy, result_type_.get_collation_type(), *res_obj, buf_obj1, res_obj))) {
if (ob_is_string_type(dest_type) && OB_ERR_DATA_TOO_LONG == ret) {
if ((obj1_round.is_character_type() || obj1_round.is_clob()) && compatbility_mode) {
ret = OB_SUCCESS;
} else {
ret = OB_ERR_TRUNCATED_WRONG_VALUE;
}
}
LOG_WARN("failed to check accuracy",
K(obj1_round),
K(*res_obj),
K(dest_type),
K(accuracy),
K(ret),
K((expr_ctx).cast_mode_));
}
}
if (OB_SUCC(ret)) {
switch (res_obj->get_type()) {