Skip to content

Commit

Permalink
fixed issue with computation of precision and scale for non-exact num…
Browse files Browse the repository at this point in the history
…eric types

Signed-off-by: Rohit Bhagat <[email protected]>
  • Loading branch information
Rohit Bhagat committed Feb 7, 2025
1 parent 879284a commit 865b5ca
Show file tree
Hide file tree
Showing 16 changed files with 103 additions and 36 deletions.
51 changes: 50 additions & 1 deletion contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ static Oid tsql_int4_bit_oid = InvalidOid;
static Oid sys_nspoid = InvalidOid;
static Oid tsql_bit_oid = InvalidOid;
static Oid tsql_fixeddecimal_oid = InvalidOid;
static Oid tsql_tinyint_oid = InvalidOid;
static Oid tsql_money_oid = InvalidOid;
static Oid tsql_smallmoney_oid = InvalidOid;

static void FillTabNameWithNumParts(StringInfo buf, uint8 numParts, TdsRelationMetaDataInfo relMetaDataInfo);
static void FillTabNameWithoutNumParts(StringInfo buf, uint8 numParts, TdsRelationMetaDataInfo relMetaDataInfo);
Expand Down Expand Up @@ -638,11 +641,57 @@ is_numeric_datatype(Oid typid)
return decimal_oid == typid;
}

/*
* is_exact_numeric_datatype - returns bool if given datatype is numeric, decimal, int, tinyint, smallint, bigint, bit, money and smallmoney.
*/
static bool
is_exact_numeric_datatype(Oid typid)
{
typid = getBaseType(typid);

if (typid == NUMERICOID || typid == INT2OID || typid == INT4OID || typid == INT8OID)
{
return true;
}
if (!OidIsValid(decimal_oid))
{
TypeName *typename = makeTypeNameFromNameList(list_make2(makeString("sys"), makeString("decimal")));
decimal_oid = LookupTypeNameOid(NULL, typename, false);
}
if (!OidIsValid(tsql_tinyint_oid))
{
TypeName *typename = makeTypeNameFromNameList(list_make2(makeString("sys"), makeString("tinyint")));
tsql_tinyint_oid = LookupTypeNameOid(NULL, typename, false);
}
if (!OidIsValid(tsql_money_oid))
{
TypeName *typename = makeTypeNameFromNameList(list_make2(makeString("sys"), makeString("money")));
tsql_money_oid = LookupTypeNameOid(NULL, typename, false);
}
if (!OidIsValid(tsql_smallmoney_oid))
{
TypeName *typename = makeTypeNameFromNameList(list_make2(makeString("sys"), makeString("smallmoney")));
tsql_smallmoney_oid = LookupTypeNameOid(NULL, typename, false);
}
if (!OidIsValid(tsql_bit_oid))
{
TypeName *typename = makeTypeNameFromNameList(list_make2(makeString("sys"), makeString("bit")));
tsql_bit_oid = LookupTypeNameOid(NULL, typename, false);
}

return (decimal_oid == typid
|| tsql_tinyint_oid == typid
|| tsql_money_oid == typid
|| tsql_smallmoney_oid == typid
|| tsql_bit_oid == typid);
}


