Refactor Dialect_Flag (#11273)

* Add property flags

* Update post initial design review

* Add more tests

* Fix tests

* Remove .LCK

* Fix
This commit is contained in:
AdRiley 2024-10-14 08:32:19 +01:00 committed by GitHub
parent 4a249688e8
commit 03369b9273
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 195 additions and 188 deletions

View File

@ -24,11 +24,11 @@ import Standard.Database.Internal.Postgres.Postgres_Type_Mapping.Postgres_Type_M
import Standard.Database.Internal.SQL_Type_Mapping.SQL_Type_Mapping
import Standard.Database.Internal.SQL_Type_Reference.SQL_Type_Reference
import Standard.Database.Internal.Statement_Setter.Statement_Setter
import Standard.Database.Dialect_Flag.Dialect_Flag
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
from Standard.Database.Internal.JDBC_Connection import JDBC_Connection
@ -132,23 +132,6 @@ type Redshift_Dialect
_ = statement
False
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
supports_nested_with_clause : Boolean
supports_nested_with_clause self = True
## PRIVATE
supports_separate_nan : Boolean
supports_separate_nan 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=False use_builtin_bankers=False
primary_key = Primary_Key_Flags.Value allows_nulls=False
Dialect_Flags.Value rounding=rounding primary_key=primary_key
## PRIVATE
Specifies how the database creates temp tables.
temp_table_style : Temp_Table_Style
@ -196,6 +179,20 @@ type Redshift_Dialect
_ = feature
True
## PRIVATE
Checks a dialect flag
flagged self flag:Dialect_Flag -> Boolean =
case flag of
Dialect_Flag.Supports_Negative_Decimal_Places -> True
Dialect_Flag.Supports_Float_Decimal_Places -> False
Dialect_Flag.Use_Builtin_Bankers -> False
Dialect_Flag.Primary_Key_Allows_Nulls -> False
## TODO: Check if Redshift supports NaN
Dialect_Flag.Supports_Separate_NaN -> False
## TODO: Check if Redshift supports WITH clauses in nested queries
Dialect_Flag.Supports_Nested_With_Clause -> True
Dialect_Flag.Supports_Case_Sensitive_Columns -> True
## PRIVATE
The default table types to use when listing tables.
default_table_types : Vector Text

View File

@ -1 +0,0 @@
C:\Code\enso\distribution\lib\Standard\Database\0.0.0-dev\src\Feature.enso

View File

@ -304,7 +304,7 @@ type DB_Column
times_ten + product_a_b + 100
let : Text -> (DB_Column -> DB_Column) -> DB_Column
let self (name : Text) (callback : (DB_Column -> DB_Column)) -> DB_Column =
use_ctes = self.connection.dialect.supports_nested_with_clause
use_ctes = self.connection.dialect.flagged ..Supports_Nested_With_Clause
if use_ctes.not then callback self else
binder = self.connection.base_connection.table_naming_helper.generate_random_table_name
@ -931,11 +931,11 @@ type DB_Column
should_use_builtin_round : Integer -> Boolean -> Boolean
should_use_builtin_round self decimal_places use_bankers =
# Don't use for banker's rounding (unless the dialect has a builtin for it)
bankers_ok = self.connection.dialect.dialect_flags.rounding.use_builtin_bankers || use_bankers.not
bankers_ok = self.connection.dialect.flagged ..Use_Builtin_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.dialect_flags.rounding.supports_negative_decimal_places
negative_dp_ok = decimal_places >= 0 || self.connection.dialect.flagged ..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.dialect_flags.rounding.supports_float_decimal_places
dp_param_ok = decimal_places == 0 || self.value_type.is_floating_point.not || self.connection.dialect.flagged ..Supports_Float_Decimal_Places
bankers_ok && negative_dp_ok && dp_param_ok
## PRIVATE
@ -1255,7 +1255,7 @@ type DB_Column
is_blank = case self_type.is_text of
True -> self.is_empty
False -> self.is_nothing
result = case treat_nans_as_blank && self_type.is_floating_point && self.connection.dialect.supports_separate_nan of
result = case treat_nans_as_blank && self_type.is_floating_point && self.connection.dialect.flagged ..Supports_Separate_NaN of
True -> is_blank || self.is_nan
False -> is_blank
result.rename new_name

View File

@ -23,10 +23,10 @@ import project.Internal.SQL_Type_Mapping.SQL_Type_Mapping
import project.Internal.SQL_Type_Reference.SQL_Type_Reference
import project.Internal.SQLite.SQLite_Dialect
import project.Internal.Statement_Setter.Statement_Setter
import project.Dialect_Flag.Dialect_Flag
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.Feature import Feature
from project.Internal.JDBC_Connection import JDBC_Connection
@ -139,26 +139,6 @@ type Dialect
_ = statement
Unimplemented.throw "This is an interface only."
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
supports_nested_with_clause : Boolean
supports_nested_with_clause self =
Unimplemented.throw "This is an interface only."
## PRIVATE
Specifies if the Database distinguishes a separate `NaN` value for
floating point columns. Some databases will not be able to distinguish
NaN from NULL.
supports_separate_nan : Boolean
supports_separate_nan self =
Unimplemented.throw "This is an interface only."
## PRIVAITE
Specifies implementation details flags.
dialect_flags : Dialect_Flags
dialect_flags -> Dialect_Flags =
Unimplemented.throw "This is an interface only."
## PRIVATE
Specifies how the database creates temp tables.
temp_table_style : Temp_Table_Style
@ -212,6 +192,12 @@ type Dialect
_ = feature
Unimplemented.throw "This is an interface only."
## PRIVATE
Checks a dialect flag
flagged self flag:Dialect_Flag -> Boolean =
_ = flag
Unimplemented.throw "This is an interface only."
## PRIVATE
Returns a helper for mapping database-specific SQL errors into our common
error types.

View File

@ -0,0 +1,25 @@
from Standard.Base import all
## PRIVATE
type Dialect_Flag
## PRIVATE
Supports_Negative_Decimal_Places
## PRIVATE
Supports_Float_Decimal_Places
## PRIVATE
Use_Builtin_Bankers
## PRIVATE
Primary_Key_Allows_Nulls
## PRIVATE
Specifies if the Database distinguishes a separate `NaN` value for
floating point columns. Some databases will not be able to distinguish
NaN from NULL.
Supports_Separate_NaN
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
Supports_Nested_With_Clause
## PRIVATE
Specifies if the backend supports case-sensitive column names. If `False`, the backend will
match column names in a case insensitive way, so that "Foo" and "foo" will refer to the
same column.
Supports_Case_Sensitive_Columns

View File

@ -1,22 +0,0 @@
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) (primary_key : Primary_Key_Flags)
## PRIVATE
type Rounding_Flags
## PRIVATE
Value (supports_negative_decimal_places : Boolean) (supports_float_decimal_places : Boolean) (use_builtin_bankers : Boolean)
type Primary_Key_Flags
Value (allows_nulls : Boolean)

