mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 10:42:05 +03:00
Better error message for NULLs in primary key columns (#11055)
This commit is contained in:
parent
8eb6aaa188
commit
859b572242
@ -145,7 +145,8 @@ type Redshift_Dialect
|
|||||||
dialect_flags : Dialect_Flags
|
dialect_flags : Dialect_Flags
|
||||||
dialect_flags self -> 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
|
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=False use_builtin_bankers=False
|
||||||
Dialect_Flags.Value rounding=rounding
|
primary_key = Primary_Key_Flags.Value allows_nulls=False
|
||||||
|
Dialect_Flags.Value rounding=rounding primary_key=primary_key
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Specifies how the database creates temp tables.
|
Specifies how the database creates temp tables.
|
||||||
|
@ -6,12 +6,17 @@ from Standard.Database.Errors import SQL_Error
|
|||||||
type Redshift_Error_Mapper
|
type Redshift_Error_Mapper
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_primary_key_violation : SQL_Error -> Boolean
|
is_duplicate_primary_key_violation : SQL_Error -> Boolean
|
||||||
is_primary_key_violation error =
|
is_duplicate_primary_key_violation error =
|
||||||
# Currently not implemented, skipping the error recognition.
|
# Currently not implemented, skipping the error recognition.
|
||||||
_ = error
|
_ = error
|
||||||
False
|
False
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
is_null_primary_key_violation : SQL_Error -> Boolean
|
||||||
|
is_null_primary_key_violation error =
|
||||||
|
error.java_exception.getMessage.contains "violates not-null constraint"
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
transform_custom_errors : SQL_Error -> Any
|
transform_custom_errors : SQL_Error -> Any
|
||||||
transform_custom_errors error = error
|
transform_custom_errors error = error
|
||||||
|
@ -11,10 +11,12 @@ from Standard.Base import all
|
|||||||
since feature flags are user-facing, and can be used to identify features
|
since feature flags are user-facing, and can be used to identify features
|
||||||
that are not yet implemented.
|
that are not yet implemented.
|
||||||
type Dialect_Flags
|
type Dialect_Flags
|
||||||
## PRIVATE
|
Value (rounding : Rounding_Flags) (primary_key : Primary_Key_Flags)
|
||||||
Value (rounding : Rounding_Flags)
|
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
type Rounding_Flags
|
type Rounding_Flags
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Value (supports_negative_decimal_places : Boolean) (supports_float_decimal_places : Boolean) (use_builtin_bankers : Boolean)
|
Value (supports_negative_decimal_places : Boolean) (supports_float_decimal_places : Boolean) (use_builtin_bankers : Boolean)
|
||||||
|
|
||||||
|
type Primary_Key_Flags
|
||||||
|
Value (allows_nulls : Boolean)
|
||||||
|
@ -11,8 +11,14 @@ type Error_Mapper
|
|||||||
## PRIVATE
|
## PRIVATE
|
||||||
Checks if the given error is related to a violation of PRIMARY KEY
|
Checks if the given error is related to a violation of PRIMARY KEY
|
||||||
uniqueness constraint.
|
uniqueness constraint.
|
||||||
is_primary_key_violation : SQL_Error -> Boolean
|
is_duplicate_primary_key_violation : SQL_Error -> Boolean
|
||||||
is_primary_key_violation error =
|
is_duplicate_primary_key_violation error =
|
||||||
|
_ = error
|
||||||
|
Unimplemented.throw "This is an interface only."
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
is_null_primary_key_violation : SQL_Error -> Boolean
|
||||||
|
is_null_primary_key_violation error =
|
||||||
_ = error
|
_ = error
|
||||||
Unimplemented.throw "This is an interface only."
|
Unimplemented.throw "This is an interface only."
|
||||||
|
|
||||||
|
@ -182,7 +182,8 @@ type Postgres_Dialect
|
|||||||
dialect_flags : Dialect_Flags
|
dialect_flags : Dialect_Flags
|
||||||
dialect_flags self -> 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
|
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=False use_builtin_bankers=False
|
||||||
Dialect_Flags.Value rounding=rounding
|
primary_key = Primary_Key_Flags.Value allows_nulls=False
|
||||||
|
Dialect_Flags.Value rounding=rounding primary_key=primary_key
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Specifies how the database creates temp tables.
|
Specifies how the database creates temp tables.
|
||||||
|
@ -6,10 +6,15 @@ from project.Errors import Invariant_Violation, SQL_Error
|
|||||||
type Postgres_Error_Mapper
|
type Postgres_Error_Mapper
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_primary_key_violation : SQL_Error -> Boolean
|
is_duplicate_primary_key_violation : SQL_Error -> Boolean
|
||||||
is_primary_key_violation error =
|
is_duplicate_primary_key_violation error =
|
||||||
error.java_exception.getMessage.contains "duplicate key value violates unique constraint"
|
error.java_exception.getMessage.contains "duplicate key value violates unique constraint"
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
is_null_primary_key_violation : SQL_Error -> Boolean
|
||||||
|
is_null_primary_key_violation error =
|
||||||
|
error.java_exception.getMessage.contains "violates not-null constraint"
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_table_already_exists_error : SQL_Error -> Boolean
|
is_table_already_exists_error : SQL_Error -> Boolean
|
||||||
is_table_already_exists_error error =
|
is_table_already_exists_error error =
|
||||||
|
@ -195,7 +195,8 @@ type SQLite_Dialect
|
|||||||
dialect_flags : Dialect_Flags
|
dialect_flags : Dialect_Flags
|
||||||
dialect_flags self -> 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
|
rounding = Rounding_Flags.Value supports_negative_decimal_places=False supports_float_decimal_places=True use_builtin_bankers=False
|
||||||
Dialect_Flags.Value rounding=rounding
|
primary_key = Primary_Key_Flags.Value allows_nulls=True
|
||||||
|
Dialect_Flags.Value rounding=rounding primary_key=primary_key
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Specifies how the database creates temp tables.
|
Specifies how the database creates temp tables.
|
||||||
|
@ -9,12 +9,17 @@ polyglot java import org.sqlite.SQLiteException
|
|||||||
type SQLite_Error_Mapper
|
type SQLite_Error_Mapper
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_primary_key_violation : SQL_Error -> Boolean
|
is_duplicate_primary_key_violation : SQL_Error -> Boolean
|
||||||
is_primary_key_violation error =
|
is_duplicate_primary_key_violation error =
|
||||||
case error.java_exception of
|
case error.java_exception of
|
||||||
sqlite_exception : SQLiteException ->
|
sqlite_exception : SQLiteException ->
|
||||||
sqlite_exception.getResultCode == SQLiteErrorCode.SQLITE_CONSTRAINT_PRIMARYKEY
|
sqlite_exception.getResultCode == SQLiteErrorCode.SQLITE_CONSTRAINT_PRIMARYKEY
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
SQLite does not mind SQLite NULL primary keys.
|
||||||
|
is_null_primary_key_violation : SQL_Error -> Boolean
|
||||||
|
is_null_primary_key_violation _ = False
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_table_already_exists_error : SQL_Error -> Boolean
|
is_table_already_exists_error : SQL_Error -> Boolean
|
||||||
is_table_already_exists_error error =
|
is_table_already_exists_error error =
|
||||||
|
@ -3,7 +3,7 @@ private
|
|||||||
from Standard.Base import all
|
from Standard.Base import all
|
||||||
|
|
||||||
from Standard.Table import Aggregate_Column
|
from Standard.Table import Aggregate_Column
|
||||||
from Standard.Table.Errors import Non_Unique_Key
|
from Standard.Table.Errors import Non_Unique_Key, Null_Values_In_Key_Columns
|
||||||
|
|
||||||
from Standard.Database.Errors import SQL_Error
|
from Standard.Database.Errors import SQL_Error
|
||||||
|
|
||||||
@ -18,22 +18,39 @@ internal_translate_known_upload_errors source_table connection primary_key ~acti
|
|||||||
handler caught_panic =
|
handler caught_panic =
|
||||||
error_mapper = connection.dialect.get_error_mapper
|
error_mapper = connection.dialect.get_error_mapper
|
||||||
sql_error = caught_panic.payload
|
sql_error = caught_panic.payload
|
||||||
case error_mapper.is_primary_key_violation sql_error of
|
case error_mapper.is_duplicate_primary_key_violation sql_error of
|
||||||
True -> Panic.throw (Non_Unique_Key_Recipe.Recipe source_table primary_key caught_panic)
|
True -> Panic.throw (Non_Unique_Key_Recipe.Recipe source_table primary_key caught_panic)
|
||||||
|
False -> case error_mapper.is_null_primary_key_violation sql_error of
|
||||||
|
True -> Panic.throw (Null_Key_Recipe.Recipe source_table primary_key caught_panic)
|
||||||
False -> Panic.throw caught_panic
|
False -> Panic.throw caught_panic
|
||||||
Panic.catch SQL_Error action handler
|
Panic.catch SQL_Error action handler
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
handle_upload_errors ~action =
|
handle_upload_duplicate_primary_key_errors ~action =
|
||||||
Panic.catch Non_Unique_Key_Recipe action caught_panic->
|
Panic.catch Non_Unique_Key_Recipe action caught_panic->
|
||||||
recipe = caught_panic.payload
|
recipe = caught_panic.payload
|
||||||
raise_duplicated_primary_key_error recipe.source_table recipe.primary_key recipe.original_panic
|
raise_duplicated_primary_key_error recipe.source_table recipe.primary_key recipe.original_panic
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
handle_upload_null_primary_key_errors ~action =
|
||||||
|
Panic.catch Null_Key_Recipe action caught_panic->
|
||||||
|
recipe = caught_panic.payload
|
||||||
|
raise_null_primary_key_error recipe.source_table recipe.primary_key recipe.original_panic
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
handle_upload_errors ~action =
|
||||||
|
handle_upload_duplicate_primary_key_errors (handle_upload_null_primary_key_errors action)
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
type Non_Unique_Key_Recipe
|
type Non_Unique_Key_Recipe
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Recipe source_table primary_key original_panic
|
Recipe source_table primary_key original_panic
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
type Null_Key_Recipe
|
||||||
|
## PRIVATE
|
||||||
|
Recipe source_table primary_key original_panic
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Creates a `Non_Unique_Key` error containing information about an
|
Creates a `Non_Unique_Key` error containing information about an
|
||||||
example group violating the uniqueness constraint.
|
example group violating the uniqueness constraint.
|
||||||
@ -52,3 +69,20 @@ raise_duplicated_primary_key_error source_table primary_key original_panic =
|
|||||||
example_count = row.last
|
example_count = row.last
|
||||||
example_entry = row.drop (..Last 1)
|
example_entry = row.drop (..Last 1)
|
||||||
Error.throw (Non_Unique_Key.Error primary_key example_entry example_count)
|
Error.throw (Non_Unique_Key.Error primary_key example_entry example_count)
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
Creates a `Null_Key` error containing information about an
|
||||||
|
example group violating the non-null constraint.
|
||||||
|
raise_null_primary_key_error source_table primary_key original_panic =
|
||||||
|
bad_rows_per_pk = primary_key.map primary_key->
|
||||||
|
filtered = source_table.filter column=primary_key Filter_Condition.Is_Nothing
|
||||||
|
filtered.read (..First 1)
|
||||||
|
tables_with_bad_rows = bad_rows_per_pk.filter (t-> t.row_count > 0)
|
||||||
|
case tables_with_bad_rows.length == 0 of
|
||||||
|
## If we couldn't find a null key, we give up the translation and
|
||||||
|
rethrow the original panic containing the SQL error.
|
||||||
|
True -> Panic.throw original_panic
|
||||||
|
False ->
|
||||||
|
table_with_bad_rows = tables_with_bad_rows.first
|
||||||
|
row = table_with_bad_rows.first_row.to_vector
|
||||||
|
Error.throw (Null_Values_In_Key_Columns.Error row)
|
||||||
|
@ -194,7 +194,8 @@ type SQLSever_Dialect
|
|||||||
dialect_flags : Dialect_Flags
|
dialect_flags : Dialect_Flags
|
||||||
dialect_flags self -> 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
|
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=True use_builtin_bankers=False
|
||||||
Dialect_Flags.Value rounding=rounding
|
primary_key = Primary_Key_Flags.Value allows_nulls=False
|
||||||
|
Dialect_Flags.Value rounding=rounding primary_key=primary_key
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Specifies how the database creates temp tables.
|
Specifies how the database creates temp tables.
|
||||||
|
@ -6,12 +6,17 @@ from Standard.Database.Errors import Invariant_Violation, SQL_Error
|
|||||||
type SQLServer_Error_Mapper
|
type SQLServer_Error_Mapper
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_primary_key_violation : SQL_Error -> Boolean
|
is_duplicate_primary_key_violation : SQL_Error -> Boolean
|
||||||
is_primary_key_violation error =
|
is_duplicate_primary_key_violation error =
|
||||||
## TODO the SQL error actually contains the duplicated primary key value!
|
## TODO the SQL error actually contains the duplicated primary key value!
|
||||||
We could use that to avoid a separate `Non_Unique_Key_Recipe` query.
|
We could use that to avoid a separate `Non_Unique_Key_Recipe` query.
|
||||||
error.java_exception.getMessage.contains "Violation of PRIMARY KEY constraint"
|
error.java_exception.getMessage.contains "Violation of PRIMARY KEY constraint"
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
is_null_primary_key_violation : SQL_Error -> Boolean
|
||||||
|
is_null_primary_key_violation error =
|
||||||
|
error.java_exception.getMessage.contains "violates not-null constraint"
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_table_already_exists_error : SQL_Error -> Boolean
|
is_table_already_exists_error : SQL_Error -> Boolean
|
||||||
is_table_already_exists_error error =
|
is_table_already_exists_error error =
|
||||||
|
@ -207,7 +207,8 @@ type Snowflake_Dialect
|
|||||||
dialect_flags : Dialect_Flags
|
dialect_flags : Dialect_Flags
|
||||||
dialect_flags self -> 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
|
rounding = Rounding_Flags.Value supports_negative_decimal_places=True supports_float_decimal_places=True use_builtin_bankers=True
|
||||||
Dialect_Flags.Value rounding=rounding
|
primary_key = Primary_Key_Flags.Value allows_nulls=False
|
||||||
|
Dialect_Flags.Value rounding=rounding primary_key=primary_key
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Specifies how the database creates temp tables.
|
Specifies how the database creates temp tables.
|
||||||
|
@ -6,11 +6,16 @@ from Standard.Database.Errors import Invariant_Violation, SQL_Error
|
|||||||
type Snowflake_Error_Mapper
|
type Snowflake_Error_Mapper
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_primary_key_violation : SQL_Error -> Boolean
|
is_duplicate_primary_key_violation : SQL_Error -> Boolean
|
||||||
is_primary_key_violation error =
|
is_duplicate_primary_key_violation error =
|
||||||
# TODO https://github.com/enso-org/enso/issues/7117
|
# TODO https://github.com/enso-org/enso/issues/7117
|
||||||
error.java_exception.getMessage.contains "A primary key already exists."
|
error.java_exception.getMessage.contains "A primary key already exists."
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
is_null_primary_key_violation : SQL_Error -> Boolean
|
||||||
|
is_null_primary_key_violation error =
|
||||||
|
error.java_exception.getMessage.contains "NULL result in a non-nullable column"
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
is_table_already_exists_error : SQL_Error -> Boolean
|
is_table_already_exists_error : SQL_Error -> Boolean
|
||||||
is_table_already_exists_error error =
|
is_table_already_exists_error error =
|
||||||
|
@ -370,6 +370,42 @@ 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 = 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
|
r1.should_fail_with Missing_Input_Columns
|
||||||
|
|
||||||
|
if data.connection.dialect.dialect_flags.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
|
||||||
|
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 <|
|
||||||
|
r1 = t1.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-0") temporary=True primary_key=[]
|
||||||
|
r1.row_count . should_equal 3
|
||||||
|
|
||||||
|
r2 = t1.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-1") temporary=True primary_key=['X']
|
||||||
|
r2.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
r2.catch . example_row . should_equal [Nothing, 5]
|
||||||
|
|
||||||
|
r3 = t1.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-2") temporary=True primary_key=['Y']
|
||||||
|
r3.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
r3.catch . example_row . should_equal [3, Nothing]
|
||||||
|
|
||||||
|
r4 = t1.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-3") temporary=True primary_key=['X', 'Y']
|
||||||
|
r4.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
r4.catch . example_row . should_equal [Nothing, 5]
|
||||||
|
|
||||||
|
large_with_null = (0.up_to 1010).to_vector + [Nothing]
|
||||||
|
big_table = Table.new [['X', large_with_null+large_with_null]]
|
||||||
|
Context.Output.with_disabled <|
|
||||||
|
r5 = big_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-4") temporary=True primary_key=['X']
|
||||||
|
r5.column_names . should_equal ['X']
|
||||||
|
r5.row_count . should_equal 1000
|
||||||
|
Context.Output.with_enabled <|
|
||||||
|
r5 = big_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-5") temporary=True primary_key=['X']
|
||||||
|
r5.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
|
||||||
snowflake_constraints_pending = if prefix.contains "Snowflake" then "Disabled until https://github.com/enso-org/enso/issues/10737 is resolved."
|
snowflake_constraints_pending = if prefix.contains "Snowflake" then "Disabled until https://github.com/enso-org/enso/issues/10737 is resolved."
|
||||||
group_builder.specify "should fail if the primary key is not unique" pending=snowflake_constraints_pending <|
|
group_builder.specify "should fail if the primary key is not unique" pending=snowflake_constraints_pending <|
|
||||||
t1 = Table.new [["X", [1, 2, 1]], ["Y", ['b', 'b', 'a']]]
|
t1 = Table.new [["X", [1, 2, 1]], ["Y", ['b', 'b', 'a']]]
|
||||||
@ -525,6 +561,49 @@ 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 = 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
|
r1.should_fail_with Missing_Input_Columns
|
||||||
|
|
||||||
|
if data.connection.dialect.dialect_flags.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 primary_key=Nothing
|
||||||
|
Problems.assume_no_problems db_table
|
||||||
|
|
||||||
|
run_with_and_without_output <|
|
||||||
|
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
|
||||||
|
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 primary_key=Nothing
|
||||||
|
Problems.assume_no_problems db_table
|
||||||
|
|
||||||
|
run_with_and_without_output <|
|
||||||
|
r1 = db_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-1") temporary=True primary_key=[]
|
||||||
|
r1.row_count . should_equal 3
|
||||||
|
|
||||||
|
r2 = db_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-2") temporary=True primary_key=['X']
|
||||||
|
r2.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
r2.catch . example_row . should_equal [Nothing, 5]
|
||||||
|
|
||||||
|
r3 = db_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-3") temporary=True primary_key=['Y']
|
||||||
|
r3.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
r3.catch . example_row . should_equal [3, Nothing]
|
||||||
|
|
||||||
|
r4 = db_table.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-4") temporary=True primary_key=['X', 'Y']
|
||||||
|
r4.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
r4.catch . example_row . should_equal [Nothing, 5]
|
||||||
|
|
||||||
|
large_with_null = (0.up_to 1010).to_vector + [Nothing]
|
||||||
|
big_table = Table.new [['X', large_with_null+large_with_null]]
|
||||||
|
db_table_2 = big_table.select_into_database_table data.connection (Name_Generator.random_name "source-table-nulls-2") temporary=True primary_key=Nothing
|
||||||
|
Context.Output.with_disabled <|
|
||||||
|
r5 = db_table_2.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-5") temporary=True primary_key=['X']
|
||||||
|
r5.column_names . should_equal ['X']
|
||||||
|
r5.row_count . should_equal 1000
|
||||||
|
Context.Output.with_enabled <|
|
||||||
|
r5 = db_table_2.select_into_database_table data.connection (Name_Generator.random_name "primary-key-null-6") temporary=True primary_key=['X']
|
||||||
|
r5.should_fail_with Null_Values_In_Key_Columns
|
||||||
|
|
||||||
snowflake_constraints_pending = if prefix.contains "Snowflake" then "Disabled until https://github.com/enso-org/enso/issues/10737 is resolved."
|
snowflake_constraints_pending = if prefix.contains "Snowflake" then "Disabled until https://github.com/enso-org/enso/issues/10737 is resolved."
|
||||||
group_builder.specify "should fail when the primary key is not unique" pending=snowflake_constraints_pending <|
|
group_builder.specify "should fail when the primary key is not unique" pending=snowflake_constraints_pending <|
|
||||||
t = Table.new [["X", [1, 2, 1]], ["Y", ['b', 'b', 'a']]]
|
t = Table.new [["X", [1, 2, 1]], ["Y", ['b', 'b', 'a']]]
|
||||||
|
Loading…
Reference in New Issue
Block a user