/* look for a typmod to return from a numeric expression */
int32
resolve_numeric_typmod_from_exp(Plan *plan, Node *expr)
{
if (expr == NULL)
if (expr == NULL || !is_exact_numeric_datatype(exprType(expr)))
return -1;
switch (nodeTag(expr))
{
Expand Down
21 changes: 19 additions & 2 deletions contrib/babelfishpg_tsql/src/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -6075,7 +6075,24 @@ remove_db_name_in_schema(const char *object_name, const char *object_type)
static int32
tsql_get_numeric_typmod_from_exp(Plan *plan, Node *expr)
{
int32 result_typmod = -1;
uint8_t scale,
precision;
if (pltsql_protocol_plugin_ptr && *pltsql_protocol_plugin_ptr && (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp)
return (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp(plan, expr);
return -1;
result_typmod = (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp(plan, expr);
if (result_typmod != -1)
{
/*
* If we are unable to get correct precision and scale for overflow cases
* then return -1
*/
scale = (result_typmod - VARHDRSZ) & 0xffff;
precision = ((result_typmod - VARHDRSZ) >> 16) & 0xffff;
if (precision > TDS_NUMERIC_MAX_PRECISION)
{
if (!(precision - scale > 32 && scale > 6) && !(precision - scale <= TDS_NUMERIC_MAX_PRECISION))
return -1;
}
}
return result_typmod;
}
4 changes: 2 additions & 2 deletions test/JDBC/expected/BABEL-1000.out
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,14 @@ SELECT * FROM babel_1000_test8(1)
GO
~~START~~
numeric
2.06000000
2.06
~~END~~

SELECT * FROM babel_1000_test8(12.345678)
GO
~~START~~
numeric
13.06000000
13.06
~~END~~

-- overflow, expect error
Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/BABEL-1164.out
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ SELECT * FROM t2;
GO
~~START~~
int#!#int#!#numeric#!#numeric
1#!#1#!#2#!#2.00000000
1#!#1#!#2#!#2
~~END~~


Expand Down
19 changes: 10 additions & 9 deletions test/JDBC/expected/BABEL-3066-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -504,15 +504,15 @@ SELECT CAST(CAST(12465781.46792 as real) as numeric(38,10)) - CAST(CAST(12465781
GO
~~START~~
numeric
0
0E-15
~~END~~


SELECT CAST(CAST(12465781.46792 as real) as numeric(38,10)) - CAST(CAST(12465781.4679213254 as real) as numeric(38,10));
GO
~~START~~
numeric
0
0E-10
~~END~~


Expand Down Expand Up @@ -540,9 +540,10 @@ GO

SELECT CAST(CAST(12465781.46792 as real) as numeric(38,10)) * CAST(CAST(12465781.4679213254 as real) as numeric(38,15));
GO
~~ERROR (Code: 33557097)~~

~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~
~~START~~
numeric
155395695939961.000000
~~END~~


SELECT CAST(CAST(CAST(CAST(12465781.46792 as real) as numeric(38,10)) * CAST(CAST(12465781.4679213254 as real) as numeric(38,15)) as real) as numeric(38,6));
Expand All @@ -557,15 +558,15 @@ SELECT CAST(CAST(12465781.46792 as real) as numeric(38,10)) * CAST(CAST(12465781
GO
~~START~~
numeric
155395695939961.00000000000000000000
155395695939961.000000
~~END~~


SELECT CAST(CAST(12465781.46792 as real) as numeric(38,0)) / CAST(CAST(12465781.4679213254 as real) as numeric(38,0));
GO
~~START~~
numeric
1.00000000000000000000
1.000000
~~END~~


Expand All @@ -587,14 +588,14 @@ SELECT CAST(CAST(12465781.46792 as real) as numeric(38,10)) / CAST(CAST(12465781
GO
~~START~~
numeric
1.00000000000000000000
1.000000
~~END~~


SELECT CAST(CAST(12465781.46792 as real) as numeric(38,10)) / CAST(CAST(12465781.4679213254 as real) as numeric(38,10));
GO
~~START~~
numeric
1.00000000000000000000
1.000000
~~END~~

4 changes: 2 additions & 2 deletions test/JDBC/expected/BABEL-381.out
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ select 2.0/1.5;
go
~~START~~
numeric
1.3333333333333333
1.333333
~~END~~


select 2.0, 2.0/1.5, 1.0/1.5;
go
~~START~~
numeric#!#numeric#!#numeric
2.0#!#1.3333333333333333#!#0.66666666666666666667
2.0#!#1.333333#!#0.666666
~~END~~

8 changes: 4 additions & 4 deletions test/JDBC/expected/BABEL-5467-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ go
-- Precision and scale details should be stored correctly
select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_avgdata_1'
where TABLE_NAME = 'babel_5467_avgdata_1' order by COLUMN_NAME
go
~~START~~
nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#tinyint#!#smallint#!#int
Expand All @@ -145,7 +145,7 @@ master#!#dbo#!#babel_5467_avgdata_1#!#count_val#!#38#!#10#!#6

select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_avgdata_2'
where TABLE_NAME = 'babel_5467_avgdata_2' order by COLUMN_NAME
go
~~START~~
nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#tinyint#!#smallint#!#int
Expand All @@ -156,7 +156,7 @@ master#!#dbo#!#babel_5467_avgdata_2#!#count_val#!#38#!#10#!#6

select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_avgdata_3'
where TABLE_NAME = 'babel_5467_avgdata_3' order by COLUMN_NAME
go
~~START~~
nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#tinyint#!#smallint#!#int
Expand All @@ -167,7 +167,7 @@ master#!#dbo#!#babel_5467_avgdata_3#!#count_val#!#38#!#10#!#6

select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_t1'
where TABLE_NAME = 'babel_5467_t1' order by COLUMN_NAME
go
~~START~~
nvarchar#!#nvarchar#!#nvarchar#!#nvarchar#!#tinyint#!#smallint#!#int
Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/BABEL-CASE_EXPR-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -13956,7 +13956,7 @@ END AS RESULT
GO
~~START~~
numeric
1234568.89010000
1234568.8901000000
~~END~~


Expand Down
8 changes: 4 additions & 4 deletions test/JDBC/expected/NUMERIC_TYPMOD.out
Original file line number Diff line number Diff line change
Expand Up @@ -1666,7 +1666,7 @@ END AS result;
GO
~~START~~
numeric
6790.080000
6790.080000000000000
~~END~~


Expand All @@ -1682,7 +1682,7 @@ END AS result;
GO
~~START~~
numeric
6790.080000
6790.080000000000000
~~END~~


Expand All @@ -1698,7 +1698,7 @@ END AS result;
GO
~~START~~
numeric
6790.080000
6790.080000000000000
~~END~~


Expand All @@ -1714,7 +1714,7 @@ END AS result;
GO
~~START~~
numeric
6790.080000
6790.080000000000000
~~END~~


Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/TestDecimal-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ numeric#!#numeric#!#numeric#!#numeric#!#numeric#!#numeric
select COALESCE( int1, int2 / COALESCE( NULLIF( rate, 0 ), 1 )) * CASE WHEN type IS NULL THEN 1 ELSE -1 END AS FTD_AMOUNT_FC from testdecimal_vu_prepare_tab1;
~~START~~
numeric
1879323.222200
1879323.222200000000
~~END~~


Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/TestDecimal.out
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ insert into testdecimal_tab values (1879323.2222, 2383823.343, 4.5484, NULL);
select COALESCE( int1, int2 / COALESCE( NULLIF( rate, 0 ), 1 )) * CASE WHEN type IS NULL THEN 1 ELSE -1 END AS FTD_AMOUNT_FC from testdecimal_tab;
~~START~~
numeric
1879323.222200
1879323.222200000000
~~END~~

drop table testdecimal_tab;
Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/TestNumeric-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ numeric#!#numeric#!#numeric#!#numeric#!#numeric#!#numeric
select COALESCE( int1, int2 / COALESCE( NULLIF( rate, 0 ), 1 )) * CASE WHEN type IS NULL THEN 1 ELSE -1 END AS FTD_AMOUNT_FC from testnumeric_vu_prepare_tab1;
~~START~~
numeric
1879323.222200
1879323.222200000000
~~END~~


Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/TestNumeric.out
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ insert into testnumeric_tab values (1879323.2222, 2383823.343, 4.5484, NULL);
select COALESCE( int1, int2 / COALESCE( NULLIF( rate, 0 ), 1 )) * CASE WHEN type IS NULL THEN 1 ELSE -1 END AS FTD_AMOUNT_FC from testnumeric_tab;
~~START~~
numeric
1879323.222200
1879323.222200000000
~~END~~

drop table testnumeric_tab;
Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/babel_datatype.out
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ select CAST(2 AS money) / CAST(0.5 AS numeric(4,2));
GO
~~START~~
numeric
4.000000
4.0000000
~~END~~

select CAST(2 AS money) / CAST(0.5 AS decimal(4,2));
Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/money_aggregate-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,6 @@ varchar#!#varchar#!#smallint#!#tinyint#!#tinyint
avgamount#!#money#!#8#!#19#!#4
maxamount#!#money#!#8#!#19#!#4
minamount#!#money#!#8#!#19#!#4
totalwithmarkup#!#numeric#!#17#!#38#!#38
totalwithmarkup#!#numeric#!#5#!#5#!#2
~~END~~

8 changes: 4 additions & 4 deletions test/JDBC/input/BABEL-5467-vu-verify.sql
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,22 @@ go
-- Precision and scale details should be stored correctly
select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_avgdata_1'
where TABLE_NAME = 'babel_5467_avgdata_1' order by COLUMN_NAME
go

select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_avgdata_2'
where TABLE_NAME = 'babel_5467_avgdata_2' order by COLUMN_NAME
go

select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_avgdata_3'
where TABLE_NAME = 'babel_5467_avgdata_3' order by COLUMN_NAME
go

select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE
from information_schema.columns
where TABLE_NAME = 'babel_5467_t1'
where TABLE_NAME = 'babel_5467_t1' order by COLUMN_NAME
go

-- tables with computed columns having expression which results in numeric
Expand Down

0 comments on commit 865b5ca

Please sign in to comment.