View File

@ -10,8 +10,6 @@ from Standard.Table.Aggregate_Column.Aggregate_Column import all
from Standard.Table.Errors import Inexact_Type_Coercion
from Standard.Table.Internal.Storage import get_storage_for_column
from Standard.Database.Dialect_Flags import all
import project.Connection.Connection.Connection
import project.DB_Column.DB_Column
import project.DB_Table.DB_Table
@ -35,6 +33,7 @@ import project.Internal.Replace_Params.Replace_Params
import project.Internal.SQL_Type_Mapping.SQL_Type_Mapping
import project.Internal.SQL_Type_Reference.SQL_Type_Reference
import project.Internal.Statement_Setter.Statement_Setter
import project.Dialect_Flag.Dialect_Flag
import project.SQL.SQL_Builder
import project.SQL.SQL_Fragment
import project.SQL_Statement.SQL_Statement
@ -169,23 +168,6 @@ type Postgres_Dialect
_ = statement
False
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
supports_nested_with_clause : Boolean
supports_nested_with_clause self = True
## PRIVATE
supports_separate_nan : Boolean
supports_separate_nan 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=False use_builtin_bankers=False
primary_key = Primary_Key_Flags.Value allows_nulls=False
Dialect_Flags.Value rounding=rounding primary_key=primary_key
## PRIVATE
Specifies how the database creates temp tables.
temp_table_style : Temp_Table_Style
@ -271,6 +253,18 @@ type Postgres_Dialect
_ = feature
True
## PRIVATE
Checks a dialect flag
flagged self flag:Dialect_Flag -> Boolean =
case flag of
Dialect_Flag.Supports_Negative_Decimal_Places -> True
Dialect_Flag.Supports_Float_Decimal_Places -> False
Dialect_Flag.Use_Builtin_Bankers -> False
Dialect_Flag.Primary_Key_Allows_Nulls -> False
Dialect_Flag.Supports_Separate_NaN -> True
Dialect_Flag.Supports_Nested_With_Clause -> True
Dialect_Flag.Supports_Case_Sensitive_Columns -> True
## PRIVATE
The default table types to use when listing tables.
default_table_types : Vector Text

View File

