From 1555e0f78a0a94de0c15d7987990c56034c0cfad Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 14:25:46 -0400 Subject: [PATCH 01/13] most tests --- .../Standard/Database/0.0.0-dev/src/Data/Table.enso | 10 +++++++--- .../Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso | 1 + .../Join/Cross_Join_Spec.enso | 12 ++++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) 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 deab21f8ddce..ba3f0a03cd99 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 @@ -1007,7 +1007,7 @@ type Table table.join other on=[Join_Condition.Equals "A" "A", Join_Condition.Equals "B" "B"] @on Widget_Helpers.make_join_condition_selector join : Table -> Join_Kind -> Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table - join self right join_kind=Join_Kind.Left_Outer on=[Join_Condition.Equals self.column_names.first] right_prefix="Right " on_problems=Report_Warning = + join self right join_kind=Join_Kind.Left_Outer on=(default_join_condition self join_kind) 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 @@ -1051,6 +1051,7 @@ type Table Join_Kind.Full -> SQL_Join_Kind.Full Join_Kind.Left_Exclusive -> SQL_Join_Kind.Left Join_Kind.Right_Exclusive -> SQL_Join_Kind.Right + Join_Kind.Cross -> SQL_Join_Kind.Cross problem_builder.attach_problems_before on_problems <| new_from = From_Spec.Join sql_join_kind left_setup.subquery right_setup.subquery on_expressions @@ -1093,8 +1094,7 @@ type Table 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 = - _ = [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.") + self.join right join_kind=Join_Kind.Cross on=[] right_prefix on_problems ## ALIAS Join By Row Position Joins two tables by zipping rows from both tables table together - the @@ -2114,3 +2114,7 @@ check_db_table arg_name table = False -> Error.throw (Illegal_Argument.Error "Currently cross-backend operations are not supported. Materialize the table using `.read` before mixing it with an in-memory Table.") True -> True + +default_join_condition table join_kind = case join_kind of + Join_Kind.Cross -> [] + _ -> [Join_Condition.Equals table.column_names.first] diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso index 0f16e765b556..3571f9cfcd56 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso @@ -36,3 +36,4 @@ type Join_Kind In this mode, unlike in others, only columns of the right table are returned, since all columns of the left table would be all null anyway. Right_Exclusive + Cross 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 3f60df4ca93a..25e8c66ecabe 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 @@ -18,8 +18,16 @@ spec setup = prefix = setup.prefix table_builder = setup.table_builder materialize = setup.materialize - db_todo = if setup.is_database.not then Nothing else "Table.cross_join is still WIP for the DB backend." - Test.group prefix+"Table.cross_join" pending=db_todo <| + + Test.group "asdfasdf" <| + Test.specify "asdf" <| + t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] + t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] + #j = t1.join join_kind=Join_Kind.Cross t2 + j = t1.cross_join t2 + j.print + + Test.group prefix+"Table.cross_joinasdfasdf" <| Test.specify "should allow to create a cross product of two tables in the right order" <| t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] From bbd47f07f2822f0bdb387072e6f89a5c21f4494b Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 14:30:56 -0400 Subject: [PATCH 02/13] wow --- .../lib/Standard/Database/0.0.0-dev/src/Data/Table.enso | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 ba3f0a03cd99..25285d84093f 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 @@ -1094,7 +1094,13 @@ type Table 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 = - self.join right join_kind=Join_Kind.Cross on=[] right_prefix on_problems + if check_db_table "right" right then + limit_problems = case right_row_limit.is_nothing.not && (right.row_count > right_row_limit) of + True -> + [Cross_Join_Row_Limit_Exceeded.Error right_row_limit right.row_count] + False -> [] + on_problems.attach_problems_before limit_problems <| + self.join right join_kind=Join_Kind.Cross on=[] right_prefix on_problems ## ALIAS Join By Row Position Joins two tables by zipping rows from both tables table together - the From 420fb2adae7b5c30693887c60f5fdaddb2991a96 Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 14:47:24 -0400 Subject: [PATCH 03/13] on test --- .../lib/Standard/Database/0.0.0-dev/src/Data/Table.enso | 4 +++- .../src/Common_Table_Operations/Join/Cross_Join_Spec.enso | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) 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 25285d84093f..3ed7b3efca2b 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 @@ -1012,8 +1012,10 @@ type Table same_backend = case right of _ : Table -> True _ -> False + join_conditions_ok = join_kind != Join_Kind.Cross || on == [] if same_backend . not then Error.throw (Illegal_Argument.Error "Currently cross-backend joins are not supported. You need to upload the in-memory table before joining it with a database one, or materialize this table.") else - True + if join_conditions_ok . not then Error.throw (Illegal_Argument.Error "Cross join does not allow join conditions") else + True if can_proceed then left = self new_table_name = left.name + "_" + right.name 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 25e8c66ecabe..65139531331d 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 @@ -1,4 +1,5 @@ from Standard.Base import all +import Standard.Base.Errors.Illegal_Argument.Illegal_Argument import Standard.Base.Errors.Illegal_State.Illegal_State from Standard.Table import all hiding Table @@ -158,3 +159,9 @@ spec setup = r5 = [100, 4, 'a', 'x'] expected_rows = [r0, r1, r2, r3, r4, r5] r.should_equal expected_rows + + Test.specify "Cross join via a direct call to .join should not allow join conditions" <| + t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] + t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] + j = t1.join t2 join_kind=Join_Kind.Cross on=[Join_Condition.Equals 'X' 'Z'] + j . should_fail_with Illegal_Argument From 1332edcb7cb3025e487966de4c1534e6dcda2b63 Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 14:52:53 -0400 Subject: [PATCH 04/13] wip --- .../Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso | 3 +++ .../Common_Table_Operations/Join/Cross_Join_Spec.enso | 10 +--------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso index 3571f9cfcd56..771b3647fb03 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso @@ -36,4 +36,7 @@ type Join_Kind In this mode, unlike in others, only columns of the right table are returned, since all columns of the left table would be all null anyway. Right_Exclusive + + ## Cartesian product: each row of the left type is paired with each row of + the right table. Cross 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 65139531331d..068d32b2ec19 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 @@ -20,15 +20,7 @@ spec setup = table_builder = setup.table_builder materialize = setup.materialize - Test.group "asdfasdf" <| - Test.specify "asdf" <| - t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] - t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] - #j = t1.join join_kind=Join_Kind.Cross t2 - j = t1.cross_join t2 - j.print - - Test.group prefix+"Table.cross_joinasdfasdf" <| + Test.group prefix+"Table.cross_join" <| Test.specify "should allow to create a cross product of two tables in the right order" <| t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] From 8097e8252782b40dab7f01b9266a8f755fe67d8f Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 15:12:22 -0400 Subject: [PATCH 05/13] sqlite fix --- .../lib/Standard/Database/0.0.0-dev/src/Data/Table.enso | 6 +----- .../src/Common_Table_Operations/Join/Cross_Join_Spec.enso | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) 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 3ed7b3efca2b..8f406e4e6b55 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 @@ -1089,11 +1089,7 @@ type Table ? Result Ordering - Rows in the result are first ordered by the order of the corresponding - rows from the left table and then the order of rows from the right - table. This applies only if the order of the rows was specified (for - example, by sorting the table; in-memory tables will keep the memory - layout order while for database tables the order may be unspecified). + The ordering of rows in the resulting table is not specified. cross_join : Table -> Integer | Nothing -> Text -> Problem_Behavior -> Table cross_join self right right_row_limit=100 right_prefix="Right " on_problems=Report_Warning = if check_db_table "right" right then 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 068d32b2ec19..867c26917ded 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 @@ -150,7 +150,9 @@ spec setup = r4 = [100, 4, 'b', 'd'] r5 = [100, 4, 'a', 'x'] expected_rows = [r0, r1, r2, r3, r4, r5] - r.should_equal expected_rows + case setup.is_database of + True -> r.should_contain_the_same_elements_as expected_rows + False -> r.should_equal expected_rows Test.specify "Cross join via a direct call to .join should not allow join conditions" <| t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] From 547d3bc9c4291e27eb729f511ff128c0a8b08db9 Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 15:24:49 -0400 Subject: [PATCH 06/13] fix/improve tests --- .../Join/Cross_Join_Spec.enso | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) 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 867c26917ded..d63b532429f5 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 @@ -77,16 +77,18 @@ spec setup = Test.specify "should ensure 1-1 mapping even with duplicate rows" <| t1 = table_builder [["X", [2, 1, 2, 2]], ["Y", [5, 4, 5, 5]]] - t2 = table_builder [["Z", ['a', 'a']]] + t2 = table_builder [["Z", ['a', 'b', 'a', 'b']]] t3 = t1.cross_join t2 expect_column_names ["X", "Y", "Z"] t3 - t3.row_count . should_equal 8 + t3.row_count . should_equal 16 r = materialize t3 . rows . map .to_vector - r.length . should_equal 8 + r.length . should_equal 16 r1 = [2, 5, 'a'] r2 = [1, 4, 'a'] - expected_rows = [r1, r1, r2, r2, r1, r1, r1, r1] + r3 = [2, 5, 'b'] + r4 = [1, 4, 'b'] + expected_rows = [r1, r3, r1, r3, r2, r4, r2, r4, r1, r3, r1, r3, r1, r3, r1, r3] case setup.is_database of True -> r.should_contain_the_same_elements_as expected_rows False -> r.should_equal expected_rows @@ -154,8 +156,9 @@ spec setup = True -> r.should_contain_the_same_elements_as expected_rows False -> r.should_equal expected_rows - Test.specify "Cross join via a direct call to .join should not allow join conditions" <| - t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] - t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] - j = t1.join t2 join_kind=Join_Kind.Cross on=[Join_Condition.Equals 'X' 'Z'] - j . should_fail_with Illegal_Argument + if setup.is_database then + Test.specify "Cross join via a direct call to .join should not allow join conditions" <| + t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] + t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] + j = t1.join t2 join_kind=Join_Kind.Cross on=[Join_Condition.Equals 'X' 'Z'] + j . should_fail_with Illegal_Argument From 9b406038119ff1a06ba5e923a70e735e8779a94b Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 15:33:54 -0400 Subject: [PATCH 07/13] cleanup --- .../lib/Standard/Database/0.0.0-dev/src/Data/Table.enso | 3 +++ .../lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso | 2 +- .../src/Common_Table_Operations/Join/Cross_Join_Spec.enso | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) 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 8f406e4e6b55..b4a578dbe9e4 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 @@ -2119,6 +2119,9 @@ check_db_table arg_name table = Error.throw (Illegal_Argument.Error "Currently cross-backend operations are not supported. Materialize the table using `.read` before mixing it with an in-memory Table.") True -> True +## By default, join on the first column, unless it's a cross join, in which + case there are no join conditions. +default_join_condition : Table -> Join_Kind -> Join_Condition default_join_condition table join_kind = case join_kind of Join_Kind.Cross -> [] _ -> [Join_Condition.Equals table.column_names.first] diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso index 771b3647fb03..f9e5832c1f27 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso @@ -37,6 +37,6 @@ type Join_Kind returned, since all columns of the left table would be all null anyway. Right_Exclusive - ## Cartesian product: each row of the left type is paired with each row of + ## Cartesian product: each row of the left table is paired with each row of the right table. Cross 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 d63b532429f5..572464288fa9 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 @@ -19,7 +19,6 @@ spec setup = prefix = setup.prefix table_builder = setup.table_builder materialize = setup.materialize - Test.group prefix+"Table.cross_join" <| Test.specify "should allow to create a cross product of two tables in the right order" <| t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] From 360ce16a6a53c2db7935971c8046e616d0db957f Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 15:36:05 -0400 Subject: [PATCH 08/13] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2bb4da7f60a..bc90802461d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -505,6 +505,7 @@ - [`Column.fill_nothing` and `.fill_empty` no longer rename the column. Added `Table.fill_nothing` and `.fill_empty`.][7166] - [Implemented `add_row_number` for Database tables.][7174] +- [Added `cross_join` support to database tables.][7234] [debug-shortcuts]: https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug @@ -731,6 +732,7 @@ [7072]: https://github.com/enso-org/enso/pull/7072 [7166]: https://github.com/enso-org/enso/pull/7166 [7174]: https://github.com/enso-org/enso/pull/7174 +[7234]: https://github.com/enso-org/enso/pull/7234 #### Enso Compiler From c479698d19077b2678f14250d5e18bff560f3e4a Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 21:46:32 -0400 Subject: [PATCH 09/13] move Join_Kind.Cross to Join_Kind_Cross --- .../Database/0.0.0-dev/src/Data/Table.enso | 17 ++++++++++++----- .../Table/0.0.0-dev/src/Data/Join_Kind.enso | 4 ---- .../0.0.0-dev/src/Data/Join_Kind_Cross.enso | 11 +++++++++++ .../Join/Cross_Join_Spec.enso | 11 +++++------ 4 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso 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 b4a578dbe9e4..31137ae3a8ca 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 @@ -14,6 +14,7 @@ import Standard.Table.Data.Expression.Expression import Standard.Table.Data.Expression.Expression_Error import Standard.Table.Data.Join_Condition.Join_Condition import Standard.Table.Data.Join_Kind.Join_Kind +import Standard.Table.Data.Join_Kind_Cross.Join_Kind_Cross import Standard.Table.Data.Match_Columns as Match_Columns_Helpers import Standard.Table.Data.Report_Unmatched.Report_Unmatched import Standard.Table.Data.Row.Row @@ -1008,11 +1009,17 @@ type Table @on Widget_Helpers.make_join_condition_selector join : Table -> Join_Kind -> Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table join self right join_kind=Join_Kind.Left_Outer on=(default_join_condition self join_kind) right_prefix="Right " on_problems=Report_Warning = + self.join_or_cross_join right join_kind on right_prefix on_problems + + ## PRIVATE + Implementation of both `join` and `cross_join`. + join_or_cross_join : Table -> Join_Kind | Join_Kind_Cross -> Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table + join_or_cross_join self right join_kind on right_prefix on_problems = 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 _ -> False - join_conditions_ok = join_kind != Join_Kind.Cross || on == [] + join_conditions_ok = join_kind != Join_Kind_Cross.Cross || on == [] if same_backend . not then Error.throw (Illegal_Argument.Error "Currently cross-backend joins are not supported. You need to upload the in-memory table before joining it with a database one, or materialize this table.") else if join_conditions_ok . not then Error.throw (Illegal_Argument.Error "Cross join does not allow join conditions") else True @@ -1053,7 +1060,7 @@ type Table Join_Kind.Full -> SQL_Join_Kind.Full Join_Kind.Left_Exclusive -> SQL_Join_Kind.Left Join_Kind.Right_Exclusive -> SQL_Join_Kind.Right - Join_Kind.Cross -> SQL_Join_Kind.Cross + Join_Kind_Cross.Cross -> SQL_Join_Kind.Cross problem_builder.attach_problems_before on_problems <| new_from = From_Spec.Join sql_join_kind left_setup.subquery right_setup.subquery on_expressions @@ -1098,7 +1105,7 @@ type Table [Cross_Join_Row_Limit_Exceeded.Error right_row_limit right.row_count] False -> [] on_problems.attach_problems_before limit_problems <| - self.join right join_kind=Join_Kind.Cross on=[] right_prefix on_problems + self.join_or_cross_join right join_kind=Join_Kind_Cross.Cross on=[] right_prefix on_problems ## ALIAS Join By Row Position Joins two tables by zipping rows from both tables table together - the @@ -2121,7 +2128,7 @@ check_db_table arg_name table = ## By default, join on the first column, unless it's a cross join, in which case there are no join conditions. -default_join_condition : Table -> Join_Kind -> Join_Condition +default_join_condition : Table -> Join_Kind | Join_Kind_Cross -> Join_Condition default_join_condition table join_kind = case join_kind of - Join_Kind.Cross -> [] + Join_Kind_Cross.Cross -> [] _ -> [Join_Condition.Equals table.column_names.first] diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso index f9e5832c1f27..0f16e765b556 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind.enso @@ -36,7 +36,3 @@ type Join_Kind In this mode, unlike in others, only columns of the right table are returned, since all columns of the left table would be all null anyway. Right_Exclusive - - ## Cartesian product: each row of the left table is paired with each row of - the right table. - Cross diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso new file mode 100644 index 000000000000..e3e2940b7bde --- /dev/null +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso @@ -0,0 +1,11 @@ +from Standard.Base import all + +type Join_Kind_Cross + ## Cartesian product: each row of the left table is paired with each row of + the right table. + Cross + + ## PRIVATE + Returns the SQL representation of this join kind as text. + to_sql : Text + to_sql self = "INNER JOIN" 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 572464288fa9..cbef2ffcebd1 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 @@ -1,18 +1,17 @@ from Standard.Base import all + import Standard.Base.Errors.Illegal_Argument.Illegal_Argument import Standard.Base.Errors.Illegal_State.Illegal_State +import Standard.Table.Data.Join_Kind_Cross.Join_Kind_Cross +import Standard.Test.Extensions +from Standard.Database.Errors import Unsupported_Database_Operation from Standard.Table import all hiding Table from Standard.Table.Errors import all - -from Standard.Database.Errors import Unsupported_Database_Operation - from Standard.Test import Test, Problems -import Standard.Test.Extensions from project.Common_Table_Operations.Util import expect_column_names, run_default_backend - main = run_default_backend spec spec setup = @@ -159,5 +158,5 @@ spec setup = Test.specify "Cross join via a direct call to .join should not allow join conditions" <| t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] - j = t1.join t2 join_kind=Join_Kind.Cross on=[Join_Condition.Equals 'X' 'Z'] + j = t1.join t2 join_kind=Join_Kind_Cross.Cross on=[Join_Condition.Equals 'X' 'Z'] j . should_fail_with Illegal_Argument From 5b6cd8f1f1ee1f2b7f8ffc5352472b1c305c4ddf Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Thu, 6 Jul 2023 21:50:33 -0400 Subject: [PATCH 10/13] docs --- .../Database/0.0.0-dev/src/Data/Table.enso | 14 +++++++++++++- .../Standard/Table/0.0.0-dev/src/Data/Table.enso | 6 +++++- 2 files changed, 18 insertions(+), 2 deletions(-) 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 31137ae3a8ca..bba015aadd60 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 @@ -1094,7 +1094,19 @@ type Table name will be in use, in this case it will be resolved using the normal renaming strategy - adding subsequent `_1`, `_2` etc. - ? Result Ordering + ? Row Ordering For In-Memory Tables + + This operation requires a well-defined order of rows in the input + tables. In-memory tables rely on the ordering stemming directly from + their layout in memory. Database tables may not impose a deterministic + ordering. If the table defines a primary key, it is used to by default + to ensure deterministic ordering. That can be overridden by specifying + a different ordering using `Table.order_by`. If no primary key was + defined nor any ordering was specified explicitly by the user, the + order of columns is undefined and the operation will fail, reporting a + `Undefined_Column_Order` problem and returning an empty table. + + ? Result Ordering For Database Tables The ordering of rows in the resulting table is not specified. cross_join : Table -> Integer | Nothing -> Text -> Problem_Behavior -> 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 0173be632438..c378b6f5b385 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 @@ -1536,7 +1536,7 @@ type Table name will be in use, in this case it will be resolved using the normal renaming strategy - adding subsequent `_1`, `_2` etc. - ? Row Ordering + ? Row Ordering For In-Memory Tables This operation requires a well-defined order of rows in the input tables. In-memory tables rely on the ordering stemming directly from @@ -1547,6 +1547,10 @@ type Table defined nor any ordering was specified explicitly by the user, the order of columns is undefined and the operation will fail, reporting a `Undefined_Column_Order` problem and returning an empty table. + + ? Result Ordering For Database Tables + + The ordering of rows in the resulting table is not specified. @keep_unmatched (make_single_choice [["True", "Boolean.True"], ["False", "Boolean.False"], ["Report", Meta.get_qualified_type_name Report_Unmatched]]) zip : Table -> Boolean | Report_Unmatched -> Text -> Problem_Behavior -> Table zip self right keep_unmatched=Report_Unmatched right_prefix="Right " on_problems=Report_Warning = From 5fcc61dd63c99a8cd9b67d7601827d892bc07cdb Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Fri, 7 Jul 2023 14:07:54 -0400 Subject: [PATCH 11/13] type test --- .../lib/Standard/Database/0.0.0-dev/src/Data/Table.enso | 4 ++-- .../src/Common_Table_Operations/Join/Cross_Join_Spec.enso | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) 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 bba015aadd60..b07469d723c3 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 @@ -1007,8 +1007,8 @@ type Table 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"] @on Widget_Helpers.make_join_condition_selector - join : Table -> Join_Kind -> Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table - join self right join_kind=Join_Kind.Left_Outer on=(default_join_condition self join_kind) right_prefix="Right " on_problems=Report_Warning = + join : Table -> Join_Kind -> Join_Condition | Text | Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table + join self right (join_kind : Join_Kind = Join_Kind.Left_Outer) (on : Join_Condition | Text | Vector (Join_Condition | Text) = (default_join_condition self join_kind)) (right_prefix:Text="Right ") (on_problems:Problem_Behavior=Report_Warning) = self.join_or_cross_join right join_kind on right_prefix on_problems ## PRIVATE 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 cbef2ffcebd1..ef6d935aa6a0 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 @@ -1,5 +1,6 @@ from Standard.Base import all +import Standard.Base.Errors.Common.Type_Error import Standard.Base.Errors.Illegal_Argument.Illegal_Argument import Standard.Base.Errors.Illegal_State.Illegal_State import Standard.Table.Data.Join_Kind_Cross.Join_Kind_Cross @@ -155,8 +156,7 @@ spec setup = False -> r.should_equal expected_rows if setup.is_database then - Test.specify "Cross join via a direct call to .join should not allow join conditions" <| + Test.specify "Cross join is not possible via call to .join" <| t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] - j = t1.join t2 join_kind=Join_Kind_Cross.Cross on=[Join_Condition.Equals 'X' 'Z'] - j . should_fail_with Illegal_Argument + Test.expect_panic_with (t1.join t2 join_kind=Join_Kind_Cross.Cross on=[]) Type_Error From 04d78c10eadd4280c0b01f981baad810ee88e29e Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Fri, 7 Jul 2023 14:10:38 -0400 Subject: [PATCH 12/13] docs --- .../Database/0.0.0-dev/src/Data/Table.enso | 14 +++++++++++++- .../Standard/Table/0.0.0-dev/src/Data/Table.enso | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) 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 b07469d723c3..5e5fc77bd483 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 @@ -989,7 +989,19 @@ type Table name will be in use, in this case it will be resolved using the normal renaming strategy - adding subsequent `_1`, `_2` etc. - ? Result Ordering + ? Row Ordering For In-Memory Tables + + This operation requires a well-defined order of rows in the input + tables. In-memory tables rely on the ordering stemming directly from + their layout in memory. Database tables may not impose a deterministic + ordering. If the table defines a primary key, it is used to by default + to ensure deterministic ordering. That can be overridden by specifying + a different ordering using `Table.order_by`. If no primary key was + defined nor any ordering was specified explicitly by the user, the + order of columns is undefined and the operation will fail, reporting a + `Undefined_Column_Order` problem and returning an empty table. + + ? Row Ordering For Database Tables The ordering of rows in the resulting table is not specified. 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 c378b6f5b385..2d197582444a 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 @@ -1548,7 +1548,7 @@ type Table order of columns is undefined and the operation will fail, reporting a `Undefined_Column_Order` problem and returning an empty table. - ? Result Ordering For Database Tables + ? Row Ordering For Database Tables The ordering of rows in the resulting table is not specified. @keep_unmatched (make_single_choice [["True", "Boolean.True"], ["False", "Boolean.False"], ["Report", Meta.get_qualified_type_name Report_Unmatched]]) From 0d80710d417b471bbd5955efe3fa6c7f013adbaf Mon Sep 17 00:00:00 2001 From: Gregory Travis Date: Mon, 10 Jul 2023 10:33:52 -0400 Subject: [PATCH 13/13] review --- .../Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso | 2 +- .../lib/Standard/Table/0.0.0-dev/src/Data/Table.enso | 2 +- .../Common_Table_Operations/Join/Cross_Join_Spec.enso | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso index e3e2940b7bde..289e45fc2c60 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Join_Kind_Cross.enso @@ -8,4 +8,4 @@ type Join_Kind_Cross ## PRIVATE Returns the SQL representation of this join kind as text. to_sql : Text - to_sql self = "INNER JOIN" + to_sql self = "CROSS JOIN" 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 2d197582444a..6a359b075e27 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 @@ -1431,7 +1431,7 @@ type Table table.join other on=[Join_Condition.Equals "A" "A", Join_Condition.Equals "B" "B"] @on Widget_Helpers.make_join_condition_selector join : Table -> Join_Kind -> Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table - join self right join_kind=Join_Kind.Left_Outer on=[Join_Condition.Equals self.column_names.first] right_prefix="Right " on_problems=Report_Warning = + join self right (join_kind : 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 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 ef6d935aa6a0..f5310ab225c7 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 @@ -155,8 +155,7 @@ spec setup = True -> r.should_contain_the_same_elements_as expected_rows False -> r.should_equal expected_rows - if setup.is_database then - Test.specify "Cross join is not possible via call to .join" <| - t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] - t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] - Test.expect_panic_with (t1.join t2 join_kind=Join_Kind_Cross.Cross on=[]) Type_Error + Test.specify "Cross join is not possible via call to .join" <| + t1 = table_builder [["X", [1, 2]], ["Y", [4, 5]]] + t2 = table_builder [["Z", ['a', 'b']], ["W", ['c', 'd']]] + Test.expect_panic_with (t1.join t2 join_kind=Join_Kind_Cross.Cross on=[]) Type_Error