Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions contrib/babelfishpg_common/src/babelfishpg_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ get_common_utility_plugin(void)
common_utility_plugin_var.is_tsql_money_datatype = &is_tsql_money_datatype;
common_utility_plugin_var.is_tsql_smallmoney_datatype = &is_tsql_smallmoney_datatype;

/* FIX ME: Remove is_tsql_int_datatype and is_tsql_bigint_datatype once BABEL-5955 is fixed */
common_utility_plugin_var.is_tsql_int_datatype = &is_tsql_int_datatype;
common_utility_plugin_var.is_tsql_bigint_datatype = &is_tsql_bigint_datatype;

common_utility_plugin_var.datetime_in_str = &datetime_in_str;
common_utility_plugin_var.datetime2sqlvariant = &datetime2sqlvariant;
common_utility_plugin_var.timestamptz_datetimeoffset = &timestamptz_datetimeoffset;
Expand Down
4 changes: 4 additions & 0 deletions contrib/babelfishpg_common/src/babelfishpg_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ typedef struct common_utility_plugin
bool (*is_tsql_tinyint_datatype) (Oid oid);
bool (*is_tsql_money_datatype) (Oid oid);
bool (*is_tsql_smallmoney_datatype) (Oid oid);

/* FIX ME: Remove is_tsql_int_datatype and is_tsql_bigint_datatype once BABEL-5955 is fixed */
bool (*is_tsql_int_datatype) (Oid oid);
bool (*is_tsql_bigint_datatype) (Oid oid);

Datum (*datetime_in_str) (char *str, Node *escontext);
Datum (*datetime2sqlvariant) (PG_FUNCTION_ARGS);
Expand Down
21 changes: 21 additions & 0 deletions contrib/babelfishpg_common/src/typecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ Oid tsql_smallmoney_oid = InvalidOid;
Oid tsql_fixeddecimal_oid = InvalidOid;
Oid tsql_bit_oid = InvalidOid;

/* FIX ME: Remove tsql_int_oid and tsql_bigint_oid once BABEL-5955 is fixed */
Oid tsql_int_oid = InvalidOid;
Oid tsql_bigint_oid = InvalidOid;

Oid
lookup_tsql_datatype_oid(const char *typename)
{
Expand Down Expand Up @@ -521,6 +525,23 @@ is_tsql_tinyint_datatype(Oid oid)
return tsql_tinyint_oid == oid;
}

/* FIX ME: Remove is_tsql_int_datatype and is_tsql_bigint_datatype once BABEL-5955 is fixed */
bool
is_tsql_int_datatype(Oid oid)
{
if (tsql_int_oid == InvalidOid)
tsql_int_oid = lookup_tsql_datatype_oid("int");
return tsql_int_oid == oid;
}

bool
is_tsql_bigint_datatype(Oid oid)
{
if (tsql_bigint_oid == InvalidOid)
tsql_bigint_oid = lookup_tsql_datatype_oid("bigint");
return tsql_bigint_oid == oid;
}