@ -7,8 +7,6 @@ import Standard.Table.Internal.Problem_Builder.Problem_Builder
from Standard.Table import Aggregate_Column, Value_Type
from Standard.Table.Aggregate_Column.Aggregate_Column import all
from Standard.Database.Dialect_Flags import all
import project.Connection.Connection.Connection
import project.DB_Column.DB_Column
import project.DB_Table.DB_Table
@ -33,6 +31,7 @@ import project.Internal.SQL_Type_Reference.SQL_Type_Reference
import project.Internal.SQLite.SQLite_Error_Mapper.SQLite_Error_Mapper
import project.Internal.SQLite.SQLite_Type_Mapping.SQLite_Type_Mapping
import project.Internal.Statement_Setter.Statement_Setter
import project.Dialect_Flag.Dialect_Flag
import project.SQL.SQL_Builder
import project.SQL_Statement.SQL_Statement
import project.SQL_Type.SQL_Type
@ -182,23 +181,6 @@ type SQLite_Dialect
_ = statement
True
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
supports_nested_with_clause : Boolean
supports_nested_with_clause self = True
## PRIVATE
supports_separate_nan : Boolean
supports_separate_nan self = False
## 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 use_builtin_bankers=False
primary_key = Primary_Key_Flags.Value allows_nulls=True
Dialect_Flags.Value rounding=rounding primary_key=primary_key
## PRIVATE
Specifies how the database creates temp tables.
temp_table_style : Temp_Table_Style
@ -282,6 +264,18 @@ type SQLite_Dialect
_ = feature
True
## PRIVATE
Checks a dialect flag
flagged self flag:Dialect_Flag -> Boolean =
case flag of
Dialect_Flag.Supports_Negative_Decimal_Places -> False
Dialect_Flag.Supports_Float_Decimal_Places -> True
Dialect_Flag.Use_Builtin_Bankers -> False
Dialect_Flag.Primary_Key_Allows_Nulls -> True
Dialect_Flag.Supports_Separate_NaN -> False
Dialect_Flag.Supports_Nested_With_Clause -> True
Dialect_Flag.Supports_Case_Sensitive_Columns -> False
## PRIVATE
The default table types to use when listing tables.
default_table_types : Vector Text

View File

@ -35,12 +35,12 @@ import Standard.Database.Internal.Replace_Params.Replace_Params
import Standard.Database.Internal.SQL_Type_Mapping.SQL_Type_Mapping
import Standard.Database.Internal.SQL_Type_Reference.SQL_Type_Reference
import Standard.Database.Internal.Statement_Setter.Statement_Setter
import Standard.Database.Dialect_Flag.Dialect_Flag
import Standard.Database.SQL.SQL_Builder
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.Base_Generator import lift_binary_op
from Standard.Database.Internal.IR.Operation_Metadata import Date_Period_Metadata
@ -181,23 +181,6 @@ type SQLServer_Dialect
_ = statement
False
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
supports_nested_with_clause : Boolean
supports_nested_with_clause self = False
## PRIVATE
supports_separate_nan : Boolean
supports_separate_nan 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 use_builtin_bankers=False
primary_key = Primary_Key_Flags.Value allows_nulls=False
Dialect_Flags.Value rounding=rounding primary_key=primary_key
## PRIVATE
Specifies how the database creates temp tables.
temp_table_style : Temp_Table_Style
@ -246,6 +229,18 @@ type SQLServer_Dialect
Feature.Select_Columns -> True
_ -> False
## PRIVATE
Checks a dialect flag
flagged self flag:Dialect_Flag -> Boolean =
case flag of
Dialect_Flag.Supports_Negative_Decimal_Places -> True
Dialect_Flag.Supports_Float_Decimal_Places -> True
Dialect_Flag.Use_Builtin_Bankers -> False
Dialect_Flag.Primary_Key_Allows_Nulls -> False
Dialect_Flag.Supports_Separate_NaN -> False
Dialect_Flag.Supports_Nested_With_Clause -> True
Dialect_Flag.Supports_Case_Sensitive_Columns -> False
## PRIVATE
The default table types to use when listing tables.
default_table_types : Vector Text

View File

@ -39,12 +39,12 @@ import Standard.Database.Internal.Replace_Params.Replace_Params
import Standard.Database.Internal.SQL_Type_Mapping.SQL_Type_Mapping
import Standard.Database.Internal.SQL_Type_Reference.SQL_Type_Reference
import Standard.Database.Internal.Statement_Setter.Statement_Setter
import Standard.Database.Dialect_Flag.Dialect_Flag
import Standard.Database.SQL.SQL_Builder
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.JDBC_Connection import JDBC_Connection
@ -194,23 +194,6 @@ type Snowflake_Dialect
needs_execute = query_text.find regex . is_nothing . not
needs_execute
## PRIVATE
Specifies if the Database backend supports WITH clauses in nested queries.
supports_nested_with_clause : Boolean
supports_nested_with_clause self = False
## PRIVATE
supports_separate_nan : Boolean
supports_separate_nan 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 use_builtin_bankers=True
primary_key = Primary_Key_Flags.Value allows_nulls=False
Dialect_Flags.Value rounding=rounding primary_key=primary_key
## PRIVATE
Specifies how the database creates temp tables.
temp_table_style : Temp_Table_Style
@ -259,6 +242,18 @@ type Snowflake_Dialect
_ = feature
True
## PRIVATE
Checks a dialect flag
flagged self flag:Dialect_Flag -> Boolean =
case flag of
Dialect_Flag.Supports_Negative_Decimal_Places -> True
Dialect_Flag.Supports_Float_Decimal_Places -> True
Dialect_Flag.Use_Builtin_Bankers -> True
Dialect_Flag.Primary_Key_Allows_Nulls -> False
Dialect_Flag.Supports_Separate_NaN -> False
Dialect_Flag.Supports_Nested_With_Clause -> True
Dialect_Flag.Supports_Case_Sensitive_Columns -> True
## PRIVATE
The default table types to use when listing tables.
default_table_types : Vector Text

View File

