-
Notifications
You must be signed in to change notification settings - Fork 101
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
Improve round() function return type handling based on input arguments data types #3567
Improve round() function return type handling based on input arguments data types #3567
Conversation
Pull Request Test Coverage Report for Build 13954105418Details
💛 - Coveralls |
{"sys", "concat_ws", "concat_ws", true, 1} | ||
{"sys", "concat_ws", "concat_ws", true, 1}, | ||
|
||
/* Since sql server round() function can take either 2 or 3 parameters, it doesn't fit into case of variable length of paraemters */ |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here i think is more of including it to tsql_special_function_list that we need to treat them specially.
* is version 12, will follow the existing behavior. | ||
* The existing behavior throws error message if nargs is not from 1 to 3. | ||
*/ | ||
if (nargs == 2 || nargs == 3) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will add a jira to document the behavior and future improvement if it need to
|| (new_input_typeids[0] == INT2OID) | ||
|| (new_input_typeids[0] == INT4OID)) | ||
{ | ||
expr_result_type = (*common_utility_plugin_ptr->lookup_tsql_datatype_oid) ("int"); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
otherwise data type will be incorrect, since the oid for that in sql server and babelfish are different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But for input arguments, they always have the same oid as postgres?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if ROUND(a, 2) while a
is a column of babelfish smallint
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will test that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test added
/* bigint will have return type bigint */ | ||
else if (new_input_typeids[0] == INT8OID) | ||
{ | ||
expr_result_type = (*common_utility_plugin_ptr->lookup_tsql_datatype_oid) ("bigint"); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
otherwise data type will be incorrect, since the oid for that in sql server and babelfish are different.
} | ||
else | ||
{ | ||
expr_result_type = (*common_utility_plugin_ptr->lookup_tsql_datatype_oid) ("decimal"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have situation hitting the last else
branch? From what I see in SQL Server doc, all situations have been covered above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it, will check sql server behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not need this else block, as the return type in other cases are not specified. For other cases lets have the existing behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed else block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
after removing this else block, it will fail tests from BABEL-1193.out and babel_function.out. Annotated in the code: add else here for backward compatibility and passing old tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do the old tests fail? We don't need to keep the backward compatibility. The behaviour of old version is wrong. We only need to keep consistent with SQL Server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ERROR (Code: 33557097)
+
+ERROR (Message: function round(text, integer) is not unique)
and another one for NULL case is:
+ERROR (Code: 33557097)
+
+ERROR (Message: function round(unknown, integer) is not unique)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chatted about behavior for this, will remove else block and modify old tests accordingly and move them to new test file I added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
test/JDBC/input/BABEL-2057.sql
Outdated
select round(cast(42 as smallmoney), 2) | ||
go | ||
|
||
select round(cast(42 as smallmoney), 999) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added in test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, looks good to me. Some minor comments and questions left.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please squash your commits into one.
test/JDBC/expected/BABEL-2057.out
Outdated
int | ||
~~ERROR (Code: 33557097)~~ | ||
|
||
~~ERROR (Message: value overflows for numeric format)~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this expected ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
test/JDBC/expected/BABEL-2057.out
Outdated
go | ||
~~ERROR (Code: 33557097)~~ | ||
|
||
~~ERROR (Message: value overflows for numeric format)~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this expected ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
test/JDBC/expected/BABEL-2057.out
Outdated
go | ||
~~ERROR (Code: 33557097)~~ | ||
|
||
~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this error msg from SQL Server ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the overflow message shown in the .out file, sql server files just return 0 or .00
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but since those are the existing babelfish behavior, I will leave them as that. If required in future for behavior change, we can revisit this.
{ | ||
ereport(ERROR, | ||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), | ||
errmsg("ROUND function expects 2 or 3 arguments"))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the test case for this ?
What's the output of sql server for this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will put an assert here instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently babelfish supports round with 1 arguments due to underlying PostgreSQL, if we do not have any good enough reason to block round function call with number of arguments other than 2 or 3, we should not block it. Lets keep the existing behaviour in this case, if we do not have any good enough reason to throw error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also during my testing, this ereport is unable to be reached. The error about the number of arguments is caught else where already. Remove this ereport
@@ -1353,6 +1357,58 @@ tsql_func_select_candidate_for_special_func(List *names, int nargs, Oid *input_t | |||
expr_arg_type = (*common_utility_plugin_ptr->lookup_tsql_datatype_oid) ("bbf_varbinary"); | |||
} | |||
} | |||
/* The return type of sys.round() will be based on input argument type */ | |||
else if (strlen(proc_name) == 5 && strncmp(proc_name, "round", 5) == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case sensitive ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
within this function, following the pattern to use lower case as other special function.
test/JDBC/input/BABEL-2057.sql
Outdated
select round(cast(748.58 as float), 2) | ||
go | ||
JBA | ||
select round(cast(748.58 as float), 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also supplement a test case with only one argument and comment on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
} | ||
else | ||
{ | ||
expr_result_type = (*common_utility_plugin_ptr->lookup_tsql_datatype_oid) ("decimal"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not need this else block, as the return type in other cases are not specified. For other cases lets have the existing behaviour.
{ | ||
ereport(ERROR, | ||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), | ||
errmsg("ROUND function expects 2 or 3 arguments"))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently babelfish supports round with 1 arguments due to underlying PostgreSQL, if we do not have any good enough reason to block round function call with number of arguments other than 2 or 3, we should not block it. Lets keep the existing behaviour in this case, if we do not have any good enough reason to throw error.
GO | ||
DROP FUNCTION IF EXISTS dbo.RoundFloat; | ||
GO | ||
DROP FUNCTION IF EXISTS dbo.RoundDecimal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test need to be added to schedule files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added accordingly
select round(cast(42 as decimal), 0) | ||
go | ||
~~START~~ | ||
numeric |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for decimal, it should return decimal according to this doc :
https://github.com/MicrosoftDocs/sql-docs/blob/live/docs/t-sql/functions/round-transact-sql.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You right. But after checking the logic in sys_functions.sql and pltsql_coerce.c, I've set them to be decimal already.
In https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver16, it says "decimal and numeric are numeric data types that have a fixed precision and scale. decimal and numeric are synonyms and can be used interchangeably."
|
||
|
||
|
||
select round(cast(42 as numeric), 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For numeric, it should return decimal according to this doc : https://github.com/MicrosoftDocs/sql-docs/blob/live/docs/t-sql/functions/round-transact-sql.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decimal is just an alias of numeric in SQL Server. Not sure if we need to pay more efforts to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, but after checking the logic in sys_functions.sql and pltsql_coerce.c, I've set them to be decimal already.
In https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver16, it says "decimal and numeric are numeric data types that have a fixed precision and scale. decimal and numeric are synonyms and can be used interchangeably."
734b657
to
35408c1
Compare
…pe and the number of arguments following sql server style Signed-off-by: RUI LUO <[email protected]>
…pe and the number of arguments following sql server style Signed-off-by: RUI LUO <[email protected]>
/* in all other cases it will default to float data type */ | ||
else | ||
{ | ||
expr_result_type = (*common_utility_plugin_ptr->lookup_tsql_datatype_oid) ("float"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tested in sql server that other data types not mentioned in round sql server documentation will be defaulted to float data type. Matching that behavior here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good finding! So SQL Server allows other types other than listed in the doc as input, right?
Have you supplemented such test cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, added to round_return_type_test-vu-verify.sql
d4b2ca5
into
babelfish-for-postgresql:BABEL_4_X_DEV
…s data types (#3592) Make the round() function clearer on return types based on argument types and number of arguments (#3592) This is a cherry-pick commit from BABEL_4_X_DEV (#3567). Changes: Add lookup functions for data types that are represented differently Introduce PLpgSQL functions for each return type to reuse the existing underlying C functions Implement logic to determine return types based on argument types and number of arguments Add tests to ensure comprehensive coverage Task: BABEL-2057 Signed-off-by: RUI LUO <[email protected]> Co-authored-by: RUI LUO <[email protected]>
Description
Make the round() function clearer on return types based on argument types and number of arguments.
Changes:
Check List
By submitting this pull request, I confirm that my contribution is under the terms of the Apache 2.0 and PostgreSQL licenses, and grant any person obtaining a copy of the contribution permission to relicense all or a portion of my contribution to the PostgreSQL License solely to contribute all or a portion of my contribution to the PostgreSQL open source project.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.