Use NUMBER(38, 12) as default range for Snowflake DECIMALs (#10971)

This commit is contained in:
GregoryTravis 2024-09-09 14:31:09 -04:00 committed by GitHub
parent 414eee0b48
commit 2adb8bb86d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 69 additions and 56 deletions

View File

@ -26,6 +26,7 @@ import Standard.Database.SQL.SQL_Builder
import Standard.Database.SQL_Statement.SQL_Statement
import Standard.Database.SQL_Type.SQL_Type
from Standard.Database.Dialect import Temp_Table_Style
from Standard.Database.Dialect_Flags import all
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
import project.Database.Redshift.Internal.Redshift_Error_Mapper.Redshift_Error_Mapper
@ -137,13 +138,12 @@ type Redshift_Dialect
supports_separate_nan : Boolean
supports_separate_nan self = True
## PRIVATE
supports_negative_round_decimal_places : Boolean
supports_negative_round_decimal_places self = True
## PRIVATE
supports_float_round_decimal_places : Boolean
supports_float_round_decimal_places self = False
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags self -> Dialect_Flags =
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=False
Dialect_Flags.Value rounding=rounding
## PRIVATE
Specifies how the database creates temp tables.

View File

@ -932,9 +932,9 @@ type DB_Column
# Don't use for banker's rounding
not_bankers = use_bankers.not
# Don't use for negative decimal places, if the backend doesn't support it
negative_dp_ok = decimal_places >= 0 || self.connection.dialect.supports_negative_round_decimal_places
negative_dp_ok = decimal_places >= 0 || self.connection.dialect.dialect_flags.rounding.supports_negative_decimal_places
# Don't use for floating-point inputs if decimal_places != 0, for Postgres
dp_param_ok = decimal_places == 0 || self.value_type.is_floating_point.not || self.connection.dialect.supports_float_round_decimal_places
dp_param_ok = decimal_places == 0 || self.value_type.is_floating_point.not || self.connection.dialect.dialect_flags.rounding.supports_float_decimal_places
not_bankers && negative_dp_ok && dp_param_ok
## PRIVATE

View File

@ -25,6 +25,7 @@ import project.Internal.Statement_Setter.Statement_Setter
import project.SQL.SQL_Builder
import project.SQL_Statement.SQL_Statement
import project.SQL_Type.SQL_Type
from project.Dialect_Flags import all
from project.Errors import SQL_Error, Unsupported_Database_Operation
from project.Internal.Result_Set import result_set_to_table
@ -149,17 +150,10 @@ type Dialect
supports_separate_nan self =
Unimplemented.throw "This is an interface only."
## PRIVATE
Specifies whether the Database ROUND() function supports negative
decimal places.
supports_negative_round_decimal_places : Boolean
supports_negative_round_decimal_places self =
Unimplemented.throw "This is an interface only."
## PRIVATE
Specifies whether round() can take a decimal_places argument for floating point values.
supports_float_round_decimal_places : Boolean
supports_float_round_decimal_places self =
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags -> Dialect_Flags =
Unimplemented.throw "This is an interface only."
## PRIVATE

View File

@ -0,0 +1,17 @@
from Standard.Base import all
## PRIVATE
Dialect flags are used to specify implementation details for different
dialects -- the existence or non-existence of certain features, or
differening implementations of the same feature.
Dialect flags differ from test config flags, in that they are used for
implementation (as well as testing). They also differ from feature flags,
since feature flags are user-facing, and can be used to identify features
that are not yet implemented.
type Dialect_Flags
Value (rounding : Rounding_Flags)
type Rounding_Flags
Value (supports_negative_decimal_places : Boolean) (supports_float_decimal_places : Boolean)

View File

@ -38,6 +38,7 @@ import project.SQL.SQL_Fragment
import project.SQL_Statement.SQL_Statement
import project.SQL_Type.SQL_Type
from project.Dialect import Temp_Table_Style
from Standard.Database.Dialect_Flags import all
from project.Errors import SQL_Error, Unsupported_Database_Operation
from project.Internal.IR.Operation_Metadata import Date_Period_Metadata
@ -174,13 +175,12 @@ type Postgres_Dialect
supports_separate_nan : Boolean
supports_separate_nan self = True
## PRIVATE
supports_negative_round_decimal_places : Boolean
supports_negative_round_decimal_places self = True
## PRIVATE
supports_float_round_decimal_places : Boolean
supports_float_round_decimal_places self = False
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags self -> Dialect_Flags =
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=False
Dialect_Flags.Value rounding=rounding
## PRIVATE
Specifies how the database creates temp tables.

View File

@ -35,6 +35,7 @@ import project.SQL.SQL_Builder
import project.SQL_Statement.SQL_Statement
import project.SQL_Type.SQL_Type
from project.Dialect import Temp_Table_Style
from Standard.Database.Dialect_Flags import all
from project.Errors import SQL_Error, Unsupported_Database_Operation
## PRIVATE
@ -187,13 +188,12 @@ type SQLite_Dialect
supports_separate_nan : Boolean
supports_separate_nan self = False
## PRIVATE
supports_negative_round_decimal_places : Boolean
supports_negative_round_decimal_places self = False
## PRIVATE
supports_float_round_decimal_places : Boolean
supports_float_round_decimal_places self = True
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags self -> Dialect_Flags =
rounding = Rounding_Flags.Value supports_negative_decimal_places=False supports_float_decimal_places=True
Dialect_Flags.Value rounding=rounding
## PRIVATE
Specifies how the database creates temp tables.

View File

@ -15,6 +15,7 @@ import project.Internal.IR.Query.Query
import project.SQL_Query.SQL_Query
from project.Dialect import Temp_Table_Style
from project.Errors import SQL_Error, Table_Already_Exists, Unsupported_Database_Operation
from project.Internal.JDBC_Connection import log_sql_if_enabled
from project.Internal.Upload.Helpers.Argument_Checks import resolve_primary_key
from project.Internal.Upload.Helpers.Constants import default_batch_size
from project.Internal.Upload.Helpers.Error_Helpers import handle_upload_errors, internal_translate_known_upload_errors
@ -30,6 +31,7 @@ internal_create_table_structure connection table_name structure primary_key temp
validate_structure connection.base_connection.column_naming_helper aligned_structure <|
create_table_statement = prepare_create_table_statement connection table_name aligned_structure resolved_primary_key temporary on_problems
update_result = create_table_statement.if_not_error <|
log_sql_if_enabled connection.jdbc_connection create_table_statement.to_text
connection.execute create_table_statement
final_result = update_result.if_not_error table_name
final_result.catch SQL_Error sql_error->

View File

@ -39,6 +39,7 @@ import Standard.Database.SQL.SQL_Fragment
import Standard.Database.SQL_Statement.SQL_Statement
import Standard.Database.SQL_Type.SQL_Type
from Standard.Database.Dialect import Temp_Table_Style
from Standard.Database.Dialect_Flags import all
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
from Standard.Database.Internal.IR.Operation_Metadata import Date_Period_Metadata
from Standard.Database.Internal.Statement_Setter import fill_hole_default
@ -186,13 +187,12 @@ type SQLSever_Dialect
supports_separate_nan : Boolean
supports_separate_nan self = True
## PRIVATE
supports_negative_round_decimal_places : Boolean
supports_negative_round_decimal_places self = True
## PRIVATE
supports_float_round_decimal_places : Boolean
supports_float_round_decimal_places self = True
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags self -> Dialect_Flags =
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=True
Dialect_Flags.Value rounding=rounding
## PRIVATE
Specifies how the database creates temp tables.

View File

@ -43,6 +43,7 @@ import Standard.Database.SQL.SQL_Fragment
import Standard.Database.SQL_Statement.SQL_Statement
import Standard.Database.SQL_Type.SQL_Type
from Standard.Database.Dialect import Temp_Table_Style
from Standard.Database.Dialect_Flags import all
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
from Standard.Database.Internal.IR.Operation_Metadata import Date_Period_Metadata
from Standard.Database.Internal.Statement_Setter import fill_hole_default
@ -200,13 +201,12 @@ type Snowflake_Dialect
supports_separate_nan : Boolean
supports_separate_nan self = True
## PRIVATE
supports_negative_round_decimal_places : Boolean
supports_negative_round_decimal_places self = True
## PRIVATE
supports_float_round_decimal_places : Boolean
supports_float_round_decimal_places self = True
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags self -> Dialect_Flags =
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=True
Dialect_Flags.Value rounding=rounding
## PRIVATE
Specifies how the database creates temp tables.

View File

@ -33,7 +33,7 @@ type Snowflake_Type_Mapping
Value_Type.Float _ -> SQL_Type.Value Types.DOUBLE "FLOAT"
Value_Type.Decimal precision scale -> case precision of
# If precision is not set, scale is also lost because SQL is unable to express a scale without a precision.
Nothing -> SQL_Type.Value Types.DECIMAL "NUMBER" Nothing Nothing
Nothing -> SQL_Type.Value Types.DECIMAL "NUMBER" 38 12
# Scale can be set or not, but if it is set, it must be in range 0-37.
# If scale or precision is out of range, we fall back to Nothing.
_ -> if (precision < 1) || (precision > 38) then SQL_Type.Value Types.DECIMAL "NUMBER" Nothing Nothing else

View File

@ -465,11 +465,11 @@ snowflake_specific_spec suite_builder default_connection db_name setup =
col . cast Value_Type.Float . round 1 . value_type . should_equal Value_Type.Float
col . cast Value_Type.Integer . round 1 . value_type . should_equal (Value_Type.Decimal 38 0)
col . cast Value_Type.Decimal . round 1 . value_type . should_equal (Value_Type.Decimal 38 0)
col . cast Value_Type.Decimal . round 1 . value_type . should_equal (Value_Type.Decimal 38 1)
col . cast Value_Type.Float . round use_bankers=True . value_type . should_equal Value_Type.Float
col . cast Value_Type.Integer . round use_bankers=True . value_type . should_equal (Value_Type.Decimal 38 6)
col . cast Value_Type.Decimal . round use_bankers=True . value_type . should_equal (Value_Type.Decimal 38 6)
col . cast Value_Type.Integer . round use_bankers=True . value_type . should_equal (Value_Type.Decimal 38 12)
col . cast Value_Type.Decimal . round use_bankers=True . value_type . should_equal (Value_Type.Decimal 38 12)
col . cast Value_Type.Float . ceil . value_type . should_equal Value_Type.Float
col . cast Value_Type.Integer . ceil . value_type . should_equal (Value_Type.Decimal 38 0)

View File

@ -1148,12 +1148,12 @@ add_specs suite_builder setup =
if setup.test_selection.supports_decimal_type then
group_builder.specify "ceil, floor and truncate should work correctly on Decimals" <|
c = table_builder [["X", [Decimal.new "123492233720368547758075678.25", Decimal.new "15250331789246130610154663179243023788662739454197523.625", Decimal.new "-123492233720368547758075678.25", Decimal.new "-15250331789246130610154663179243023788662739454197523.625"]]] . at "X"
c = table_builder [["X", [Decimal.new "123492233720368547758075678.25", Decimal.new "179243023788662739454197523.625", Decimal.new "-123492233720368547758075678.25", Decimal.new "-179243023788662739454197523.625"]]] . at "X"
c.value_type.is_decimal . should_be_true
c.floor.to_vector.should_equal [Decimal.new "123492233720368547758075678.0", Decimal.new "15250331789246130610154663179243023788662739454197523.0", Decimal.new "-123492233720368547758075679.0", Decimal.new "-15250331789246130610154663179243023788662739454197524.0"]
c.ceil.to_vector.should_equal [Decimal.new "123492233720368547758075679.0", Decimal.new "15250331789246130610154663179243023788662739454197524.0", Decimal.new "-123492233720368547758075678.0", Decimal.new "-15250331789246130610154663179243023788662739454197523.0"]
c.truncate.to_vector.should_equal [Decimal.new "123492233720368547758075678.0", Decimal.new "15250331789246130610154663179243023788662739454197523.0", Decimal.new "-123492233720368547758075678.0", Decimal.new "-15250331789246130610154663179243023788662739454197523.0"]
c.floor.to_vector.should_equal [Decimal.new "123492233720368547758075678.0", Decimal.new "179243023788662739454197523.0", Decimal.new "-123492233720368547758075679.0", Decimal.new "-179243023788662739454197524.0"]
c.ceil.to_vector.should_equal [Decimal.new "123492233720368547758075679.0", Decimal.new "179243023788662739454197524.0", Decimal.new "-123492233720368547758075678.0", Decimal.new "-179243023788662739454197523.0"]
c.truncate.to_vector.should_equal [Decimal.new "123492233720368547758075678.0", Decimal.new "179243023788662739454197523.0", Decimal.new "-123492233720368547758075678.0", Decimal.new "-179243023788662739454197523.0"]
group_builder.specify "round should work correctly on Decimals" <|
c = table_builder [["X", [Decimal.new "1.3", Decimal.new "1.5", Decimal.new "1.7", Decimal.new "-1.3", Decimal.new "-1.5", Decimal.new "-1.7"]]] . at "X"