@ -5,6 +5,7 @@ from Standard.Table import Table, Value_Type, Bits
from Standard.Database import all
import Standard.Database.Feature.Feature
import Standard.Database.Dialect_Flag.Dialect_Flag
from Standard.AWS import Redshift_Details, AWS_Credential
@ -74,7 +75,7 @@ add_database_specs suite_builder create_connection_fn =
default_connection.get.base_connection.create_literal_table (Table.new columns) "literal_table"
materialize = .read
common_selection = Common_Table_Operations.Main.Test_Selection.Config supports_case_sensitive_columns=True order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False supports_decimal_type=True run_advanced_edge_case_tests_by_default=False
common_selection = Common_Table_Operations.Main.Test_Selection.Config order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False supports_decimal_type=True run_advanced_edge_case_tests_by_default=False
aggregate_selection = Common_Table_Operations.Aggregate_Spec.Test_Selection.Config first_last_row_order=False aggregation_problems=False date_support=False
agg_in_memory_table = (enso_project.data / "data.csv") . read
agg_table_fn = _->
@ -84,8 +85,9 @@ add_database_specs suite_builder create_connection_fn =
(agg_in_memory_table.take (..First 0)).select_into_database_table default_connection.get (Name_Generator.random_name "Agg_Empty") primary_key=Nothing temporary=True
is_feature_supported_fn feature:Feature = default_connection.get.dialect.is_feature_supported feature
flagged_fn = default_connection.get.dialect.flagged
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn flagged=flagged_fn
Common_Spec.add_specs suite_builder prefix create_connection_fn default_connection setup
add_redshift_specific_specs suite_builder create_connection_fn setup

View File

@ -9,6 +9,7 @@ from Standard.Table.Errors import Invalid_Column_Names, Inexact_Type_Coercion, D
import Standard.Database.DB_Column.DB_Column
import Standard.Database.DB_Table.DB_Table
import Standard.Database.Feature.Feature
import Standard.Database.Dialect_Flag.Dialect_Flag
import Standard.Database.SQL_Type.SQL_Type
import Standard.Database.Internal.Replace_Params.Replace_Params
from Standard.Database import all
@ -177,7 +178,7 @@ add_sqlserver_specs suite_builder create_connection_fn =
materialize = .read
common_selection = Common_Table_Operations.Main.Test_Selection.Config supports_case_sensitive_columns=False order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False text_length_limited_columns=True fixed_length_text_columns=True removes_trailing_whitespace_casting_from_char_to_varchar=True char_max_size_after_substring=..Reset supports_decimal_type=True supported_replace_params=supported_replace_params run_advanced_edge_case_tests_by_default=True supports_date_time_without_timezone=False date_time=False is_nan_comparable=True
common_selection = Common_Table_Operations.Main.Test_Selection.Config order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False text_length_limited_columns=True fixed_length_text_columns=True removes_trailing_whitespace_casting_from_char_to_varchar=True char_max_size_after_substring=..Reset supports_decimal_type=True supported_replace_params=supported_replace_params run_advanced_edge_case_tests_by_default=True supports_date_time_without_timezone=False date_time=False is_nan_comparable=True
aggregate_selection = Common_Table_Operations.Aggregate_Spec.Test_Selection.Config first_last_row_order=False aggregation_problems=False
agg_in_memory_table = (enso_project.data / "data.csv") . read
@ -188,8 +189,9 @@ add_sqlserver_specs suite_builder create_connection_fn =
(agg_in_memory_table.take (..First 0)).select_into_database_table default_connection.get (Name_Generator.random_name "Agg_Empty") primary_key=Nothing temporary=True
is_feature_supported_fn feature:Feature = default_connection.get.dialect.is_feature_supported feature
flagged_fn = default_connection.get.dialect.flagged
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn flagged=flagged_fn
Common_Spec.add_specs suite_builder prefix create_connection_fn default_connection setup
Common_Table_Operations.Main.add_specs suite_builder setup

View File

@ -9,6 +9,7 @@ from Standard.Table.Errors import Invalid_Column_Names, Inexact_Type_Coercion, D
import Standard.Database.DB_Column.DB_Column
import Standard.Database.DB_Table.DB_Table
import Standard.Database.Feature.Feature
import Standard.Database.Dialect_Flag.Dialect_Flag
import Standard.Database.SQL_Type.SQL_Type
import Standard.Database.Internal.Replace_Params.Replace_Params
from Standard.Database import all
@ -531,7 +532,7 @@ add_snowflake_specs suite_builder create_connection_fn db_name =
default_connection.get.base_connection.create_literal_table (Table.new columns) "literal_table"
materialize = .read
common_selection = Common_Table_Operations.Main.Test_Selection.Config supports_case_sensitive_columns=True order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False text_length_limited_columns=True fixed_length_text_columns=False different_size_integer_types=False removes_trailing_whitespace_casting_from_char_to_varchar=False supports_decimal_type=True supported_replace_params=supported_replace_params run_advanced_edge_case_tests_by_default=False supports_date_time_without_timezone=True supports_nanoseconds_in_time=True is_nan_comparable=True distinct_returns_first_row_from_group_if_ordered=False
common_selection = Common_Table_Operations.Main.Test_Selection.Config order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False text_length_limited_columns=True fixed_length_text_columns=False different_size_integer_types=False removes_trailing_whitespace_casting_from_char_to_varchar=False supports_decimal_type=True supported_replace_params=supported_replace_params run_advanced_edge_case_tests_by_default=False supports_date_time_without_timezone=True supports_nanoseconds_in_time=True is_nan_comparable=True distinct_returns_first_row_from_group_if_ordered=False
aggregate_selection = Common_Table_Operations.Aggregate_Spec.Test_Selection.Config first_last_row_order=False aggregation_problems=False text_concat=False
agg_in_memory_table = ((Project_Description.new enso_dev.Table_Tests).data / "data.csv") . read
@ -542,8 +543,9 @@ add_snowflake_specs suite_builder create_connection_fn db_name =
(agg_in_memory_table.take (..First 0)).select_into_database_table default_connection.get (Name_Generator.random_name "Agg_Empty") primary_key=Nothing temporary=True
is_feature_supported_fn feature:Feature = default_connection.get.dialect.is_feature_supported feature
flagged_fn = default_connection.get.dialect.flagged
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_integer_type=is_snowflake_integer is_feature_supported=is_feature_supported_fn
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_integer_type=is_snowflake_integer is_feature_supported=is_feature_supported_fn flagged=flagged_fn
Common_Spec.add_specs suite_builder prefix create_connection_fn default_connection setup
snowflake_specific_spec suite_builder default_connection db_name setup

