Skip to content

Commit

Permalink
Implement more strict no-type-widening mode
Browse files Browse the repository at this point in the history
  • Loading branch information
radeusgd committed Jan 14, 2023
1 parent 131d4a7 commit 4f35eeb
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 35 deletions.
45 changes: 23 additions & 22 deletions distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table.enso
Original file line number Diff line number Diff line change
Expand Up @@ -1208,32 +1208,33 @@ type Table
result_type = case allow_type_widening of
True ->
types = columns.filter Filter_Condition.Not_Nothing . map .value_type
Value_Type.find_common_type types strict=True
common_type = Value_Type.find_common_type types strict=True
if common_type.is_nothing then
problem_builder.report_other_warning (No_Common_Type.Error column_set.name)
common_type
False ->
first_column = columns.find (c-> c.is_nothing.not)
first_column.value_type
first_type = first_column.value_type
if first_type == Value_Type.Mixed then Value_Type.Mixed else
first_wrong_column = columns.find if_missing=Nothing col->
col.is_nothing.not && col.value_type != first_type
if first_wrong_column.is_nothing then first_type else
got_type = first_wrong_column.value_type
problem_builder.report_other_warning (Column_Type_Mismatch.Error column_set.name first_type got_type)
Nothing
case result_type of
Nothing ->
problem_builder.report_other_warning (No_Common_Type.Error column_set.name)
Nothing
Nothing -> Nothing
_ ->
handle_storage_type_mismatch caught_panic =
exception = caught_panic.payload
got_type = Storage.from_java exception.gotType . to_approximate_value_type
expected_type = result_type
problem_builder.report_other_warning (Column_Type_Mismatch.Error column_set.name expected_type got_type)
Nothing
Panic.catch StorageTypeMismatch handler=handle_storage_type_mismatch <|
storage_builder = Column_Module.make_storage_builder_for_type result_type initial_size=new_row_count
column_set.column_indices.zip all_tables i-> parent_table->
case i of
Nothing ->
null_row_count = parent_table.row_count
storage_builder.appendNulls null_row_count
_ : Integer ->
storage = parent_table.at i . java_column . getStorage
storage_builder.appendBulkStorage storage
Column.from_storage column_set.name storage_builder.seal
storage_builder = Column_Module.make_storage_builder_for_type result_type initial_size=new_row_count
column_set.column_indices.zip all_tables i-> parent_table->
case i of
Nothing ->
null_row_count = parent_table.row_count
storage_builder.appendNulls null_row_count
_ : Integer ->
storage = parent_table.at i . java_column . getStorage
storage_builder.appendBulkStorage storage
Column.from_storage column_set.name storage_builder.seal
good_columns = merged_columns.filter Filter_Condition.Not_Nothing
if good_columns.is_empty then Error.throw No_Output_Columns else
problem_builder.attach_problems_before on_problems <|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public StorageTypeMismatch(int expectedType, int gotType) {

@Override
public String getMessage() {
return "Expected storage of type " + expectedType + ", got " + gotType + ".";
return "Expected storage of type " + expectedType + ", got " + gotType + ". This is a bug in the Table library.";
}

public int gotType() {
Expand Down
41 changes: 29 additions & 12 deletions test/Table_Tests/src/Common_Table_Operations/Union_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -233,39 +233,56 @@ spec setup =
Problems.test_problem_handling action problems tester

Test.specify "if type widening is not allowed, should use the type from first table that contained the given column" <|
t1 = table_builder [["A", [1, 2, 3]], ["B", [1.5, 2.5, 3.5]]]
t2 = table_builder [["A", [4, 5, 6]], ["B", [1, 2, 3]]]
t1 = table_builder [["A", [1, 2, 3]]]
t2 = table_builder [["A", [4, 5, 6]], ["B", [1.2, 2.2, 3.1]]]

t1.at "B" . value_type . should_equal Value_Type.Float
t2.at "B" . value_type . should_equal Value_Type.Integer
t2.at "B" . value_type . should_equal Value_Type.Float

t3 = t1.union t2 allow_type_widening=False
t3 = t1.union t2 allow_type_widening=False keep_unmatched_columns=True
within_table t3 <|
Problems.assume_no_problems t3
expect_column_names ["A", "B"] t3
t3.at "A" . to_vector . should_equal [1, 2, 3, 4, 5, 6]
t3.at "B" . to_vector . should_equal [1.5, 2.5, 3.5, 1, 2, 3]
t3.at "A" . value_type . should_equal Value_Type.Integer
t3.at "B" . to_vector . should_equal [Nothing, Nothing, Nothing, 1.2, 2.2, 3.1]
t3.at "B" . value_type . should_equal Value_Type.Float

Test.specify "if type widening is not allowed and types do not match, should report error and drop the problematic column" <|
t1 = table_builder [["A", [1, 2, 3]], ["B", [1, 2, 3]], ["C", [True, False, Nothing]], ["D", [10, 20, 30]]]
t2 = table_builder [["A", [4, 5, 6]], ["B", [1.5, 2.5, 3.5]], ["C", [1, 2, 3]], ["D", [True, True, True]]]
t1 = table_builder [["A", [1, 2, 3]], ["B", [1, 2, 3]], ["C", [True, False, Nothing]], ["D", [10, 20, 30]], ["E", [1.1, 2.5, 3.2]]]
t2 = table_builder [["A", [4, 5, 6]], ["B", [1.5, 2.5, 3.5]], ["C", [1, 2, 3]], ["D", [True, True, True]], ["E", [1, 2, 3]]]

t1.at "B" . value_type . should_equal Value_Type.Float
t1.at "B" . value_type . should_equal Value_Type.Integer
t1.at "C" . value_type . should_equal Value_Type.Boolean
t1.at "D" . value_type . should_equal Value_Type.Integer
t1.at "E" . value_type . should_equal Value_Type.Float

t2.at "B" . value_type . should_equal Value_Type.Integer
t2.at "B" . value_type . should_equal Value_Type.Float
t2.at "C" . value_type . should_equal Value_Type.Integer
t2.at "D" . value_type . should_equal Value_Type.Boolean
t2.at "E" . value_type . should_equal Value_Type.Integer

action = t1.union t2 allow_type_widening=False on_problems=_
tester table =
expect_column_names ["A"] table
table.at "A" . to_vector . should_equal [4, 5, 6, 1, 2, 3]
problems = [Column_Type_Mismatch.Error "B" Value_Type.Integer Value_Type.Float, Column_Type_Mismatch.Error "C" Value_Type.Boolean Value_Type.Integer, Column_Type_Mismatch.Error "D" Value_Type.Integer Value_Type.Boolean]
table.at "A" . to_vector . should_equal [1, 2, 3, 4, 5, 6]
problems = [Column_Type_Mismatch.Error "B" Value_Type.Integer Value_Type.Float, Column_Type_Mismatch.Error "C" Value_Type.Boolean Value_Type.Integer, Column_Type_Mismatch.Error "D" Value_Type.Integer Value_Type.Boolean, Column_Type_Mismatch.Error "E" Value_Type.Float Value_Type.Integer]
Problems.test_problem_handling action problems tester

Test.specify "even if type widening is not allowed, if the first column is mixed, it should accept any column to be concatenated to it" <|
t1 = table_builder [["X", ["a", 1, Nothing]]]
t2 = table_builder [["X", [1]]]
t3 = table_builder [["X", [1.2, 2.3, 3.4]]]
t4 = table_builder [["X", ["a", "b"]]]
t5 = table_builder [["X", [True, False]]]

t1.at "X" . value_type . should_equal Value_Type.Mixed
t2.at "X" . value_type . should_equal Value_Type.Integer

t6 = t1.union [t2, t3, t4, t5] allow_type_widening=False
Problems.assume_no_problems t6
t6.at "X" . value_type . should_equal Value_Type.Mixed
t6.at "X" . to_vector . should_equal ["a", 1, Nothing, 1, 1.2, 2.3, 3.4, "a", "b", True, False]

Test.specify "if type mismatches cause all columns to be dropped, fail with No_Output_Columns" <|
t1 = table_builder [["A", [1, 2, 3]]]
t2 = table_builder [["A", ['x']]]
Expand Down

0 comments on commit 4f35eeb

Please sign in to comment.