Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added BBF hook to truncate numeric result to correct scale #3521

Open
wants to merge 19 commits into
base: BABEL_4_X_DEV
Choose a base branch
from
Open
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
281 changes: 222 additions & 59 deletions contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contrib/babelfishpg_tds/src/include/tds_response.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ extern void TDSStatementExceptionCallback(PLtsql_execstate *estate, PLtsql_stmt
bool terminate_batch);
extern void SendColumnMetadata(TupleDesc typeinfo, List *targetlist, int16 *formats);
extern bool GetTdsEstateErrorData(int *number, int *severity, int *state);
extern int32 resolve_numeric_typmod_from_exp(Plan *plan, Node *expr);
extern int32 resolve_numeric_typmod_from_exp(Plan *plan, Node *expr, bool *found);

#endif /* TDS_H */
136 changes: 135 additions & 1 deletion contrib/babelfishpg_tsql/src/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ static void pltsql_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, ui
static void pltsql_ExecutorFinish(QueryDesc *queryDesc);
static void pltsql_ExecutorEnd(QueryDesc *queryDesc);
static bool pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event);
static Datum pltsql_trunc_numeric_result(Plan *plan, Node *fn_expr, Datum result, Oid result_type, int32 result_typmod);
static void pltsql_ExecInitResultTypeTL(PlanState *planstate);

static bool plsql_TriggerRecursiveCheck(ResultRelInfo *resultRelInfo);
static bool bbf_check_rowcount_hook(int es_processed);
Expand Down Expand Up @@ -214,6 +216,7 @@ static Oid set_param_collation(Param *param);
static Oid default_collation_for_builtin_type(Type typ, bool handle_text);
static char* pltsql_get_object_identity_event_trigger(ObjectAddress *addr);
static const char *remove_db_name_in_schema(const char *schema_name, const char *object_type);
static int32 pltsql_exprTypmod(Plan *plan, Node *expr);

/***************************************************
* Temp Table Related Declarations + Hooks
Expand Down Expand Up @@ -260,10 +263,13 @@ static pltsql_is_local_only_inval_msg_hook_type prev_pltsql_is_local_only_inval_
static pltsql_get_tsql_enr_from_oid_hook_type prev_pltsql_get_tsql_enr_from_oid_hook = NULL;
static inherit_view_constraints_from_table_hook_type prev_inherit_view_constraints_from_table = NULL;
static bbfViewHasInsteadofTrigger_hook_type prev_bbfViewHasInsteadofTrigger_hook = NULL;
static pltsql_trunc_numeric_result_hook_type prev_pltsql_trunc_numeric_result_hook = NULL;
static pltsql_ExecInitResultTypeTL_hook_type prev_pltsql_ExecInitResultTypeTL_hook = NULL;
static detect_numeric_overflow_hook_type prev_detect_numeric_overflow_hook = NULL;
static match_pltsql_func_call_hook_type prev_match_pltsql_func_call_hook = NULL;
static insert_pltsql_function_defaults_hook_type prev_insert_pltsql_function_defaults_hook = NULL;
static replace_pltsql_function_defaults_hook_type prev_replace_pltsql_function_defaults_hook = NULL;
static pltsql_exprTypmod_hook_type prev_pltsql_exprTypmod_hook = NULL;
static print_pltsql_function_arguments_hook_type prev_print_pltsql_function_arguments_hook = NULL;
static planner_hook_type prev_planner_hook = NULL;
static transform_check_constraint_expr_hook_type prev_transform_check_constraint_expr_hook = NULL;
Expand Down Expand Up @@ -402,6 +408,12 @@ InstallExtendedHooks(void)
prev_bbfViewHasInsteadofTrigger_hook = bbfViewHasInsteadofTrigger_hook;
bbfViewHasInsteadofTrigger_hook = pltsql_bbfViewHasInsteadofTrigger;

prev_pltsql_trunc_numeric_result_hook = pltsql_trunc_numeric_result_hook;
pltsql_trunc_numeric_result_hook = pltsql_trunc_numeric_result;

prev_pltsql_ExecInitResultTypeTL_hook = pltsql_ExecInitResultTypeTL_hook;
pltsql_ExecInitResultTypeTL_hook = pltsql_ExecInitResultTypeTL;

prev_detect_numeric_overflow_hook = detect_numeric_overflow_hook;
detect_numeric_overflow_hook = pltsql_detect_numeric_overflow;

Expand All @@ -414,6 +426,9 @@ InstallExtendedHooks(void)
prev_replace_pltsql_function_defaults_hook = replace_pltsql_function_defaults_hook;
replace_pltsql_function_defaults_hook = replace_pltsql_function_defaults;

prev_pltsql_exprTypmod_hook = pltsql_exprTypmod_hook;
pltsql_exprTypmod_hook = pltsql_exprTypmod;

prev_print_pltsql_function_arguments_hook = print_pltsql_function_arguments_hook;
print_pltsql_function_arguments_hook = print_pltsql_function_arguments;

Expand Down Expand Up @@ -553,10 +568,13 @@ UninstallExtendedHooks(void)
GetNewTempOidWithIndex_hook = prev_GetNewTempOidWithIndex_hook;
inherit_view_constraints_from_table_hook = prev_inherit_view_constraints_from_table;
bbfViewHasInsteadofTrigger_hook = prev_bbfViewHasInsteadofTrigger_hook;
pltsql_trunc_numeric_result_hook = prev_pltsql_trunc_numeric_result_hook;
pltsql_ExecInitResultTypeTL_hook = prev_pltsql_ExecInitResultTypeTL_hook;
detect_numeric_overflow_hook = prev_detect_numeric_overflow_hook;
match_pltsql_func_call_hook = prev_match_pltsql_func_call_hook;
insert_pltsql_function_defaults_hook = prev_insert_pltsql_function_defaults_hook;
replace_pltsql_function_defaults_hook = prev_replace_pltsql_function_defaults_hook;
pltsql_exprTypmod_hook = prev_pltsql_exprTypmod_hook;
print_pltsql_function_arguments_hook = prev_print_pltsql_function_arguments_hook;
planner_hook = prev_planner_hook;
transform_check_constraint_expr_hook = prev_transform_check_constraint_expr_hook;
Expand Down Expand Up @@ -1171,6 +1189,31 @@ pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event)
return false;
}

/*
* pltsql_trunc_numeric_result
* truncates the result value to the correct scale based on result_typmod.
* for result_typmod = -1, computes the result_typmod using pltsql_exprTypmod function.
*/
static Datum
pltsql_trunc_numeric_result(Plan *plan, Node *fn_expr, Datum result, Oid result_type, int32 result_typmod)
{
int32 scale;

if (result && OidIsValid(result_type) && getBaseType(result_type) == NUMERICOID)
{
if (fn_expr != NULL && result_typmod == -1)
result_typmod = pltsql_exprTypmod(plan, fn_expr);

if (result_typmod != -1)
{
scale = (result_typmod - VARHDRSZ) & 0xffff;
return DirectFunctionCall2(numeric_trunc, result, Int32GetDatum(scale));
}
}

return result;
}