View File

@ -28,7 +28,7 @@ add_specs suite_builder setup =
add_column_name_edge_cases_specs suite_builder setup =
materialize = setup.materialize
create_connection_fn = setup.create_connection_func
is_case_sensitive = setup.test_selection.supports_case_sensitive_columns
is_case_sensitive = setup.flagged ..Supports_Case_Sensitive_Columns
suite_builder.group setup.prefix+"Column Naming edge cases" group_builder->
data = Data.setup create_connection_fn

View File

@ -1797,7 +1797,7 @@ add_column_operation_specs suite_builder setup =
group_builder.teardown <|
connection_data.teardown
if connection_data.connection.dialect.supports_nested_with_clause then
if connection_data.connection.dialect.flagged ..Supports_Nested_With_Clause then
group_builder.specify "Should allow the use of let-style CTEs" <|
t = table_builder [["X", [1, 2, 3, 4]], ["Y", [4, 3, 100, 200]], ["Z", [12.1, 23.4, -4.5, 44.33]]]
x = t.at "X"

View File

@ -69,7 +69,11 @@ type Test_Setup
Note that it has less guarantees about column types, but is faster.
- is_integer_type: A predicate specifying if the given backend treats the
given type as an integer type. See `SQL_Type_Mapping.is_integer_type` for more information.
Config prefix table_fn empty_table_fn (table_builder : (Vector Any -> (Any|Nothing)) -> Any) materialize is_database test_selection aggregate_test_selection create_connection_func light_table_builder is_integer_type=(.is_integer) is_feature_supported
- is_feature_supported: A function that takes a `Feature` and returns a
boolean indicating if the feature is supported by the backend.
- flagged: A function that takes a `Dialect_Flag` and returns a boolean indicating if the
flag is set for the backend.
Config prefix table_fn empty_table_fn (table_builder : (Vector Any -> (Any|Nothing)) -> Any) materialize is_database test_selection aggregate_test_selection create_connection_func light_table_builder is_integer_type=(.is_integer) is_feature_supported flagged
## Specifies if the given Table backend supports custom Enso types.
@ -89,10 +93,6 @@ type Test_Selection
backend, driving what kind of test suites should be enabled.
Arguments:
- supports_case_sensitive_columns: Specifies if the backend supports
case-sensitive column names. If `False`, the backend will match column
names in a case insensitive way, so that "Foo" and "foo" will refer to
the same column.
- natural_ordering: Specifies if the backend supports natural ordering
operations.
- case_insensitive_ordering: Specifies if the backend supports case
@ -157,7 +157,7 @@ type Test_Selection
- supports_date_time_without_timezone: Specifies if the backend supports
date/time operations without a timezone (true for most Database backends).
Defaults to `.is_integer`.
Config supports_case_sensitive_columns=True natural_ordering=False case_insensitive_ordering=True order_by_unicode_normalization_by_default=False case_insensitive_ascii_only=False allows_mixed_type_comparisons=True supports_unicode_normalization=False is_nan_and_nothing_distinct=True is_nan_comparable=False distinct_returns_first_row_from_group_if_ordered=True date_time=True text_length_limited_columns=False fixed_length_text_columns=False length_restricted_text_columns=True removes_trailing_whitespace_casting_from_char_to_varchar=False char_max_size_after_substring:Char_Max_Size_After_Substring_Behavior=..Kept different_size_integer_types=True supports_8bit_integer=False supports_decimal_type=False supports_time_duration=False supports_nanoseconds_in_time=False supports_mixed_columns=False supported_replace_params=Nothing run_advanced_edge_case_tests_by_default=True supports_date_time_without_timezone=False
Config natural_ordering=False case_insensitive_ordering=True order_by_unicode_normalization_by_default=False case_insensitive_ascii_only=False allows_mixed_type_comparisons=True supports_unicode_normalization=False is_nan_and_nothing_distinct=True is_nan_comparable=False distinct_returns_first_row_from_group_if_ordered=True date_time=True text_length_limited_columns=False fixed_length_text_columns=False length_restricted_text_columns=True removes_trailing_whitespace_casting_from_char_to_varchar=False char_max_size_after_substring:Char_Max_Size_After_Substring_Behavior=..Kept different_size_integer_types=True supports_8bit_integer=False supports_decimal_type=False supports_time_duration=False supports_nanoseconds_in_time=False supports_mixed_columns=False supported_replace_params=Nothing run_advanced_edge_case_tests_by_default=True supports_date_time_without_timezone=False
## Specifies if the advanced edge case tests shall be run.

