diff --git a/contrib/dolphin/expected/uint_cast.out b/contrib/dolphin/expected/uint_cast.out index 05483684ee5de36c6675f70e6b128a31e437f7e5..03d14796d989ee221b02ee2f3b82dfb09ea63a34 100644 --- a/contrib/dolphin/expected/uint_cast.out +++ b/contrib/dolphin/expected/uint_cast.out @@ -1666,5 +1666,105 @@ select (1)::uint8::bool; t (1 row) +-- 严格模式 +drop table if exists t_longtext; +NOTICE: table "t_longtext" does not exist, skipping +create table t_longtext(a longtext); +insert into t_longtext select '-1'::uint8; +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('-1' as uint1); +WARNING: Cast to tinyint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint1 +insert into t_longtext select cast('-1' as uint2); +WARNING: Cast to smallint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint2 +insert into t_longtext select cast('-1' as uint4); +WARNING: Cast to int unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint4 +insert into t_longtext select cast('-1' as uint8); +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('-1' as unsigned); +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('0' as unsigned); +insert into t_longtext select cast('-9223372036854775808' as unsigned); +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('-9223372036854775809' as unsigned); +ERROR: bigint unsigned out of range +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('18446744073709551615' as unsigned); +insert into t_longtext select cast('18446744073709551616' as unsigned); +ERROR: bigint unsigned out of range +CONTEXT: referenced column: uint8 +select * from t_longtext; + a +---------------------- + 18446744073709551615 + 255 + 65535 + 4294967295 + 18446744073709551615 + 18446744073709551615 + 0 + 9223372036854775808 + 18446744073709551615 +(9 rows) + +drop table if exists t_longtext; +-- 非严格模式 +set dolphin.sql_mode = ''; +drop table if exists t_longtext; +NOTICE: table "t_longtext" does not exist, skipping +create table t_longtext(a longtext); +insert into t_longtext select '-1'::uint8; +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('-1' as uint1); +WARNING: Cast to tinyint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint1 +insert into t_longtext select cast('-1' as uint2); +WARNING: Cast to smallint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint2 +insert into t_longtext select cast('-1' as uint4); +WARNING: Cast to int unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint4 +insert into t_longtext select cast('-1' as uint8); +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('-1' as unsigned); +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('0' as unsigned); +insert into t_longtext select cast('-9223372036854775808' as unsigned); +WARNING: Cast to bigint unsigned converted negative integer to it's positive complement +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('-9223372036854775809' as unsigned); +WARNING: bigint unsigned out of range +CONTEXT: referenced column: uint8 +insert into t_longtext select cast('18446744073709551615' as unsigned); +insert into t_longtext select cast('18446744073709551616' as unsigned); +WARNING: bigint unsigned out of range +CONTEXT: referenced column: uint8 +select * from t_longtext; + a +---------------------- + 18446744073709551615 + 255 + 65535 + 4294967295 + 18446744073709551615 + 18446744073709551615 + 0 + 9223372036854775808 + 9223372036854775808 + 18446744073709551615 + 18446744073709551615 +(11 rows) + +drop table if exists t_longtext; +reset dolphin.sql_mode; drop schema uint_cast cascade; reset current_schema; diff --git a/contrib/dolphin/plugin_parser/parse_coerce.cpp b/contrib/dolphin/plugin_parser/parse_coerce.cpp index c0236d3c2c315d308641b36f5f0ab13ab9ac390d..f756df1bdc4fc0fbdad8c793047c087ecbedfabe 100644 --- a/contrib/dolphin/plugin_parser/parse_coerce.cpp +++ b/contrib/dolphin/plugin_parser/parse_coerce.cpp @@ -334,6 +334,22 @@ Node *const_expression_to_const(Node *node) return eval_const_expression_value(NULL, result, NULL); } +#ifdef DOLPHIN +static bool hasTextCoercePath(Oid* srcoid, Oid destoid, CoercionContext ccontext, bool* changed) +{ + if (ccontext == COERCION_EXPLICIT && + (destoid == get_typeoid(PG_CATALOG_NAMESPACE, "uint1") || + destoid == get_typeoid(PG_CATALOG_NAMESPACE, "uint2") || + destoid == get_typeoid(PG_CATALOG_NAMESPACE, "uint4") || + destoid == get_typeoid(PG_CATALOG_NAMESPACE, "uint8"))) { + *srcoid = TEXTOID; + *changed = true; + return true; + } + return false; +} +#endif + /* * coerce_type() * Convert an expression to a different type. @@ -362,6 +378,9 @@ Node* coerce_type(ParseState* pstate, Node* node, Oid inputTypeId, Oid targetTyp Node* result = NULL; CoercionPathType pathtype; Oid funcId; +#ifdef DOLPHIN + bool change_unknown = false; +#endif if (targetTypeId == inputTypeId || node == NULL) { /* no conversion needed */ @@ -410,7 +429,12 @@ Node* coerce_type(ParseState* pstate, Node* node, Oid inputTypeId, Oid targetTyp } } +#ifdef DOLPHIN + if (inputTypeId == UNKNOWNOID && IsA(node, Const) && + !hasTextCoercePath(&inputTypeId, targetTypeId, ccontext, &change_unknown)) { +#else if (inputTypeId == UNKNOWNOID && IsA(node, Const)) { +#endif /* * Input is a string constant with previously undetermined type. Apply * the target type's typinput function to it to produce a constant of @@ -547,6 +571,12 @@ Node* coerce_type(ParseState* pstate, Node* node, Oid inputTypeId, Oid targetTyp ccontext = COERCION_ASSIGNMENT; } pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext, &funcId); +#ifdef DOLPHIN + if (change_unknown) { + inputTypeId = UNKNOWNOID; + change_unknown = false; + } +#endif if (pathtype != COERCION_PATH_NONE) { if (pathtype != COERCION_PATH_RELABELTYPE) { /* diff --git a/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp b/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp index 7167d2db98f6d1c8771ef2fa592ac69deb0dc251..46a9149f03b35808f2da0b18aab78cd2474f8220 100644 --- a/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp +++ b/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp @@ -4189,9 +4189,9 @@ static int uint1_fastcmp(Datum x, Datum y, SortSupport ssup) uint8 b = DatumGetUInt8(y); if (a > b) { - return 1; + return 1; } else if (a == b) { - return 0; + return 0; } else { return -1; } @@ -4211,9 +4211,9 @@ static int uint2_fastcmp(Datum x, Datum y, SortSupport ssup) uint16 b = DatumGetUInt16(y); if (a > b) { - return 1; + return 1; } else if (a == b) { - return 0; + return 0; } else { return -1; } @@ -4233,9 +4233,9 @@ static int uint4_fastcmp(Datum x, Datum y, SortSupport ssup) uint32 b = DatumGetUInt32(y); if (a > b) { - return 1; + return 1; } else if (a == b) { - return 0; + return 0; } else { return -1; } @@ -4255,9 +4255,9 @@ static int uint8_fastcmp(Datum x, Datum y, SortSupport ssup) uint64 b = DatumGetUInt64(y); if (a > b) { - return 1; + return 1; } else if (a == b) { - return 0; + return 0; } else { return -1; } @@ -4295,6 +4295,30 @@ int128 text_uintInternal(Datum txt, int128 min, int128 max, char* intType, bool return result; } +static int128 UnknownUintInternal(Datum txt, int128 min, int128 max, char* intType, bool canIgnore, Oid oid) +{ + char* tmp = NULL; + int128 result; + Oid typeOutput; + bool typIsVarlena; + getTypeOutputInfo(oid, &typeOutput, &typIsVarlena); + tmp = DatumGetCString(OidOutputFunctionCall(typeOutput, txt)); + result = DatumGetInt128(DirectFunctionCall1(int16in, CStringGetDatum(tmp))); + pfree_ext(tmp); + if (result < 0 && result >= min) { + ereport(WARNING, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("Cast to %s unsigned converted negative integer to it's positive complement", intType))); + } + if (result < min || result > max) { + result = result < min ? min : max; + ereport((canIgnore || !SQL_MODE_STRICT()) ? WARNING : ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("%s unsigned out of range", intType))); + } + return result; +} + Datum text_uint1(PG_FUNCTION_ARGS) { Datum txt = PG_GETARG_DATUM(0); @@ -4322,25 +4346,29 @@ Datum text_uint8(PG_FUNCTION_ARGS) Datum text_cast_uint1(PG_FUNCTION_ARGS) { Datum txt = PG_GETARG_DATUM(0); - PG_RETURN_UINT8(text_uintInternal(txt, SCHAR_MIN, UCHAR_MAX, "tinyint", fcinfo->can_ignore)); + Oid typeoid = fcinfo->argTypes[0]; + PG_RETURN_UINT8(UnknownUintInternal(txt, SCHAR_MIN, UCHAR_MAX, "tinyint", fcinfo->can_ignore, typeoid)); } Datum text_cast_uint2(PG_FUNCTION_ARGS) { Datum txt = PG_GETARG_DATUM(0); - PG_RETURN_UINT16(text_uintInternal(txt, SHRT_MIN, USHRT_MAX, "smallint", fcinfo->can_ignore)); + Oid typeoid = fcinfo->argTypes[0]; + PG_RETURN_UINT16(UnknownUintInternal(txt, SHRT_MIN, USHRT_MAX, "smallint", fcinfo->can_ignore, typeoid)); } Datum text_cast_uint4(PG_FUNCTION_ARGS) { Datum txt = PG_GETARG_DATUM(0); - PG_RETURN_UINT32(text_uintInternal(txt, INT_MIN, UINT_MAX, "int", fcinfo->can_ignore)); + Oid typeoid = fcinfo->argTypes[0]; + PG_RETURN_UINT32(UnknownUintInternal(txt, INT_MIN, UINT_MAX, "int", fcinfo->can_ignore, typeoid)); } Datum text_cast_uint8(PG_FUNCTION_ARGS) { Datum txt = PG_GETARG_DATUM(0); - PG_RETURN_UINT64(text_uintInternal(txt, LONG_MIN, ULONG_MAX, "bigint", fcinfo->can_ignore)); + Oid typeoid = fcinfo->argTypes[0]; + PG_RETURN_UINT64(UnknownUintInternal(txt, LONG_MIN, ULONG_MAX, "bigint", fcinfo->can_ignore, typeoid)); } #ifdef DOLPHIN diff --git a/contrib/dolphin/sql/uint_cast.sql b/contrib/dolphin/sql/uint_cast.sql index 06371b512ed532037e1e746d0d816628a4c3646e..afb22937b9dda89682477b713c6b24c32d7b4403 100644 --- a/contrib/dolphin/sql/uint_cast.sql +++ b/contrib/dolphin/sql/uint_cast.sql @@ -283,5 +283,40 @@ select (1)::uint4::bool; select (0)::uint8::bool; select (1)::uint8::bool; +-- 严格模式 +drop table if exists t_longtext; +create table t_longtext(a longtext); +insert into t_longtext select '-1'::uint8; +insert into t_longtext select cast('-1' as uint1); +insert into t_longtext select cast('-1' as uint2); +insert into t_longtext select cast('-1' as uint4); +insert into t_longtext select cast('-1' as uint8); +insert into t_longtext select cast('-1' as unsigned); +insert into t_longtext select cast('0' as unsigned); +insert into t_longtext select cast('-9223372036854775808' as unsigned); +insert into t_longtext select cast('-9223372036854775809' as unsigned); +insert into t_longtext select cast('18446744073709551615' as unsigned); +insert into t_longtext select cast('18446744073709551616' as unsigned); +select * from t_longtext; +drop table if exists t_longtext; +-- 非严格模式 +set dolphin.sql_mode = ''; +drop table if exists t_longtext; +create table t_longtext(a longtext); +insert into t_longtext select '-1'::uint8; +insert into t_longtext select cast('-1' as uint1); +insert into t_longtext select cast('-1' as uint2); +insert into t_longtext select cast('-1' as uint4); +insert into t_longtext select cast('-1' as uint8); +insert into t_longtext select cast('-1' as unsigned); +insert into t_longtext select cast('0' as unsigned); +insert into t_longtext select cast('-9223372036854775808' as unsigned); +insert into t_longtext select cast('-9223372036854775809' as unsigned); +insert into t_longtext select cast('18446744073709551615' as unsigned); +insert into t_longtext select cast('18446744073709551616' as unsigned); +select * from t_longtext; +drop table if exists t_longtext; +reset dolphin.sql_mode; + drop schema uint_cast cascade; reset current_schema; \ No newline at end of file