Add selecting by type to the table (#9334)

- Adds `select_by_type` and `remove_by_type` to tables.
This commit is contained in:
James Dunkerley 2024-03-08 18:40:53 +00:00 committed by GitHub
parent 614a5a610b
commit 9f9cf58d28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 173 additions and 1 deletions

View File

@ -626,6 +626,7 @@
- [Implement Data Links to Postgres (accessing a DB connection or a table
directly)][9269]
- [Added `Xml_Document.write`][9299]
- [Added `select_by_type` and `remove_by_type` to `Table` and `DB_Table`][9334]
[debug-shortcuts]:
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
@ -907,6 +908,7 @@
[9249]: https://github.com/enso-org/enso/pull/9249
[9269]: https://github.com/enso-org/enso/pull/9269
[9299]: https://github.com/enso-org/enso/pull/9299
[9344]: https://github.com/enso-org/enso/pull/9344
#### Enso Compiler

View File

@ -241,6 +241,23 @@ type DB_Table
new_columns = self.columns_helper.select_columns columns case_sensitivity reorder error_on_missing_columns on_problems
self.updated_columns new_columns
## GROUP Standard.Base.Selections
ICON select_column
Returns a new table with the chosen set of columns filtered by the type
of the column.
Arguments:
- types: The types of columns to select.
- strict: If `True`, only columns with exactly the specified types will
be selected. If `False`, columns with related types will also be
selected (i.e. ignore size, precision).
@types Widget_Helpers.make_value_type_vector_selector
select_by_type : Vector Value_Type -> Boolean -> Table
select_by_type self types:Vector strict:Boolean=False =
helper = Table_Helpers.Table_Column_Helper.Value self.columns self.make_column self .read
new_columns = helper.select_by_type types strict
self.updated_columns (new_columns.map _.as_internal)
## ALIAS drop_columns
GROUP Standard.Base.Selections
ICON select_column
@ -295,6 +312,23 @@ type DB_Table
new_columns = self.columns_helper.remove_columns columns case_sensitivity error_on_missing_columns=error_on_missing_columns on_problems=on_problems
self.updated_columns new_columns
## GROUP Standard.Base.Selections
ICON select_column
Returns a new table with the chosen set of columns filtering out based
on the type of the column.
Arguments:
- types: The types of columns to remove.
- strict: If `True`, only columns with exactly the specified types will
be removed. If `False`, columns with related types will also be
removed (i.e. ignore size, precision).
@types Widget_Helpers.make_value_type_vector_selector
remove_by_type : Vector Value_Type -> Boolean -> Table
remove_by_type self types:Vector strict:Boolean=False =
helper = Table_Helpers.Table_Column_Helper.Value self.columns self.make_column self .read
new_columns = helper.remove_by_type types strict
self.updated_columns (new_columns.map _.as_internal)
## ALIAS select_missing_columns, select_na
GROUP Standard.Base.Selections
ICON select_column

View File

@ -389,6 +389,22 @@ type Table
new_columns = self.columns_helper.select_columns columns case_sensitivity reorder error_on_missing_columns on_problems
Table.new new_columns
## GROUP Standard.Base.Selections
ICON select_column
Returns a new table with the chosen set of columns filtered by the type
of the column.
Arguments:
- types: The types of columns to select.
- strict: If `True`, only columns with exactly the specified types will
be selected. If `False`, columns with related types will also be
selected (i.e. ignore size, precision).
@types Widget_Helpers.make_value_type_vector_selector
select_by_type : Vector Value_Type -> Boolean -> Table
select_by_type self types:Vector strict:Boolean=False =
new_columns = self.columns_helper.select_by_type types strict
Table.new new_columns
## ALIAS drop_columns
GROUP Standard.Base.Selections
ICON select_column
@ -443,6 +459,22 @@ type Table
new_columns = self.columns_helper.remove_columns columns case_sensitivity error_on_missing_columns=error_on_missing_columns on_problems=on_problems
Table.new new_columns
## GROUP Standard.Base.Selections
ICON select_column
Returns a new table with the chosen set of columns filtering out based
on the type of the column.
Arguments:
- types: The types of columns to remove.
- strict: If `True`, only columns with exactly the specified types will
be removed. If `False`, columns with related types will also be
removed (i.e. ignore size, precision).
@types Widget_Helpers.make_value_type_vector_selector
remove_by_type : Vector Value_Type -> Boolean -> Table
remove_by_type self types:Vector strict:Boolean=False =
new_columns = self.columns_helper.remove_by_type types strict
Table.new new_columns
## ALIAS select_missing_columns, select_na
GROUP Standard.Base.Selections
ICON select_column

View File

@ -452,6 +452,13 @@ type Value_Type
JS_Object.from_pairs <|
[["type", "Value_Type"], ["constructor", constructor_name]] + additional_fields
## Check if the same type of value ignoring size, precision and scale.
is_same_type : Value_Type -> Boolean
is_same_type self other:Value_Type =
self_ctor = Meta.meta self . constructor
other_ctor = Meta.meta other . constructor
self_ctor == other_ctor
## The type representing inferring the column type automatically based on values
present in the column.

View File

@ -70,6 +70,21 @@ type Table_Column_Helper
problem_builder.attach_problems_before on_problems <|
if error_on_empty && result.is_empty then problem_builder.raise_no_output_columns_with_cause else result
## PRIVATE
A helper to returns a set of columns filtered by the type of the column.
Arguments:
- types: The types of columns to select.
- strict: If `True`, only columns with exactly the specified types will
be selected. If `False`, columns with types that are subtypes of the
specified types will also be selected (i.e. ignore size, precision).
select_by_type : Vector Value_Type -> Boolean -> Vector
select_by_type self types:Vector strict:Boolean=False =
columns = if strict then self.internal_columns.filter c-> types.contains c.value_type else
self.internal_columns.filter c-> types.any t-> c.value_type.is_same_type t
if columns.length == 0 then Error.throw (No_Output_Columns.Error "No columns of the specified types were found.") else
columns
## PRIVATE
A helper function encapsulating shared code for `remove_columns`
implementations of various Table variants. See the documentation for the
@ -101,6 +116,22 @@ type Table_Column_Helper
if result.is_empty then Error.throw No_Output_Columns.Error else
problem_builder.attach_problems_after on_problems result
## PRIVATE
A helper to returns a set of columns filtering out based on the type of
the column.
Arguments:
- types: The types of columns to remove.
- strict: If `True`, only columns with exactly the specified types will
be selected. If `False`, columns with types that are subtypes of the
specified types will also be selected (i.e. ignore size, precision).
remove_by_type : Vector Value_Type -> Boolean -> Vector
remove_by_type self types:Vector strict:Boolean=False =
columns = if strict then self.internal_columns.filter (c->(types.contains c.value_type).not) else
self.internal_columns.filter c->(types.all (t->(c.value_type.is_same_type t . not)))
if columns.length == 0 then Error.throw (No_Output_Columns.Error "No columns of the specified types were found.") else
columns
## PRIVATE
A helper function encapsulating shared code for `reorder_columns`
implementations of various Table variants. See the documentation for the

View File

@ -210,3 +210,12 @@ make_format_chooser_for_type value_type =
include_time = value_type==Value_Type.Time || value_type==Value_Type.Mixed
include_boolean = value_type.is_boolean || value_type==Value_Type.Mixed
make_format_chooser include_number include_date include_date_time include_time include_boolean
## PRIVATE
Make value type selector for type filtering
make_value_type_vector_selector : Widget
make_value_type_vector_selector =
meta = Meta.meta Value_Type
options = meta.constructors.map c-> Option c.name meta.qualified_name+"."+c.name
item_editor = Single_Choice display=Display.Always values=options
Vector_Editor item_editor=item_editor item_default="Value_Type.Boolean" display=Display.Always

View File

@ -18,6 +18,7 @@ import project.Data.Simple_Expression.Simple_Expression
import project.Data.Sort_Column.Sort_Column
import project.Data.Table.Table
import project.Data.Type.Value_Type.Auto
import project.Data.Type.Value_Type.Bits
import project.Data.Type.Value_Type.Value_Type
import project.Delimited.Delimited_Format.Delimited_Format
import project.Delimited.Quote_Style.Quote_Style
@ -49,6 +50,7 @@ export project.Data.Simple_Expression.Simple_Expression
export project.Data.Sort_Column.Sort_Column
export project.Data.Table.Table
export project.Data.Type.Value_Type.Auto
export project.Data.Type.Value_Type.Bits
export project.Data.Type.Value_Type.Value_Type
export project.Delimited.Delimited_Format.Delimited_Format
export project.Delimited.Quote_Style.Quote_Style

View File

@ -1,6 +1,6 @@
from Standard.Base import all
from Standard.Table import Position
from Standard.Table import Position, Value_Type, Bits
from Standard.Table.Errors import all
from Standard.Test import all
@ -32,6 +32,25 @@ type Select_Columns_Data
teardown self =
self.connection.close
type Mixed_Columns_Data
Value ~data
connection self = self.data.at 0
table self = self.data.at 1
setup create_connection_fn table_builder = Mixed_Columns_Data.Value <|
connection = create_connection_fn Nothing
table =
col1 = ["int", [1, 2, 3]]
col2 = ["float", [4.1, 5.2, 6.3]]
col3 = ["text", ["A", "B", "C"]]
col4 = ["bool", [True, False, True]]
table_builder [col1, col2, col3, col4] connection=connection
[connection, table]
teardown self =
self.connection.close
type Sort_Columns_Data
Value ~data
@ -203,6 +222,42 @@ add_specs suite_builder setup =
r2.catch.cause . should_be_a Missing_Input_Columns
r2.catch.to_display_text . should_equal "No columns in the result, because of another problem: The criteria 'hmmm' did not match any columns."
suite_builder.group prefix+"Table.select_by_type and Table.remove_by_type" group_builder->
data = Mixed_Columns_Data.setup create_connection_fn table_builder
group_builder.teardown <|
data.teardown
group_builder.specify "should be able to select by type of columns" <|
expect_column_names ["int"] <| data.table.select_by_type [Value_Type.Integer]
expect_column_names ["float"] <| data.table.select_by_type [Value_Type.Float]
expect_column_names ["int", "float"] <| data.table.select_by_type [Value_Type.Integer, Value_Type.Float]
expect_column_names ["text"] <| data.table.select_by_type [Value_Type.Char]
expect_column_names ["bool"] <| data.table.select_by_type [Value_Type.Boolean]
group_builder.specify "should be able to drop by type of columns" <|
expect_column_names ["float", "text", "bool"] <| data.table.remove_by_type [Value_Type.Integer]
expect_column_names ["int", "text", "bool"] <| data.table.remove_by_type [Value_Type.Float]
expect_column_names ["text", "bool"] <| data.table.remove_by_type [Value_Type.Integer, Value_Type.Float]
expect_column_names ["int", "float", "bool"] <| data.table.remove_by_type [Value_Type.Char]
expect_column_names ["int", "float", "text"] <| data.table.remove_by_type [Value_Type.Boolean]
group_builder.specify "should be able to select by strict type" <|
expect_column_names ["int"] <| data.table.select_by_type [Value_Type.Integer] strict=True
data.table.select_by_type [Value_Type.Integer Bits.Bits_16] strict=True . should_fail_with No_Output_Columns
expect_column_names ["float"] <| data.table.select_by_type [Value_Type.Float] strict=True
data.table.select_by_type [Value_Type.Float Bits.Bits_32] strict=True . should_fail_with No_Output_Columns
expect_column_names ["text"] <| data.table.select_by_type [Value_Type.Char] strict=True
data.table.select_by_type [Value_Type.Char 3 False] strict=True . should_fail_with No_Output_Columns
group_builder.specify "should be able to remove by strict type" <|
expect_column_names ["float", "text", "bool"] <| data.table.remove_by_type [Value_Type.Integer] strict=True
expect_column_names ["int", "float", "text", "bool"] <| data.table.remove_by_type [Value_Type.Integer Bits.Bits_16] strict=True
expect_column_names ["int", "text", "bool"] <| data.table.remove_by_type [Value_Type.Float] strict=True
expect_column_names ["int", "float", "text", "bool"] <| data.table.remove_by_type [Value_Type.Float Bits.Bits_32] strict=True
expect_column_names ["int", "float", "bool"] <| data.table.remove_by_type [Value_Type.Char] strict=True
expect_column_names ["int", "float", "text", "bool"] <| data.table.remove_by_type [Value_Type.Char 3 False] strict=True
suite_builder.group prefix+"Table.remove_columns" group_builder->
data = Select_Columns_Data.setup create_connection_fn table_builder