/*
* Wrapper function that calls the initilization function.
* Calls the pre function call hook on the procname
Expand Down Expand Up @@ -5924,4 +5967,95 @@ remove_db_name_in_schema(const char *object_name, const char *object_type)
pfree(splited_object_name);

return (const char *)pstrdup(object_name + prefix_len);
}
}

/*
* pltsql_exprTypmod -
* returns the type-specific modifier of the expression's result type,
* if it can be determined, else we return -1.
*/
static int32
pltsql_exprTypmod(Plan *plan, Node *expr)
{
int32 result_typmod = -1;
uint8_t scale,
precision;
Oid expr_type = exprType(expr);

if (!OidIsValid(expr_type))
return -1;

if (getBaseType(expr_type) == NUMERICOID)
{
if (plan == NULL && IsA(expr, Aggref) && ((Aggref *)expr)->aggsplit == AGGSPLIT_FINAL_DESERIAL)
return -1;
/*
* use get_numeric_typmod_from_exp function to get the typmod
* from the expression node, when the expression type is numeric.
*/
if (*pltsql_protocol_plugin_ptr && (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp)
result_typmod = (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp(plan, expr, NULL);
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;
}

/*
* pltsql_ExecInitResultTypeTL -
* Initialize result type, using the plan node's targetlist.
* Following function is same as PostgreSQL ExecInitResultTypeTL() function,
* only difference is for computation of typmod for numeric expression type
* used pltsql_exprTypmod instead of exprTypmod function.
*/
void
pltsql_ExecInitResultTypeTL(PlanState *planstate)
{
TupleDesc typeInfo;
ListCell *l;
int len;
int cur_resno = 1;
List *targetList = planstate->plan->targetlist;
Oid expr_type = InvalidOid;
int32 expr_typmod = -1;

len = ExecTargetListLength(targetList);
typeInfo = CreateTemplateTupleDesc(len);

foreach(l, targetList)
{
TargetEntry *tle = lfirst(l);

expr_type = exprType((Node *) tle->expr);
if (getBaseType(expr_type) == NUMERICOID)
expr_typmod = pltsql_exprTypmod(planstate->plan, (Node *) tle->expr);
else
expr_typmod = exprTypmod((Node *) tle->expr);

TupleDescInitEntry(typeInfo,
cur_resno,
tle->resname,
expr_type,
expr_typmod,
0);
TupleDescInitEntryCollation(typeInfo,
cur_resno,
exprCollation((Node *) tle->expr));
cur_resno++;
}

planstate->ps_ResultTupleDesc = typeInfo;
}

2 changes: 1 addition & 1 deletion contrib/babelfishpg_tsql/src/pltsql.h
Original file line number Diff line number Diff line change
Expand Up @@ -1803,7 +1803,7 @@ typedef struct PLtsql_protocol_plugin
bool (*get_reset_tds_connection_flag) ();
void (*get_tvp_typename_typeschemaname) (char *proc_name, char *target_arg_name,
char **tvp_type_name, char **tvp_type_schema_name);
int32 (*get_numeric_typmod_from_exp) (Plan *plan, Node *expr);
int32 (*get_numeric_typmod_from_exp) (Plan *plan, Node *expr, bool *found);
/* Session level GUCs */
bool quoted_identifier;
bool arithabort;
Expand Down
2 changes: 1 addition & 1 deletion contrib/babelfishpg_tsql/src/pltsql_coerce.c
Original file line number Diff line number Diff line change
Expand Up @@ -2088,7 +2088,7 @@ tsql_select_common_typmod_hook(ParseState *pstate, List *exprs, Oid common_type)
type = getBaseTypeAndTypmod(type, &typmod);

if (typmod == -1 && (*pltsql_protocol_plugin_ptr))
typmod = (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp(NULL, expr);
typmod = (*pltsql_protocol_plugin_ptr)->get_numeric_typmod_from_exp(NULL, expr, NULL);

if (typmod == -1 || getBaseType(type) != NUMERICOID)
continue;
Expand Down
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~~

Loading
Loading