View File

@ -87,7 +87,6 @@ add_specs suite_builder setup =
add_select_column_specs suite_builder setup =
prefix = setup.prefix
table_builder = Util.build_sorted_table setup
test_selection = setup.test_selection
suite_builder.group prefix+"Table.select_columns" group_builder->
data = Select_Columns_Data.setup table_builder
@ -119,15 +118,25 @@ add_select_column_specs suite_builder setup =
expect_column_names ["foo", "bar", "foo 1", "foo 2", "abcd123"] <| data.table.select_columns [-1, "bar", "foo.*".to_regex]
expect_column_names ["foo", "foo 1", "foo 2", "bar", "abcd123"] <| data.table.select_columns ["foo.*".to_regex, "bar", "foo", -1] reorder=True
if test_selection.supports_case_sensitive_columns then
group_builder.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
col3 = ["Bar", [7,8,9]]
table_builder [col1, col2, col3]
group_builder.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
col3 = ["Bar", [7,8,9]]
table_builder [col1, col2, col3]
if setup.flagged ..Supports_Case_Sensitive_Columns then
expect_column_names ["bar", "Bar"] <| table.select_columns ["bar"] case_sensitivity=Case_Sensitivity.Insensitive
group_builder.specify "should correctly handle mis-matches due to case insensitivity regardless of backend support" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
table_builder [col1, col2]
result = table.select_columns ["Bar"] case_sensitivity=Case_Sensitivity.Default
case setup.flagged ..Supports_Case_Sensitive_Columns of
True -> result.should_fail_with (Missing_Input_Columns.Error ["Bar"])
False -> result.should_fail_with (Missing_Input_Columns.Error ["Bar"])
group_builder.specify "should correctly handle regexes matching multiple names" <|
expect_column_names ["foo", "bar", "foo 1", "foo 2"] <| data.table.select_columns ["b.*".to_regex, "f.+".to_regex]
expect_column_names ["bar", "foo", "foo 1", "foo 2"] <| data.table.select_columns ["b.*".to_regex, "f.+".to_regex] reorder=True
@ -245,15 +254,25 @@ add_select_column_specs suite_builder setup =
group_builder.specify "should allow negative indices" <|
expect_column_names ["Baz", "foo 1", "ab.+123"] <| data.table.remove_columns [-1, -3, 0, 1]
if test_selection.supports_case_sensitive_columns then
group_builder.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
col3 = ["Bar", [7,8,9]]
table_builder [col1, col2, col3]
group_builder.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
col3 = ["Bar", [7,8,9]]
table_builder [col1, col2, col3]
if setup.flagged ..Supports_Case_Sensitive_Columns then
expect_column_names ["foo"] <| table.remove_columns "bar" Case_Sensitivity.Insensitive
group_builder.specify "should correctly handle mis-matches due to case insensitivity regardless of backend support" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
table_builder [col1, col2]
result = table.remove_columns "Bar" Case_Sensitivity.Default
case setup.flagged ..Supports_Case_Sensitive_Columns of
True -> expect_column_names ["foo", "bar"] <| result
False -> expect_column_names ["foo", "bar"] <| result
group_builder.specify "should correctly handle regexes matching multiple names" <|
expect_column_names ["Baz", "ab.+123", "abcd123"] <| data.table.remove_columns ["f.+".to_regex, "b.*".to_regex]
@ -331,15 +350,25 @@ add_select_column_specs suite_builder setup =
group_builder.specify "should allow negative indices" <|
expect_column_names ["abcd123", "foo 2", "foo", "bar", "Baz", "foo 1", "ab.+123"] <| data.table.reorder_columns [-1, -3, 0, 1]
if test_selection.supports_case_sensitive_columns then
group_builder.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
col3 = ["Bar", [7,8,9]]
table_builder [col1, col2, col3]
group_builder.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
col3 = ["Bar", [7,8,9]]
table_builder [col1, col2, col3]
if setup.flagged ..Supports_Case_Sensitive_Columns then
expect_column_names ["bar", "Bar", "foo"] <| table.reorder_columns ["bar"] case_sensitivity=Case_Sensitivity.Insensitive
group_builder.specify "should correctly handle mis-matches due to case insensitivity regardless of backend support" <|
table =
col1 = ["foo", [1,2,3]]
col2 = ["bar", [4,5,6]]
table_builder [col1, col2]
result = table.reorder_columns ["Bar"] case_sensitivity=Case_Sensitivity.Default
case setup.flagged ..Supports_Case_Sensitive_Columns of
True -> expect_column_names ["foo", "bar"] <| result
False -> expect_column_names ["foo", "bar"] <| result
group_builder.specify "should correctly handle regexes matching multiple names" <|
expect_column_names ["bar", "foo", "foo 1", "foo 2", "Baz", "ab.+123", "abcd123"] <| data.table.reorder_columns ["b.*".to_regex, "f.+".to_regex]

