@@ -82,11 +82,12 @@ static bool is_tsql_numeric_fixeddecimal(Oid oid);
8282static bool is_tsql_bit_numeric (Oid oid );
8383static bool is_tsql_int4_bit (Oid oid );
8484
85- #define SMALLINT_PRECISION_RADIX 5
86- #define INT_PRECISION_RADIX 10
87- #define BIGINT_PRECISION_RADIX 19
88- #define TINYINT_PRECISION_RADIX 3
85+ #define TINYINT_PRECISION_RADIX 3
86+ #define SMALLINT_PRECISION_RADIX 5
87+ #define INT_PRECISION_RADIX 10
88+ #define BIGINT_PRECISION_RADIX 19
8989
90+ #define DEFAULT_TINYINT_TYPMOD ((TINYINT_PRECISION_RADIX << 16) | 0) + VARHDRSZ
9091#define DEFAULT_SMALLINT_TYPMOD ((SMALLINT_PRECISION_RADIX << 16) | 0) + VARHDRSZ
9192#define DEFAULT_INT_TYPMOD ((INT_PRECISION_RADIX << 16) | 0) + VARHDRSZ
9293#define DEFAULT_BIGINT_TYPMOD ((BIGINT_PRECISION_RADIX << 16) | 0) + VARHDRSZ
@@ -1205,15 +1206,43 @@ is_numeric_datatype(Oid typid)
12051206 return false;
12061207}
12071208
1209+ /*
1210+ * get_default_typmod_for_fixedsize_dataypes
1211+ *
1212+ * Assigns predefined typmod values for fixed-length datatypes
1213+ * (int, bigint, smallint, tinyint) and money/smallmoney.
1214+ * These typmods represent the maximum allowed precision for each type
1215+ * and are used during typmod resolution to ensure consistent handling
1216+ * in expressions involving fixed-size numeric types.
1217+ */
1218+ static int32
1219+ get_default_typmod_for_fixedsize_dataypes (Oid resulttype )
1220+ {
1221+ if (resulttype == INT4OID )
1222+ return DEFAULT_INT_TYPMOD ;
1223+ else if (resulttype == INT8OID )
1224+ return DEFAULT_BIGINT_TYPMOD ;
1225+ else if (resulttype == INT2OID )
1226+ return DEFAULT_SMALLINT_TYPMOD ;
1227+ else if ((* common_utility_plugin_ptr -> is_tsql_tinyint_datatype )(resulttype ))
1228+ return DEFAULT_TINYINT_TYPMOD ;
1229+ else if ((* common_utility_plugin_ptr -> is_tsql_money_datatype )(resulttype ))
1230+ return TSQL_MONEY_TYPMOD ;
1231+ else if ((* common_utility_plugin_ptr -> is_tsql_smallmoney_datatype )(resulttype ))
1232+ return TSQL_SMALLMONEY_TYPMOD ;
1233+
1234+ return -1 ;
1235+ }
1236+
12081237/*
1209- * look for a typmod to return from a numeric expression,
1210- * Also for cases where we cannot compute the expression typmod return -1 and set found as false.
1238+ * Look for a typmod to return from a numeric expression,
1239+ * also for cases where we cannot compute the expression typmod return -1 and set found as false.
12111240 */
12121241int32
12131242resolve_numeric_typmod_from_exp (Plan * plan , Node * expr , bool * found )
12141243{
12151244 /*
1216- * set found value as true by default, if we are unable to
1245+ * Set found value as true by default, if we are unable to
12171246 * find the expression typmod found will be set to false.
12181247 */
12191248 if (found != NULL )
@@ -1231,6 +1260,7 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
12311260 Param * param = (Param * ) expr ;
12321261 if (param -> paramtypmod == -1 )
12331262 {
1263+ int32 fixlen_default_typmod ;
12341264 /* UDT handling in T_Param */
12351265 Oid immediate_base_type = get_immediate_base_type_of_UDT_internal (param -> paramtype );
12361266 if (OidIsValid (immediate_base_type ))
@@ -1241,15 +1271,14 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
12411271 return typmod ;
12421272 }
12431273
1244- /* handling for fixed length datatypes */
1245- if (param -> paramtype == INT4OID )
1246- return DEFAULT_INT_TYPMOD ;
1247- else if (param -> paramtype == INT8OID )
1248- return DEFAULT_BIGINT_TYPMOD ;
1249- else if (param -> paramtype == INT2OID )
1250- return DEFAULT_SMALLINT_TYPMOD ;
1251- else if ((* common_utility_plugin_ptr -> is_tsql_tinyint_datatype ) (param -> paramtype ))
1252- return DEFAULT_TINYINT_TYPMOD ;
1274+ /*
1275+ * Handle default typmod for supported fixed-length datatypes
1276+ * such as bigint, int, smallint, and tinyint.
1277+ * These typmods represent the maximum allowed digits for each type.
1278+ */
1279+ fixlen_default_typmod = get_default_typmod_for_fixedsize_dataypes (param -> paramtype );
1280+ if (fixlen_default_typmod != -1 )
1281+ return fixlen_default_typmod ;
12531282 }
12541283
12551284 if (!is_numeric_datatype (param -> paramtype ) &&
@@ -1302,17 +1331,20 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
13021331 {
13031332 val = con -> constvalue ;
13041333 num = int64_to_numeric (val );
1305- if (* pltsql_protocol_plugin_ptr && (* pltsql_protocol_plugin_ptr )-> get_tds_numeric_get_typmod )
1306- return (* pltsql_protocol_plugin_ptr )-> get_tds_numeric_get_typmod (num );
1334+ if ((* common_utility_plugin_ptr -> tsql_numeric_get_typmod ))
1335+ {
1336+ return ((* common_utility_plugin_ptr -> tsql_numeric_get_typmod )(num ));
1337+ }
13071338
13081339 if (found != NULL ) * found = false;
13091340 return -1 ;
13101341 }
13111342
13121343 num = (Numeric ) con -> constvalue ;
1313- if (* pltsql_protocol_plugin_ptr && (* pltsql_protocol_plugin_ptr )-> get_tds_numeric_get_typmod )
1314- return (* pltsql_protocol_plugin_ptr )-> get_tds_numeric_get_typmod (num );
1315-
1344+ if ((* common_utility_plugin_ptr -> tsql_numeric_get_typmod ))
1345+ {
1346+ return ((* common_utility_plugin_ptr -> tsql_numeric_get_typmod )(num ));
1347+ }
13161348 if (found != NULL ) * found = false;
13171349 return -1 ;
13181350 }
@@ -1416,15 +1448,21 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
14161448 return typmod ;
14171449 }
14181450
1419- /* handling for fixed length datatypes */
1420- if (plan && var -> vartype == INT4OID )
1421- return DEFAULT_INT_TYPMOD ;
1422- else if (plan && var -> vartype == INT8OID )
1423- return DEFAULT_BIGINT_TYPMOD ;
1424- else if (plan && var -> vartype == INT2OID )
1425- return DEFAULT_SMALLINT_TYPMOD ;
1426- else if (plan && (* common_utility_plugin_ptr -> is_tsql_tinyint_datatype ) (var -> vartype ))
1427- return DEFAULT_TINYINT_TYPMOD ;
1451+ /*
1452+ * Handle default typmod for supported fixed-length datatypes
1453+ * such as bigint, int, smallint, and tinyint.
1454+ * These typmods represent the maximum allowed digits for each type.
1455+ *
1456+ * Plan check ensures typmod consistency to preventing incorrect values,
1457+ * ensuring plan is not changed if typmod is calculated in execution stage.
1458+ */
1459+ if (plan )
1460+ {
1461+ int32 fixlen_default_typmod ;
1462+ fixlen_default_typmod = get_default_typmod_for_fixedsize_dataypes (var -> vartype );
1463+ if (fixlen_default_typmod != -1 )
1464+ return fixlen_default_typmod ;
1465+ }
14281466
14291467 if (found != NULL ) * found = false;
14301468 }
@@ -1447,8 +1485,19 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found)
14471485 precision ;
14481486 uint8_t integralDigitCount = 0 ;
14491487 bool found_typmod ;
1488+ int32 fixsize_default_typmod ;
14501489
14511490 Assert (list_length (op -> args ) == 2 || list_length (op -> args ) == 1 );
1491+
1492+ /*
1493+ * Handle default typmod for supported fixed-size datatypes
1494+ * such as money, smallmoney, bigint, int, smallint, and tinyint.
1495+ * These typmods represent the maximum allowed digits for each type.
1496+ */
1497+ fixsize_default_typmod = get_default_typmod_for_fixedsize_dataypes (op -> opresulttype );
1498+ if (fixsize_default_typmod != -1 )
1499+ return fixsize_default_typmod ;
1500+
14521501 if (list_length (op -> args ) == 2 )
14531502 {
14541503 arg1 = linitial (op -> args );
0 commit comments