bool
is_tsql_money_datatype(Oid oid)
{
Expand Down
4 changes: 4 additions & 0 deletions contrib/babelfishpg_common/src/typecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ extern bool is_tsql_tinyint_datatype(Oid oid);
extern bool is_tsql_money_datatype(Oid oid);
extern bool is_tsql_smallmoney_datatype(Oid oid);

/* FIX ME: Remove is_tsql_int_datatype and is_tsql_bigint_datatype once BABEL-5955 is fixed */
extern bool is_tsql_int_datatype(Oid oid);
extern bool is_tsql_bigint_datatype(Oid oid);

extern void handle_type_and_collation(struct Node *node, Oid typid, Oid collationid);
extern bool check_target_type_is_sys_varchar(Oid funcid);
extern type_info_t get_tsql_type_info(uint8_t type_code);
Expand Down
182 changes: 179 additions & 3 deletions contrib/babelfishpg_tsql/src/pltsql_coerce.c
Original file line number Diff line number Diff line change
Expand Up @@ -1220,9 +1220,10 @@ is_numeric_datatype(Oid typid)
static int32
get_default_typmod_for_fixedsize_dataypes(Oid resulttype)
{
if (resulttype == INT4OID)
/* FIX ME: Remove is_tsql_int_datatype and is_tsql_bigint_datatype once BABEL-5955 is fixed */
if (resulttype == INT4OID || (*common_utility_plugin_ptr->is_tsql_int_datatype)(resulttype))
return DEFAULT_INT_TYPMOD;
else if (resulttype == INT8OID)
else if (resulttype == INT8OID || (*common_utility_plugin_ptr->is_tsql_bigint_datatype)(resulttype))
return DEFAULT_BIGINT_TYPMOD;
else if (resulttype == INT2OID)
return DEFAULT_SMALLINT_TYPMOD;
Expand All @@ -1236,6 +1237,42 @@ get_default_typmod_for_fixedsize_dataypes(Oid resulttype)
return -1;
}

/*
* get_typmod_from_func_arg()
* This function retrieves the typmod from the first argument of a function.
* If the typmod cannot be determined, it returns -1.
*/
static int32
get_typmod_from_func_arg(Plan *plan, bool *found_typmod, List *args)
{
int32 rettypmod = -1;
Node *arg = NULL;

if (list_length(args) >= 1)
{
arg = linitial(args);
rettypmod = resolve_numeric_typmod_from_exp(plan, arg, found_typmod);
}
else if (found_typmod != NULL)
{
*found_typmod = false;
}
return rettypmod;
}

/*
* is_namespace_sys_or_pg_catalog
* Returns true if the given namespace Oid is either sys or pg_catalog.
*/
static bool
is_namespace_sys_or_pg_catalog(Oid nspoid)
{
if (nspoid == PG_CATALOG_NAMESPACE || get_namespace_oid("sys", false))
return true;

return false;
}

/*
* Look for a typmod to return from a numeric expression,
* also for cases where we cannot compute the expression typmod return -1 and set found as false.
Expand Down Expand Up @@ -1659,6 +1696,9 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
int rettypmod = -1;
bool found_typmod;
Node *arg = NULL;
char *funcName;
Oid func_namespace_oid = InvalidOid;

/* Be smart about length-coercion functions... */
if (exprIsLengthCoercion(expr, &rettypmod))
{
Expand Down Expand Up @@ -1699,10 +1739,145 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
return rettypmod;
}

/* We will find typmod for mathematical functions. */
funcName = get_func_name(func_oid);
func_namespace_oid = get_func_namespace(func_oid);

if (funcName &&
is_namespace_sys_or_pg_catalog(func_namespace_oid))
{
/*
* For round functions we have already deprecated the functions
* in previous versions so can't change that doing the exact match
* and adding additional handling for prefix matching of all functions
*/
if ((strlen(funcName) == 5 && (strncmp(funcName, "round", 5) == 0)) ||
(strlen(funcName) == 4 && (strncmp(funcName, "sign", 4) == 0)) ||
(strlen(funcName) == 3 && (strncmp(funcName, "abs", 3) == 0)) ||
(strlen(funcName) == 34 && (strncmp(funcName, "bbf_numeric_round_deprecated_5_2_0", 34) == 0)) ||
(strlen(funcName) == 34 && (strncmp(funcName, "bbf_numeric_trunc_deprecated_5_2_0", 34) == 0)) ||
(strlen(funcName) >= 20 && (strncmp(funcName, "bbf_round_deprecated", 20) == 0)) ||
(strlen(funcName) >= 19 && (strncmp(funcName, "bbf_sign_deprecated", 19) == 0)) ||
(strlen(funcName) >= 18 && (strncmp(funcName, "bbf_abs_deprecated", 18) == 0)))
{
int32 fixsize_default_typmod = get_default_typmod_for_fixedsize_dataypes(func->funcresulttype);
if (fixsize_default_typmod != -1)
{
pfree(funcName);
return fixsize_default_typmod;
}
else
{
int32 argtypmod = get_typmod_from_func_arg(plan, &found_typmod, func->args);
if (!found_typmod)
{
if (found != NULL) *found = false;
}
if (argtypmod != -1)
{
pfree(funcName);
return argtypmod;
}
}
}
else if ((strlen(funcName) == 7 && (strncmp(funcName, "ceiling", 7) == 0)) ||
(strlen(funcName) == 5 && (strncmp(funcName, "floor", 5) == 0)) ||
(strlen(funcName) >= 20 && (strncmp(funcName, "bbf_floor_deprecated", 20) == 0)) ||
(strlen(funcName) >= 22 && (strncmp(funcName, "bbf_ceiling_deprecated", 22) == 0)))
{
int32 fixsize_default_typmod = get_default_typmod_for_fixedsize_dataypes(func->funcresulttype);
if (fixsize_default_typmod != -1)
{
pfree(funcName);
return fixsize_default_typmod;
}
else
{
int32 argtypmod = get_typmod_from_func_arg(plan, &found_typmod, func->args);
if (!found_typmod)
{
if (found != NULL) *found = false;
}
if (argtypmod != -1)
{
/* for ceiling and floor functions, we return 0 scale */
uint8_t precision = ((argtypmod - VARHDRSZ) >> 16) & 0xffff;
pfree(funcName);
return ((precision << 16) | 0) + VARHDRSZ;
}
}
}
else if ((strlen(funcName) == 7 && (strncmp(funcName, "degrees", 7) == 0)) ||
(strlen(funcName) == 7 && (strncmp(funcName, "radians", 7) == 0)) ||
(strlen(funcName) >= 22 && (strncmp(funcName, "bbf_degrees_deprecated", 22) == 0)) ||
(strlen(funcName) >= 22 && (strncmp(funcName, "bbf_radians_deprecated", 22) == 0)))
{
int32 fixsize_default_typmod = get_default_typmod_for_fixedsize_dataypes(func->funcresulttype);
if (fixsize_default_typmod != -1)
{
pfree(funcName);
return fixsize_default_typmod;
}
else
{
/*
* for radians and degrees functions, we return
* scale as 18 and precision as max precision
*/
pfree(funcName);
return ((tds_default_numeric_precision << 16) | 18) + VARHDRSZ;
}
}
else if ((strlen(funcName) == 5 && (strncmp(funcName, "power", 5) == 0)) ||
(strlen(funcName) >= 20 && (strncmp(funcName, "bbf_power_deprecated", 20) == 0)))
{
int32 fixsize_default_typmod = get_default_typmod_for_fixedsize_dataypes(func->funcresulttype);
if (fixsize_default_typmod != -1)
{
pfree(funcName);
return fixsize_default_typmod;
}
else
{
int32 argtypmod = get_typmod_from_func_arg(plan, &found_typmod, func->args);
if (!found_typmod)
{
if (found != NULL) *found = false;
}
if (argtypmod != -1)
{
/* For abs and power functions, precision as 38. */
uint8_t scale = (argtypmod - VARHDRSZ) & 0xffff;
pfree(funcName);
return ((tds_default_numeric_precision << 16) | scale) + VARHDRSZ;
}
}
}
else if ((strlen(funcName) == 14 && (strncmp(funcName, "scope_identity", 14) == 0)) ||
(strlen(funcName) == 10 && (strncmp(funcName, "ident_seed", 10) == 0)) ||
(strlen(funcName) == 10 && (strncmp(funcName, "ident_incr", 10) == 0)) ||
(strlen(funcName) == 13 && (strncmp(funcName, "ident_current", 13) == 0)) ||
(strlen(funcName) >= 29 && (strncmp(funcName, "bbf_scope_identity_deprecated", 29) == 0)) ||
(strlen(funcName) >= 25 && (strncmp(funcName, "bbf_ident_seed_deprecated", 25) == 0)) ||
(strlen(funcName) >= 25 && (strncmp(funcName, "bbf_ident_incr_deprecated", 25) == 0)) ||
(strlen(funcName) >= 28 && (strncmp(funcName, "bbf_ident_current_deprecated", 28) == 0)))
{
/*
* For scope_identity, ident_seed, ident_incr and ident_current
* functions, we return 0 scale and precision as 38.
*/
pfree(funcName);
return ((tds_default_numeric_precision << 16) | 0) + VARHDRSZ;
}
}

if (rettypmod == -1)
{
if (found != NULL) *found = false;
}

if (funcName)
pfree(funcName);
return rettypmod;
}
case T_NullIfExpr:
Expand Down Expand Up @@ -1958,7 +2133,8 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
}
}

pfree(aggFuncName);
if (aggFuncName)
pfree(aggFuncName);
return ((precision << 16) | scale) + VARHDRSZ;
}
case T_PlaceHolderVar:
Expand Down
8 changes: 4 additions & 4 deletions test/JDBC/expected/BABEL-3802-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ SELECT power(a,b), power(b,b), power(c,b), power(d,b), power(e,b) from BABEL_380
GO
~~START~~
int#!#numeric#!#bigint#!#int#!#int
<NULL>#!#1.00000000#!#<NULL>#!#<NULL>#!#<NULL>
-2147483648#!#1.00000000#!#-9223372036854775808#!#-32768#!#0
101#!#1.00000000#!#97777#!#376#!#120
2147483647#!#1.00000000#!#9223372036854#!#32767#!#255
<NULL>#!#1#!#<NULL>#!#<NULL>#!#<NULL>
-2147483648#!#1#!#-9223372036854775808#!#-32768#!#0
101#!#1#!#97777#!#376#!#120
2147483647#!#1#!#9223372036854#!#32767#!#255
~~END~~


Expand Down
Loading
Loading