View File

@ -91,7 +91,7 @@ add_specs (suite_builder : Suite_Builder) setup (prefix : Text) default_connecti
big.to_vector
results.flatten.flatten.flatten.distinct.length . should_equal 1
if data.connection.dialect.supports_nested_with_clause then
if data.connection.dialect.flagged ..Supports_Nested_With_Clause then
group_builder.specify "should convert WITH binders to short names that do not conflict with existing table names" <|
t = Table.new [["x", [1, 2]], ["y", ['a', 'b']]]
let0 = t.select_into_database_table data.connection "let_0" temporary=True

View File

@ -12,6 +12,7 @@ from Standard.Table.Errors import Invalid_Column_Names, Inexact_Type_Coercion, D
import Standard.Database.DB_Column.DB_Column
import Standard.Database.DB_Table.DB_Table
import Standard.Database.Feature.Feature
import Standard.Database.Dialect_Flag.Dialect_Flag
import Standard.Database.SQL_Type.SQL_Type
import Standard.Database.Internal.Postgres.Pgpass
import Standard.Database.Internal.Replace_Params.Replace_Params
@ -725,7 +726,7 @@ add_postgres_specs suite_builder create_connection_fn db_name =
common_selection = Common_Table_Operations.Main.Test_Selection.Config supports_case_sensitive_columns=True order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False text_length_limited_columns=True fixed_length_text_columns=True removes_trailing_whitespace_casting_from_char_to_varchar=True char_max_size_after_substring=..Reset supports_decimal_type=True supported_replace_params=supported_replace_params run_advanced_edge_case_tests_by_default=True supports_date_time_without_timezone=True is_nan_comparable=True
common_selection = Common_Table_Operations.Main.Test_Selection.Config order_by_unicode_normalization_by_default=True allows_mixed_type_comparisons=False text_length_limited_columns=True fixed_length_text_columns=True removes_trailing_whitespace_casting_from_char_to_varchar=True char_max_size_after_substring=..Reset supports_decimal_type=True supported_replace_params=supported_replace_params run_advanced_edge_case_tests_by_default=True supports_date_time_without_timezone=True is_nan_comparable=True
aggregate_selection = Common_Table_Operations.Aggregate_Spec.Test_Selection.Config first_last_row_order=False aggregation_problems=False
agg_in_memory_table = (enso_project.data / "data.csv") . read
@ -736,8 +737,9 @@ add_postgres_specs suite_builder create_connection_fn db_name =
(agg_in_memory_table.take (..First 0)).select_into_database_table default_connection.get (Name_Generator.random_name "Agg_Empty") primary_key=Nothing temporary=True
is_feature_supported_fn feature:Feature = default_connection.get.dialect.is_feature_supported feature
flagged_fn = default_connection.get.dialect.flagged
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_fn light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn flagged=flagged_fn
Common_Spec.add_specs suite_builder prefix create_connection_fn default_connection setup
postgres_specific_spec suite_builder create_connection_fn db_name setup

View File

@ -9,6 +9,7 @@ from Standard.Table.Errors import Invalid_Column_Names, Duplicate_Output_Column_
import Standard.Database.Internal.Replace_Params.Replace_Params
import Standard.Database.Feature.Feature
import Standard.Database.Dialect_Flag.Dialect_Flag
from Standard.Database import all
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation, Unsupported_Database_Type
@ -331,7 +332,7 @@ sqlite_spec suite_builder prefix create_connection_func persistent_connector =
materialize = .read
common_selection = Common_Table_Operations.Main.Test_Selection.Config supports_case_sensitive_columns=False natural_ordering=False case_insensitive_ordering=True case_insensitive_ascii_only=True is_nan_and_nothing_distinct=False date_time=False supported_replace_params=supported_replace_params different_size_integer_types=False length_restricted_text_columns=False char_max_size_after_substring=..Reset run_advanced_edge_case_tests_by_default=True
common_selection = Common_Table_Operations.Main.Test_Selection.Config natural_ordering=False case_insensitive_ordering=True case_insensitive_ascii_only=True is_nan_and_nothing_distinct=False date_time=False supported_replace_params=supported_replace_params different_size_integer_types=False length_restricted_text_columns=False char_max_size_after_substring=..Reset run_advanced_edge_case_tests_by_default=True
## For now `advanced_stats`, `text_shortest_longest` and
`multi_distinct` remain disabled, because SQLite does not provide the
@ -351,8 +352,9 @@ sqlite_spec suite_builder prefix create_connection_func persistent_connector =
(agg_in_memory_table.take (..First 0)).select_into_database_table default_connection.get (Name_Generator.random_name "Agg_Empty") primary_key=Nothing temporary=True
is_feature_supported_fn feature:Feature = default_connection.get.dialect.is_feature_supported feature
flagged_fn = default_connection.get.dialect.flagged
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_func light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn
setup = Common_Table_Operations.Main.Test_Setup.Config prefix agg_table_fn empty_agg_table_fn table_builder materialize is_database=True test_selection=common_selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_func light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn flagged=flagged_fn
Common_Spec.add_specs suite_builder prefix create_connection_func default_connection setup
sqlite_specific_spec suite_builder prefix create_connection_func setup

