From 2c62cf7c7bdc63489b7002b4ac6eefd1ae8b00e2 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 11 Jul 2024 12:16:26 +0530 Subject: [PATCH] Fix protocol violation error happening due to Const node under append node (#2720) (#2734) Previously, certain driver was running into an protocol violation error when Const node in target list appears under Append node. This was happening because resolve_numeric_typmod_from_exp was not implemented to handle Const node properly for decimal data types. This commit fixes that issue by properly handling decimal data type for Const node under Append node. Task: BABEL-5086 Signed-off-by: Dipesh Dhameliya --- .../src/backend/tds/tdsresponse.c | 32 +- test/JDBC/expected/babel_numeric.out | 365 ++++++++++++++++++ test/JDBC/input/babel_numeric.sql | 195 +++++++++- 3 files changed, 583 insertions(+), 9 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index ab674d84bf..9fa76a8d35 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -24,8 +24,10 @@ #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "nodes/pathnodes.h" #include "parser/parse_coerce.h" +#include "parser/parse_type.h" #include "parser/parsetree.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" @@ -126,6 +128,7 @@ static TdsColumnMetaData *colMetaData = NULL; static List *relMetaDataInfoList = NULL; static Oid sys_vector_oid = InvalidOid; +static Oid decimal_oid = InvalidOid; static void FillTabNameWithNumParts(StringInfo buf, uint8 numParts, TdsRelationMetaDataInfo relMetaDataInfo); static void FillTabNameWithoutNumParts(StringInfo buf, uint8 numParts, TdsRelationMetaDataInfo relMetaDataInfo); @@ -511,6 +514,24 @@ resolve_numeric_typmod_outer_var(Plan *plan, AttrNumber attno) return resolve_numeric_typmod_from_exp(outerplan, (Node *)tle->expr); } +/* + * is_numeric_datatype - returns bool if given datatype is numeric or decimal. + */ +static bool +is_numeric_datatype(Oid typid) +{ + if (typid == NUMERICOID) + { + return true; + } + if (!OidIsValid(decimal_oid)) + { + TypeName *typename = makeTypeNameFromNameList(list_make2(makeString("sys"), makeString("decimal"))); + decimal_oid = LookupTypeNameOid(NULL, typename, false); + } + return decimal_oid == typid; +} + /* look for a typmod to return from a numeric expression */ static int32 resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) @@ -524,15 +545,10 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) Const *con = (Const *) expr; Numeric num; - /* - * TODO: We used a workaround here, that we will assume typmod - * is 0 if the value we have is not numeric. See walkaround in - * T_FuncExpr part of this function. JIRA: BABEL-1007 - */ - if (con->consttype != NUMERICOID || con->constisnull) + if (!is_numeric_datatype(con->consttype) || con->constisnull) { - return 0; - /* Typmod doesn 't really matter since it' s a const NULL. */ + /* typmod is undefined */ + return -1; } else { diff --git a/test/JDBC/expected/babel_numeric.out b/test/JDBC/expected/babel_numeric.out index 40988a6857..8d3bb92a09 100644 --- a/test/JDBC/expected/babel_numeric.out +++ b/test/JDBC/expected/babel_numeric.out @@ -121,3 +121,368 @@ numeric drop table t1; go + +select * from +( + select cast(1.23 as decimal(18,2)) as col + union all + select cast(1.23 as decimal(7,2)) as col +) dummy order by col; +go +~~START~~ +numeric +1.23 +1.23 +~~END~~ + + +select * from +( + select cast(NULL as decimal(18,2)) as col + union all + select cast(1.23 as decimal(7,2)) as col +) dummy order by col; +go +~~START~~ +numeric + +1.23 +~~END~~ + + +select * from +( + select cast(9999999999999999.99 as decimal(18,2)) as col + union all + select cast(99999.99 as decimal(7,2)) as col +) dummy order by col; +go +~~START~~ +numeric +99999.99 +9999999999999999.99 +~~END~~ + + +create type decimal_18_2 from decimal(18,2); +go + +create type decimal_7_2 from decimal(7,2); +go + +select * from +( + select cast(1.23 as decimal_18_2) as col + union all + select cast(1.23 as decimal_7_2) as col +) dummy order by col; +go +~~START~~ +numeric +1.23 +1.23 +~~END~~ + + +select * from +( + select cast(1.23 as decimal_18_2) as col + union all + select cast(NULL as decimal_7_2) as col +) dummy order by col; +go +~~START~~ +numeric + +1.23 +~~END~~ + + +select * from +( + select cast(9999999999999999.99 as decimal_18_2) as col + union all + select cast(99999.99 as decimal_7_2) as col +) dummy order by col; +go +~~START~~ +numeric +99999.99 +9999999999999999.99 +~~END~~ + + +create table babel_5086_t1 (a decimal(18,2), b decimal(7,2), c decimal_18_2, d decimal_7_2); +go + +insert into babel_5086_t1 values (1.23, 1.23, 1.23, 1.23); +insert into babel_5086_t1 values (9999999999999999.99, NULL, 9999999999999999.99, NULL); +insert into babel_5086_t1 values (NULL, 99999.99, NULL, 99999.99); +go +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select * from +( + select a as col from babel_5086_t1 + union all + select b as col from babel_5086_t1 +) dummy order by col; +go +~~START~~ +numeric + + +1.23 +1.23 +99999.99 +9999999999999999.99 +~~END~~ + + +select * from +( + select c as col from babel_5086_t1 + union all + select d as col from babel_5086_t1 +) dummy order by col; +go +~~START~~ +numeric + + +1.23000000 +1.23000000 +99999.99000000 +9999999999999999.99000000 +~~END~~ + + +select * from +( + select a as col from babel_5086_t1 + union all + select b as col from babel_5086_t1 + union all + select c as col from babel_5086_t1 + union all + select d as col from babel_5086_t1 +) dummy order by col; +go +~~START~~ +numeric + + + + +1.23 +1.23 +1.23 +1.23 +99999.99 +99999.99 +9999999999999999.99 +9999999999999999.99 +~~END~~ + + +select * from +( + select a as col from babel_5086_t1 + union all + select c as col from babel_5086_t1 +) dummy order by col; +go +~~START~~ +numeric + + +1.23 +1.23 +9999999999999999.99 +9999999999999999.99 +~~END~~ + + +select * from +( + select b as col from babel_5086_t1 + union all + select d as col from babel_5086_t1 +) dummy order by col; +go +~~START~~ +numeric + + +1.23 +1.23 +99999.99 +99999.99 +~~END~~ + + +create type numeric_18_2 from numeric(18,2); +go + +create type numeric_7_2 from numeric(7,2); +go + +select * from +( + select cast(1.23 as numeric_18_2) as col + union all + select cast(1.23 as numeric_7_2) as col +) dummy order by col; +go +~~START~~ +numeric +1.23 +1.23 +~~END~~ + + +select * from +( + select cast(12344.234 as numeric_18_2) as col + union all + select cast(1.23 as numeric_7_2) as col +) dummy order by col; +go +~~START~~ +numeric +1.23 +12344.23 +~~END~~ + + +create table babel_5086_t2 (a numeric(18,2), b numeric(7,2), c numeric_18_2, d numeric_7_2); +go + +insert into babel_5086_t2 values (1.23, 1.23, 1.23, 1.23); +insert into babel_5086_t2 values (9999999999999999.99, NULL, 9999999999999999.99, NULL); +insert into babel_5086_t2 values (NULL, 99999.99, NULL, 99999.99); +go +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select * from +( + select a as col from babel_5086_t2 + union all + select b as col from babel_5086_t2 +) dummy order by col; +go +~~START~~ +numeric + + +1.23 +1.23 +99999.99 +9999999999999999.99 +~~END~~ + + +select * from +( + select c as col from babel_5086_t2 + union all + select d as col from babel_5086_t2 +) dummy order by col; +go +~~START~~ +numeric + + +1.23000000 +1.23000000 +99999.99000000 +9999999999999999.99000000 +~~END~~ + + +select * from +( + select a as col from babel_5086_t2 + union all + select b as col from babel_5086_t2 + union all + select c as col from babel_5086_t2 + union all + select d as col from babel_5086_t2 +) dummy order by col; +go +~~START~~ +numeric + + + + +1.23 +1.23 +1.23 +1.23 +99999.99 +99999.99 +9999999999999999.99 +9999999999999999.99 +~~END~~ + + +select * from +( + select a as col from babel_5086_t2 + union all + select c as col from babel_5086_t2 +) dummy order by col; +go +~~START~~ +numeric + + +1.23 +1.23 +9999999999999999.99 +9999999999999999.99 +~~END~~ + + + +select * from +( + select b as col from babel_5086_t2 + union all + select d as col from babel_5086_t2 +) dummy order by col; +go +~~START~~ +numeric + + +1.23 +1.23 +99999.99 +99999.99 +~~END~~ + + +drop table babel_5086_t1; +go + +drop table babel_5086_t2; +go + +drop type decimal_18_2; +drop type decimal_7_2; +drop type numeric_18_2; +drop type numeric_7_2; +go diff --git a/test/JDBC/input/babel_numeric.sql b/test/JDBC/input/babel_numeric.sql index 2dab904ac1..5717e3e540 100644 --- a/test/JDBC/input/babel_numeric.sql +++ b/test/JDBC/input/babel_numeric.sql @@ -60,4 +60,197 @@ select * from t1; go drop table t1; -go \ No newline at end of file +go + +select * from +( + select cast(1.23 as decimal(18,2)) as col + union all + select cast(1.23 as decimal(7,2)) as col +) dummy order by col; +go + +select * from +( + select cast(NULL as decimal(18,2)) as col + union all + select cast(1.23 as decimal(7,2)) as col +) dummy order by col; +go + +select * from +( + select cast(9999999999999999.99 as decimal(18,2)) as col + union all + select cast(99999.99 as decimal(7,2)) as col +) dummy order by col; +go + +create type decimal_18_2 from decimal(18,2); +go + +create type decimal_7_2 from decimal(7,2); +go + +select * from +( + select cast(1.23 as decimal_18_2) as col + union all + select cast(1.23 as decimal_7_2) as col +) dummy order by col; +go + +select * from +( + select cast(1.23 as decimal_18_2) as col + union all + select cast(NULL as decimal_7_2) as col +) dummy order by col; +go + +select * from +( + select cast(9999999999999999.99 as decimal_18_2) as col + union all + select cast(99999.99 as decimal_7_2) as col +) dummy order by col; +go + +create table babel_5086_t1 (a decimal(18,2), b decimal(7,2), c decimal_18_2, d decimal_7_2); +go + +insert into babel_5086_t1 values (1.23, 1.23, 1.23, 1.23); +insert into babel_5086_t1 values (9999999999999999.99, NULL, 9999999999999999.99, NULL); +insert into babel_5086_t1 values (NULL, 99999.99, NULL, 99999.99); +go + +select * from +( + select a as col from babel_5086_t1 + union all + select b as col from babel_5086_t1 +) dummy order by col; +go + +select * from +( + select c as col from babel_5086_t1 + union all + select d as col from babel_5086_t1 +) dummy order by col; +go + +select * from +( + select a as col from babel_5086_t1 + union all + select b as col from babel_5086_t1 + union all + select c as col from babel_5086_t1 + union all + select d as col from babel_5086_t1 +) dummy order by col; +go + +select * from +( + select a as col from babel_5086_t1 + union all + select c as col from babel_5086_t1 +) dummy order by col; +go + +select * from +( + select b as col from babel_5086_t1 + union all + select d as col from babel_5086_t1 +) dummy order by col; +go + +create type numeric_18_2 from numeric(18,2); +go + +create type numeric_7_2 from numeric(7,2); +go + +select * from +( + select cast(1.23 as numeric_18_2) as col + union all + select cast(1.23 as numeric_7_2) as col +) dummy order by col; +go + +select * from +( + select cast(12344.234 as numeric_18_2) as col + union all + select cast(1.23 as numeric_7_2) as col +) dummy order by col; +go + +create table babel_5086_t2 (a numeric(18,2), b numeric(7,2), c numeric_18_2, d numeric_7_2); +go + +insert into babel_5086_t2 values (1.23, 1.23, 1.23, 1.23); +insert into babel_5086_t2 values (9999999999999999.99, NULL, 9999999999999999.99, NULL); +insert into babel_5086_t2 values (NULL, 99999.99, NULL, 99999.99); +go + +select * from +( + select a as col from babel_5086_t2 + union all + select b as col from babel_5086_t2 +) dummy order by col; +go + +select * from +( + select c as col from babel_5086_t2 + union all + select d as col from babel_5086_t2 +) dummy order by col; +go + +select * from +( + select a as col from babel_5086_t2 + union all + select b as col from babel_5086_t2 + union all + select c as col from babel_5086_t2 + union all + select d as col from babel_5086_t2 +) dummy order by col; +go + +select * from +( + select a as col from babel_5086_t2 + union all + select c as col from babel_5086_t2 +) dummy order by col; +go + + +select * from +( + select b as col from babel_5086_t2 + union all + select d as col from babel_5086_t2 +) dummy order by col; +go + +drop table babel_5086_t1; +go + +drop table babel_5086_t2; +go + +drop type decimal_18_2; +drop type decimal_7_2; +drop type numeric_18_2; +drop type numeric_7_2; +go