From bc0db18a6eed07c5c3acee593fa1e322e413a861 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Sat, 6 May 2023 11:10:24 +0100 Subject: [PATCH] Small changes from Book Club issues (#6533) - Add dropdown to tokenize and split `column`. - Remove the custom `Join_Kind` dropdown. - Adjust split and tokenize names to start numbering from 1, not 0. - Add JS_Object serialization for Period. - Add `days_until` and `until` to `Date`. - Add `Date_Period.Day` and create `next` and `previous` on `Date`. - Use simple names with `File_Format` dropdown. - Avoid using `Main.enso` based imports in `Standard.Base.Data.Map` and `Standard.Base.Data.Text.Helpers`. - Remove an incorrect import from `Standard.Database.Data.Table`. From #6587: A few small changes, lots of lines because this affected lots of tests: - `Table.join` now defaults to `Join_Kind.Left_Outer`, to avoid losing rows in the left table unexpectedly. If the user really wants to have an Inner join, they can switch to it. - `Table.join` now defaults to joining columns by name not by index - it looks in the right table for a column with the same name as the first column in left table. - Missing Input Column errors now specify which table they refer to in the join. - The unique name suffix in column renaming / default column names when loading from file is now a space instead of underscore. --- .../Standard/Base/0.0.0-dev/src/Data/Map.enso | 5 +- .../0.0.0-dev/src/Data/Text/Extensions.enso | 2 +- .../Base/0.0.0-dev/src/Data/Text/Helpers.enso | 6 +- .../Base/0.0.0-dev/src/Data/Time/Date.enso | 50 +++- .../0.0.0-dev/src/Data/Time/Date_Period.enso | 16 +- .../Base/0.0.0-dev/src/Data/Time/Period.enso | 19 ++ .../0.0.0-dev/src/System/File_Format.enso | 2 +- .../Database/0.0.0-dev/src/Data/Table.enso | 50 ++-- .../Standard/Database/0.0.0-dev/src/Main.enso | 2 + .../Table/0.0.0-dev/src/Data/Table.enso | 34 ++- .../src/Delimited/Delimited_Format.enso | 2 +- .../Standard/Table/0.0.0-dev/src/Errors.enso | 7 +- .../0.0.0-dev/src/Internal/Join_Helpers.enso | 17 +- .../src/Internal/Problem_Builder.enso | 10 +- .../src/Internal/Split_Tokenize.enso | 4 +- .../src/Internal/Unique_Name_Strategy.enso | 8 +- .../src/Internal/Widget_Helpers.enso | 72 +++++- .../org/enso/base/time/Date_Period_Utils.java | 14 ++ .../org/enso/table/read/DelimitedReader.java | 2 +- .../org/enso/table/util/NameDeduplicator.java | 4 +- .../Aggregate_Spec.enso | 24 +- .../Common_Table_Operations/Core_Spec.enso | 14 +- .../Cross_Tab_Spec.enso | 4 +- .../Integration_Tests.enso | 2 +- .../Join/Cross_Join_Spec.enso | 22 +- .../Join/Join_Spec.enso | 226 +++++++++--------- .../Join/Zip_Spec.enso | 30 +-- .../Select_Columns_Spec.enso | 104 ++++---- .../Transpose_Spec.enso | 12 +- .../src/Database/Codegen_Spec.enso | 4 +- .../Table_Tests/src/Database/Upload_Spec.enso | 12 +- .../Helpers/Unique_Naming_Strategy_Spec.enso | 58 ++--- test/Table_Tests/src/IO/Csv_Spec.enso | 18 +- .../src/IO/Delimited_Read_Spec.enso | 60 ++--- .../src/IO/Delimited_Write_Spec.enso | 2 +- test/Table_Tests/src/IO/Excel_Spec.enso | 20 +- .../src/In_Memory/Column_Spec.enso | 4 +- .../src/In_Memory/Join_Performance_Spec.enso | 2 +- .../src/In_Memory/Split_Tokenize_Spec.enso | 46 ++-- .../Table_Tests/src/In_Memory/Table_Spec.enso | 8 +- test/Table_Tests/src/Util.enso | 43 ++-- test/Tests/src/Data/Time/Date_Spec.enso | 16 ++ .../src/Lazy_Table_Spec.enso | 4 +- 43 files changed, 643 insertions(+), 418 deletions(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Map.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Map.enso index 108115c8c1a..10767ffea67 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Map.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Map.enso @@ -1,13 +1,16 @@ +import project.Any.Any import project.Data.Numbers.Integer import project.Data.Vector.Vector import project.Data.Pair.Pair import project.Data.Text.Extensions import project.Data.Text.Text +import project.Error.Error import project.Errors.Illegal_Argument.Illegal_Argument import project.Errors.No_Such_Key.No_Such_Key +import project.Nothing.Nothing +import project.Panic.Panic from project.Data.Boolean import Boolean, True, False -from project import Error, Nothing, Any, Panic ## A key-value store. It is possible to use any type as keys and values and mix them in one Map. Keys are checked for equality based on their hash code and `==` operator, which diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso index c36c4ba34b7..fc2c1c6d3b5 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso @@ -900,7 +900,7 @@ Text.repeat : Integer -> Text Text.repeat self count=1 = 0.up_to count . fold "" acc-> _-> acc + self -## ALIAS first, last, left, right, mid, substring +## ALIAS first, last, left, right, mid, substring, slice Creates a new Text by selecting the specified range of the input. This can select a section of text from the beginning, end, or middle of the diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Helpers.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Helpers.enso index ef6c323d638..9b046dced94 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Helpers.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Helpers.enso @@ -1,8 +1,6 @@ -from Standard.Base import all - import project.Any.Any -import project.Data.Locale.Locale -import project.Data.Text.Case_Sensitivity.Case_Sensitivity +import project.Data.Text.Text +import project.Error.Error import project.Errors.Common.Type_Error import project.Meta diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso index 34907d65c09..954d2998efa 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso @@ -314,6 +314,54 @@ type Date end_of : Date_Period -> Date end_of self period=Date_Period.Month = period.adjust_end self + ## Returns the next date adding the `Date_Period` to self. + + Produces a warning for a Date that is before epoch start. + See `Date_Time.enso_epoch_start`. + + Arguments: + - period: the period to add to self. + next : Date_Period -> Date + next self period=Date_Period.Day = self + period.to_period + + ## Returns the previous date subtracting the `Date_Period` from self. + + Produces a warning for a Date that is before epoch start. + See `Date_Time.enso_epoch_start`. + + Arguments: + - period: the period to add to self. + previous : Date_Period -> Date + previous self period=Date_Period.Day = self - period.to_period + + ## Creates a `Period` between self and the provided end date. + + Produces a warning for a Date that is before epoch start. + See `Date_Time.enso_epoch_start`. + + Arguments: + - end: the end date of the interval to count workdays in. + until : Date -> Period + until self end = + ensure_in_epoch self <| ensure_in_epoch end <| + Period.between self end + + ## Counts the days between self (inclusive) and the provided end date + (exclusive). + + Produces a warning for a Date that is before epoch start. + See `Date_Time.enso_epoch_start`. + + Arguments: + - end: the end date of the interval to count workdays in. + - include_end_date: whether to include the end date in the count. + By default the end date is not included in the interval. + days_until : Date -> Boolean -> Integer + days_until self end include_end_date=False = + if end < self then -(end.days_until self include_end_date) else + ensure_in_epoch self <| ensure_in_epoch end <| + (Time_Utils.days_between self end) + if include_end_date then 1 else 0 + ## Counts workdays between self (inclusive) and the provided end date (exclusive). @@ -331,7 +379,7 @@ type Date end-exclusive manner), by default the end date is not included in the count. This has the nice property that for example to count the work days within the next week you can do - `date.work_days_until (date + (Period.new days=7)` and it will look at + `date.work_days_until (date + (Period.new days=7))` and it will look at the 7 days starting from the current `date` and not 8 days. This also gives us a property that `date.work_days_until (date.add_work_days N) == N` for any non-negative diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso index 0df833bbeb1..4eab0356cb2 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso @@ -1,4 +1,5 @@ import project.Data.Time.Date.Date +import project.Data.Time.Period.Period import project.Data.Time.Date_Time.Date_Time import project.Data.Time.Day_Of_Week.Day_Of_Week from project.Data.Boolean import Boolean, True, False @@ -22,6 +23,8 @@ type Date_Period to any other day. Week (first_day:Day_Of_Week = Day_Of_Week.Monday) + Day + ## PRIVATE This method could be replaced with matching on `Date_Period` supertype if/when that is supported. @@ -36,14 +39,25 @@ type Date_Period Date_Period.Quarter -> Date_Period_Utils.quarter_start Date_Period.Month -> TemporalAdjusters.firstDayOfMonth Date_Period.Week first_day -> TemporalAdjusters.previousOrSame first_day.to_java + Date_Period.Day -> Date_Period_Utils.day_start (Time_Utils.utils_for date).apply_adjuster date adjuster ## PRIVATE adjust_end : (Date | Date_Time) -> (Date | Date_Time) - adjust_end self date = + adjust_end self date = if self == Date_Period.Day then date else adjuster = case self of Date_Period.Year -> TemporalAdjusters.lastDayOfYear Date_Period.Quarter -> Date_Period_Utils.quarter_end Date_Period.Month -> TemporalAdjusters.lastDayOfMonth Date_Period.Week first_day -> Date_Period_Utils.end_of_week first_day.to_java + Date_Period.Day -> Date_Period_Utils.day_end (Time_Utils.utils_for date).apply_adjuster date adjuster + + ## PRIVATE + to_period : Period + to_period self = case self of + Date_Period.Year -> Period.new years=1 + Date_Period.Quarter -> Period.new months=3 + Date_Period.Month -> Period.new months=1 + Date_Period.Week _ -> Period.new days=7 + Date_Period.Day -> Period.new days=1 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso index ed1daadba25..cc2fbab1670 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso @@ -1,10 +1,12 @@ import project.Any.Any +import project.Data.Json.JS_Object import project.Data.Numbers.Integer import project.Data.Ordering.Comparable import project.Data.Text.Extensions import project.Data.Text.Text import project.Data.Time.Date.Date import project.Data.Time.Duration.Duration +import project.Data.Vector.Vector import project.Error.Error import project.Errors.Illegal_Argument.Illegal_Argument import project.Errors.Time_Error.Time_Error @@ -144,3 +146,20 @@ type Period m = if months == 0 && (y=="" || d=="") then "" else months.to_text + "M " (y + m + d) . trim + + ## PRIVATE + Convert to a JavaScript Object representing a Period. + + > Example + Convert a period of 10 months to a JS_Object. + + example_to_json = (Period.new months=10).to_js_object + to_js_object : JS_Object + to_js_object self = + b = Vector.new_builder 7 + b.append ["type", "Period"] + b.append ["constructor", "new"] + if self.years==0 . not then b.append ["years", self.years] + if self.months==0 . not then b.append ["months", self.months] + if self.days==0 . not then b.append ["days", self.days] + JS_Object.from_pairs b.to_vector diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File_Format.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File_Format.enso index 292b5502706..a92f9aff7d2 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File_Format.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File_Format.enso @@ -45,7 +45,7 @@ format_widget : Single_Choice format_widget = all_types = [Auto_Detect] + format_types make_ctor type_obj = - type_name = Meta.get_qualified_type_name type_obj + type_name = Meta.get_simple_type_name type_obj ctors = Meta.meta type_obj . constructors is_singleton_type = ctors.length == 0 if is_singleton_type then type_name else diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso index 8c355eedf35..7173af43bc8 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso @@ -8,7 +8,7 @@ import Standard.Base.Errors.Illegal_Argument.Illegal_Argument import Standard.Base.Errors.Illegal_State.Illegal_State import Standard.Base.Errors.Unimplemented.Unimplemented -from Standard.Table import Auto_Detect, Aggregate_Column, Data_Formatter, Column_Selector, Sort_Column, Match_Columns, Position, Set_Mode, Auto, Value_Type +from Standard.Table import Aggregate_Column, Data_Formatter, Column_Selector, Sort_Column, Match_Columns, Position, Set_Mode, Auto, Value_Type import Standard.Table.Data.Expression.Expression import Standard.Table.Data.Expression.Expression_Error import Standard.Table.Data.Join_Condition.Join_Condition @@ -23,6 +23,7 @@ import Standard.Table.Internal.Java_Exports import Standard.Table.Internal.Table_Helpers import Standard.Table.Internal.Table_Helpers.Table_Column_Helper import Standard.Table.Internal.Problem_Builder.Problem_Builder +import Standard.Table.Internal.Unique_Name_Strategy.Unique_Name_Strategy import Standard.Table.Internal.Widget_Helpers from Standard.Table.Data.Column import get_item_string, normalize_string_for_display from Standard.Table.Data.Table import print_table @@ -187,6 +188,7 @@ type Table table.select_columns [-1, 0, 1] reorder=True Icon: select_column + @columns Widget_Helpers.make_column_name_vector_selector select_columns : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Boolean -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | Column_Indexes_Out_Of_Range select_columns self (columns = [0]) (reorder = False) (error_on_missing_columns = True) (on_problems = Report_Warning) = new_columns = self.columns_helper.select_columns selectors=columns reorder=reorder error_on_missing_columns=error_on_missing_columns on_problems=on_problems @@ -239,6 +241,7 @@ type Table Remove the first two columns and the last column. table.remove_columns [-1, 0, 1] + @columns Widget_Helpers.make_column_name_vector_selector remove_columns : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | Column_Indexes_Out_Of_Range remove_columns self (columns = [0]) (error_on_missing_columns = False) (on_problems = Report_Warning) = new_columns = self.columns_helper.remove_columns selectors=columns error_on_missing_columns=error_on_missing_columns on_problems=on_problems @@ -294,6 +297,7 @@ type Table Move the first column to back. table.reorder_columns [0] position=Position.After_Other_Columns + @columns Widget_Helpers.make_column_name_vector_selector reorder_columns : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Position -> Boolean -> Problem_Behavior -> Table ! Missing_Input_Columns | Column_Indexes_Out_Of_Range reorder_columns self (columns = [0]) (position = Position.Before_Other_Columns) (error_on_missing_columns = False) (on_problems = Report_Warning) = new_columns = self.columns_helper.reorder_columns selectors=columns position=position error_on_missing_columns on_problems=on_problems @@ -617,6 +621,7 @@ type Table double_inventory = table.at "total_stock" * 2 table.set double_inventory new_name="total_stock" table.set "2 * [total_stock]" new_name="total_stock_expr" + @new_name Widget_Helpers.make_column_name_selector set : Column | Text -> Text | Nothing -> Set_Mode -> Problem_Behavior -> Table ! Unsupported_Name | Existing_Column | Missing_Column | No_Such_Column | Expression_Error set self column new_name=Nothing set_mode=Set_Mode.Add_Or_Update on_problems=Report_Warning = resolved = case column of @@ -794,6 +799,7 @@ type Table Sort the table by columns whose names start with letter `a`. table.order_by [(Sort_Column.Select_By_Name "a.*" use_regex=True case_sensitivity=Case_Sensitivity.Insensitive)] + @columns Widget_Helpers.make_order_by_selector order_by : Text | Sort_Column | Vector (Text | Sort_Column) -> Text_Ordering -> Boolean -> Problem_Behavior -> Table ! Incomparable_Values | No_Input_Columns_Selected | Missing_Input_Columns | Column_Indexes_Out_Of_Range order_by self (columns = ([(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering.Default error_on_missing_columns=True on_problems=Problem_Behavior.Report_Warning = Panic.handle_wrapped_dataflow_error <| problem_builder = Problem_Builder.new error_on_missing_columns=error_on_missing_columns types_to_always_throw=[No_Input_Columns_Selected] @@ -843,6 +849,7 @@ type Table - If floating points values are present in the distinct columns, a `Floating_Point_Equality` is reported according to the `on_problems` setting. + @columns Widget_Helpers.make_column_name_vector_selector distinct : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Case_Sensitivity -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | No_Input_Columns_Selected | Floating_Point_Equality distinct self columns=self.column_names case_sensitivity=Case_Sensitivity.Default error_on_missing_columns=True on_problems=Report_Warning = key_columns = self.columns_helper.select_columns selectors=columns reorder=True error_on_missing_columns=error_on_missing_columns on_problems=on_problems . catch No_Output_Columns _-> @@ -855,12 +862,15 @@ type Table Arguments: - right: The table to join with. - - join_kind: The `Join_Kind` for the joining the two tables. + - join_kind: The `Join_Kind` for the joining the two tables. It defaults + to `Left_Outer`. - on: A single condition or a common column name, or a list thereof, on which to correlate rows from the two tables. If multiple conditions are supplied, rows are correlated only if all are true. If common column names are provided, these columns should be present in both tables and an equality condition is added for each of them. + By default, the join is performed on the first column of the left table + correlated with a column in the right table with the same name. - right_prefix: The prefix added to right table column names in case of name conflict. - on_problems: Specifies how to handle problems if they occur, reporting @@ -908,10 +918,9 @@ type Table allows to join the two tables on equality of corresponding columns with the same name. So `table.join other on=["A", "B"]` is a shorthand for: table.join other on=[Join_Condition.Equals "A" "A", Join_Condition.Equals "B" "B"] - @join_kind Widget_Helpers.join_kind_selector @on Widget_Helpers.make_column_name_selector join : Table -> Join_Kind -> Join_Condition | Text | Vector (Join_Condition | Text) -> Text -> Problem_Behavior -> Table - join self right join_kind=Join_Kind.Inner on=[Join_Condition.Equals 0 0] right_prefix="Right_" on_problems=Report_Warning = + join self right join_kind=Join_Kind.Left_Outer on=[Join_Condition.Equals self.column_names.first] right_prefix="Right " on_problems=Report_Warning = can_proceed = if Table_Helpers.is_table right . not then Error.throw (Type_Error.Error Table right "right") else same_backend = case right of _ : Table -> True @@ -996,7 +1005,7 @@ type Table example, by sorting the table; in-memory tables will keep the memory layout order while for database tables the order may be unspecified). cross_join : Table -> Integer | Nothing -> Text -> Problem_Behavior -> Table - cross_join self right right_row_limit=100 right_prefix="Right_" on_problems=Report_Warning = + cross_join self right right_row_limit=100 right_prefix="Right " on_problems=Report_Warning = _ = [right, right_row_limit, right_prefix, on_problems] Error.throw (Unsupported_Database_Operation.Error "Table.cross_join is not implemented yet for the Database backends.") @@ -1045,7 +1054,7 @@ type Table order of columns is undefined and the operation will fail, reporting a `Undefined_Column_Order` problem and returning an empty table. zip : Table -> Boolean | Report_Unmatched -> Text -> Problem_Behavior -> Table - zip self right keep_unmatched=Report_Unmatched right_prefix="Right_" on_problems=Report_Warning = + zip self right keep_unmatched=Report_Unmatched right_prefix="Right " on_problems=Report_Warning = _ = [right, keep_unmatched, right_prefix, on_problems] Error.throw (Unsupported_Database_Operation.Error "Table.zip is not implemented yet for the Database backends.") @@ -1340,6 +1349,7 @@ type Table - If any column names in the new table are clashing, a `Duplicate_Output_Column_Names` is reported according to the `on_problems` setting. + @id_fields Widget_Helpers.make_column_name_vector_selector transpose : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Text -> Text -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | Column_Indexes_Out_Of_Range | Duplicate_Output_Column_Names transpose self id_fields=[] (name_field="Name") (value_field="Value") (error_on_missing_columns=True) (on_problems = Report_Warning) = ## Avoid unused arguments warning. We cannot rename arguments to `_`, @@ -1382,6 +1392,9 @@ type Table an `Unquoted_Delimiter` - If there are more than 10 issues with a single column, an `Additional_Warnings`. + @group_by Widget_Helpers.make_column_name_vector_selector + @name_column Widget_Helpers.make_column_name_selector + @values (Widget_Helpers.make_aggregate_column_selector include_group_by=False) cross_tab : Aggregate_Column | Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector | Aggregate_Column) -> (Text | Integer | Column) -> Vector Aggregate_Column -> Problem_Behavior -> Table ! Missing_Input_Columns | Column_Indexes_Out_Of_Range | Invalid_Aggregate_Column | Floating_Point_Equality | Invalid_Aggregation | Unquoted_Delimiter | Additional_Warnings cross_tab self group_by=[] name_column=self.column_names.first values=Aggregate_Column.Count (on_problems=Report_Warning) = ## Avoid unused arguments warning. We cannot rename arguments to `_`, @@ -1392,6 +1405,8 @@ type Table ## Parsing values is not supported in database tables, the table has to be loaded into memory first with `read`. + @type Widget_Helpers.parse_type_selector + @columns Widget_Helpers.make_column_name_vector_selector parse : Text | Integer | Column_Selector | Vector (Text | Integer | Column_Selector) -> Value_Type | Auto -> Text | Data_Formatter -> Boolean -> Problem_Behavior -> Table parse columns=(self.columns . filter (c-> c.value_type.is_text) . map .name) type=Auto format=Data_Formatter.Value error_on_missing_columns=True on_problems=Report_Warning = ## Avoid unused arguments warning. We cannot rename arguments to `_`, @@ -1415,6 +1430,7 @@ type Table ! Error Conditions If the data exceeds the `column_count`, a `Column_Count_Exceeded` will be reported according to the `on_problems` behavior. + @column Widget_Helpers.make_column_name_selector split_to_columns : Text | Integer -> Text -> Integer | Nothing -> Problem_Behavior -> Table split_to_columns self column delimiter="," column_count=Nothing on_problems=Report_Error = _ = [column delimiter column_count on_problems] @@ -1426,6 +1442,7 @@ type Table Arguments: - column: The name or index of the column to split the text of. - delimiter: The term or terms used to split the text. + @column Widget_Helpers.make_column_name_selector split_to_rows : Text | Integer -> Text -> Table split_to_rows self column delimiter="," = _ = [column delimiter] @@ -1451,6 +1468,7 @@ type Table ! Error Conditions If the data exceeds the `column_count`, a `Column_Count_Exceeded` will be reported according to the `on_problems` behavior. + @column Widget_Helpers.make_column_name_selector tokenize_to_columns : Text | Integer -> Text -> Case_Sensitivity -> Integer | Nothing -> Problem_Behavior -> Table tokenize_to_columns self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive column_count=Nothing on_problems=Report_Error = _ = [column pattern case_sensitivity column_count on_problems] @@ -1470,6 +1488,7 @@ type Table - at_least_one_row: If True, a tokenization that returns no values will still produce at least one row, with `Nothing` for the output column values. Equivalent to converting a tokenization output of [] to [Nothing]. + @column Widget_Helpers.make_column_name_selector tokenize_to_rows : Text | Integer -> Text -> Case_Sensitivity -> Boolean -> Table tokenize_to_rows self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive at_least_one_row=False = _ = [column, pattern, case_sensitivity, at_least_one_row] @@ -1499,6 +1518,7 @@ type Table will be named ` ` where `N` is the number of the marked group. If the new name is already in use it will be renamed following the normal suffixing strategy. + @column Widget_Helpers.make_column_name_selector parse_to_columns : Text | Integer -> Text -> Case_Sensitivity -> Boolean -> Problem_Behavior -> Table parse_to_columns self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive parse_values=True on_problems=Report_Error = _ = [column, pattern, case_sensitivity, parse_values, on_problems] @@ -1554,6 +1574,7 @@ type Table If the backend does not support the requested target type, the closest supported type is chosen and a `Inexact_Type_Coercion` problem is reported. + @columns Widget_Helpers.make_column_name_vector_selector cast : (Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector)) -> Value_Type -> Problem_Behavior -> Table ! Illegal_Argument | Inexact_Type_Coercion | Lossy_Conversion cast self columns=[0] value_type=Value_Type.Char on_problems=Problem_Behavior.Report_Warning = selected = self.select_columns columns @@ -1593,9 +1614,7 @@ type Table table = self.connection.read_statement sql table.at column_name . at 0 - ## UNSTABLE - - Returns a materialized dataframe containing rows of this table. + ## Returns a materialized dataframe containing rows of this table. Arguments: - max_rows: specifies a maximum amount of rows to fetch; if not set, all @@ -1859,16 +1878,9 @@ display_dataframe df indices_count all_rows_count format_terminal = is, otherwise numerical suffixes are added. fresh_names : Vector Text -> Vector Text -> Vector Text fresh_names used_names preferred_names = - freshen currently_used name ix = - new_name = if ix == 0 then name else name+"_"+ix.to_text - case currently_used.contains new_name of - False -> new_name - True -> freshen currently_used name ix+1 - res = preferred_names . fold [used_names, []] acc-> name-> - used = acc.first - new_name = freshen used name 0 - [used_names + [new_name], acc.second + [new_name]] - res.second + unique = Unique_Name_Strategy.new + unique.mark_used used_names + unique.make_all_unique preferred_names ## PRIVATE diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Main.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Main.enso index 6986f97ec3a..66e8fec763b 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Main.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Main.enso @@ -6,6 +6,7 @@ import project.Connection.Database import project.Connection.Postgres_Details.Postgres_Details import project.Connection.SQLite_Details.SQLite_Details import project.Connection.SQLite_Details.In_Memory +import project.Connection.SQLite_Format.SQLite_Format import project.Connection.SSL_Mode.SSL_Mode import project.Data.SQL_Query.SQL_Query import project.Extensions.Upload_Table @@ -21,6 +22,7 @@ export project.Connection.Database export project.Connection.Postgres_Details.Postgres_Details export project.Connection.SQLite_Details.SQLite_Details export project.Connection.SQLite_Details.In_Memory +export project.Connection.SQLite_Format.SQLite_Format export project.Connection.SSL_Mode.SSL_Mode export project.Data.SQL_Query.SQL_Query export project.Extensions.Upload_Table 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 49dae0ee81b..44210006552 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 @@ -311,6 +311,7 @@ type Table table.select_columns [-1, 0, 1] reorder=True Icon: select_column + @columns Widget_Helpers.make_column_name_vector_selector select_columns : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Boolean -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | Column_Indexes_Out_Of_Range select_columns self columns=[0] (reorder = False) (error_on_missing_columns = True) (on_problems = Report_Warning) = new_columns = self.columns_helper.select_columns selectors=columns reorder=reorder error_on_missing_columns=error_on_missing_columns on_problems=on_problems @@ -363,7 +364,7 @@ type Table Remove the first two columns and the last column. table.remove_columns [-1, 0, 1] - + @columns Widget_Helpers.make_column_name_vector_selector remove_columns : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | Column_Indexes_Out_Of_Range remove_columns self (columns=[0]) (error_on_missing_columns = False) (on_problems = Report_Warning) = new_columns = self.columns_helper.remove_columns selectors=columns error_on_missing_columns=error_on_missing_columns on_problems=on_problems @@ -419,7 +420,7 @@ type Table Move the first column to back. table.reorder_columns [0] position=Position.After_Other_Columns - + @columns Widget_Helpers.make_column_name_vector_selector reorder_columns : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Position -> Boolean -> Problem_Behavior -> Table ! Missing_Input_Columns | Column_Indexes_Out_Of_Range reorder_columns self (columns = [0]) (position = Position.Before_Other_Columns) (error_on_missing_columns = False) (on_problems = Report_Warning) = new_columns = self.columns_helper.reorder_columns selectors=columns position=position error_on_missing_columns=error_on_missing_columns on_problems=on_problems @@ -681,6 +682,7 @@ type Table Sort the table by columns whose names start with letter `a`. table.order_by [(Sort_Column.Select_By_Name "a.*" use_regex=True case_sensitivity=Case_Sensitivity.Insensitive)] + @columns Widget_Helpers.make_order_by_selector order_by : Text | Sort_Column | Vector (Text | Sort_Column) -> Text_Ordering -> Boolean -> Problem_Behavior -> Table ! Incomparable_Values | No_Input_Columns_Selected | Missing_Input_Columns | Column_Indexes_Out_Of_Range order_by self (columns = ([(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering.Default error_on_missing_columns=True on_problems=Problem_Behavior.Report_Warning = problem_builder = Problem_Builder.new error_on_missing_columns=error_on_missing_columns types_to_always_throw=[No_Input_Columns_Selected] @@ -739,6 +741,7 @@ type Table - If floating points values are present in the distinct columns, a `Floating_Point_Equality` is reported according to the `on_problems` setting. + @columns Widget_Helpers.make_column_name_vector_selector distinct : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Case_Sensitivity -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | No_Input_Columns_Selected | Floating_Point_Equality distinct self (columns = self.column_names) case_sensitivity=Case_Sensitivity.Default error_on_missing_columns=True on_problems=Report_Warning = key_columns = self.columns_helper.select_columns selectors=columns reorder=True error_on_missing_columns=error_on_missing_columns on_problems=on_problems . catch No_Output_Columns _-> @@ -833,6 +836,8 @@ type Table Parse all columns inferring their types, using `,` as the decimal point for numbers. table.parse format=(Data_Formatter.Value.with_number_formatting decimal_point=',') + @type Widget_Helpers.parse_type_selector + @columns Widget_Helpers.make_column_name_vector_selector parse : Text | Integer | Column_Selector | Vector (Text | Integer | Column_Selector) -> Value_Type | Auto -> Text | Data_Formatter -> Boolean -> Problem_Behavior -> Table parse self columns=(self.columns . filter (c-> c.value_type.is_text) . map .name) type=Auto format=Data_Formatter.Value error_on_missing_columns=True on_problems=Report_Warning = formatter = case format of @@ -918,6 +923,7 @@ type Table If the backend does not support the requested target type, the closest supported type is chosen and a `Inexact_Type_Coercion` problem is reported. + @columns Widget_Helpers.make_column_name_vector_selector cast : (Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector)) -> Value_Type -> Problem_Behavior -> Table ! Illegal_Argument | Inexact_Type_Coercion | Lossy_Conversion cast self columns=[0] value_type=Value_Type.Char on_problems=Problem_Behavior.Report_Warning = _ = [columns, value_type, on_problems] @@ -939,6 +945,7 @@ type Table ! Error Conditions If the data exceeds the `column_count`, a `Column_Count_Exceeded` will be reported according to the `on_problems` behavior. + @column Widget_Helpers.make_column_name_selector split_to_columns : Text | Integer -> Text -> Integer | Nothing -> Problem_Behavior -> Table split_to_columns self column delimiter="," column_count=Nothing on_problems=Report_Error = Split_Tokenize.split_to_columns self column delimiter column_count on_problems @@ -949,6 +956,7 @@ type Table Arguments: - column: The name or index of the column to split the text of. - delimiter: The term or terms used to split the text. + @column Widget_Helpers.make_column_name_selector split_to_rows : Text | Integer -> Text -> Table split_to_rows self column delimiter="," = Split_Tokenize.split_to_rows self column delimiter @@ -973,6 +981,7 @@ type Table ! Error Conditions If the data exceeds the `column_count`, a `Column_Count_Exceeded` will be reported according to the `on_problems` behavior. + @column Widget_Helpers.make_column_name_selector tokenize_to_columns : Text | Integer -> Text -> Case_Sensitivity -> Integer | Nothing -> Problem_Behavior -> Table tokenize_to_columns self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive column_count=Nothing on_problems=Report_Error = Split_Tokenize.tokenize_to_columns self column pattern case_sensitivity column_count on_problems @@ -991,6 +1000,7 @@ type Table - at_least_one_row: If True, a tokenization that returns no values will still produce at least one row, with `Nothing` for the output column values. Equivalent to converting a tokenization output of [] to [Nothing]. + @column Widget_Helpers.make_column_name_selector tokenize_to_rows : Text | Integer -> Text -> Case_Sensitivity -> Boolean -> Table tokenize_to_rows self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive at_least_one_row=False = Split_Tokenize.tokenize_to_rows self column pattern case_sensitivity at_least_one_row @@ -1019,6 +1029,7 @@ type Table will be named ` ` where `N` is the number of the marked group. If the new name is already in use it will be renamed following the normal suffixing strategy. + @column Widget_Helpers.make_column_name_selector parse_to_columns : Text | Integer -> Text -> Case_Sensitivity -> Boolean -> Problem_Behavior -> Table parse_to_columns self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive parse_values=True on_problems=Report_Error = Split_Tokenize.parse_to_columns self column pattern case_sensitivity parse_values on_problems @@ -1208,6 +1219,7 @@ type Table double_inventory = table.at "total_stock" * 2 table.set double_inventory new_name="total_stock" table.set "2 * [total_stock]" new_name="total_stock_expr" + @new_name Widget_Helpers.make_column_name_selector set : Column | Text -> Text | Nothing -> Set_Mode -> Problem_Behavior -> Table ! Existing_Column | Missing_Column | No_Such_Column | Expression_Error set self column new_name=Nothing set_mode=Set_Mode.Add_Or_Update on_problems=Report_Warning = resolved = case column of @@ -1322,12 +1334,15 @@ type Table Arguments: - right: The table to join with. - - join_kind: The `Join_Kind` for the joining the two tables. + - join_kind: The `Join_Kind` for the joining the two tables. It defaults + to `Left_Outer`. - on: A single condition or a common column name, or a list thereof, on which to correlate rows from the two tables. If multiple conditions are supplied, rows are correlated only if all are true. If common column names are provided, these columns should be present in both tables and an equality condition is added for each of them. + By default, the join is performed on the first column of the left table + correlated with a column in the right table with the same name. - right_prefix: The prefix added to right table column names in case of name conflict. - on_problems: Specifies how to handle problems if they occur, reporting @@ -1375,10 +1390,9 @@ type Table allows to join the two tables on equality of corresponding columns with the same name. So `table.join other on=["A", "B"]` is a shorthand for: table.join other on=[Join_Condition.Equals "A" "A", Join_Condition.Equals "B" "B"] - @join_kind Widget_Helpers.join_kind_selector @on Widget_Helpers.make_column_name_selector join : Table -> Join_Kind -> Join_Condition | Text | Vector (Join_Condition | Text) -> Text -> Problem_Behavior -> Table - join self right join_kind=Join_Kind.Inner on=[Join_Condition.Equals 0 0] right_prefix="Right_" on_problems=Report_Warning = + join self right join_kind=Join_Kind.Left_Outer on=[Join_Condition.Equals self.column_names.first] right_prefix="Right " on_problems=Report_Warning = if check_table "right" right then # [left_unmatched, matched, right_unmatched] rows_to_keep = case join_kind of @@ -1439,7 +1453,7 @@ type Table example, by sorting the table; in-memory tables will keep the memory layout order while for database tables the order may be unspecified). cross_join : Table -> Integer | Nothing -> Text -> Problem_Behavior -> Table - cross_join self right right_row_limit=100 right_prefix="Right_" on_problems=Report_Warning = + cross_join self right right_row_limit=100 right_prefix="Right " on_problems=Report_Warning = if check_table "right" right then limit_problems = case right_row_limit.is_nothing.not && (right.row_count > right_row_limit) of True -> @@ -1495,7 +1509,7 @@ type Table order of columns is undefined and the operation will fail, reporting a `Undefined_Column_Order` problem and returning an empty table. zip : Table -> Boolean | Report_Unmatched -> Text -> Problem_Behavior -> Table - zip self right keep_unmatched=Report_Unmatched right_prefix="Right_" on_problems=Report_Warning = + zip self right keep_unmatched=Report_Unmatched right_prefix="Right " on_problems=Report_Warning = if check_table "right" right then keep_unmatched_bool = case keep_unmatched of Report_Unmatched -> True @@ -1694,6 +1708,7 @@ type Table - If any column names in the new table are clashing, a `Duplicate_Output_Column_Names` is reported according to the `on_problems` setting. + @id_fields Widget_Helpers.make_column_name_vector_selector transpose : Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector) -> Text -> Text -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns | Column_Indexes_Out_Of_Range | Duplicate_Output_Column_Names transpose self (id_fields = []) (name_field="Name") (value_field="Value") (error_on_missing_columns=True) (on_problems = Report_Warning) = columns_helper = self.columns_helper @@ -1749,7 +1764,10 @@ type Table an `Unquoted_Delimiter` - If there are more than 10 issues with a single column, an `Additional_Warnings`. - cross_tab : Aggregate_Column | Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector | Aggregate_Column) -> (Text | Integer) -> Vector Aggregate_Column -> Problem_Behavior -> Table ! Missing_Input_Columns | Column_Indexes_Out_Of_Range | Invalid_Aggregate_Column | Floating_Point_Equality | Invalid_Aggregation | Unquoted_Delimiter | Additional_Warnings + @group_by Widget_Helpers.make_column_name_vector_selector + @name_column Widget_Helpers.make_column_name_selector + @values (Widget_Helpers.make_aggregate_column_selector include_group_by=False) + cross_tab : Aggregate_Column | Text | Integer | Column_Selector | Vector (Integer | Text | Column_Selector | Aggregate_Column) -> (Text | Integer) -> Aggregate_Column | Vector Aggregate_Column -> Problem_Behavior -> Table ! Missing_Input_Columns | Column_Indexes_Out_Of_Range | Invalid_Aggregate_Column | Floating_Point_Equality | Invalid_Aggregation | Unquoted_Delimiter | Additional_Warnings cross_tab self group_by=[] name_column=self.column_names.first values=Aggregate_Column.Count (on_problems=Report_Warning) = columns_helper = self.columns_helper problem_builder = Problem_Builder.new error_on_missing_columns=True diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Format.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Format.enso index d2b8799dc71..67910e938f2 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Format.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Format.enso @@ -49,7 +49,7 @@ type Delimited_Format character if it anywhere else than at the beginning of the line. This option is only applicable for read mode and does not affect writing. It defaults to `Nothing` which means that comments are disabled. - Delimited (delimiter:Text) (encoding:Encoding=Encoding.utf_8) (skip_rows:Integer=0) (row_limit:Integer|Nothing=Nothing) (quote_style:Quote_Style=Quote_Style.With_Quotes) (headers:Boolean|Infer=Infer) (value_formatter:Data_Formatter|Nothing=Data_Formatter.Value) (keep_invalid_rows:Boolean=True) (line_endings:Line_Ending_Style=Infer) (comment_character:Text|Nothing=Nothing) + Delimited (delimiter:Text=',') (encoding:Encoding=Encoding.utf_8) (skip_rows:Integer=0) (row_limit:Integer|Nothing=Nothing) (quote_style:Quote_Style=Quote_Style.With_Quotes) (headers:Boolean|Infer=Infer) (value_formatter:Data_Formatter|Nothing=Data_Formatter.Value) (keep_invalid_rows:Boolean=True) (line_endings:Line_Ending_Style=Infer) (comment_character:Text|Nothing=Nothing) ## PRIVATE ADVANCED diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso index 33a1dd505f5..ad9fcbeea23 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso @@ -12,14 +12,17 @@ polyglot java import org.enso.table.error.EmptySheetException type Missing_Input_Columns ## PRIVATE One or more columns not found in the input table. - Error (criteria : [Text]) + Error (criteria : [Text]) (where:Text|Nothing = Nothing) ## PRIVATE Convert a missing input error to a human-readable form. to_display_text : Text to_display_text self = - "The criteria "+self.criteria.to_text+" did not match any columns." + where = case self.where of + Nothing -> "." + location : Text -> " in "+location+"." + "The criteria "+self.criteria.to_text+" did not match any columns"+where type Column_Indexes_Out_Of_Range ## PRIVATE diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Join_Helpers.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Join_Helpers.enso index 313ac6a9c70..abdd958ea67 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Join_Helpers.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Join_Helpers.enso @@ -23,9 +23,10 @@ type Join_Condition_Resolver resolve : Join_Condition | Text | Vector (Join_Condition | Text) -> Problem_Behavior -> Join_Condition_Resolution resolve self conditions on_problems = redundant_names = Vector.new_builder - problem_builder = Problem_Builder.new types_to_always_throw=[Missing_Input_Columns, Column_Indexes_Out_Of_Range] + left_problem_builder = Problem_Builder.new missing_input_columns_location="the left table" types_to_always_throw=[Missing_Input_Columns, Column_Indexes_Out_Of_Range] + right_problem_builder = Problem_Builder.new missing_input_columns_location="the right table" types_to_always_throw=[Missing_Input_Columns, Column_Indexes_Out_Of_Range] - resolve_selector resolver selector = + resolve_selector problem_builder resolver selector = r_1 = resolver selector r_2 = r_1.catch No_Such_Column _-> problem_builder.report_missing_input_columns [selector] @@ -33,9 +34,10 @@ type Join_Condition_Resolver r_2.catch Index_Out_Of_Bounds _-> problem_builder.report_oob_indices [selector] Nothing - resolve_left = resolve_selector self.left_at - resolve_right = resolve_selector self.right_at + resolve_left = resolve_selector left_problem_builder self.left_at + resolve_right = resolve_selector right_problem_builder self.right_at + problem_builder = Problem_Builder.new is_nothing column = case column of Nothing -> True _ -> False @@ -70,7 +72,12 @@ type Join_Condition_Resolver Value_Type.expect_comparable left right_lower <| Value_Type.expect_comparable left right_upper <| self.make_between problem_builder left right_lower right_upper - problem_builder.attach_problems_before on_problems <| + attach_problems ~result = + left_problem_builder.attach_problems_before on_problems <| + right_problem_builder.attach_problems_before on_problems <| + problem_builder.attach_problems_before on_problems <| + result + attach_problems <| if converted.contains Nothing then Panic.throw (Illegal_State.Error "Impossible: unresolved columns remaining in the join resolution. This should have raised a dataflow error. This is a bug in the Table library.") else Join_Condition_Resolution.Result converted redundant_names.to_vector diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Problem_Builder.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Problem_Builder.enso index c90d924b277..2c668f40a80 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Problem_Builder.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Problem_Builder.enso @@ -8,7 +8,7 @@ from project.Errors import Missing_Input_Columns, Column_Indexes_Out_Of_Range, D ## PRIVATE type Problem_Builder ## PRIVATE - Value types_to_always_throw oob_indices missing_input_columns other + Value types_to_always_throw oob_indices missing_input_columns missing_input_columns_location other ## PRIVATE report_oob_indices self indices = @@ -39,7 +39,7 @@ type Problem_Builder if vec.not_empty then problems.append (problem_creator vec) - build_vector_and_append self.missing_input_columns Missing_Input_Columns.Error + build_vector_and_append self.missing_input_columns (Missing_Input_Columns.Error _ where=self.missing_input_columns_location) build_vector_and_append self.oob_indices Column_Indexes_Out_Of_Range.Error self.other.to_vector.each problems.append @@ -91,10 +91,12 @@ type Problem_Builder methods regardless of the `Problem_Behavior` used. Defaults to `False`. Setting this to `True` is essentially a shorthand for adding these two problem types to `types_to_always_throw`. + - missing_input_columns_location: The location to add to the missing + input column error to make it more informative. Defaults to `Nothing`. new : Vector -> Boolean -> Problem_Builder - new types_to_always_throw=[] error_on_missing_columns=False = + new types_to_always_throw=[] error_on_missing_columns=False missing_input_columns_location=Nothing = additional_types_to_throw = if error_on_missing_columns then [Missing_Input_Columns, Column_Indexes_Out_Of_Range, Invalid_Aggregate_Column] else [] - Problem_Builder.Value types_to_always_throw+additional_types_to_throw (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) other=Vector.new_builder + Problem_Builder.Value types_to_always_throw+additional_types_to_throw (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) missing_input_columns_location other=Vector.new_builder ## PRIVATE Appends a `Vector` to a `Vector_Builder` stored in a `Ref`. diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Split_Tokenize.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Split_Tokenize.enso index fb2199da456..46b8ac42e53 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Split_Tokenize.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Split_Tokenize.enso @@ -173,7 +173,7 @@ fan_out_to_rows table input_column_id function at_least_one_row=False on_problem x | 12 34 56 | y ===> ... | ... | ... - foo | bar 0 | bar 1 | baz + foo | bar 1 | bar 2 | baz ----+-------+-------+---- x | 1 | 2 | y x | 3 | 4 | y @@ -367,7 +367,7 @@ repeat_each n ~action = 0.up_to n . each _-> action ## PRIVATE Name a column by appending an integer to a base column name. default_column_namer : Text -> Integer -> Text -default_column_namer base_name i = base_name + " " + i.to_text +default_column_namer base_name i = base_name + " " + (i+1).to_text ## PRIVATE Pad or truncate a vector to be a specified length; if altered, report diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Unique_Name_Strategy.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Unique_Name_Strategy.enso index 867c80966e0..853836a5189 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Unique_Name_Strategy.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Unique_Name_Strategy.enso @@ -56,10 +56,10 @@ type Unique_Name_Strategy > Example Rename names from a second list to avoid clashing with the first one. - first = ["A", "B", "second_A"] - second = ["A", "B", "second_A_1", "C"] + first = ["A", "B", "second A"] + second = ["A", "B", "second A 1", "C"] unique_second = Unique_Name_Strategy.combine_with_prefix first second "second_" - unique_second == ["second_A_2", "second_B", "second_A_1", "C"] + unique_second == ["second A 2", "second_B", "second A 1", "C"] combine_with_prefix : Vector Text -> Vector Text -> Text -> Unique_Name_Strategy combine_with_prefix self first second second_prefix = Vector.from_polyglot_array <| @@ -110,7 +110,7 @@ type Unique_Name_Strategy > Example strategy = Unique_Name_Strategy.new strategy.make_unique "A" # returns "A" - strategy.make_unique "A" # returns "A_1" + strategy.make_unique "A" # returns "A 1" make_unique : Text -> Text make_unique self name = self.deduplicator.makeUnique name diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Widget_Helpers.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Widget_Helpers.enso index c6274fca3cb..b1bfae4ab6e 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Widget_Helpers.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Widget_Helpers.enso @@ -1,16 +1,72 @@ from Standard.Base import all - -from Standard.Base.Metadata.Widget import Single_Choice +from Standard.Base.Metadata.Widget import Single_Choice, Vector_Editor from Standard.Base.Metadata.Choice import Option import Standard.Base.Metadata.Display -from project.Data.Table import Table +import project.Data.Table.Table +import project.Data.Aggregate_Column.Aggregate_Column + +## PRIVATE + Make an aggregate column selector. +make_aggregate_column_selector : Table -> Display -> Boolean -> Single_Choice +make_aggregate_column_selector table display=Display.Always include_group_by=True = + col_names_selector = make_column_name_selector table display=Display.Always + column_widget = Pair.new "column" col_names_selector + + col_list_selector = make_column_name_vector_selector table display=Display.Always + + group_by = if include_group_by then [Option "Group By" "(Aggregate_Column.Group_By)" [column_widget]] else [] + count = Option "Count" "Aggregate_Column.Count" + count_distinct = Option "Count Distinct" "(Aggregate_Column.Count_Distinct)" [Pair.new "columns" (col_list_selector)] + first = Option "First" "(Aggregate_Column.First)" [column_widget, Pair.new "order_by" (col_list_selector)] + last = Option "Last" "(Aggregate_Column.Last)" [column_widget, Pair.new "order_by" (col_list_selector)] + + count_not_nothing = Option "Count Not Nothing" "(Aggregate_Column.Count_Not_Nothing)" [column_widget] + count_nothing = Option "Count Nothing" "(Aggregate_Column.Count_Nothing)" [column_widget] + + ## Should be a list of Text columns only + count_not_empty = Option "Count Not Empty" "(Aggregate_Column.Count_Not_Empty)" [column_widget] + count_empty = Option "Count Empty" "(Aggregate_Column.Count_Empty)" [column_widget] + concatenate = Option "Concatenate" "(Aggregate_Column.Concatenate)" [column_widget] + shortest = Option "Shortest" "(Aggregate_Column.Shortest)" [column_widget] + longest = Option "Longest" "(Aggregate_Column.Longest)" [column_widget] + + ## Should be a list of Numeric columns only + sum = Option "Sum" "(Aggregate_Column.Sum)" [column_widget] + average = Option "Average" "(Aggregate_Column.Average)" [column_widget] + median = Option "Median" "(Aggregate_Column.Median)" [column_widget] + percentile = Option "Percentile" "(Aggregate_Column.Percentile)" [column_widget] + mode = Option "Mode" "(Aggregate_Column.Mode)" [column_widget] + standard_deviation = Option "Standard Deviation" "(Aggregate_Column.Standard_Deviation)" [column_widget] + + # Should be a list of comparable columns only + maximum = Option "Maximum" "(Aggregate_Column.Maximum)" [column_widget] + minimum = Option "Minimum" "(Aggregate_Column.Minimum)" [column_widget] + + Single_Choice display=display values=(group_by+[count, count_distinct, first, last, count_not_nothing, count_nothing, count_not_empty, count_empty, concatenate, shortest, longest, sum, average, median, percentile, mode, standard_deviation, maximum, minimum]) ## PRIVATE Make a column name selector. make_column_name_selector : Table -> Display -> Single_Choice make_column_name_selector table display=Display.Always = - Single_Choice display=display values=(table.column_names.map n->(Option n n.pretty)) + col_names = table.column_names + names = col_names.map n-> Option n n.pretty + Single_Choice display=display values=names + +## PRIVATE + Make a multiple column name selector. +make_column_name_vector_selector : Table -> Display -> Vector_Editor +make_column_name_vector_selector table display=Display.Always = + item_editor = make_column_name_selector table display=Display.Always + Vector_Editor item_editor=item_editor item_default=table.column_names.first.pretty display=display + +## PRIVATE + Make a column name selector. +make_order_by_selector : Table -> Display -> Single_Choice +make_order_by_selector table display=Display.Always = + col_names = table.column_names + names = col_names.fold [] c-> n-> c + [Option n+" (Asc)" n.pretty, Option n+" (Desc)" "(Sort_Column.Name "+n.pretty+" Sort_Direction.Descending)"] + Single_Choice display=display values=names ## PRIVATE Selector for type argument on `Column.parse`. @@ -21,11 +77,3 @@ parse_type_selector = options = names.zip choice . map pair-> Option pair.first pair.second Single_Choice display=Display.Always values=options -## PRIVATE - Selector for type argument on `Column.parse`. -join_kind_selector : Single_Choice -join_kind_selector = - choice = ['Join_Kind.Inner','Join_Kind.Left_Outer','Join_Kind.Right_Outer','Join_Kind.Full','Join_Kind.Left_Exclusive','Join_Kind.Right_Exclusive'] - names = ['Inner', 'Left Outer', 'Right Outer', 'Full', 'Left Exclusive', 'Right Exclusive'] - options = names.zip choice . map pair-> Option pair.first pair.second - Single_Choice display=Display.Always values=options diff --git a/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java b/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java index bf4b5f88263..48902640e92 100644 --- a/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java +++ b/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java @@ -5,6 +5,20 @@ import java.time.YearMonth; import java.time.temporal.*; public class Date_Period_Utils implements TimeUtilsBase { + private static final long NANOSECONDS_IN_DAY = 86_400_000_000_000L; + public static TemporalAdjuster day_start = + (Temporal temporal) -> { + return temporal.isSupported(ChronoField.NANO_OF_DAY) + ? temporal.with(ChronoField.NANO_OF_DAY, 0) + : temporal; + }; + + public static TemporalAdjuster day_end = + (Temporal temporal) -> { + return temporal.isSupported(ChronoField.NANO_OF_DAY) + ? temporal.with(ChronoField.NANO_OF_DAY, NANOSECONDS_IN_DAY - 1) + : temporal; + }; public static TemporalAdjuster quarter_start = (Temporal temporal) -> { diff --git a/std-bits/table/src/main/java/org/enso/table/read/DelimitedReader.java b/std-bits/table/src/main/java/org/enso/table/read/DelimitedReader.java index 82103f7c294..ff90cf4facf 100644 --- a/std-bits/table/src/main/java/org/enso/table/read/DelimitedReader.java +++ b/std-bits/table/src/main/java/org/enso/table/read/DelimitedReader.java @@ -334,7 +334,7 @@ public class DelimitedReader { private WithProblems> generateDefaultHeaders(int columnCount) { List headerNames = new ArrayList<>(columnCount); for (int i = 0; i < columnCount; ++i) { - headerNames.add(COLUMN_NAME + "_" + (i + 1)); + headerNames.add(COLUMN_NAME + " " + (i + 1)); } return new WithProblems<>(headerNames, Collections.emptyList()); } diff --git a/std-bits/table/src/main/java/org/enso/table/util/NameDeduplicator.java b/std-bits/table/src/main/java/org/enso/table/util/NameDeduplicator.java index 73f8486e9ee..b5fa13f3046 100644 --- a/std-bits/table/src/main/java/org/enso/table/util/NameDeduplicator.java +++ b/std-bits/table/src/main/java/org/enso/table/util/NameDeduplicator.java @@ -87,7 +87,7 @@ public class NameDeduplicator { if (index == 0) { return name; } - return name + "_" + index; + return name + " " + index; } public String[] getInvalidNames() { @@ -134,7 +134,7 @@ public class NameDeduplicator { String name = second.get(i); if (output.get(i) == null) { var prefixed = secondPrefix + name; - output.set(i, makeUnique(secondPrefix + name)); + output.set(i, makeUnique(prefixed)); } } return output; diff --git a/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso index 95a75f0b7c5..8f691bdeefd 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso @@ -111,9 +111,9 @@ spec setup = materialized.columns.at 0 . at 0 . should_equal 56.708660 epsilon=0.000001 materialized.columns.at 1 . name . should_equal "Standard Deviation ValueWithNothing" materialized.columns.at 1 . at 0 . should_equal 58.588610 epsilon=0.000001 - materialized.columns.at 2 . name . should_equal "Standard Deviation Value_1" + materialized.columns.at 2 . name . should_equal "Standard Deviation Value 1" materialized.columns.at 2 . at 0 . should_equal 56.697317 epsilon=0.000001 - materialized.columns.at 3 . name . should_equal "Standard Deviation ValueWithNothing_1" + materialized.columns.at 3 . name . should_equal "Standard Deviation ValueWithNothing 1" materialized.columns.at 3 . at 0 . should_equal 58.575554 epsilon=0.000001 Test.specify "should be able to create median, mode and percentile values" (pending = resolve_pending test_selection.advanced_stats) <| @@ -153,7 +153,7 @@ spec setup = materialized.column_count . should_equal 3 materialized.columns.at 0 . name . should_equal "First TextWithNothing" materialized.columns.at 0 . at 0 . should_equal "riwaiqq1io" - materialized.columns.at 1 . name . should_equal "First TextWithNothing_1" + materialized.columns.at 1 . name . should_equal "First TextWithNothing 1" materialized.columns.at 1 . at 0 . should_equal "j4i2ua7uft" materialized.columns.at 2 . name . should_equal "Last ValueWithNothing" materialized.columns.at 2 . at 0 . should_equal -38.56 epsilon=0.000001 @@ -236,7 +236,7 @@ spec setup = materialized.column_count . should_equal 2 materialized.columns.at 0 . name . should_equal "Count Distinct Code" materialized.columns.at 0 . at 0 . should_equal 0 - materialized.columns.at 1 . name . should_equal "Count Distinct Code_1" + materialized.columns.at 1 . name . should_equal "Count Distinct Code 1" materialized.columns.at 1 . at 0 . should_equal 0 Test.specify "should be able to compute sum and average of values" <| @@ -527,9 +527,9 @@ spec setup = materialized.columns.at 1 . at idx . should_equal 60.272158 epsilon=0.000001 materialized.columns.at 2 . name . should_equal "Standard Deviation ValueWithNothing" materialized.columns.at 2 . at idx . should_equal 56.798691 epsilon=0.000001 - materialized.columns.at 3 . name . should_equal "Standard Deviation Value_1" + materialized.columns.at 3 . name . should_equal "Standard Deviation Value 1" materialized.columns.at 3 . at idx . should_equal 60.156583 epsilon=0.000001 - materialized.columns.at 4 . name . should_equal "Standard Deviation ValueWithNothing_1" + materialized.columns.at 4 . name . should_equal "Standard Deviation ValueWithNothing 1" materialized.columns.at 4 . at idx . should_equal 56.677714 epsilon=0.000001 Test.specify "should be able to create median values" (pending = resolve_pending test_selection.advanced_stats) <| @@ -735,9 +735,9 @@ spec setup = materialized.columns.at 2 . at idx . should_equal 58.979275 epsilon=0.000001 materialized.columns.at 3 . name . should_equal "Standard Deviation ValueWithNothing" materialized.columns.at 3 . at idx . should_equal 57.561756 epsilon=0.000001 - materialized.columns.at 4 . name . should_equal "Standard Deviation Value_1" + materialized.columns.at 4 . name . should_equal "Standard Deviation Value 1" materialized.columns.at 4 . at idx . should_equal 58.746614 epsilon=0.000001 - materialized.columns.at 5 . name . should_equal "Standard Deviation ValueWithNothing_1" + materialized.columns.at 5 . name . should_equal "Standard Deviation ValueWithNothing 1" materialized.columns.at 5 . at idx . should_equal 57.306492 epsilon=0.000001 Test.specify "should be able to create median values" (pending = resolve_pending test_selection.advanced_stats) <| @@ -1366,25 +1366,25 @@ spec setup = Test.specify "should raise a warning when an invalid output name" <| action = table.aggregate [Group_By "Index" ""] on_problems=_ problems = [Invalid_Output_Column_Names.Error [""]] - tester = expect_column_names ["Column_1"] + tester = expect_column_names ["Column 1"] Problems.test_problem_handling action problems tester Test.specify "should raise a warning when a duplicate column name" <| action = table.aggregate [Group_By "Index", Group_By 0] on_problems=_ problems = [Duplicate_Output_Column_Names.Error ["Index"]] - tester = expect_column_names ["Index", "Index_1"] + tester = expect_column_names ["Index", "Index 1"] Problems.test_problem_handling action problems tester Test.specify "should raise a warning when a duplicate column name and rename default names first" <| action = table.aggregate [Group_By "Value", Group_By "Index" "Value"] on_problems=_ problems = [Duplicate_Output_Column_Names.Error ["Value"]] - tester = expect_column_names ["Value_1", "Value"] + tester = expect_column_names ["Value 1", "Value"] Problems.test_problem_handling action problems tester Test.specify "should raise a warning when duplicate column names" <| action = table.aggregate [Sum "Value" new_name="AGG1", Count new_name="AGG1"] on_problems=_ problems = [Duplicate_Output_Column_Names.Error ["AGG1"]] - tester = expect_column_names ["AGG1", "AGG1_1"] + tester = expect_column_names ["AGG1", "AGG1 1"] Problems.test_problem_handling action problems tester Test.specify "should allow partial matches on Count_Distinct" <| diff --git a/test/Table_Tests/src/Common_Table_Operations/Core_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Core_Spec.enso index 6091137b646..ae7842786fb 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Core_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Core_Spec.enso @@ -21,8 +21,8 @@ spec setup = col1 = ["foo", [1,2,3]] col2 = ["bar", [4,5,6]] col3 = ["Baz", [7,8,9]] - col4 = ["foo_1", [10,11,12]] - col5 = ["foo_2", [13,14,15]] + col4 = ["foo 1", [10,11,12]] + col5 = ["foo 2", [13,14,15]] col6 = ["ab.+123", [16,17,18]] col7 = ["abcd123", [19,20,21]] table_builder [col1, col2, col3, col4, col5, col6, col7] @@ -100,11 +100,11 @@ spec setup = Test.specify "should allow adding a column" <| bar2 = table.get "bar" . rename "bar2" t2 = table.set bar2 - t2.column_names . should_equal ["foo", "bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "bar2"] + t2.column_names . should_equal ["foo", "bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "bar2"] t2.get "bar2" . to_vector . should_equal [4, 5, 6] t3 = t2.set bar2 "bar3" - t3.column_names . should_equal ["foo", "bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "bar2", "bar3"] + t3.column_names . should_equal ["foo", "bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "bar2", "bar3"] Test.specify "should not allow illegal column names" <| table.set (table.get "bar") new_name="" . should_fail_with Illegal_Argument @@ -113,11 +113,11 @@ spec setup = Test.specify "should allow replacing a column" <| foo = table.get "bar" . rename "foo" t2 = table.set foo - t2.column_names . should_equal ["foo", "bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] + t2.column_names . should_equal ["foo", "bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] t2.get "foo" . to_vector . should_equal [4, 5, 6] t3 = t2.set foo "bar3" - t3.column_names . should_equal ["foo", "bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "bar3"] + t3.column_names . should_equal ["foo", "bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "bar3"] Test.specify "should allow adding a column" <| bar2 = table.get "bar" . rename "bar2" @@ -166,7 +166,7 @@ spec setup = Test.group prefix+"Table.column_names" <| Test.specify "should return the names of all columns" <| - table.column_names . should_equal ["foo", "bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] + table.column_names . should_equal ["foo", "bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] Test.specify "should allow weird column names in all backends" <| columns = weird_names.map_with_index ix-> name-> diff --git a/test/Table_Tests/src/Common_Table_Operations/Cross_Tab_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Cross_Tab_Spec.enso index d45c83be88f..bfe835b49b9 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Cross_Tab_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Cross_Tab_Spec.enso @@ -149,14 +149,14 @@ spec setup = Test.specify "should gracefully handle duplicate aggregate names" <| action = table.cross_tab [] "Key" values=[Count new_name="Agg1", Sum "Value" new_name="Agg1"] on_problems=_ tester table = - table.column_names . should_equal ["x Agg1", "x Agg1_1", "y Agg1", "y Agg1_1", "z Agg1", "z Agg1_1"] + table.column_names . should_equal ["x Agg1", "x Agg1 1", "y Agg1", "y Agg1 1", "z Agg1", "z Agg1 1"] problems = [Duplicate_Output_Column_Names.Error ["x Agg1", "y Agg1", "z Agg1"]] Problems.test_problem_handling action problems tester table3 = table2.rename_columns (Map.from_vector [["Group", "x"]]) action3 = table3.cross_tab ["x"] "Key" on_problems=_ tester3 table = - table.column_names . should_equal ["x", "x_1", "y", "z"] + table.column_names . should_equal ["x", "x 1", "y", "z"] problems3 = [Duplicate_Output_Column_Names.Error ["x"]] Problems.test_problem_handling action3 problems3 tester3 diff --git a/test/Table_Tests/src/Common_Table_Operations/Integration_Tests.enso b/test/Table_Tests/src/Common_Table_Operations/Integration_Tests.enso index 94eafeba889..8ae48df0538 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Integration_Tests.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Integration_Tests.enso @@ -37,7 +37,7 @@ spec setup = t3 = t2.aggregate [Group_By "Letter", Count] t4 = t3.join t1 on="Count" join_kind=Join_Kind.Left_Outer |> materialize |> _.order_by "Letter" - t4.columns.map .name . should_equal ["Letter", "Count", "Right_Count", "Class"] + t4.columns.map .name . should_equal ["Letter", "Count", "Right Count", "Class"] rows = t4.rows . map .to_vector rows.at 0 . should_equal ["A", 4, Nothing, Nothing] rows.at 1 . should_equal ["B", 3, 3, "Z"] diff --git a/test/Table_Tests/src/Common_Table_Operations/Join/Cross_Join_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Join/Cross_Join_Spec.enso index ba11a64b515..3f60df4ca93 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Join/Cross_Join_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Join/Cross_Join_Spec.enso @@ -94,7 +94,7 @@ spec setup = t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] t2 = t1.cross_join t1 - expect_column_names ["X", "Y", "Right_X", "Right_Y"] t2 + expect_column_names ["X", "Y", "Right X", "Right Y"] t2 t2.row_count . should_equal 4 r = materialize t2 . rows . map .to_vector r.length . should_equal 4 @@ -108,26 +108,26 @@ spec setup = False -> r.should_equal expected_rows Test.specify "should rename columns of the right table to avoid duplicates" <| - t1 = table_builder [["X", [1]], ["Y", [5]], ["Right_Y", [10]]] + t1 = table_builder [["X", [1]], ["Y", [5]], ["Right Y", [10]]] t2 = table_builder [["X", ['a']], ["Y", ['d']]] t3 = t1.cross_join t2 - expect_column_names ["X", "Y", "Right_Y", "Right_X", "Right_Y_1"] t3 - Problems.get_attached_warnings t3 . should_equal [Duplicate_Output_Column_Names.Error ["Right_Y"]] + expect_column_names ["X", "Y", "Right Y", "Right X", "Right Y 1"] t3 + Problems.get_attached_warnings t3 . should_equal [Duplicate_Output_Column_Names.Error ["Right Y"]] t3.row_count . should_equal 1 t3.at "X" . to_vector . should_equal [1] t3.at "Y" . to_vector . should_equal [5] - t3.at "Right_Y" . to_vector . should_equal [10] - t3.at "Right_X" . to_vector . should_equal ['a'] - t3.at "Right_Y_1" . to_vector . should_equal ['d'] + t3.at "Right Y" . to_vector . should_equal [10] + t3.at "Right X" . to_vector . should_equal ['a'] + t3.at "Right Y 1" . to_vector . should_equal ['d'] t1.cross_join t2 on_problems=Problem_Behavior.Report_Error . should_fail_with Duplicate_Output_Column_Names - expect_column_names ["X", "Y", "Right_Y", "X_1", "Y_1"] (t1.cross_join t2 right_prefix="") + expect_column_names ["X", "Y", "Right Y", "X 1", "Y 1"] (t1.cross_join t2 right_prefix="") - t4 = table_builder [["X", [1]], ["Right_X", [5]]] - expect_column_names ["X", "Y", "Right_Y", "Right_X_1", "Right_X"] (t1.cross_join t4) - expect_column_names ["X", "Right_X", "Right_X_1", "Y", "Right_Y"] (t4.cross_join t1) + t4 = table_builder [["X", [1]], ["Right X", [5]]] + expect_column_names ["X", "Y", "Right Y", "Right X 1", "Right X"] (t1.cross_join t4) + expect_column_names ["X", "Right X", "Right X 1", "Y", "Right Y"] (t4.cross_join t1) Test.specify "should respect the column ordering" <| t1 = table_builder [["X", [100, 2]], ["Y", [4, 5]]] diff --git a/test/Table_Tests/src/Common_Table_Operations/Join/Join_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Join/Join_Spec.enso index b0b56bfffd6..910080636be 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Join/Join_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Join/Join_Spec.enso @@ -34,9 +34,18 @@ spec setup = Test.group prefix+"Table.join" <| t1 = table_builder [["X", [1, 2, 3]], ["Y", [4, 5, 6]]] t2 = table_builder [["Z", [2, 3, 2, 4]], ["W", [4, 5, 6, 7]]] - Test.specify "should allow to Inner join on equality of a the first column by default" <| - t3 = t1.join t2 + Test.specify "should by default do a Left Outer join on equality of first column in the left table, correlated with column of the same name in the right one" <| + t3 = table_builder [["Z", [4, 5, 6, 7]], ["X", [2, 3, 2, 4]]] + t4 = t1.join t3 |> materialize |> _.order_by ["X", "Z"] + expect_column_names ["X", "Y", "Z", "Right X"] t4 + t4.at "X" . to_vector . should_equal [1, 2, 2, 3] + t4.at "Y" . to_vector . should_equal [4, 5, 5, 6] + t4.at "Right X" . to_vector . should_equal [Nothing, 2, 2, 3] + t4.at "Z" . to_vector . should_equal [Nothing, 4, 6, 5] + + Test.specify "should allow Inner join" <| + t3 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals 0 0) expect_column_names ["X", "Y", "Z", "W"] t3 t4 = t3 |> materialize |> _.order_by ["X", "W"] t4.at "X" . to_vector . should_equal [2, 2, 3] @@ -45,23 +54,15 @@ spec setup = t4.at "W" . to_vector . should_equal [4, 6, 5] Test.specify "should allow Full join" <| - t3 = t1.join t2 join_kind=Join_Kind.Full |> materialize |> _.order_by ["X", "W"] + t3 = t1.join t2 join_kind=Join_Kind.Full on=(Join_Condition.Equals 0 0) |> materialize |> _.order_by ["X", "W"] expect_column_names ["X", "Y", "Z", "W"] t3 t3.at "X" . to_vector . should_equal [Nothing, 1, 2, 2, 3] t3.at "Y" . to_vector . should_equal [Nothing, 4, 5, 5, 6] t3.at "Z" . to_vector . should_equal [4, Nothing, 2, 2, 3] t3.at "W" . to_vector . should_equal [7, Nothing, 4, 6, 5] - Test.specify "should allow Left Outer join" <| - t4 = t1.join t2 join_kind=Join_Kind.Left_Outer |> materialize |> _.order_by ["X", "W"] - expect_column_names ["X", "Y", "Z", "W"] t4 - t4.at "X" . to_vector . should_equal [1, 2, 2, 3] - t4.at "Y" . to_vector . should_equal [4, 5, 5, 6] - t4.at "Z" . to_vector . should_equal [Nothing, 2, 2, 3] - t4.at "W" . to_vector . should_equal [Nothing, 4, 6, 5] - Test.specify "should allow Right Outer join" <| - t5 = t1.join t2 join_kind=Join_Kind.Right_Outer |> materialize |> _.order_by ["X", "W"] + t5 = t1.join t2 join_kind=Join_Kind.Right_Outer on=(Join_Condition.Equals 0 0) |> materialize |> _.order_by ["X", "W"] expect_column_names ["X", "Y", "Z", "W"] t5 t5.at "X" . to_vector . should_equal [Nothing, 2, 2, 3] t5.at "Y" . to_vector . should_equal [Nothing, 5, 5, 6] @@ -69,12 +70,12 @@ spec setup = t5.at "W" . to_vector . should_equal [7, 4, 6, 5] Test.specify "should allow to perform anti-joins" <| - t6 = t1.join t2 join_kind=Join_Kind.Left_Exclusive |> materialize |> _.order_by ["X"] + t6 = t1.join t2 join_kind=Join_Kind.Left_Exclusive on=(Join_Condition.Equals 0 0) |> materialize |> _.order_by ["X"] t6.columns.map .name . should_equal ["X", "Y"] t6.at "X" . to_vector . should_equal [1] t6.at "Y" . to_vector . should_equal [4] - t7 = t1.join t2 join_kind=Join_Kind.Right_Exclusive |> materialize |> _.order_by ["Z"] + t7 = t1.join t2 join_kind=Join_Kind.Right_Exclusive on=(Join_Condition.Equals 0 0) |> materialize |> _.order_by ["Z"] t7.columns.map .name . should_equal ["Z", "W"] t7.at "Z" . to_vector . should_equal [4] t7.at "W" . to_vector . should_equal [7] @@ -82,39 +83,39 @@ spec setup = t3 = table_builder [["X", [1, 1, 1, 2, 2, 2]], ["Y", ["A", "B", "B", "C", "C", "A"]], ["Z", [1, 2, 3, 4, 5, 6]]] t4 = table_builder [["X", [1, 1, 3, 2, 2, 4]], ["Y", ["B", "B", "C", "C", "D", "A"]], ["Z", [1, 2, 3, 4, 5, 6]]] check_xy_joined r = - expect_column_names ["X", "Y", "Z", "Right_Z"] r + expect_column_names ["X", "Y", "Z", "Right Z"] r r.at "X" . to_vector . should_equal [1, 1, 1, 1, 2, 2] r.at "Y" . to_vector . should_equal ["B", "B", "B", "B", "C", "C"] r.at "Z" . to_vector . should_equal [2, 2, 3, 3, 4, 5] - r.at "Right_Z" . to_vector . should_equal [1, 2, 1, 2, 4, 4] + r.at "Right Z" . to_vector . should_equal [1, 2, 1, 2, 4, 4] Test.specify "should allow to join on equality of multiple columns and drop redundant columns if Inner join" <| conditions = [Join_Condition.Equals "Y" "Y", Join_Condition.Equals "X" "X"] - r = t3.join t4 on=conditions |> materialize |> _.order_by ["X", "Y", "Z", "Right_Z"] + r = t3.join t4 join_kind=Join_Kind.Inner on=conditions |> materialize |> _.order_by ["X", "Y", "Z", "Right Z"] check_xy_joined r [Join_Kind.Full, Join_Kind.Left_Outer, Join_Kind.Right_Outer].each kind-> r2 = t3.join t4 join_kind=kind on=conditions - expect_column_names ["X", "Y", "Z", "Right_X", "Right_Y", "Right_Z"] r2 + expect_column_names ["X", "Y", "Z", "Right X", "Right Y", "Right Z"] r2 Test.specify "should support same-name column join shorthand" <| - r = t3.join t4 on=["X", "Y"] |> materialize |> _.order_by ["X", "Y", "Z", "Right_Z"] + r = t3.join t4 join_kind=Join_Kind.Inner on=["X", "Y"] |> materialize |> _.order_by ["X", "Y", "Z", "Right Z"] check_xy_joined r Test.specify "should allow to join on text equality ignoring case" <| t1 = table_builder [["X", ["a", "B"]], ["Y", [1, 2]]] t2 = table_builder [["X", ["A", "a", "b"]], ["Z", [1, 2, 3]]] - r1 = t1.join t2 + r1 = t1.join t2 join_kind=Join_Kind.Inner expect_column_names ["X", "Y", "Z"] r1 r1 . at "X" . to_vector . should_equal ["a"] r1 . at "Y" . to_vector . should_equal [1] r1 . at "Z" . to_vector . should_equal [2] - r2 = t1.join t2 on=(Join_Condition.Equals_Ignore_Case "X") |> materialize |> _.order_by ["Z"] - expect_column_names ["X", "Y", "Right_X", "Z"] r2 + r2 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals_Ignore_Case "X") |> materialize |> _.order_by ["Z"] + expect_column_names ["X", "Y", "Right X", "Z"] r2 r2 . at "X" . to_vector . should_equal ["a", "a", "B"] - r2 . at "Right_X" . to_vector . should_equal ["A", "a", "b"] + r2 . at "Right X" . to_vector . should_equal ["A", "a", "b"] r2 . at "Y" . to_vector . should_equal [1, 1, 2] r2 . at "Z" . to_vector . should_equal [1, 2, 3] @@ -123,16 +124,16 @@ spec setup = t1 = table_builder [["X", ['s\u0301', 'S\u0301']], ["Y", [1, 2]]] t2 = table_builder [["X", ['s', 'S', 'ś']], ["Z", [1, 2, 3]]] - r1 = t1.join t2 + r1 = t1.join t2 join_kind=Join_Kind.Inner expect_column_names ["X", "Y", "Z"] r1 r1 . at "X" . to_vector . should_equal ['ś'] r1 . at "Y" . to_vector . should_equal [1] r1 . at "Z" . to_vector . should_equal [3] - r2 = t1.join t2 on=(Join_Condition.Equals_Ignore_Case "X") |> materialize |> _.order_by ["Y"] - expect_column_names ["X", "Y", "Right_X", "Z"] r2 + r2 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals_Ignore_Case "X") |> materialize |> _.order_by ["Y"] + expect_column_names ["X", "Y", "Right X", "Z"] r2 r2 . at "X" . to_vector . should_equal ['s\u0301', 'S\u0301'] - r2 . at "Right_X" . to_vector . should_equal ['ś', 'ś'] + r2 . at "Right X" . to_vector . should_equal ['ś', 'ś'] r2 . at "Y" . to_vector . should_equal [1, 2] r2 . at "Z" . to_vector . should_equal [3, 3] @@ -141,7 +142,7 @@ spec setup = t1 = table_builder [["X", [1, 2]], ["Y", [10, 20]]] t2 = table_builder [["X", [2.0, 2.1, 0.0]], ["Z", [1, 2, 3]]] - r1 = t1.join t2 + r1 = t1.join t2 join_kind=Join_Kind.Inner expect_column_names ["X", "Y", "Z"] r1 r1 . at "X" . to_vector . should_equal [2] r1 . at "Y" . to_vector . should_equal [20] @@ -152,14 +153,14 @@ spec setup = t1 = table_builder [["X", [My_Type.Value 1 2, My_Type.Value 2 3]], ["Y", [1, 2]]] t2 = table_builder [["X", [My_Type.Value 5 0, My_Type.Value 2 1]], ["Z", [10, 20]]] - r1 = t1.join t2 |> materialize |> _.order_by ["Y"] + r1 = t1.join t2 join_kind=Join_Kind.Inner |> materialize |> _.order_by ["Y"] expect_column_names ["X", "Y", "Z"] r1 r1 . at "X" . to_vector . should_equal [My_Type.Value 1 2, My_Type.Value 2 3] ## We don't keep the other column, because the values in both are equal. However, with custom comparators, they may not be the same values, so we may consider keeping it. For not it is dropped though for consistency. - # r1 . at "Right_X" . to_vector . should_equal [My_Type.Value 1 2, My_Type.Value 2 3] + # r1 . at "Right X" . to_vector . should_equal [My_Type.Value 1 2, My_Type.Value 2 3] r1 . at "Y" . to_vector . should_equal [1, 2] r1 . at "Z" . to_vector . should_equal [20, 10] @@ -167,7 +168,7 @@ spec setup = t1 = table_builder [["X", [1, 10, 12]], ["Y", [1, 2, 3]]] t2 = table_builder [["lower", [1, 10, 8, 12]], ["upper", [1, 12, 30, 0]], ["Z", [1, 2, 3, 4]]] - r1 = t1.join t2 on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["X", "Z"] + r1 = t1.join join_kind=Join_Kind.Inner t2 on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["X", "Z"] expect_column_names ["X", "Y", "lower", "upper", "Z"] r1 r1 . at "X" . to_vector . should_equal [1, 10, 10, 12, 12] r1 . at "Y" . to_vector . should_equal [1, 2, 2, 3, 3] @@ -179,7 +180,7 @@ spec setup = t1 = table_builder [["X", ["a", "b", "c"]], ["Y", [1, 2, 3]]] t2 = table_builder [["lower", ["a", "b"]], ["upper", ["a", "ccc"]], ["Z", [10, 20]]] - r1 = t1.join t2 on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["X", "Z"] + r1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["X", "Z"] expect_column_names ["X", "Y", "lower", "upper", "Z"] r1 r1 . at "X" . to_vector . should_equal ["a", "b", "c"] r1 . at "Y" . to_vector . should_equal [1, 2, 3] @@ -192,7 +193,7 @@ spec setup = t1 = table_builder [["X", ['s\u0301', 's']], ["Y", [1, 2]]] t2 = table_builder [["lower", ['s', 'ś']], ["upper", ['sa', 'ś']], ["Z", [10, 20]]] - r1 = t1.join t2 on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["Y"] + r1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["Y"] expect_column_names ["X", "Y", "lower", "upper", "Z"] r1 r1 . at "X" . to_vector . should_equal ['s\u0301', 's'] r1 . at "Y" . to_vector . should_equal [1, 2] @@ -205,7 +206,7 @@ spec setup = t1 = table_builder [["X", [My_Type.Value 20 30, My_Type.Value 1 2]], ["Y", [1, 2]]] t2 = table_builder [["lower", [My_Type.Value 3 0, My_Type.Value 10 10]], ["upper", [My_Type.Value 2 1, My_Type.Value 100 0]], ["Z", [10, 20]]] - r1 = t1.join t2 on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["Z"] + r1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Between "X" "lower" "upper") |> materialize |> _.order_by ["Z"] expect_column_names ["X", "Y", "lower", "upper", "Z"] r1 r1 . at "X" . to_vector . to_text . should_equal "[(My_Type.Value 1 2), (My_Type.Value 20 30)]" r1 . at "Y" . to_vector . should_equal [2, 1] @@ -217,25 +218,25 @@ spec setup = t1 = table_builder [["X", [1, 12, 12, 0]], ["Y", [1, 2, 3, 4]], ["Z", ["a", "A", "a", "ą"]], ["W", [1, 2, 3, 4]]] t2 = table_builder [["X", [12, 12, 1]], ["l", [0, 100, 100]], ["u", [10, 100, 100]], ["Z", ["A", "A", "A"]], ["W'", [10, 20, 30]]] - r1 = t1.join t2 on=[Join_Condition.Between "Y" "l" "u", Join_Condition.Equals_Ignore_Case "Z" "Z", Join_Condition.Equals "X" "X"] |> materialize |> _.order_by ["Y"] - expect_column_names ["X", "Y", "Z", "W", "l", "u", "Right_Z", "W'"] r1 + r1 = t1.join t2 join_kind=Join_Kind.Inner on=[Join_Condition.Between "Y" "l" "u", Join_Condition.Equals_Ignore_Case "Z" "Z", Join_Condition.Equals "X" "X"] |> materialize |> _.order_by ["Y"] + expect_column_names ["X", "Y", "Z", "W", "l", "u", "Right Z", "W'"] r1 r1.at "X" . to_vector . should_equal [12, 12] r1.at "Y" . to_vector . should_equal [2, 3] r1.at "Z" . to_vector . should_equal ["A", "a"] r1.at "W" . to_vector . should_equal [2, 3] r1.at "l" . to_vector . should_equal [0, 0] r1.at "u" . to_vector . should_equal [10, 10] - r1.at "Right_Z" . to_vector . should_equal ["A", "A"] + r1.at "Right Z" . to_vector . should_equal ["A", "A"] r1.at "W'" . to_vector . should_equal [10, 10] Test.specify "should work fine if the same condition is specified multiple times" <| - r = t3.join t4 on=["X", "X", "Y", "X", "Y"] |> materialize |> _.order_by ["X", "Y", "Z", "Right_Z"] + r = t3.join t4 join_kind=Join_Kind.Inner on=["X", "X", "Y", "X", "Y"] |> materialize |> _.order_by ["X", "Y", "Z", "Right Z"] check_xy_joined r t5 = table_builder [["X", [1, 10, 12]], ["Y", [1, 2, 3]]] t6 = table_builder [["lower", [1, 10, 8, 12]], ["upper", [1, 12, 30, 0]], ["Z", [1, 2, 3, 4]]] - r1 = t5.join t6 on=[Join_Condition.Between "X" "lower" "upper", Join_Condition.Between "X" "lower" "upper", Join_Condition.Between "X" "lower" "upper"] |> materialize |> _.order_by ["X", "Z"] + r1 = t5.join t6 join_kind=Join_Kind.Inner on=[Join_Condition.Between "X" "lower" "upper", Join_Condition.Between "X" "lower" "upper", Join_Condition.Between "X" "lower" "upper"] |> materialize |> _.order_by ["X", "Z"] r1 . at "X" . to_vector . should_equal [1, 10, 10, 12, 12] r1 . at "Y" . to_vector . should_equal [1, 2, 2, 3, 3] r1 . at "Z" . to_vector . should_equal [1, 2, 3, 2, 3] @@ -243,64 +244,71 @@ spec setup = t7 = table_builder [["X", ["a", "B"]], ["Y", [1, 2]]] t8 = table_builder [["X", ["A", "a", "b"]], ["Z", [1, 2, 3]]] - r2 = t7.join t8 on=[Join_Condition.Equals_Ignore_Case "X", Join_Condition.Equals_Ignore_Case "X", Join_Condition.Equals_Ignore_Case "X" "X"] |> materialize |> _.order_by ["Z"] + r2 = t7.join t8 join_kind=Join_Kind.Inner on=[Join_Condition.Equals_Ignore_Case "X", Join_Condition.Equals_Ignore_Case "X", Join_Condition.Equals_Ignore_Case "X" "X"] |> materialize |> _.order_by ["Z"] r2 . at "X" . to_vector . should_equal ["a", "a", "B"] - r2 . at "Right_X" . to_vector . should_equal ["A", "a", "b"] + r2 . at "Right X" . to_vector . should_equal ["A", "a", "b"] r2 . at "Z" . to_vector . should_equal [1, 2, 3] Test.specify "should correctly handle joining a table with itself" <| t1 = table_builder [["X", [0, 1, 2, 3, 2]], ["Y", [1, 2, 3, 4, 100]], ["A", ["B", "C", "D", "E", "X"]]] - t2 = t1.join t1 on=(Join_Condition.Equals left="X" right="Y") |> materialize |> _.order_by ["X", "Y"] + t2 = t1.join t1 join_kind=Join_Kind.Inner on=(Join_Condition.Equals left="X" right="Y") |> materialize |> _.order_by ["X", "Y"] - expect_column_names ["X", "Y", "A", "Right_X", "Right_Y", "Right_A"] t2 + expect_column_names ["X", "Y", "A", "Right X", "Right Y", "Right A"] t2 t2.at "X" . to_vector . should_equal [1, 2, 2, 3] - t2.at "Right_Y" . to_vector . should_equal [1, 2, 2, 3] + t2.at "Right Y" . to_vector . should_equal [1, 2, 2, 3] t2.at "Y" . to_vector . should_equal [2, 3, 100, 4] t2.at "A" . to_vector . should_equal ["C", "D", "X", "E"] - t2.at "Right_X" . to_vector . should_equal [0, 1, 1, 2] - t2.at "Right_A" . to_vector . should_equal ["B", "C", "C", "D"] + t2.at "Right X" . to_vector . should_equal [0, 1, 1, 2] + t2.at "Right A" . to_vector . should_equal ["B", "C", "C", "D"] - t3 = t1.join t1 join_kind=Join_Kind.Full on=(Join_Condition.Equals left="X" right="Y") |> materialize |> _.order_by ["X", "Y", "Right_X"] - expect_column_names ["X", "Y", "A", "Right_X", "Right_Y", "Right_A"] t3 + t3 = t1.join t1 join_kind=Join_Kind.Full on=(Join_Condition.Equals left="X" right="Y") |> materialize |> _.order_by ["X", "Y", "Right X"] + expect_column_names ["X", "Y", "A", "Right X", "Right Y", "Right A"] t3 t3.at "X" . to_vector . should_equal [Nothing, Nothing, 0, 1, 2, 2, 3] - t3.at "Right_Y" . to_vector . should_equal [100, 4, Nothing, 1, 2, 2, 3] + t3.at "Right Y" . to_vector . should_equal [100, 4, Nothing, 1, 2, 2, 3] t3.at "Y" . to_vector . should_equal [Nothing, Nothing, 1, 2, 3, 100, 4] t3.at "A" . to_vector . should_equal [Nothing, Nothing, "B", "C", "D", "X", "E"] - t3.at "Right_X" . to_vector . should_equal [2, 3, Nothing, 0, 1, 1, 2] - t3.at "Right_A" . to_vector . should_equal ["X", "E", Nothing, "B", "C", "C", "D"] + t3.at "Right X" . to_vector . should_equal [2, 3, Nothing, 0, 1, 1, 2] + t3.at "Right A" . to_vector . should_equal ["X", "E", Nothing, "B", "C", "C", "D"] t4 = table_builder [["X", [Nothing, "a", "B"]], ["Y", ["ą", "b", Nothing]], ["Z", [1, 2, 3]]] - t5 = t4.join t4 on=(Join_Condition.Equals_Ignore_Case left="Y" right="X") |> materialize |> _.order_by ["Y"] - expect_column_names ["X", "Y", "Z", "Right_X", "Right_Y", "Right_Z"] t5 + t5 = t4.join t4 join_kind=Join_Kind.Inner on=(Join_Condition.Equals_Ignore_Case left="Y" right="X") |> materialize |> _.order_by ["Y"] + expect_column_names ["X", "Y", "Z", "Right X", "Right Y", "Right Z"] t5 # TODO enable once we handle nothing properly # t5.at "Y" . to_vector . should_equal [Nothing, "b"] - # t5.at "Right_X" . to_vector . should_equal [Nothing, "B"] + # t5.at "Right X" . to_vector . should_equal [Nothing, "B"] # t5.at "X" . to_vector . should_equal ["B", "a"] # t5.at "Z" . to_vector . should_equal [3, 2] - # t5.at "Right_Y" . to_vector . should_equal ["ą", Nothing] - # t5.at "Right_Z" . to_vector . should_equal [1, 3] + # t5.at "Right Y" . to_vector . should_equal ["ą", Nothing] + # t5.at "Right Z" . to_vector . should_equal [1, 3] Test.specify "should gracefully handle unmatched columns in Join_Conditions" <| t1 = table_builder [["X", [1, 2]], ["Y", [3, 4]]] t2 = table_builder [["Z", [2, 1]], ["W", [5, 6]]] + # Report error if the default fails - the right table does not have a column with same name as first column of left one: + r1 = t1.join t2 + r1.should_fail_with Missing_Input_Columns + r1.catch.criteria.should_equal ["X"] + r1.catch.to_display_text.should_equal "The criteria [X] did not match any columns in the right table." + conditions = [Join_Condition.Equals "foo" 42, Join_Condition.Equals "X" -3, Join_Condition.Equals -1 "baz"] - r1 = t1.join t2 on=conditions on_problems=Problem_Behavior.Ignore + r2 = t1.join t2 on=conditions on_problems=Problem_Behavior.Ignore ## We have both - Column_Indexes_Out_Of_Range.Error [42, -3] - Missing_Input_Columns.Error ["foo", "baz"] here, but we can throw only one error. I think column names error will be more useful, so I'd prioritize it. - r1.should_fail_with Missing_Input_Columns - r1.catch.criteria.should_equal ["foo", "baz"] + r2.should_fail_with Missing_Input_Columns + r2.catch.criteria.should_equal ["foo"] + r2.catch.to_display_text.should_equal "The criteria [foo] did not match any columns in the left table." - r2 = t1.join t2 on=[Join_Condition.Equals 42 0] on_problems=Problem_Behavior.Ignore - r2.should_fail_with Column_Indexes_Out_Of_Range - r2.catch.indexes.should_equal [42] + r3 = t1.join t2 on=[Join_Condition.Equals 42 0] on_problems=Problem_Behavior.Ignore + r3.should_fail_with Column_Indexes_Out_Of_Range + r3.catch.indexes.should_equal [42] Test.specify "should report Invalid_Value_Type if non-text columns are provided to Equals_Ignore_Case" <| t1 = table_builder [["X", ["1", "2", "c"]], ["Y", [1, 2, 3]]] @@ -317,7 +325,7 @@ spec setup = Test.specify "should report Invalid_Value_Type if incompatible types are correlated" <| t1 = table_builder [["X", ["1", "2", "c"]]] - t2 = table_builder [["Y", [1, 2, 3]]] + t2 = table_builder [["X", [1, 2, 3]]] r1 = t1.join t2 on_problems=Problem_Behavior.Ignore r1.should_fail_with Invalid_Value_Type @@ -334,7 +342,7 @@ spec setup = t1 = table_builder [["X", [1.5, 2.0, 2.00000000001]], ["Y", [10, 20, 30]]] t2 = table_builder [["Z", [2.0, 1.5, 2.0]], ["W", [1, 2, 3]]] - action1 = t1.join t2 on=(Join_Condition.Equals "X" "Z") on_problems=_ + action1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "X" "Z") on_problems=_ tester1 table = expect_column_names ["X", "Y", "Z", "W"] table t1 = table.order_by ["Y", "W"] @@ -345,7 +353,7 @@ spec setup = problems1 = [Floating_Point_Equality.Error "X", Floating_Point_Equality.Error "Z"] Problems.test_problem_handling action1 problems1 tester1 - action2 = t1.join t2 on=(Join_Condition.Equals "X" "W") on_problems=_ + action2 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "X" "W") on_problems=_ tester2 table = expect_column_names ["X", "Y", "Z", "W"] table t1 = table.order_by ["Y", "W"] @@ -363,7 +371,7 @@ spec setup = if setup.supports_custom_objects then t1 = table_builder [["X", [My_Type.Value 1 2, 2.0, 2]], ["Y", [10, 20, 30]]] t2 = table_builder [["Z", [2.0, 1.5, 2.0]], ["W", [1, 2, 3]]] - action3 = t1.join t2 on=(Join_Condition.Equals "X" "Z") on_problems=_ + action3 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "X" "Z") on_problems=_ tester3 table = expect_column_names ["X", "Y", "Z", "W"] table t1 = table.order_by ["Y", "W"] @@ -378,7 +386,7 @@ spec setup = t1 = table_builder [["X", ["A", Nothing, "a", Nothing, "ą"]], ["Y", [0, 1, 2, 3, 4]]] t2 = table_builder [["X", ["a", Nothing, Nothing]], ["Z", [10, 20, 30]]] - r1 = t1.join t2 |> materialize |> _.order_by ["Y"] + r1 = t1.join t2 join_kind=Join_Kind.Inner |> materialize |> _.order_by ["Y"] expect_column_names ["X", "Y", "Z"] r1 r1.at "X" . to_vector . should_equal [Nothing, Nothing, "a", Nothing, Nothing] r1.at "Y" . to_vector . should_equal [1, 1, 2, 3, 3] @@ -388,10 +396,10 @@ spec setup = t1 = table_builder [["X", ["A", Nothing, "a", Nothing, "ą"]], ["Y", [0, 1, 2, 3, 4]]] t2 = table_builder [["X", ["a", Nothing, Nothing]], ["Z", [10, 20, 30]]] - r1 = t1.join t2 on=(Join_Condition.Equals_Ignore_Case "X") |> materialize |> _.order_by ["Y"] - expect_column_names ["X", "Y", "Right_X", "Z"] r1 + r1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals_Ignore_Case "X") |> materialize |> _.order_by ["Y"] + expect_column_names ["X", "Y", "Right X", "Z"] r1 r1.at "X" . to_vector . should_equal ["A", Nothing, Nothing, "a", Nothing, Nothing] - r1.at "Right_X" . to_vector . should_equal ["a", Nothing, Nothing, "a", Nothing, Nothing] + r1.at "Right X" . to_vector . should_equal ["a", Nothing, Nothing, "a", Nothing, Nothing] r1.at "Y" . to_vector . should_equal [0, 1, 1, 2, 3, 3] r1.at "Z" . to_vector . should_equal [10, 20, 30, 10, 20, 30] @@ -399,7 +407,7 @@ spec setup = t1 = table_builder [["X", [1, Nothing, 2, Nothing]], ["Y", [0, 1, 2, 3]]] t2 = table_builder [["l", [Nothing, 0, 1]], ["u", [100, 10, Nothing]], ["Z", [10, 20, 30]]] - r1 = t1.join t2 on=(Join_Condition.Between "X" "l" "u") |> materialize |> _.order_by ["Y"] + r1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Between "X" "l" "u") |> materialize |> _.order_by ["Y"] expect_column_names ["X", "Y", "l", "u", "Z"] r1 r1.at "X" . to_vector . should_equal [1, 2] r1.at "Y" . to_vector . should_equal [0, 2] @@ -408,51 +416,55 @@ spec setup = r1.at "Z" . to_vector . should_equal [20, 20] Test.specify "should rename columns of the right table to avoid duplicates" <| - t1 = table_builder [["X", [1, 2]], ["Y", [3, 4]], ["Right_Y", [5, 6]]] + t1 = table_builder [["X", [1, 2]], ["Y", [3, 4]], ["Right Y", [5, 6]]] t2 = table_builder [["X", [2, 1]], ["Y", [2, 2]]] - t3 = t1.join t2 on=(Join_Condition.Equals "X" "Y") |> materialize |> _.order_by ["Right_X"] - Problems.get_attached_warnings t3 . should_equal [Duplicate_Output_Column_Names.Error ["Right_Y"]] - expect_column_names ["X", "Y", "Right_Y", "Right_X", "Right_Y_1"] t3 + t3 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "X" "Y") |> materialize |> _.order_by ["Right X"] + Problems.get_attached_warnings t3 . should_equal [Duplicate_Output_Column_Names.Error ["Right Y"]] + t3.column_names.should_equal ["X", "Y", "Right Y", "Right X", "Right Y 1"] t3.at "X" . to_vector . should_equal [2, 2] t3.at "Y" . to_vector . should_equal [4, 4] - t3.at "Right_Y" . to_vector . should_equal [6, 6] - t3.at "Right_X" . to_vector . should_equal [1, 2] - t3.at "Right_Y_1" . to_vector . should_equal [2, 2] + t3.at "Right Y" . to_vector . should_equal [6, 6] + t3.at "Right X" . to_vector . should_equal [1, 2] + t3.at "Right Y 1" . to_vector . should_equal [2, 2] - err1 = t1.join t2 on=(Join_Condition.Equals "X" "Y") on_problems=Problem_Behavior.Report_Error + err1 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "X" "Y") on_problems=Problem_Behavior.Report_Error err1.should_fail_with Duplicate_Output_Column_Names - err1.catch.column_names . should_equal ["Right_Y"] + err1.catch.column_names . should_equal ["Right Y"] - t4 = table_builder [["Right_X", [1, 1]], ["X", [1, 2]], ["Y", [3, 4]], ["Right_Y_2", [2, 2]]] - t5 = table_builder [["Right_X", [2, 1]], ["X", [2, 2]], ["Y", [2, 2]], ["Right_Y", [2, 2]], ["Right_Y_1", [2, 2]], ["Right_Y_4", [2, 2]]] + t4 = table_builder [["Right X", [1, 1]], ["X", [1, 2]], ["Y", [3, 4]], ["Right Y 2", [2, 2]]] + t5 = table_builder [["Right X", [2, 1]], ["X", [2, 2]], ["Y", [2, 2]], ["Right Y", [2, 2]], ["Right Y 1", [2, 2]], ["Right Y 4", [2, 2]]] t6 = t4.join t5 on=(Join_Condition.Equals "X" "Y") - expect_column_names ["Right_X", "X", "Y", "Right_Y_2"]+["Right_Right_X", "Right_X_1", "Right_Y_3", "Right_Y", "Right_Y_1", "Right_Y_4"] t6 + t6.column_names.should_equal ["Right X", "X", "Y", "Right Y 2"]+["Right Right X", "Right X 1", "Right Y 3", "Right Y", "Right Y 1", "Right Y 4"] action = t1.join t2 right_prefix="" on_problems=_ - tester = expect_column_names ["X", "Y", "Right_Y", "Y_1"] - problems = [Duplicate_Output_Column_Names.Error ["Y"]] + tester = expect_column_names ["X", "Y", "Right Y", "X 1", "Y 1"] + problems = [Duplicate_Output_Column_Names.Error ["X", "Y"]] Problems.test_problem_handling action problems tester - t8 = t1.join t2 right_prefix="P" - expect_column_names ["X", "Y", "Right_Y", "PY"] t8 + action_2 = t1.join t2 join_kind=Join_Kind.Inner right_prefix="" on_problems=_ + tester_2 = expect_column_names ["X", "Y", "Right Y", "Y 1"] + problems_2 = [Duplicate_Output_Column_Names.Error ["Y"]] + Problems.test_problem_handling action_2 problems_2 tester_2 + + t8 = t1.join t2 join_kind=Join_Kind.Inner right_prefix="P" + t8.column_names.should_equal ["X", "Y", "Right Y", "PY"] Test.specify "should warn about renamed columns" <| t1 = table_builder [["X", [1, 2]], ["Y", [3, 4]]] - t2 = table_builder [["X", [2, 1]], ["Y", [2, 2]], ["Right_Y", [2, 44]]] + t2 = table_builder [["X", [2, 1]], ["Y", [2, 2]], ["Right Y", [2, 44]]] action1 = t1.join t2 on=(Join_Condition.Equals "X" "Y") on_problems=_ tester1 table = - expect_column_names ["X", "Y", "Right_X", "Right_Y_1", "Right_Y"] table - problems1 = [Duplicate_Output_Column_Names.Error ["Right_Y"]] + expect_column_names ["X", "Y", "Right X", "Right Y 1", "Right Y"] table + problems1 = [Duplicate_Output_Column_Names.Error ["Right Y"]] Problems.test_problem_handling action1 problems1 tester1 - - action2 = t1.join t2 on=(Join_Condition.Equals "X" "X") on_problems=_ + action2 = t1.join t2 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "X" "X") on_problems=_ tester2 table = - expect_column_names ["X", "Y", "Right_Y_1", "Right_Y"] table - problems2 = [Duplicate_Output_Column_Names.Error ["Right_Y"]] + expect_column_names ["X", "Y", "Right Y 1", "Right Y"] table + problems2 = [Duplicate_Output_Column_Names.Error ["Right Y"]] Problems.test_problem_handling action2 problems2 tester2 Test.specify "should pass dataflow errors through" <| @@ -527,13 +539,13 @@ spec setup = t7 = table_builder [["A", [Nothing, 2]], ["B", [Nothing, 3]]] t8 = table_builder [["C", [2, 3]], ["D", [4, 5]]] - t9 = t7.join t8 join_kind=Join_Kind.Inner + t9 = t7.join t8 on=[Join_Condition.Equals "A" "C"] join_kind=Join_Kind.Inner r9 = materialize t9 . order_by ["A", "B", "D"] . rows . map .to_vector within_table t9 <| r9.length . should_equal 1 r9.at 0 . should_equal [2, 3, 2, 4] - t10 = t7.join t8 join_kind=Join_Kind.Full + t10 = t7.join t8 on=[Join_Condition.Equals "A" "C"] join_kind=Join_Kind.Full r10 = materialize t10 . order_by ["A", "C"] . rows . map .to_vector within_table t10 <| r10.length . should_equal 3 @@ -541,27 +553,27 @@ spec setup = r10.at 1 . should_equal [Nothing, Nothing, 3, 5] r10.at 2 . should_equal [2, 3, 2, 4] - t10_2 = t7.join t8 join_kind=Join_Kind.Left_Outer + t10_2 = t7.join t8 on=[Join_Condition.Equals "A" "C"] join_kind=Join_Kind.Left_Outer r10_2 = materialize t10_2 . order_by ["A", "C"] . rows . map .to_vector within_table t10_2 <| r10_2.length . should_equal 2 r10_2.at 0 . should_equal [Nothing, Nothing, Nothing, Nothing] r10_2.at 1 . should_equal [2, 3, 2, 4] - t10_3 = t7.join t8 join_kind=Join_Kind.Right_Outer + t10_3 = t7.join t8 on=[Join_Condition.Equals "A" "C"] join_kind=Join_Kind.Right_Outer r10_3 = materialize t10_3 . order_by ["A", "C"] . rows . map .to_vector within_table t10_3 <| r10_3.length . should_equal 2 r10_3.at 0 . should_equal [Nothing, Nothing, 3, 5] r10_3.at 1 . should_equal [2, 3, 2, 4] - t11 = t7.join t8 join_kind=Join_Kind.Left_Exclusive + t11 = t7.join t8 on=[Join_Condition.Equals "A" "C"] join_kind=Join_Kind.Left_Exclusive r11 = materialize t11 . rows . map .to_vector within_table t11 <| r11.length . should_equal 1 r11.at 0 . should_equal [Nothing, Nothing] - t12 = t7.join t8 join_kind=Join_Kind.Right_Exclusive + t12 = t7.join t8 on=[Join_Condition.Equals "A" "C"] join_kind=Join_Kind.Right_Exclusive r12 = materialize t12 . rows . map .to_vector within_table t12 <| r12.length . should_equal 1 @@ -585,18 +597,18 @@ spec setup = t1_2 = t1.set "10*[X]+1" new_name="A" t1_3 = t1.set "[X]+20" new_name="B" - t2 = t1_2.join t1_3 on=(Join_Condition.Equals "A" "B") + t2 = t1_2.join t1_3 join_kind=Join_Kind.Inner on=(Join_Condition.Equals "A" "B") t2.at "A" . to_vector . should_equal [21] t2.at "X" . to_vector . should_equal [2] t2.at "B" . to_vector . should_equal [21] - t2.at "Right_X" . to_vector . should_equal [1] + t2.at "Right X" . to_vector . should_equal [1] t4 = table_builder [["X", [1, 2, 3]], ["Y", [10, 20, 30]]] t5 = table_builder [["X", [5, 7, 1]], ["Z", [100, 200, 300]]] t4_2 = t4.set "2*[X]+1" new_name="C" t6 = t4_2.join t5 on=(Join_Condition.Equals "C" "X") join_kind=Join_Kind.Inner - expect_column_names ["X", "Y", "C", "Right_X", "Z"] t6 + expect_column_names ["X", "Y", "C", "Right X", "Z"] t6 r2 = materialize t6 . order_by ["Y"] . rows . map .to_vector r2.length . should_equal 2 r2.at 0 . should_equal [2, 20, 5, 5, 100] @@ -607,7 +619,7 @@ spec setup = t2 = table_builder [["X", ["Ć", "A", "b"]], ["Z", [100, 200, 300]]] t3 = t1.join t2 on=(Join_Condition.Equals_Ignore_Case "X") join_kind=Join_Kind.Full - expect_column_names ["X", "Y", "Right_X", "Z"] t3 + expect_column_names ["X", "Y", "Right X", "Z"] t3 r = materialize t3 . order_by ["Y"] . rows . map .to_vector r.length . should_equal 4 r.at 0 . should_equal [Nothing, Nothing, "Ć", 100] @@ -620,7 +632,7 @@ spec setup = t4_2 = t4.set "2*[X]+1" new_name="C" t6 = t4_2.join t5 on=(Join_Condition.Equals "C" "X") join_kind=Join_Kind.Full - expect_column_names ["X", "Y", "C", "Right_X", "Z"] t6 + expect_column_names ["X", "Y", "C", "Right X", "Z"] t6 r2 = materialize t6 . order_by ["Y"] . rows . map .to_vector r2.length . should_equal 4 r2.at 0 . should_equal [Nothing, Nothing, Nothing, 1, 300] @@ -632,8 +644,8 @@ spec setup = t4_4 = t4_3.set (t4_3.at "X" . fill_nothing 7) new_name="C" t7 = t4_4.join t5 on=(Join_Condition.Equals "C" "X") join_kind=Join_Kind.Full within_table t7 <| - expect_column_names ["X", "Y", "C", "Right_X", "Z"] t7 - r3 = materialize t7 . order_by ["Y", "Right_X"] . rows . map .to_vector + expect_column_names ["X", "Y", "C", "Right X", "Z"] t7 + r3 = materialize t7 . order_by ["Y", "Right X"] . rows . map .to_vector r3.length . should_equal 5 r3.at 0 . should_equal [Nothing, Nothing, Nothing, 1, 300] r3.at 1 . should_equal [Nothing, Nothing, Nothing, 5, 100] diff --git a/test/Table_Tests/src/Common_Table_Operations/Join/Zip_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Join/Zip_Spec.enso index b186cbe73a9..e8fb5c328fe 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Join/Zip_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Join/Zip_Spec.enso @@ -148,33 +148,33 @@ spec setup = t3.at "W" . to_vector . should_equal ['b', Nothing, Nothing] Test.specify "should rename columns of the right table to avoid duplicates" <| - t1 = table_builder [["X", [1, 2]], ["Y", [5, 6]], ["Right_Y", [7, 8]]] + t1 = table_builder [["X", [1, 2]], ["Y", [5, 6]], ["Right Y", [7, 8]]] t2 = table_builder [["X", ['a']], ["Y", ['d']]] t3 = t1.zip t2 keep_unmatched=True - expect_column_names ["X", "Y", "Right_Y", "Right_X", "Right_Y_1"] t3 - Problems.get_attached_warnings t3 . should_equal [Duplicate_Output_Column_Names.Error ["Right_Y"]] + expect_column_names ["X", "Y", "Right Y", "Right X", "Right Y 1"] t3 + Problems.get_attached_warnings t3 . should_equal [Duplicate_Output_Column_Names.Error ["Right Y"]] t3.row_count . should_equal 2 t3.at "X" . to_vector . should_equal [1, 2] t3.at "Y" . to_vector . should_equal [5, 6] - t3.at "Right_Y" . to_vector . should_equal [7, 8] - t3.at "Right_X" . to_vector . should_equal ['a', Nothing] - t3.at "Right_Y_1" . to_vector . should_equal ['d', Nothing] + t3.at "Right Y" . to_vector . should_equal [7, 8] + t3.at "Right X" . to_vector . should_equal ['a', Nothing] + t3.at "Right Y 1" . to_vector . should_equal ['d', Nothing] t1.zip t2 keep_unmatched=False on_problems=Problem_Behavior.Report_Error . should_fail_with Duplicate_Output_Column_Names - expect_column_names ["X", "Y", "Right_Y", "X_1", "Y_1"] (t1.zip t2 right_prefix="") + expect_column_names ["X", "Y", "Right Y", "X 1", "Y 1"] (t1.zip t2 right_prefix="") - t4 = table_builder [["X", [1]], ["Right_X", [5]]] - expect_column_names ["X", "Y", "Right_Y", "Right_X_1", "Right_X"] (t1.zip t4) - expect_column_names ["X", "Right_X", "Right_X_1", "Y", "Right_Y"] (t4.zip t1) + t4 = table_builder [["X", [1]], ["Right X", [5]]] + expect_column_names ["X", "Y", "Right Y", "Right X 1", "Right X"] (t1.zip t4) + expect_column_names ["X", "Right X", "Right X 1", "Y", "Right Y"] (t4.zip t1) Test.specify "should report both row count mismatch and duplicate column warnings at the same time" <| - t1 = table_builder [["X", [1, 2]], ["Right_X", [5, 6]]] + t1 = table_builder [["X", [1, 2]], ["Right X", [5, 6]]] t2 = table_builder [["X", ['a']], ["Z", ['d']]] t3 = t1.zip t2 - expected_problems = [Row_Count_Mismatch.Error 2 1, Duplicate_Output_Column_Names.Error ["Right_X"]] + expected_problems = [Row_Count_Mismatch.Error 2 1, Duplicate_Output_Column_Names.Error ["Right X"]] Problems.get_attached_warnings t3 . should_contain_the_same_elements_as expected_problems Test.specify "should allow to zip the table with itself" <| @@ -183,12 +183,12 @@ spec setup = the Database backend. t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] t2 = t1.zip t1 - expect_column_names ["X", "Y", "Right_X", "Right_Y"] t2 + expect_column_names ["X", "Y", "Right X", "Right Y"] t2 t2.row_count . should_equal 2 t2.at "X" . to_vector . should_equal [1, 2] t2.at "Y" . to_vector . should_equal [4, 5] - t2.at "Right_X" . to_vector . should_equal [1, 2] - t2.at "Right_Y" . to_vector . should_equal [4, 5] + t2.at "Right X" . to_vector . should_equal [1, 2] + t2.at "Right Y" . to_vector . should_equal [4, 5] if setup.is_database.not then Test.specify "should correctly pad/truncate all kinds of column types" <| diff --git a/test/Table_Tests/src/Common_Table_Operations/Select_Columns_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Select_Columns_Spec.enso index 55fdc51974a..b79d762f1b8 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Select_Columns_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Select_Columns_Spec.enso @@ -19,8 +19,8 @@ spec setup = col1 = ["foo", [1,2,3]] col2 = ["bar", [4,5,6]] col3 = ["Baz", [7,8,9]] - col4 = ["foo_1", [10,11,12]] - col5 = ["foo_2", [13,14,15]] + col4 = ["foo 1", [10,11,12]] + col5 = ["foo 2", [13,14,15]] col6 = ["ab.+123", [16,17,18]] col7 = ["abcd123", [19,20,21]] table_builder [col1, col2, col3, col4, col5, col6, col7] @@ -28,7 +28,7 @@ spec setup = Test.group prefix+"Table.select_columns" <| Test.specify "should work as shown in the doc examples" <| expect_column_names ["foo", "bar"] <| table.select_columns ["bar", "foo"] - expect_column_names ["bar", "Baz", "foo_1", "foo_2"] <| table.select_columns [By_Name "foo.+" use_regex=True, By_Name "b.*" use_regex=True] + expect_column_names ["bar", "Baz", "foo 1", "foo 2"] <| table.select_columns [By_Name "foo.+" use_regex=True, By_Name "b.*" use_regex=True] expect_column_names ["abcd123", "foo", "bar"] <| table.select_columns [-1, 0, 1] reorder=True Test.specify "should allow to reorder columns if asked to" <| @@ -45,13 +45,13 @@ spec setup = expect_column_names ["abcd123"] <| table.select_columns [By_Name "abcd123" Case_Sensitivity.Sensitive use_regex=True] Test.specify "should allow negative indices" <| - expect_column_names ["foo", "bar", "foo_2"] <| table.select_columns [-3, 0, 1] + expect_column_names ["foo", "bar", "foo 2"] <| table.select_columns [-3, 0, 1] Test.specify "should allow mixed names and indexes" <| - expect_column_names ["foo", "bar", "foo_2"] <| table.select_columns [-3, "bar", 0] - expect_column_names ["foo_2", "bar", "foo"] <| table.select_columns [-3, "bar", 0] reorder=True - expect_column_names ["foo", "bar", "foo_1", "foo_2", "abcd123"] <| table.select_columns [-1, "bar", By_Name "foo.*" Case_Sensitivity.Sensitive use_regex=True] - expect_column_names ["foo", "foo_1", "foo_2", "bar", "abcd123"] <| table.select_columns [By_Name "foo.*" Case_Sensitivity.Sensitive use_regex=True, "bar", "foo", -1] reorder=True + expect_column_names ["foo", "bar", "foo 2"] <| table.select_columns [-3, "bar", 0] + expect_column_names ["foo 2", "bar", "foo"] <| table.select_columns [-3, "bar", 0] reorder=True + expect_column_names ["foo", "bar", "foo 1", "foo 2", "abcd123"] <| table.select_columns [-1, "bar", By_Name "foo.*" Case_Sensitivity.Sensitive use_regex=True] + expect_column_names ["foo", "foo 1", "foo 2", "bar", "abcd123"] <| table.select_columns [By_Name "foo.*" Case_Sensitivity.Sensitive use_regex=True, "bar", "foo", -1] reorder=True if test_selection.supports_case_sensitive_columns then Test.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <| @@ -63,8 +63,8 @@ spec setup = expect_column_names ["bar", "Bar"] <| table.select_columns [By_Name "bar"] Test.specify "should correctly handle regexes matching multiple names" <| - expect_column_names ["foo", "bar", "foo_1", "foo_2"] <| table.select_columns [By_Name "b.*" Case_Sensitivity.Sensitive use_regex=True, By_Name "f.+" Case_Sensitivity.Sensitive use_regex=True] - expect_column_names ["bar", "foo", "foo_1", "foo_2"] <| table.select_columns [By_Name "b.*" Case_Sensitivity.Sensitive use_regex=True, By_Name "f.+" Case_Sensitivity.Sensitive use_regex=True] reorder=True + expect_column_names ["foo", "bar", "foo 1", "foo 2"] <| table.select_columns [By_Name "b.*" Case_Sensitivity.Sensitive use_regex=True, By_Name "f.+" Case_Sensitivity.Sensitive use_regex=True] + expect_column_names ["bar", "foo", "foo 1", "foo 2"] <| table.select_columns [By_Name "b.*" Case_Sensitivity.Sensitive use_regex=True, By_Name "f.+" Case_Sensitivity.Sensitive use_regex=True] reorder=True Test.specify "should correctly handle problems: out of bounds indices" <| selector = [1, 0, 100, -200, 300] @@ -142,21 +142,21 @@ spec setup = Test.group prefix+"Table.remove_columns" <| Test.specify "should work as shown in the doc examples" <| - expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] <| table.remove_columns ["bar", "foo"] + expect_column_names ["Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] <| table.remove_columns ["bar", "foo"] expect_column_names ["foo", "ab.+123", "abcd123"] <| table.remove_columns [By_Name "foo.+" Case_Sensitivity.Insensitive use_regex=True, By_Name "b.*" Case_Sensitivity.Insensitive use_regex=True] - expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123"] <| table.remove_columns [-1, 0, 1] + expect_column_names ["Baz", "foo 1", "foo 2", "ab.+123"] <| table.remove_columns [-1, 0, 1] Test.specify "should correctly handle regex matching" <| last_ones = table.columns.drop 1 . map .name expect_column_names last_ones <| table.remove_columns [By_Name "foo" Case_Sensitivity.Sensitive use_regex=True] - first_ones = ["foo", "bar", "Baz", "foo_1", "foo_2"] + first_ones = ["foo", "bar", "Baz", "foo 1", "foo 2"] expect_column_names first_ones <| table.remove_columns [By_Name "a.*" Case_Sensitivity.Sensitive use_regex=True] expect_column_names first_ones <| table.remove_columns [By_Name "ab.+123" Case_Sensitivity.Sensitive use_regex=True] expect_column_names first_ones+["abcd123"] <| table.remove_columns [By_Name "ab.+123"] expect_column_names first_ones+["ab.+123"] <| table.remove_columns [By_Name "abcd123" Case_Sensitivity.Sensitive use_regex=True] Test.specify "should allow negative indices" <| - expect_column_names ["Baz", "foo_1", "ab.+123"] <| table.remove_columns [-1, -3, 0, 1] + expect_column_names ["Baz", "foo 1", "ab.+123"] <| table.remove_columns [-1, -3, 0, 1] if test_selection.supports_case_sensitive_columns then Test.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <| @@ -173,7 +173,7 @@ spec setup = Test.specify "should correctly handle problems: out of bounds indices" <| selector = [1, 0, 100, -200, 300] action = table.remove_columns selector on_problems=_ - tester = expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] + tester = expect_column_names ["Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] problems = [Column_Indexes_Out_Of_Range.Error [100, -200, 300]] Problems.test_problem_handling action problems tester @@ -183,28 +183,28 @@ spec setup = Test.specify "should correctly handle edge-cases: duplicate indices" <| selector = [0, 0, 0] t = table.remove_columns selector on_problems=Problem_Behavior.Report_Error - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] t + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] t Test.specify "should correctly handle edge-cases: aliased indices" <| selector = [0, -7, -6, 1] t = table.remove_columns selector on_problems=Problem_Behavior.Report_Error - expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] t + expect_column_names ["Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] t Test.specify "should correctly handle edge-cases: duplicate names" <| selector = ["foo", "foo"] t = table.remove_columns selector on_problems=Problem_Behavior.Report_Error - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] t + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] t Test.specify "should correctly handle edge-cases: duplicate matches due to case insensitivity" <| selector = [By_Name "FOO", By_Name "foo"] t = table.remove_columns selector on_problems=Problem_Behavior.Report_Error - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] t + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] t Test.specify "should correctly handle problems: unmatched names" <| weird_name = '.*?-!@#!"' selector = ["foo", "hmm", weird_name] action = table.remove_columns selector on_problems=_ - tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] + tester = expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] problems = [Missing_Input_Columns.Error ["hmm", weird_name]] Problems.test_problem_handling action problems tester @@ -223,22 +223,22 @@ spec setup = Test.group prefix+"Table.reorder_columns" <| Test.specify "should work as shown in the doc examples" <| - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns "foo" Position.After_Other_Columns - expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo", "bar"] <| table.reorder_columns ["foo", "bar"] Position.After_Other_Columns - expect_column_names ["foo_1", "foo_2", "bar", "Baz", "foo", "ab.+123", "abcd123"] <| table.reorder_columns [By_Name "foo.+" Case_Sensitivity.Insensitive use_regex=True, By_Name "b.*" Case_Sensitivity.Insensitive use_regex=True] - expect_column_names ["bar", "foo", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] <| table.reorder_columns [1, 0] Position.Before_Other_Columns - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns [0] Position.After_Other_Columns + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns "foo" Position.After_Other_Columns + expect_column_names ["Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo", "bar"] <| table.reorder_columns ["foo", "bar"] Position.After_Other_Columns + expect_column_names ["foo 1", "foo 2", "bar", "Baz", "foo", "ab.+123", "abcd123"] <| table.reorder_columns [By_Name "foo.+" Case_Sensitivity.Insensitive use_regex=True, By_Name "b.*" Case_Sensitivity.Insensitive use_regex=True] + expect_column_names ["bar", "foo", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] <| table.reorder_columns [1, 0] Position.Before_Other_Columns + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns [0] Position.After_Other_Columns Test.specify "should correctly handle regex matching" <| - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns [By_Name "foo" Case_Sensitivity.Sensitive use_regex=True] Position.After_Other_Columns - rest = ["foo", "bar", "Baz", "foo_1", "foo_2"] + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns [By_Name "foo" Case_Sensitivity.Sensitive use_regex=True] Position.After_Other_Columns + rest = ["foo", "bar", "Baz", "foo 1", "foo 2"] expect_column_names ["ab.+123", "abcd123"]+rest <| table.reorder_columns [By_Name "a.*" Case_Sensitivity.Sensitive use_regex=True] expect_column_names ["ab.+123", "abcd123"]+rest <| table.reorder_columns [By_Name "ab.+123" Case_Sensitivity.Sensitive use_regex=True] expect_column_names ["ab.+123"]+rest+["abcd123"] <| table.reorder_columns ["ab.+123"] expect_column_names ["abcd123"]+rest+["ab.+123"] <| table.reorder_columns [By_Name "abcd123" Case_Sensitivity.Sensitive use_regex=True] Test.specify "should allow negative indices" <| - expect_column_names ["abcd123", "foo_2", "foo", "bar", "Baz", "foo_1", "ab.+123"] <| table.reorder_columns [-1, -3, 0, 1] + expect_column_names ["abcd123", "foo 2", "foo", "bar", "Baz", "foo 1", "ab.+123"] <| table.reorder_columns [-1, -3, 0, 1] if test_selection.supports_case_sensitive_columns then Test.specify "should correctly handle exact matches matching multiple names due to case insensitivity" <| @@ -250,12 +250,12 @@ spec setup = expect_column_names ["bar", "Bar", "foo"] <| table.reorder_columns [By_Name "bar"] Test.specify "should correctly handle regexes matching multiple names" <| - expect_column_names ["bar", "foo", "foo_1", "foo_2", "Baz", "ab.+123", "abcd123"] <| table.reorder_columns [By_Name "b.*" Case_Sensitivity.Sensitive use_regex=True, By_Name "f.+" Case_Sensitivity.Sensitive use_regex=True] + expect_column_names ["bar", "foo", "foo 1", "foo 2", "Baz", "ab.+123", "abcd123"] <| table.reorder_columns [By_Name "b.*" Case_Sensitivity.Sensitive use_regex=True, By_Name "f.+" Case_Sensitivity.Sensitive use_regex=True] Test.specify "should correctly handle problems: out of bounds indices" <| selector = [1, 0, 100, -200, 300] action = table.reorder_columns selector on_problems=_ - tester = expect_column_names ["bar", "foo", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] + tester = expect_column_names ["bar", "foo", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123"] problems = [Column_Indexes_Out_Of_Range.Error [100, -200, 300]] Problems.test_problem_handling action problems tester @@ -265,23 +265,23 @@ spec setup = Test.specify "should correctly handle edge-cases: duplicate indices" <| selector = [0, 0, 0] t = table.reorder_columns selector Position.After_Other_Columns on_problems=Problem_Behavior.Report_Error - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] t + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo"] t Test.specify "should correctly handle edge-cases: aliased indices" <| selector = [0, -7, -6, 1] t = table.reorder_columns selector Position.After_Other_Columns on_problems=Problem_Behavior.Report_Error - expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo", "bar"] t + expect_column_names ["Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo", "bar"] t Test.specify "should correctly handle edge-cases: duplicate names" <| selector = ["foo", "foo"] t = table.reorder_columns selector Position.After_Other_Columns on_problems=Problem_Behavior.Report_Error - expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] t + expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo"] t Test.specify "should correctly handle problems: unmatched names" <| weird_name = '.*?-!@#!"' selector = ["foo", "hmm", weird_name] action = table.reorder_columns selector Position.After_Other_Columns on_problems=_ - tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] + tester = expect_column_names ["bar", "Baz", "foo 1", "foo 2", "ab.+123", "abcd123", "foo"] problems = [Missing_Input_Columns.Error ["hmm", weird_name]] Problems.test_problem_handling action problems tester @@ -290,31 +290,31 @@ spec setup = Test.group prefix+"Table.sort_columns" <| table = - col1 = ["foo_21", [1,2,3]] - col2 = ["foo_100", [4,5,6]] - col3 = ["foo_1", [7,8,9]] - col4 = ["Foo_2", [10,11,12]] - col5 = ["foo_3", [13,14,15]] - col6 = ["foo_001", [16,17,18]] + col1 = ["foo 21", [1,2,3]] + col2 = ["foo 100", [4,5,6]] + col3 = ["foo 1", [7,8,9]] + col4 = ["Foo 2", [10,11,12]] + col5 = ["foo 3", [13,14,15]] + col6 = ["foo 001", [16,17,18]] col7 = ["bar", [19,20,21]] table_builder [col1, col2, col3, col4, col5, col6, col7] Test.specify "should work as shown in the doc examples" <| sorted = table.sort_columns - expect_column_names ["Foo_2", "bar", "foo_001", "foo_1", "foo_100", "foo_21", "foo_3"] sorted + expect_column_names ["Foo 2", "bar", "foo 001", "foo 1", "foo 100", "foo 21", "foo 3"] sorted sorted.columns.first.to_vector . should_equal [10,11,12] - expect_column_names ["bar", "foo_001", "foo_1", "Foo_2", "foo_3", "foo_21", "foo_100"] <| table.sort_columns text_ordering=(Text_Ordering.Case_Insensitive sort_digits_as_numbers=True) - expect_column_names ["foo_3", "foo_21", "foo_100", "foo_1", "foo_001", "bar", "Foo_2"] <| table.sort_columns Sort_Direction.Descending + expect_column_names ["bar", "foo 001", "foo 1", "Foo 2", "foo 3", "foo 21", "foo 100"] <| table.sort_columns text_ordering=(Text_Ordering.Case_Insensitive sort_digits_as_numbers=True) + expect_column_names ["foo 3", "foo 21", "foo 100", "foo 1", "foo 001", "bar", "Foo 2"] <| table.sort_columns Sort_Direction.Descending Test.specify "should correctly handle case-insensitive sorting" <| - expect_column_names ["bar", "foo_001", "foo_1", "foo_100", "Foo_2", "foo_21", "foo_3"] <| table.sort_columns text_ordering=(Text_Ordering.Case_Insensitive) + expect_column_names ["bar", "foo 001", "foo 1", "foo 100", "Foo 2", "foo 21", "foo 3"] <| table.sort_columns text_ordering=(Text_Ordering.Case_Insensitive) Test.specify "should correctly handle natural order sorting" <| - expect_column_names ["Foo_2", "bar", "foo_001", "foo_1", "foo_3", "foo_21", "foo_100"] <| table.sort_columns text_ordering=(Text_Ordering.Default sort_digits_as_numbers=True) + expect_column_names ["Foo 2", "bar", "foo 001", "foo 1", "foo 3", "foo 21", "foo 100"] <| table.sort_columns text_ordering=(Text_Ordering.Default sort_digits_as_numbers=True) Test.specify "should correctly handle various combinations of options" <| - expect_column_names ["foo_100", "foo_21", "foo_3", "Foo_2", "foo_1", "foo_001", "bar"] <| table.sort_columns Sort_Direction.Descending text_ordering=(Text_Ordering.Case_Insensitive sort_digits_as_numbers=True) + expect_column_names ["foo 100", "foo 21", "foo 3", "Foo 2", "foo 1", "foo 001", "bar"] <| table.sort_columns Sort_Direction.Descending text_ordering=(Text_Ordering.Case_Insensitive sort_digits_as_numbers=True) Test.group prefix+"Table.rename_columns" <| table = @@ -441,41 +441,41 @@ spec setup = Test.specify "should correctly handle problems: invalid names ''" <| map = Map.from_vector [[1, ""]] action = table.rename_columns map on_problems=_ - tester = expect_column_names ["alpha", "Column_1", "gamma", "delta"] + tester = expect_column_names ["alpha", "Column 1", "gamma", "delta"] problems = [Invalid_Output_Column_Names.Error [""]] Problems.test_problem_handling action problems tester Test.specify "should correctly handle problems: invalid names Nothing" <| map = ["alpha", Nothing] action = table.rename_columns map on_problems=_ - tester = expect_column_names ["alpha", "Column_1", "gamma", "delta"] + tester = expect_column_names ["alpha", "Column 1", "gamma", "delta"] problems = [Invalid_Output_Column_Names.Error [Nothing]] Problems.test_problem_handling action problems tester Test.specify "should correctly handle problems: invalid names null character" <| map = ["alpha", 'a\0b'] action = table.rename_columns map on_problems=_ - tester = expect_column_names ["alpha", "Column_1", "gamma", "delta"] + tester = expect_column_names ["alpha", "Column 1", "gamma", "delta"] problems = [Invalid_Output_Column_Names.Error ['a\0b']] Problems.test_problem_handling action problems tester Test.specify "should correctly handle problems: duplicate names" <| map = ["Test", "Test", "Test", "Test"] action = table.rename_columns map on_problems=_ - tester = expect_column_names ["Test", "Test_1", "Test_2", "Test_3"] + tester = expect_column_names ["Test", "Test 1", "Test 2", "Test 3"] problems = [Duplicate_Output_Column_Names.Error ["Test", "Test", "Test"]] Problems.test_problem_handling action problems tester Test.specify "should correctly handle problems: new name is clashing with existing name of existing column" <| map = Map.from_vector [["alpha", "beta"]] action = table.rename_columns map on_problems=_ - tester = expect_column_names ["beta", "beta_1", "gamma", "delta"] + tester = expect_column_names ["beta", "beta 1", "gamma", "delta"] problems = [Duplicate_Output_Column_Names.Error ["beta"]] Problems.test_problem_handling action problems tester map2 = Map.from_vector [["beta", "alpha"]] action2 = table.rename_columns map2 on_problems=_ - tester2 = expect_column_names ["alpha_1", "alpha", "gamma", "delta"] + tester2 = expect_column_names ["alpha 1", "alpha", "gamma", "delta"] problems2 = [Duplicate_Output_Column_Names.Error ["alpha"]] Problems.test_problem_handling action2 problems2 tester2 diff --git a/test/Table_Tests/src/Common_Table_Operations/Transpose_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Transpose_Spec.enso index 4a3d340b673..1fa3b63e4f0 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Transpose_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Transpose_Spec.enso @@ -73,18 +73,18 @@ spec setup = Test.specify "should handle missing columns" <| t1 = table_builder [["Key", ["x", "y", "z"]], ["Value", [1, 2, 3]], ["Another", [10, Nothing, 20]]] - err1 = t1.transpose ["Key", "Missing", "Missing_2"] + err1 = t1.transpose ["Key", "Missing", "Missing 2"] err1.should_fail_with Missing_Input_Columns - err1.catch.criteria . should_equal ["Missing", "Missing_2"] + err1.catch.criteria . should_equal ["Missing", "Missing 2"] err2 = t1.transpose [0, -1, 42, -100] err2.should_fail_with Column_Indexes_Out_Of_Range err2.catch.indexes . should_equal [42, -100] - action1 = t1.transpose ["Key", "Missing", "Missing_2"] error_on_missing_columns=False on_problems=_ + action1 = t1.transpose ["Key", "Missing", "Missing 2"] error_on_missing_columns=False on_problems=_ tester1 table = table.column_names . should_equal ["Key", "Name", "Value"] - problems1 = [Missing_Input_Columns.Error ["Missing", "Missing_2"]] + problems1 = [Missing_Input_Columns.Error ["Missing", "Missing 2"]] Problems.test_problem_handling action1 problems1 tester1 action2 = t1.transpose [0, -1, 42, -100] error_on_missing_columns=False on_problems=_ @@ -98,13 +98,13 @@ spec setup = action1 = t1.transpose ["X", "Y", "Z"] name_field="Y" value_field="Z" on_problems=_ tester1 table = - table.column_names . should_equal ["X", "Y", "Z", "Y_1", "Z_1"] + table.column_names . should_equal ["X", "Y", "Z", "Y 1", "Z 1"] problems1 = [Duplicate_Output_Column_Names.Error ["Y", "Z"]] Problems.test_problem_handling action1 problems1 tester1 action2 = t1.transpose ["X"] name_field="F" value_field="F" on_problems=_ tester2 table = - table.column_names . should_equal ["X", "F", "F_1"] + table.column_names . should_equal ["X", "F", "F 1"] problems2 = [Duplicate_Output_Column_Names.Error ["F"]] Problems.test_problem_handling action2 problems2 tester2 diff --git a/test/Table_Tests/src/Database/Codegen_Spec.enso b/test/Table_Tests/src/Database/Codegen_Spec.enso index cdc4e6b8f51..f2f12b50ec7 100644 --- a/test/Table_Tests/src/Database/Codegen_Spec.enso +++ b/test/Table_Tests/src/Database/Codegen_Spec.enso @@ -115,9 +115,9 @@ spec = Test.group "Helpers" <| Test.specify "fresh_names should provide fresh names" <| - used_names = ["A", "A_1"] + used_names = ["A", "A 1"] preferred_names = ["A", "A", "B"] - fresh_names used_names preferred_names . should_equal ["A_2", "A_3", "B"] + fresh_names used_names preferred_names . should_equal ["A 2", "A 3", "B"] Test.group "[Codegen] Aggregation" <| Test.specify "should allow to count rows" <| diff --git a/test/Table_Tests/src/Database/Upload_Spec.enso b/test/Table_Tests/src/Database/Upload_Spec.enso index 3e3f0bfba7b..57ec8feb107 100644 --- a/test/Table_Tests/src/Database/Upload_Spec.enso +++ b/test/Table_Tests/src/Database/Upload_Spec.enso @@ -34,7 +34,7 @@ spec make_new_connection prefix persistent_connector=True = Test.group prefix+"Uploading an in-memory Table" <| in_memory_table = Table.new [["X", [1, 2, 3]], ["Y", ['a', 'b', 'c']]] Test.specify "should include the created table in the tables directory" <| - db_table = in_memory_table.create_database_table connection (Name_Generator.random_name "permanent_table_1") temporary=False + db_table = in_memory_table.create_database_table connection (Name_Generator.random_name "permanent_table 1") temporary=False Panic.with_finalizer (connection.drop_table db_table.name) <| db_table.at "X" . to_vector . should_equal [1, 2, 3] @@ -42,7 +42,7 @@ spec make_new_connection prefix persistent_connector=True = connection.query db_table.name . at "X" . to_vector . should_equal [1, 2, 3] Test.specify "should include the temporary table in the tables directory" <| - db_table = in_memory_table.create_database_table connection (Name_Generator.random_name "temporary_table_1") temporary=True + db_table = in_memory_table.create_database_table connection (Name_Generator.random_name "temporary_table 1") temporary=True db_table.at "X" . to_vector . should_equal [1, 2, 3] connection.tables.at "Name" . to_vector . should_contain db_table.name connection.query db_table.name . at "X" . to_vector . should_equal [1, 2, 3] @@ -50,7 +50,7 @@ spec make_new_connection prefix persistent_connector=True = if persistent_connector then Test.specify "should drop the temporary table after the connection is closed" <| tmp_connection = make_new_connection Nothing - db_table = in_memory_table.create_database_table tmp_connection (Name_Generator.random_name "temporary_table_2") temporary=True + db_table = in_memory_table.create_database_table tmp_connection (Name_Generator.random_name "temporary_table 2") temporary=True name = db_table.name tmp_connection.query (SQL_Query.Table_Name name) . at "X" . to_vector . should_equal [1, 2, 3] tmp_connection.close @@ -58,7 +58,7 @@ spec make_new_connection prefix persistent_connector=True = Test.specify "should preserve the regular table after the connection is closed" <| tmp_connection = make_new_connection Nothing - db_table = in_memory_table.create_database_table tmp_connection (Name_Generator.random_name "permanent_table_1") temporary=False + db_table = in_memory_table.create_database_table tmp_connection (Name_Generator.random_name "permanent_table 1") temporary=False name = db_table.name Panic.with_finalizer (connection.drop_table name) <| tmp_connection.query (SQL_Query.Table_Name name) . at "X" . to_vector . should_equal [1, 2, 3] @@ -143,11 +143,11 @@ spec make_new_connection prefix persistent_connector=True = db_table_4 = db_table_2.join db_table_3 join_kind=Join_Kind.Left_Outer copied_table = db_table_4.create_database_table connection (Name_Generator.random_name "copied-table") temporary=True primary_key=Nothing - copied_table.column_names . should_equal ["X", "Y", "C1", "C2", "Right_X", "C3"] + copied_table.column_names . should_equal ["X", "Y", "C1", "C2", "Right X", "C3"] copied_table.at "X" . to_vector . should_equal [1, 1, 2] copied_table.at "C1" . to_vector . should_equal [101, 102, 203] copied_table.at "C2" . to_vector . should_equal ["constant_text", "constant_text", "constant_text"] - copied_table.at "Right_X" . to_vector . should_equal [Nothing, Nothing, 2] + copied_table.at "Right X" . to_vector . should_equal [Nothing, Nothing, 2] copied_table.at "C3" . to_vector . should_equal [Nothing, Nothing, 5] # We check that this is indeed querying a simple DB table and not a complex query like `db_table_4` would be, diff --git a/test/Table_Tests/src/Helpers/Unique_Naming_Strategy_Spec.enso b/test/Table_Tests/src/Helpers/Unique_Naming_Strategy_Spec.enso index 2bc8d7f5d6c..c9d3ef258fd 100644 --- a/test/Table_Tests/src/Helpers/Unique_Naming_Strategy_Spec.enso +++ b/test/Table_Tests/src/Helpers/Unique_Naming_Strategy_Spec.enso @@ -30,28 +30,28 @@ spec = Test.specify 'should rename duplicates names' <| strategy = Unique_Name_Strategy.new strategy.make_unique "A" . should_equal "A" - strategy.make_unique "A" . should_equal "A_1" - strategy.make_unique "A" . should_equal "A_2" + strategy.make_unique "A" . should_equal "A 1" + strategy.make_unique "A" . should_equal "A 2" strategy.renames.length . should_equal 2 strategy.invalid_names.length . should_equal 0 Test.specify 'should preserve existing suffix' <| strategy = Unique_Name_Strategy.new strategy.make_unique "A" . should_equal "A" - strategy.make_unique "A_1" . should_equal "A_1" - strategy.make_unique "A" . should_equal "A_2" - strategy.make_unique "A_1" . should_equal "A_1_1" + strategy.make_unique "A 1" . should_equal "A 1" + strategy.make_unique "A" . should_equal "A 2" + strategy.make_unique "A 1" . should_equal "A 1 1" strategy.renames.length . should_equal 2 strategy.invalid_names.length . should_equal 0 Test.specify "should always add a counter when renaming invalid names" <| strategy = Unique_Name_Strategy.new - strategy.make_unique "" . should_equal "Column_1" - strategy.make_unique "" . should_equal "Column_2" - strategy.make_unique Nothing . should_equal "Column_3" + strategy.make_unique "" . should_equal "Column 1" + strategy.make_unique "" . should_equal "Column 2" + strategy.make_unique Nothing . should_equal "Column 3" strategy.make_unique "Foo" . should_equal "Foo" strategy.make_unique "Column" . should_equal "Column" - strategy.make_unique "" . should_equal "Column_4" + strategy.make_unique "" . should_equal "Column 4" Test.specify 'should work as in examples' <| unique_name_strategy = Unique_Name_Strategy.new @@ -60,19 +60,19 @@ spec = invalid = unique_name_strategy.invalid_names duplicates.should_equal ["A"] invalid.should_equal [""] - unique_names.should_equal ["A", "B", "A_1", "Column_1"] + unique_names.should_equal ["A", "B", "A 1", "Column 1"] strategy_1 = Unique_Name_Strategy.new strategy_1.make_unique "A" . should_equal "A" - strategy_1.make_unique "A" . should_equal "A_1" + strategy_1.make_unique "A" . should_equal "A 1" Test.group "Unique_Name_Strategy.combine_with_prefix" <| Test.specify "should work as in examples" <| strategy = Unique_Name_Strategy.new first = ["A", "B", "second_A"] - second = ["A", "B", "second_A_1", "C"] + second = ["A", "B", "second_A 1", "C"] unique_second = strategy.combine_with_prefix first second "second_" - unique_second . should_equal ["second_A_2", "second_B", "second_A_1", "C"] + unique_second . should_equal ["second_A 2", "second_B", "second_A 1", "C"] strategy.invalid_names . should_equal [] strategy.renames . should_equal ["second_A"] @@ -81,7 +81,7 @@ spec = second = ["B", "A", "C"] strategy = Unique_Name_Strategy.new r = strategy.combine_with_prefix first second "" - r . should_equal ["B_1", "A_1", "C"] + r . should_equal ["B 1", "A 1", "C"] Test.specify "should work for empty input" <| Unique_Name_Strategy.new.combine_with_prefix [] [] "" . should_equal [] @@ -89,34 +89,34 @@ spec = Unique_Name_Strategy.new.combine_with_prefix [] ["a"] "" . should_equal ["a"] Test.specify "should find the first free spot" <| - Unique_Name_Strategy.new.combine_with_prefix ["A", "A_1", "A_2"] ["A"] "" . should_equal ["A_3"] - Unique_Name_Strategy.new.combine_with_prefix ["A", "A_1", "A_2"] ["A_4", "A_6", "A_100", "A", "A_3"] "" . should_equal ["A_4", "A_6", "A_100", "A_5", "A_3"] + Unique_Name_Strategy.new.combine_with_prefix ["A", "A 1", "A 2"] ["A"] "" . should_equal ["A 3"] + Unique_Name_Strategy.new.combine_with_prefix ["A", "A 1", "A 2"] ["A 4", "A 6", "A 100", "A", "A 3"] "" . should_equal ["A 4", "A 6", "A 100", "A 5", "A 3"] - Unique_Name_Strategy.new.combine_with_prefix ["A", "A_1", "A_2"] ["A"] "P_" . should_equal ["P_A"] - Unique_Name_Strategy.new.combine_with_prefix ["A", "A_1", "A_2", "P_A"] ["A"] "P_" . should_equal ["P_A_1"] - Unique_Name_Strategy.new.combine_with_prefix ["A", "A_1", "A_2", "P_A_1"] ["A"] "P_" . should_equal ["P_A"] - Unique_Name_Strategy.new.combine_with_prefix ["A", "A_1", "A_2", "P_A_1"] ["A", "P_A", "P_A_2"] "P_" . should_equal ["P_A_3", "P_A", "P_A_2"] + Unique_Name_Strategy.new.combine_with_prefix ["A", "A 1", "A 2"] ["A"] "P_" . should_equal ["P_A"] + Unique_Name_Strategy.new.combine_with_prefix ["A", "A 1", "A 2", "P_A"] ["A"] "P_" . should_equal ["P_A 1"] + Unique_Name_Strategy.new.combine_with_prefix ["A", "A 1", "A 2", "P_A 1"] ["A"] "P_" . should_equal ["P_A"] + Unique_Name_Strategy.new.combine_with_prefix ["A", "A 1", "A 2", "P_A 1"] ["A", "P_A", "P_A 2"] "P_" . should_equal ["P_A 3", "P_A", "P_A 2"] Test.specify "will add a prefix/suffix, not increment an existing counter" <| - first = ["A", "A_1", "A_2", "A_3"] - Unique_Name_Strategy.new.combine_with_prefix first ["A_2"] "P_" . should_equal ["P_A_2"] - Unique_Name_Strategy.new.combine_with_prefix first ["A_2"] "" . should_equal ["A_2_1"] - Unique_Name_Strategy.new.combine_with_prefix first+["P_A_2"] ["A_2"] "P_" . should_equal ["P_A_2_1"] + first = ["A", "A 1", "A 2", "A 3"] + Unique_Name_Strategy.new.combine_with_prefix first ["A 2"] "P_" . should_equal ["P_A 2"] + Unique_Name_Strategy.new.combine_with_prefix first ["A 2"] "" . should_equal ["A 2 1"] + Unique_Name_Strategy.new.combine_with_prefix first+["P_A 2"] ["A 2"] "P_" . should_equal ["P_A 2 1"] Test.specify "should prioritize existing names when renaming conflicts and rename only ones that are clashing with the other list" <| first = ["A", "B"] - second = ["B", "A", "B_1", "C", "B_2", "B_4"] + second = ["B", "A", "B 1", "C", "B 2", "B_4"] strategy = Unique_Name_Strategy.new r = strategy.combine_with_prefix first second "" - r . should_equal ["B_3", "A_1", "B_1", "C", "B_2", "B_4"] + r . should_equal ["B 3", "A 1", "B 1", "C", "B 2", "B_4"] strategy.invalid_names . should_equal [] strategy.renames . should_equal ["B", "A"] r2 = Unique_Name_Strategy.new.combine_with_prefix first second "P_" - r2 . should_equal ["P_B", "P_A", "B_1", "C", "B_2", "B_4"] + r2 . should_equal ["P_B", "P_A", "B 1", "C", "B 2", "B_4"] - third = ["B", "A", "P_B", "X", "P_B_1", "P_B_2"] + third = ["B", "A", "P_B", "X", "P_B 1", "P_B 2"] r3 = Unique_Name_Strategy.new.combine_with_prefix first third "P_" - r3 . should_equal ["P_B_3", "P_A", "P_B", "X", "P_B_1", "P_B_2"] + r3 . should_equal ["P_B 3", "P_A", "P_B", "X", "P_B 1", "P_B 2"] main = Test_Suite.run_main spec diff --git a/test/Table_Tests/src/IO/Csv_Spec.enso b/test/Table_Tests/src/IO/Csv_Spec.enso index 7bfbf817c17..56b8f0377d1 100644 --- a/test/Table_Tests/src/IO/Csv_Spec.enso +++ b/test/Table_Tests/src/IO/Csv_Spec.enso @@ -29,13 +29,13 @@ spec = Test.specify "should correctly infer types of varied-type columns" <| varied_column = (enso_project.data / "varied_column.csv") . read - c_1 = ["Column_1", ["2005-02-25", "2005-02-28", "4", "2005-03-02", Nothing, "2005-03-04", "2005-03-07", "2005-03-08"]] + c_1 = ["Column 1", ["2005-02-25", "2005-02-28", "4", "2005-03-02", Nothing, "2005-03-04", "2005-03-07", "2005-03-08"]] # We can re-enable this once date support is improved. - #c_2 = ["Column_2", ["2005-02-25", "2005-02-28", "2005-03-01", Nothing, "2005-03-03", "2005-03-04", "2005-03-07", "2005-03-08"]] - c_3 = ["Column_3", [1, 2, 3, 4, 5, Nothing, 7, 8]] - c_4 = ["Column_4", [1, 2, 3, 4, 5, 6, 7, 8]] - c_5 = ["Column_5", [1.0, 2.0, 3.0, 4.0, 5.0, 6.25, 7.0, 8.0]] - c_6 = ["Column_6", ['1', '2', '3', '4', '5', '6.25', '7', 'osiem']] + #c_2 = ["Column 2", ["2005-02-25", "2005-02-28", "2005-03-01", Nothing, "2005-03-03", "2005-03-04", "2005-03-07", "2005-03-08"]] + c_3 = ["Column 3", [1, 2, 3, 4, 5, Nothing, 7, 8]] + c_4 = ["Column 4", [1, 2, 3, 4, 5, 6, 7, 8]] + c_5 = ["Column 5", [1.0, 2.0, 3.0, 4.0, 5.0, 6.25, 7.0, 8.0]] + c_6 = ["Column 6", ['1', '2', '3', '4', '5', '6.25', '7', 'osiem']] expected = Table.new [c_1, c_3, c_4, c_5, c_6] varied_column.select_columns [0, 2, 3, 4, 5] . should_equal expected @@ -45,14 +45,14 @@ spec = name,x,y,x,y foo,10,20,30,20 t = Table.from csv (format = Delimited ",") - t.columns.map .name . should_equal ['name', 'x', 'y', 'x_1', 'y_1'] + t.columns.map .name . should_equal ['name', 'x', 'y', 'x 1', 'y 1'] Test.group 'Writing' <| Test.specify 'should properly serialize simple tables' <| varied_column = (enso_project.data / "varied_column.csv") . read res = Text.from varied_column format=(Delimited ",") exp = normalize_lines <| ''' - Column_1,Column_2,Column_3,Column_4,Column_5,Column_6 + Column 1,Column 2,Column 3,Column 4,Column 5,Column 6 2005-02-25,2005-02-25,1,1,1.0,1 2005-02-28,2005-02-28,2,2,2.0,2 4,2005-03-01,3,3,3.0,3 @@ -98,7 +98,7 @@ spec = out.delete_if_exists varied_column.write out exp = normalize_lines <| ''' - Column_1,Column_2,Column_3,Column_4,Column_5,Column_6 + Column 1,Column 2,Column 3,Column 4,Column 5,Column 6 2005-02-25,2005-02-25,1,1,1.0,1 2005-02-28,2005-02-28,2,2,2.0,2 4,2005-03-01,3,3,3.0,3 diff --git a/test/Table_Tests/src/IO/Delimited_Read_Spec.enso b/test/Table_Tests/src/IO/Delimited_Read_Spec.enso index f13068001b9..6237f164c44 100644 --- a/test/Table_Tests/src/IO/Delimited_Read_Spec.enso +++ b/test/Table_Tests/src/IO/Delimited_Read_Spec.enso @@ -25,9 +25,9 @@ spec = simple_empty.should_equal expected_table Test.specify "should load a simple table without headers" <| - c_1 = ["Column_1", ['a', '1', '4', '7', '10']] - c_2 = ["Column_2", ['b', '2', Nothing, '8', '11']] - c_3 = ["Column_3", ['c', Nothing, '6', '9', '12']] + c_1 = ["Column 1", ['a', '1', '4', '7', '10']] + c_2 = ["Column 2", ['b', '2', Nothing, '8', '11']] + c_3 = ["Column 3", ['c', Nothing, '6', '9', '12']] expected_table = Table.new [c_1, c_2, c_3] simple_empty = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=False value_formatter=Nothing) simple_empty.should_equal expected_table @@ -35,11 +35,11 @@ spec = Test.specify "should work in presence of missing headers" <| action on_problems = Data.read (enso_project.data / "missing_header.csv") (Delimited "," headers=True value_formatter=Nothing) on_problems tester table = - table.columns.map .name . should_equal ["a", "Column_1", "c", "Column_2", "d"] + table.columns.map .name . should_equal ["a", "Column 1", "c", "Column 2", "d"] table.at "a" . to_vector . should_equal ["1"] - table.at "Column_1" . to_vector . should_equal ["2"] + table.at "Column 1" . to_vector . should_equal ["2"] table.at "c" . to_vector . should_equal ["3"] - table.at "Column_2" . to_vector . should_equal ["4"] + table.at "Column 2" . to_vector . should_equal ["4"] table.at "d" . to_vector . should_equal ["5"] problems = [Invalid_Output_Column_Names.Error [Nothing, Nothing]] Problems.test_problem_handling action problems tester @@ -49,9 +49,9 @@ spec = t1.columns.map .name . should_equal ["Code", "Index", "Flag", "Value", "ValueWithNothing", "TextWithNothing", "Hexadecimal", "Leading0s", "QuotedNumbers", "Mixed Types"] t2 = Data.read (enso_project.data / "all_text.csv") (Delimited ",") - t2.columns.map .name . should_equal ["Column_1", "Column_2"] - t2.at "Column_1" . to_vector . should_equal ["a", "c", "e", "g"] - t2.at "Column_2" . to_vector . should_equal ["b", "d", "f", "h"] + t2.columns.map .name . should_equal ["Column 1", "Column 2"] + t2.at "Column 1" . to_vector . should_equal ["a", "c", "e", "g"] + t2.at "Column 2" . to_vector . should_equal ["b", "d", "f", "h"] t3 = Data.read (enso_project.data / "two_rows1.csv") (Delimited ",") t3.columns.map .name . should_equal ["a", "b", "c"] @@ -60,16 +60,16 @@ spec = t3.at "c" . to_vector . should_equal [Nothing] t4 = Data.read (enso_project.data / "two_rows2.csv") (Delimited ",") - t4.columns.map .name . should_equal ["Column_1", "Column_2", "Column_3"] - t4.at "Column_1" . to_vector . should_equal ["a", "d"] - t4.at "Column_2" . to_vector . should_equal ["b", "e"] - t4.at "Column_3" . to_vector . should_equal ["c", "f"] + t4.columns.map .name . should_equal ["Column 1", "Column 2", "Column 3"] + t4.at "Column 1" . to_vector . should_equal ["a", "d"] + t4.at "Column 2" . to_vector . should_equal ["b", "e"] + t4.at "Column 3" . to_vector . should_equal ["c", "f"] t5 = Data.read (enso_project.data / "numbers_in_header.csv") (Delimited ",") - t5.columns.map .name . should_equal ["Column_1", "Column_2", "Column_3"] - t5.at "Column_1" . to_vector . should_equal ["a", "1"] - t5.at "Column_2" . to_vector . should_equal ["b", "2"] - t5.at "Column_3" . to_vector . should_equal [0, 3] + t5.columns.map .name . should_equal ["Column 1", "Column 2", "Column 3"] + t5.at "Column 1" . to_vector . should_equal ["a", "1"] + t5.at "Column 2" . to_vector . should_equal ["b", "2"] + t5.at "Column 3" . to_vector . should_equal [0, 3] t6 = Data.read (enso_project.data / "quoted_numbers_in_header.csv") (Delimited ",") t6.columns.map .name . should_equal ["1", "x"] @@ -78,10 +78,10 @@ spec = Test.specify "should not use the first row as headers if it is the only row, unless specifically asked to" <| t1 = Data.read (enso_project.data / "one_row.csv") (Delimited ",") - t1.columns.map .name . should_equal ["Column_1", "Column_2", "Column_3"] - t1.at "Column_1" . to_vector . should_equal ["x"] - t1.at "Column_2" . to_vector . should_equal ["y"] - t1.at "Column_3" . to_vector . should_equal ["z"] + t1.columns.map .name . should_equal ["Column 1", "Column 2", "Column 3"] + t1.at "Column 1" . to_vector . should_equal ["x"] + t1.at "Column 2" . to_vector . should_equal ["y"] + t1.at "Column 3" . to_vector . should_equal ["z"] t2 = Data.read (enso_project.data / "one_row.csv") (Delimited "," headers=True) t2.columns.map .name . should_equal ["x", "y", "z"] @@ -138,10 +138,10 @@ spec = format = Delimited ',' headers=False value_formatter=(Data_Formatter.Value trim_values=False) - reference_table = Table.new [["Column_1", ["a", "d", "1"]], ["Column_2", ["b", "e", "2"]], ["Column_3", ["c", "f", "3"]]] + reference_table = Table.new [["Column 1", ["a", "d", "1"]], ["Column 2", ["b", "e", "2"]], ["Column 3", ["c", "f", "3"]]] collapsed_table = Table.new <| ['a', 'b', 'c\nd', 'e', 'f\n1', 2, 3].map_with_index i-> v-> - ["Column_" + (i+1).to_text, [v]] + ["Column " + (i+1).to_text, [v]] Data.read file format . should_equal reference_table Data.read file (format.with_line_endings Line_Ending_Style.Unix) . should_equal reference_table Data.read file (format.with_line_endings Line_Ending_Style.Mac_Legacy) . should_equal collapsed_table @@ -201,9 +201,9 @@ spec = Test.specify "should handle duplicated columns" <| action on_problems = Data.read (enso_project.data / "duplicated_columns.csv") (Delimited "," headers=True value_formatter=Nothing) on_problems tester table = - table.columns.map .name . should_equal ['a', 'b', 'c', 'a_1'] + table.columns.map .name . should_equal ['a', 'b', 'c', 'a 1'] table.at 'a' . to_vector . should_equal ['1'] - table.at 'a_1' . to_vector . should_equal ['4'] + table.at 'a 1' . to_vector . should_equal ['4'] problems = [Duplicate_Output_Column_Names.Error ['a']] Problems.test_problem_handling action problems tester @@ -337,7 +337,7 @@ spec = Test.specify "should allow to skip rows" <| t1 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=False skip_rows=3 value_formatter=Nothing) - t1.at "Column_1" . to_vector . should_equal ['7', '10'] + t1.at "Column 1" . to_vector . should_equal ['7', '10'] t2 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=True skip_rows=3 value_formatter=Nothing) t2.columns.map .name . should_equal ['7', '8', '9'] @@ -345,16 +345,16 @@ spec = Test.specify "should allow to set a limit of rows to read" <| t1 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=False row_limit=2 value_formatter=Nothing) - t1.at "Column_1" . to_vector . should_equal ['a', '1'] + t1.at "Column 1" . to_vector . should_equal ['a', '1'] t2 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=True row_limit=2 value_formatter=Nothing) t2.at "a" . to_vector . should_equal ['1', '4'] t3 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=False skip_rows=3 row_limit=1 value_formatter=Nothing) - t3.at "Column_1" . to_vector . should_equal ['7'] + t3.at "Column 1" . to_vector . should_equal ['7'] t4 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=False row_limit=0 value_formatter=Nothing) - t4.columns.map .name . should_equal ['Column_1', 'Column_2', 'Column_3'] + t4.columns.map .name . should_equal ['Column 1', 'Column 2', 'Column 3'] t4.row_count . should_equal 0 t5 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=True row_limit=0 value_formatter=Nothing) @@ -363,7 +363,7 @@ spec = t5.row_count . should_equal 0 t6 = Data.read (enso_project.data / "simple_empty.csv") (Delimited "," headers=False skip_rows=3 row_limit=1000 value_formatter=Nothing) - t6.at "Column_1" . to_vector . should_equal ['7', '10'] + t6.at "Column 1" . to_vector . should_equal ['7', '10'] Test.specify "should check arguments" <| path = (enso_project.data / "simple_empty.csv") diff --git a/test/Table_Tests/src/IO/Delimited_Write_Spec.enso b/test/Table_Tests/src/IO/Delimited_Write_Spec.enso index 086ebc14fa1..3f57f964d4b 100644 --- a/test/Table_Tests/src/IO/Delimited_Write_Spec.enso +++ b/test/Table_Tests/src/IO/Delimited_Write_Spec.enso @@ -347,7 +347,7 @@ spec = with_headers = base_format . with_headers expected_table_with_headers = Table.new [["A", [1,2,33,44]], ["B", [1.0,1.5,Nothing,0]], ["C", ["x","y","a","BB"]]] - expected_table_without_headers = expected_table_with_headers.rename_columns ["Column_1", "Column_2", "Column_3"] + expected_table_without_headers = expected_table_with_headers.rename_columns ["Column 1", "Column 2", "Column 3"] test_append initial_file_format=with_headers append_format=no_headers expected_table_with_headers test_append initial_file_format=with_headers append_format=base_format expected_table_with_headers diff --git a/test/Table_Tests/src/IO/Excel_Spec.enso b/test/Table_Tests/src/IO/Excel_Spec.enso index 9daa23cf7d6..239b449363c 100644 --- a/test/Table_Tests/src/IO/Excel_Spec.enso +++ b/test/Table_Tests/src/IO/Excel_Spec.enso @@ -47,8 +47,8 @@ spec_fmt header file read_method sheet_count=5 = Test.specify "should gracefully handle duplicate column names and formulas" <| t = read_method file (Excel (Worksheet "Duplicate Columns")) - t.columns.map .name . should_equal ['Item', 'Price', 'Quantity', 'Price_1'] - t.at 'Price_1' . to_vector . should_equal [20, 40, 0, 60, 0, 10] + t.columns.map .name . should_equal ['Item', 'Price', 'Quantity', 'Price 1'] + t.at 'Price 1' . to_vector . should_equal [20, 40, 0, 60, 0, 10] Test.specify "should allow reading with cell range specified" <| t_1 = read_method file (Excel (Cell_Range "Simple!B:C")) @@ -292,8 +292,8 @@ spec_write suffix test_sheet_name = Test.specify 'should be able to append to a range by name after deduplication of names' <| out.delete_if_exists (enso_project.data / test_sheet_name) . copy_to out - extra_another = Table.new [['AA', ['d', 'e']], ['BB',[4, 5]], ['AA_1',[True, False]], ['BB_1', ['2022-01-20', '2022-01-21']]] - expected = Table.new [['AA', ['f', 'g', 'h', 'd', 'e']], ['BB',[1, 2, 3, 4, 5]], ['AA_1',[True, False, False, True, False]]] + extra_another = Table.new [['AA', ['d', 'e']], ['BB',[4, 5]], ['AA 1',[True, False]], ['BB 1', ['2022-01-20', '2022-01-21']]] + expected = Table.new [['AA', ['f', 'g', 'h', 'd', 'e']], ['BB',[1, 2, 3, 4, 5]], ['AA 1',[True, False, False, True, False]]] extra_another.write out (Excel (Cell_Range "Random!S3")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed written = out.read (Excel (Cell_Range "Random!S3")) . select_columns [0, 1, 2] written.should_equal expected @@ -725,10 +725,10 @@ spec = check_table (file.read (Excel (Cell_Range "Sheet1!B2"))) ["B"] [["A","B","C","D","E","F"]] Test.specify "Patchy table" <| - check_table (file.read (Excel (Cell_Range "Sheet1!D1"))) ["A", "B", "Column_1"] [[1,2,4], [4,4,Nothing], [6,Nothing,6]] + check_table (file.read (Excel (Cell_Range "Sheet1!D1"))) ["A", "B", "Column 1"] [[1,2,4], [4,4,Nothing], [6,Nothing,6]] check_table (file.read (Excel (Cell_Range "Sheet1!D2"))) ["D", "E", "F"] [[1,2,4], [4,4,Nothing], [6,Nothing,6]] check_table (file.read (Excel (Cell_Range "Sheet1!E"))) ["B"] [[4,4,Nothing,Nothing,Nothing,Nothing]] - check_table (file.read (Excel (Cell_Range "Sheet1!E1"))) ["B", "Column_1"] [[4,4,Nothing], [6,Nothing,6]] + check_table (file.read (Excel (Cell_Range "Sheet1!E1"))) ["B", "Column 1"] [[4,4,Nothing], [6,Nothing,6]] check_table (file.read (Excel (Cell_Range "Sheet1!E2"))) ["E", "F"] [[4,4,Nothing], [6,Nothing,6]] Test.specify "Single cell" <| @@ -739,19 +739,19 @@ spec = check_table (file.read (Excel (Cell_Range "Sheet1!J1"))) ["J", "K", "L"] [["Just"],["Some"],["Headers"]] Test.specify "Growing table" <| - check_table (file.read (Excel (Cell_Range "Sheet1!N1"))) ["A", "Full", "Table", "Column_1"] [["Hello","World",Nothing,"Extend"],[1,Nothing,"Gap",3],[2,2,"Here",5],[Nothing,Nothing,"To","Hello"]] - check_table (file.read (Excel (Cell_Range "Sheet1!O1"))) ["Full", "Table", "Column_1"] [[1,Nothing,"Gap",3],[2,2,"Here",5],[Nothing,Nothing,"To","Hello"]] + check_table (file.read (Excel (Cell_Range "Sheet1!N1"))) ["A", "Full", "Table", "Column 1"] [["Hello","World",Nothing,"Extend"],[1,Nothing,"Gap",3],[2,2,"Here",5],[Nothing,Nothing,"To","Hello"]] + check_table (file.read (Excel (Cell_Range "Sheet1!O1"))) ["Full", "Table", "Column 1"] [[1,Nothing,"Gap",3],[2,2,"Here",5],[Nothing,Nothing,"To","Hello"]] check_table (file.read (Excel (Cell_Range "Sheet1!O2"))) ["O", "P", "Q"] [[1,Nothing,"Gap",3],[2,2,"Here",5],[Nothing,Nothing,"To","Hello"]] Test.specify "Should handle invalid headers with warnings" <| action = file.read (Excel (Cell_Range "Sheet1!D1")) on_problems=_ - tester = check_table _ ["A", "B", "Column_1"] [[1,2,4], [4,4,Nothing], [6,Nothing,6]] + tester = check_table _ ["A", "B", "Column 1"] [[1,2,4], [4,4,Nothing], [6,Nothing,6]] problems = [Invalid_Output_Column_Names.Error [""]] Problems.test_problem_handling action problems tester Test.specify "Should handle duplicate headers with warnings" <| action = file.read (Excel (Cell_Range "Sheet1!S1")) on_problems=_ - tester = check_table _ ["DD", "DD_1"] [[1,3], [2,4]] + tester = check_table _ ["DD", "DD 1"] [[1,3], [2,4]] problems = [Duplicate_Output_Column_Names.Error ["DD"]] Problems.test_problem_handling action problems tester diff --git a/test/Table_Tests/src/In_Memory/Column_Spec.enso b/test/Table_Tests/src/In_Memory/Column_Spec.enso index 97426a5f9f2..6318ad66d21 100644 --- a/test/Table_Tests/src/In_Memory/Column_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Column_Spec.enso @@ -66,10 +66,10 @@ spec = Test.group "Columns" <| r.to_vector . should_equal [0, 2, 4, 5, Nothing, 30] Test.specify "should allow to count duplicate value occurences" <| - c_1 = Column.from_vector "c_1" [0, 1, 2, 2, 1, 0, 2] + c_1 = Column.from_vector "c 1" [0, 1, 2, 2, 1, 0, 2] c_1.duplicate_count.to_vector.should_equal [0, 0, 0, 1, 1, 1, 2] - c_2 = Column.from_vector "c_2" ["foo", "bar", "foo", "baz", "bar"] + c_2 = Column.from_vector "c 2" ["foo", "bar", "foo", "baz", "bar"] c_2.duplicate_count.to_vector.should_equal [0, 0, 1, 0, 1] Test.specify "should result in correct Storage if operation allows it" <| diff --git a/test/Table_Tests/src/In_Memory/Join_Performance_Spec.enso b/test/Table_Tests/src/In_Memory/Join_Performance_Spec.enso index be94acae671..5014a25555f 100644 --- a/test/Table_Tests/src/In_Memory/Join_Performance_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Join_Performance_Spec.enso @@ -76,7 +76,7 @@ spec = t4 = r2.second . order_by "N" t4.row_count . should_equal n t4.at "X" . to_vector . should_equal lowers - t4.at "Right_X" . to_vector . should_equal uppers + t4.at "Right X" . to_vector . should_equal uppers t4.at "Z" . to_vector . should_equal <| 1.up_to n+1 . to_vector . reverse base_ms = r1.first.total_milliseconds diff --git a/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso b/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso index a68fd39f669..e2b7079ce00 100644 --- a/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso @@ -14,7 +14,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["abc", "cbdbef", "ghbijbu"]]] t = Table.new cols expected_rows = [[0, "a", "c", Nothing], [1, "c", "d", "ef"], [2, "gh", "ij", "u"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3"] expected_rows t2 = t.split_to_columns "bar" "b" t2.should_equal expected @@ -30,7 +30,7 @@ spec = cols = [["foo", [0, 1, 2, 3]], ["bar", ["abc", "cbdbef", Nothing, "ghbijbu"]]] t = Table.new cols expected_rows = [[0, "a", "c", Nothing], [1, "c", "d", "ef"], [2, Nothing, Nothing, Nothing], [3, "gh", "ij", "u"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3"] expected_rows t2 = t.split_to_columns "bar" "b" t2.should_equal expected @@ -47,7 +47,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["a12b34r5", "23", "2r4r55"]]] t = Table.new cols expected_rows = [[0, "12", "34", "5"], [1, "23", Nothing, Nothing], [2, "2", "4", "55"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3"] expected_rows t2 = t.tokenize_to_columns "bar" "\d+" t2.should_equal expected @@ -63,7 +63,7 @@ spec = cols = [["foo", [0, 1, 2, 3]], ["bar", ["a12b34r5", Nothing, "23", "2r4r55"]]] t = Table.new cols expected_rows = [[0, "12", "34", "5"], [1, Nothing, Nothing, Nothing], [2, "23", Nothing, Nothing], [3, "2", "4", "55"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3"] expected_rows t2 = t.tokenize_to_columns "bar" "\d+" t2.should_equal expected @@ -87,7 +87,7 @@ spec = cols = [["foo", [0, 1]], ["bar", ["r a-1, b-12,qd-50", "ab-10:bc-20c"]]] t = Table.new cols expected_rows = [[0, "a1", "b12", "d50"], [1, "b10", "c20", Nothing]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3"] expected_rows t2 = t.tokenize_to_columns "bar" "([a-z]).(\d+)" t2.should_equal expected @@ -103,7 +103,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["aBqcE", "qcBr", "cCb"]]] t = Table.new cols expected_rows = [[0, "B", "c", Nothing], [1, "c", "B", Nothing], [2, "c", "C", "b"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3"] expected_rows t2 = t.tokenize_to_columns "bar" "[bc]" case_sensitivity=Case_Sensitivity.Insensitive t2.should_equal expected @@ -132,7 +132,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["abc", "cbdbef", "ghbijbu"]]] t = Table.new cols expected_rows = [[0, "a", "c", Nothing, Nothing], [1, "c", "d", "ef", Nothing], [2, "gh", "ij", "u", Nothing]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2", "bar 3"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3", "bar 3"] expected_rows t2 = t.split_to_columns "bar" "b" column_count=4 t2.should_equal expected t2.at "bar 3" . value_type . is_text . should_be_true @@ -141,7 +141,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["abc", "cbdbef", "ghbijbu"]]] t = Table.new cols expected_rows = [[0, "a", "c"], [1, "c", "d"], [2, "gh", "ij"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2"] expected_rows action = t.split_to_columns "bar" "b" column_count=2 on_problems=_ tester = t-> t.should_equal expected problems = [Column_Count_Exceeded.Error 2 3] @@ -151,7 +151,7 @@ spec = cols = [["foo", [0, 1]], ["bar", ["r a-1, b-12,qd-50", "ab-10:bc-20c"]]] t = Table.new cols expected_rows = [[0, "a1", "b12", "d50"], [1, "b10", "c20", Nothing]] - expected = Table.from_rows ["foo", "bar 0", "bar 1"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2"] expected_rows action = t.tokenize_to_columns "bar" "([a-z]).(\d+)" column_count=2 on_problems=_ tester = t-> t.should_equal expected problems = [Column_Count_Exceeded.Error 2 3] @@ -161,7 +161,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["ghbijbu", "cbdbef", "abc"]]] t = Table.new cols expected_rows = [[0, "gh", "ij", "u", Nothing], [1, "c", "d", "ef", Nothing], [2, "a", "c", Nothing, Nothing]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2", "bar 3"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3", "bar 3"] expected_rows t2 = t.split_to_columns "bar" "b" column_count=4 t2.should_equal expected t2.at "bar 3" . value_type . is_text . should_be_true @@ -198,7 +198,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["abc", "cbdbef", "ghbijbu"]], ["bar 1", ["a", "b", "c"]]] t = Table.new cols expected_rows = [[0, "a", "c", Nothing, "a"], [1, "c", "d", "ef", "b"], [2, "gh", "ij", "u", "c"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1_1", "bar 2", "bar 1"] expected_rows + expected = Table.from_rows ["foo", "bar 1 1", "bar 2", "bar 3", "bar 1"] expected_rows action = t.split_to_columns "bar" "b" on_problems=_ tester = t-> t.should_equal expected problems = [Duplicate_Output_Column_Names.Error ["bar 1"]] @@ -208,7 +208,7 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["a12b34r5", "23", "2r4r55"]], ["bar 1", ["a", "b", "c"]]] t = Table.new cols expected_rows = [[0, "12", "34", "5", "a"], [1, "23", Nothing, Nothing, "b"], [2, "2", "4", "55", "c"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1_1", "bar 2", "bar 1"] expected_rows + expected = Table.from_rows ["foo", "bar 1 1", "bar 2", "bar 3", "bar 1"] expected_rows action = t.tokenize_to_columns "bar" "\d+" on_problems=_ tester = t-> t.should_equal expected problems = [Duplicate_Output_Column_Names.Error ["bar 1"]] @@ -219,14 +219,14 @@ spec = cols = [["foo", [0, 1, 2]], ["bar", ["abc", "cbdbef", "ghbijbu"]], ["baz", [1, 2, 3]]] t = Table.new cols expected_rows = [[0, "a", "c", Nothing, 1], [1, "c", "d", "ef", 2], [2, "gh", "ij", "u", 3]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2", "baz"] expected_rows + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3", "baz"] expected_rows t2 = t.split_to_columns "bar" "b" t2.should_equal expected Test.group "Table.parse_to_columns" <| Test.specify "can parse to columns" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "12 34p q56", "y"], ["xx", "a48 59b", "yy"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "baz"] [["x", 1, 2, "y"], ["x", 3, 4, "y"], ["x", 5, 6, "y"], ["xx", 4, 8, "yy"], ["xx", 5, 9, "yy"]] + expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", 1, 2, "y"], ["x", 3, 4, "y"], ["x", 5, 6, "y"], ["xx", 4, 8, "yy"], ["xx", 5, 9, "yy"]] actual = t.parse_to_columns "bar" "(\d)(\d)" actual.should_equal expected @@ -244,31 +244,31 @@ spec = Test.specify "non-participating groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "q1", "y"], ["xx", "qp", "yy"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "bar 2", "baz"] [["x", "1", 1, Nothing, "y"], ["xx", "p", Nothing, "p", "yy"]] + expected = Table.from_rows ["foo", "bar 1", "bar 2", "bar 3", "baz"] [["x", "1", 1, Nothing, "y"], ["xx", "p", Nothing, "p", "yy"]] actual = t.parse_to_columns "bar" "q((\d)|([a-z]))" actual.should_equal expected Test.specify "case-insensitive" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "qq", "y"], ["xx", "qQ", "yy"]] - expected = Table.from_rows ["foo", "bar 0", "baz"] [["x", "q", "y"], ["xx", "Q", "yy"]] + expected = Table.from_rows ["foo", "bar 1", "baz"] [["x", "q", "y"], ["xx", "Q", "yy"]] actual = t.parse_to_columns "bar" "q(q)" case_sensitivity=Case_Sensitivity.Insensitive actual.should_equal expected Test.specify "no post-parsing" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "12 34p q56", "y"], ["xx", "a48 59b", "yy"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "baz"] [["x", "1", "2", "y"], ["x", "3", "4", "y"], ["x", "5", "6", "y"], ["xx", "4", "8", "yy"], ["xx", "5", "9", "yy"]] + expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", "1", "2", "y"], ["x", "3", "4", "y"], ["x", "5", "6", "y"], ["xx", "4", "8", "yy"], ["xx", "5", "9", "yy"]] actual = t.parse_to_columns "bar" "(\d)(\d)" parse_values=False actual.should_equal expected Test.specify "column name clash" <| t = Table.from_rows ["foo", "bar", "bar 1"] [["x", "12 34p q56", "y"], ["xx", "a48 59b", "yy"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1_1", "bar 1"] [["x", 1, 2, "y"], ["x", 3, 4, "y"], ["x", 5, 6, "y"], ["xx", 4, 8, "yy"], ["xx", 5, 9, "yy"]] + expected = Table.from_rows ["foo", "bar 1 1", "bar 2", "bar 1"] [["x", 1, 2, "y"], ["x", 3, 4, "y"], ["x", 5, 6, "y"], ["xx", 4, 8, "yy"], ["xx", 5, 9, "yy"]] actual = t.parse_to_columns "bar" "(\d)(\d)" actual.should_equal expected Test.specify "column and group name clash" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "123", "y"]] - expected = Table.from_rows ["foo", "bar", "baz_1", "quux", "baz"] [["x", 1, 2, 3, "y"]] + expected = Table.from_rows ["foo", "bar", "baz 1", "quux", "baz"] [["x", 1, 2, 3, "y"]] actual = t.parse_to_columns "bar" "(?\d)(?\d)(?\d)" actual.should_equal expected @@ -280,13 +280,13 @@ spec = Test.specify "empty table, with regex groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] . take 0 - expected = Table.from_rows ["foo", "bar 0", "bar 1", "baz"] [["x", "a", "a", "y"]] . take 0 + expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", "a", "a", "y"]] . take 0 actual = t.parse_to_columns "bar" "(\d)(\d)" actual.should_equal expected Test.specify "empty table, with named and unnamed regex groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] . take 0 - expected = Table.from_rows ["foo", "quux", "bar 0", "foo_1", "bar 1", "baz"] [["x", "a", "a", "a", "a", "y"]] . take 0 + expected = Table.from_rows ["foo", "quux", "bar 1", "foo 1", "bar 2", "baz"] [["x", "a", "a", "a", "a", "y"]] . take 0 actual = t.parse_to_columns "bar" "(?)(\d)(?\d)(\d)" actual.should_equal expected @@ -298,13 +298,13 @@ spec = Test.specify "input with no matches, with regex groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] - expected = Table.from_rows ["foo", "bar 0", "bar 1", "baz"] [] + expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [] actual = t.parse_to_columns "bar" "(\d)(\d)" actual.should_equal expected Test.specify "input with no matches, with named and unnamed regex groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] - expected = Table.from_rows ["foo", "quux", "bar 0", "foo_1", "bar 1", "baz"] [] + expected = Table.from_rows ["foo", "quux", "bar 1", "foo 1", "bar 2", "baz"] [] actual = t.parse_to_columns "bar" "(?)(\d)(?\d)(\d)" actual.should_equal expected diff --git a/test/Table_Tests/src/In_Memory/Table_Spec.enso b/test/Table_Tests/src/In_Memory/Table_Spec.enso index a6af3f7d817..43384190d36 100644 --- a/test/Table_Tests/src/In_Memory/Table_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Table_Spec.enso @@ -541,7 +541,7 @@ spec = c_4 = ['Z', [True, False, True]] table = Table.new [c_0, c_1, c_2, c_3, c_4] action = table.use_first_row_as_names on_problems=_ - tester = expect_column_names ["Column_1", "1980-01-01", "1", "5.3", "True"] + tester = expect_column_names ["Column 1", "1980-01-01", "1", "5.3", "True"] problems = [Invalid_Output_Column_Names.Error [""]] Problems.test_problem_handling action problems tester @@ -553,7 +553,7 @@ spec = c_4 = ['Z', [True, False, True]] table = Table.new [c_0, c_1, c_2, c_3, c_4] action = table.use_first_row_as_names on_problems=_ - tester = expect_column_names ["A", "1980-01-01", "Column_1", "5.3", "True"] + tester = expect_column_names ["A", "1980-01-01", "Column 1", "5.3", "True"] problems = [Invalid_Output_Column_Names.Error [Nothing]] Problems.test_problem_handling action problems tester @@ -565,7 +565,7 @@ spec = c_4 = ['Z', [True, False, True]] table = Table.new [c_0, c_1, c_2, c_3, c_4] action = table.use_first_row_as_names on_problems=_ - tester = expect_column_names ["Column_1", "1980-01-01", "Column_2", "5.3", "True"] + tester = expect_column_names ["Column 1", "1980-01-01", "Column 2", "5.3", "True"] problems = [Invalid_Output_Column_Names.Error ["", Nothing]] Problems.test_problem_handling action problems tester @@ -576,7 +576,7 @@ spec = c_3 = ['C', ["A", "B", "C"]] table = Table.new [c_0, c_1, c_2, c_3] action = table.use_first_row_as_names on_problems=_ - tester = expect_column_names ["A", "A_1", "A_2", "A_3"] + tester = expect_column_names ["A", "A 1", "A 2", "A 3"] problems = [Duplicate_Output_Column_Names.Error ["A", "A", "A"]] Problems.test_problem_handling action problems tester diff --git a/test/Table_Tests/src/Util.enso b/test/Table_Tests/src/Util.enso index aa20695bda5..3d586781b41 100644 --- a/test/Table_Tests/src/Util.enso +++ b/test/Table_Tests/src/Util.enso @@ -4,27 +4,36 @@ from Standard.Table import Table, Column from Standard.Test import Test import Standard.Test.Extensions +import Standard.Test.Test_Result.Test_Result polyglot java import org.enso.base_test_helpers.FileSystemHelper -Table.should_equal self expected = case expected of - _ : Table -> - tables_equal t0 t1 = - same_headers = (t0.columns.map .name) == (t1.columns.map .name) - same_columns = (t0.columns.map .to_vector) == (t1.columns.map .to_vector) - same_headers && same_columns - equal = tables_equal self expected - if equal.not then - msg = 'Tables differ.\nActual:\n' + self.display + '\nExpected:\n' + expected.display - Test.fail msg - _ -> Test.fail "Got a Table, but expected a "+expected.to_display_text +Table.should_equal : Any -> Integer -> Test_Result +Table.should_equal self expected frames_to_skip=0 = + loc = Meta.get_source_location 1+frames_to_skip + case expected of + _ : Table -> + tables_equal t0 t1 = + same_headers = (t0.columns.map .name) == (t1.columns.map .name) + same_columns = (t0.columns.map .to_vector) == (t1.columns.map .to_vector) + same_headers && same_columns + equal = tables_equal self expected + if equal.not then + msg = 'Tables differ at '+loc+'.\nActual:\n' + self.display + '\nExpected:\n' + expected.display + Test.fail msg + _ -> Test.fail "Got a Table, but expected a "+expected.to_display_text+' (at '+loc+').' -Column.should_equal self expected = - if self.name != expected.name then - Test.fail "Expected column name "+expected.name+", but got "+self.name+"." - if self.length != expected.length then - Test.fail "Expected column length "+expected.length.to_text+", but got "+self.length.to_text+"." - self.to_vector.should_equal expected.to_vector +Column.should_equal : Any -> Integer -> Test_Result +Column.should_equal self expected frames_to_skip=0 = + loc = Meta.get_source_location 1+frames_to_skip + case expected of + _ : Column -> + if self.name != expected.name then + Test.fail "Expected column name "+expected.name+", but got "+self.name+" (at "+loc+")." + if self.length != expected.length then + Test.fail "Expected column length "+expected.length.to_text+", but got "+self.length.to_text+" (at "+loc+")." + self.to_vector.should_equal expected.to_vector + _ -> Test.fail "Got a Column, but expected a "+expected.to_display_text+' (at '+loc+').' normalize_lines string line_separator=Line_Ending_Style.Unix.to_text newline_at_end=True = case newline_at_end of diff --git a/test/Tests/src/Data/Time/Date_Spec.enso b/test/Tests/src/Data/Time/Date_Spec.enso index edc0f589baf..6dd5f6b67fd 100644 --- a/test/Tests/src/Data/Time/Date_Spec.enso +++ b/test/Tests/src/Data/Time/Date_Spec.enso @@ -229,6 +229,22 @@ spec_with name create_new_date parse_date = (create_new_date 2000 7 1).end_of Date_Period.Quarter . should_equal (Date.new 2000 9 30) (create_new_date 2000 6 30).end_of Date_Period.Quarter . should_equal (Date.new 2000 6 30) + Test.specify "should allow to compute the number of days until a date" <| + create_new_date 2000 2 1 . days_until (create_new_date 2000 2 1) . should_equal 0 + create_new_date 2000 2 1 . days_until (create_new_date 2000 2 2) . should_equal 1 + create_new_date 2000 2 2 . days_until (create_new_date 2000 2 1) . should_equal -1 + create_new_date 2001 3 1 . days_until (create_new_date 2001 4 1) . should_equal 31 + create_new_date 2000 3 1 . days_until (create_new_date 2001 3 1) . should_equal 365 + create_new_date 2001 3 1 . days_until (create_new_date 2000 3 1) . should_equal -365 + + Test.specify "should allow to compute the number of days until a date including the end date" <| + create_new_date 2000 2 1 . days_until (create_new_date 2000 2 1) include_end_date=True . should_equal 1 + create_new_date 2000 2 1 . days_until (create_new_date 2000 2 2) include_end_date=True . should_equal 2 + create_new_date 2000 2 2 . days_until (create_new_date 2000 2 1) include_end_date=True . should_equal -2 + create_new_date 2001 3 1 . days_until (create_new_date 2001 4 1) include_end_date=True . should_equal 32 + create_new_date 2000 3 1 . days_until (create_new_date 2001 3 1) include_end_date=True . should_equal 366 + create_new_date 2001 3 1 . days_until (create_new_date 2000 3 1) include_end_date=True . should_equal -366 + Test.specify "should allow to compute the number of working days until a later date" <| # 2000-2-1 is a Tuesday create_new_date 2000 2 1 . work_days_until (create_new_date 2000 2 1) . should_equal 0 diff --git a/test/Visualization_Tests/src/Lazy_Table_Spec.enso b/test/Visualization_Tests/src/Lazy_Table_Spec.enso index 293f2bc6465..e61e92266a2 100644 --- a/test/Visualization_Tests/src/Lazy_Table_Spec.enso +++ b/test/Visualization_Tests/src/Lazy_Table_Spec.enso @@ -16,8 +16,8 @@ sample_table = col1 = ["foo", [123456789,23456789,987654321]] col2 = ["bar", [4,5,6]] col3 = ["Baz", [7,8,9]] - col4 = ["foo_1", [10,11,12]] - col5 = ["foo_2", [13,14,15]] + col4 = ["foo 1", [10,11,12]] + col5 = ["foo 2", [13,14,15]] col6 = ["ab.+123", [16,17,18]] col7 = ["abcd123", ["19",20, t1]] Table.new [col1, col2, col3, col4, col5, col6, col7]