View File

@ -375,14 +375,14 @@ add_specs suite_builder setup make_new_connection persistent_connector=True =
r1 = data.in_memory_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-4") primary_key=["X", "nonexistent"]
r1.should_fail_with Missing_Input_Columns
if data.connection.dialect.dialect_flags.primary_key.allows_nulls then
if data.connection.dialect.flagged ..Primary_Key_Allows_Nulls then
group_builder.specify "should not fail if the primary key contains nulls" <|
t1 = Table.new [['X', [1, Nothing, 3]], ['Y', [4, 5, Nothing]]]
run_with_and_without_output <|
r2 = t1.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-1") temporary=True primary_key=['X']
r2.row_count . should_equal 3
if data.connection.dialect.dialect_flags.primary_key.allows_nulls.not then
if data.connection.dialect.flagged ..Primary_Key_Allows_Nulls . not then
group_builder.specify "should fail if the primary key contains nulls" <|
t1 = Table.new [['X', [1, Nothing, 3]], ['Y', [4, 5, Nothing]]]
run_with_and_without_output <|
@ -566,7 +566,7 @@ add_specs suite_builder setup make_new_connection persistent_connector=True =
r1 = db_table.select_into_database_table data.connection (Name_Generator.random_name "copied-table") temporary=True primary_key=["nonexistent"]
r1.should_fail_with Missing_Input_Columns
if data.connection.dialect.dialect_flags.primary_key.allows_nulls then
if data.connection.dialect.flagged ..Primary_Key_Allows_Nulls then
group_builder.specify "should fail when the primary key contains nulls" <|
t = Table.new [['X', [1, Nothing, 3]], ['Y', [4, 5, Nothing]]]
db_table = t.select_into_database_table data.connection (Name_Generator.random_name "source-table-nulls-1") temporary=True
@ -576,7 +576,7 @@ add_specs suite_builder setup make_new_connection persistent_connector=True =
r2 = db_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-2") temporary=True primary_key=['X']
r2.row_count . should_equal 3
if data.connection.dialect.dialect_flags.primary_key.allows_nulls.not then
if data.connection.dialect.flagged ..Primary_Key_Allows_Nulls . not then
group_builder.specify "should fail when the primary key contains nulls" <|
t = Table.new [['X', [1, Nothing, 3]], ['Y', [4, 5, Nothing]]]
db_table = t.select_into_database_table data.connection (Name_Generator.random_name "source-table-nulls-1") temporary=True

View File

@ -4,6 +4,8 @@ from Standard.Table import Table
from Standard.Test import Test
import Standard.Database.Dialect_Flag.Dialect_Flag
import project.Common_Table_Operations
type Dummy_Connection
@ -16,7 +18,7 @@ type Dummy_Connection
Nothing
in_memory_setup =
selection = Common_Table_Operations.Main.Test_Selection.Config supports_case_sensitive_columns=True natural_ordering=True case_insensitive_ordering=True order_by_unicode_normalization_by_default=True supports_unicode_normalization=True supports_decimal_type=True supports_time_duration=True supports_nanoseconds_in_time=True supports_mixed_columns=True text_length_limited_columns=True fixed_length_text_columns=True supports_8bit_integer=True
selection = Common_Table_Operations.Main.Test_Selection.Config natural_ordering=True case_insensitive_ordering=True order_by_unicode_normalization_by_default=True supports_unicode_normalization=True supports_decimal_type=True supports_time_duration=True supports_nanoseconds_in_time=True supports_mixed_columns=True text_length_limited_columns=True fixed_length_text_columns=True supports_8bit_integer=True
aggregate_selection = Common_Table_Operations.Aggregate_Spec.Test_Selection.Config
agg_table_fn _ = (enso_project.data / "data.csv") . read
@ -35,8 +37,11 @@ in_memory_setup =
Dummy_Connection.Value
is_feature_supported_fn _ =
True
flagged_fn flag:Dialect_Flag =
case flag of
Dialect_Flag.Supports_Case_Sensitive_Columns -> True
Common_Table_Operations.Main.Test_Setup.Config "[In-Memory] " agg_table_fn empty_table_fn table_builder materialize is_database=False test_selection=selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_func light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn
Common_Table_Operations.Main.Test_Setup.Config "[In-Memory] " agg_table_fn empty_table_fn table_builder materialize is_database=False test_selection=selection aggregate_test_selection=aggregate_selection create_connection_func=create_connection_func light_table_builder=light_table_builder is_feature_supported=is_feature_supported_fn flagged=flagged_fn
add_specs suite_builder =
Common_Table_Operations.Main.add_specs suite_builder in_memory_setup