diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table.enso index 6d47a83302c9c..b64bbfe1239bf 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table.enso @@ -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 <| diff --git a/std-bits/table/src/main/java/org/enso/table/data/column/builder/object/StorageTypeMismatch.java b/std-bits/table/src/main/java/org/enso/table/data/column/builder/object/StorageTypeMismatch.java index 962cbd8be8dd7..b8ef4e417d203 100644 --- a/std-bits/table/src/main/java/org/enso/table/data/column/builder/object/StorageTypeMismatch.java +++ b/std-bits/table/src/main/java/org/enso/table/data/column/builder/object/StorageTypeMismatch.java @@ -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() { diff --git a/test/Table_Tests/src/Common_Table_Operations/Union_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Union_Spec.enso index 801ed0bb7eb34..656c4e8e138b3 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Union_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Union_Spec.enso @@ -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']]]