From 9301f2dcc5ee652341671689b2d806d04f4f3ef9 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Fri, 7 Oct 2022 12:32:00 +0100 Subject: [PATCH] Sort out statics in Database. (#3774) - Moved `Standard.Database.connect` into `Standard.Database.Database.connect`, so can now just `from Standard.Database import ...`. - Removed all `Dubious constructor export`s. - Switched to using `project` for internal imports. - Moved to using `Value` for private constructors and not re-exporting. - Export types not modules from `Standard.Database`. - Broke up `IR` into separate files (Context, Expression, From_Spec, Internal_Column, Join_Kind, Query). - No longer use `IR.` instead via specific types. - Broke up `SQL` into separate files (SQL_Type and SQL_Statement). Additionally; - Standard.Table: Moved `storage_types` into `Storage`. - Standard.Table: Switched to using `project` for internal imports. - Standard.Table.Excel: Renamed modules `Range` to `Excel_Range` and `Section` to `Excel_Section`. - `Standard.Visualisation`: Switched to using `project` for internal imports. - `Standard.Visualisation`: Moved to using `Value` for private constructors and not re-exporting. # Important Notes - Have not cleared up the `Errors` yet. - Have not switched to type pattern matching. --- .../src/Connection/Client_Certificate.enso | 6 +- .../0.0.0-dev/src/Connection/Connection.enso | 50 +- .../src/Connection/Connection_Options.enso | 5 +- .../0.0.0-dev/src/Connection/Credentials.enso | 4 - .../0.0.0-dev/src/Connection/Database.enso | 15 +- .../src/Connection/Postgres_Options.enso | 41 +- .../src/Connection/Redshift_Options.enso | 45 +- .../src/Connection/SQLite_Options.enso | 9 +- .../0.0.0-dev/src/Connection/SSL_Mode.enso | 4 - .../Database/0.0.0-dev/src/Data/Column.enso | 65 ++- .../Database/0.0.0-dev/src/Data/Dialect.enso | 19 +- .../Database/0.0.0-dev/src/Data/SQL.enso | 255 ++-------- .../0.0.0-dev/src/Data/SQL_Query.enso | 4 - .../0.0.0-dev/src/Data/SQL_Statement.enso | 78 +++ .../Database/0.0.0-dev/src/Data/SQL_Type.enso | 108 +++++ .../Database/0.0.0-dev/src/Data/Table.enso | 109 ++--- .../src/Internal/Aggregate_Helper.enso | 65 +-- .../src/Internal/Base_Generator.enso | 68 +-- .../0.0.0-dev/src/Internal/Helpers.enso | 14 +- .../Database/0.0.0-dev/src/Internal/IR.enso | 451 ------------------ .../0.0.0-dev/src/Internal/IR/Context.enso | 164 +++++++ .../0.0.0-dev/src/Internal/IR/Expression.enso | 46 ++ .../0.0.0-dev/src/Internal/IR/From_Spec.enso | 60 +++ .../src/Internal/IR/Internal_Column.enso | 24 + .../0.0.0-dev/src/Internal/IR/Join_Kind.enso | 44 ++ .../src/Internal/IR/Nulls_Order.enso | 16 + .../src/Internal/IR/Order_Descriptor.enso | 8 + .../0.0.0-dev/src/Internal/IR/Query.enso | 37 ++ .../src/Internal/JDBC_Connection.enso | 37 +- .../src/Internal/Postgres/Pgpass.enso | 8 +- .../Postgres/Postgres_Connection.enso | 42 +- .../Internal/Postgres/Postgres_Dialect.enso | 50 +- .../Internal/Redshift/Redshift_Dialect.enso | 25 +- .../0.0.0-dev/src/Internal/Result_Set.enso | 15 +- .../Internal/SQLite/SQLite_Connection.enso | 40 +- .../src/Internal/SQLite/SQLite_Dialect.enso | 38 +- .../Standard/Database/0.0.0-dev/src/Main.enso | 37 +- .../0.0.0-dev/src/Data/Aggregate_Column.enso | 6 +- .../Table/0.0.0-dev/src/Data/Column.enso | 24 +- .../0.0.0-dev/src/Data/Data_Formatter.enso | 7 +- .../src/Data/Sort_Column_Selector.enso | 4 +- .../Table/0.0.0-dev/src/Data/Storage.enso | 8 + .../Table/0.0.0-dev/src/Data/Table.enso | 40 +- .../0.0.0-dev/src/Data/Table_Conversions.enso | 10 +- .../Table/0.0.0-dev/src/Data/Value_Type.enso | 2 +- .../src/Delimited/Delimited_Format.enso | 12 +- .../src/Delimited/Delimited_Reader.enso | 10 +- .../src/Delimited/Delimited_Writer.enso | 17 +- .../0.0.0-dev/src/Excel/Excel_Format.enso | 8 +- .../Excel/{Range.enso => Excel_Range.enso} | 0 .../0.0.0-dev/src/Excel/Excel_Reader.enso | 9 +- .../{Section.enso => Excel_Section.enso} | 6 +- .../0.0.0-dev/src/Excel/Excel_Writer.enso | 13 +- .../Table/0.0.0-dev/src/IO/Auto_Detect.enso | 4 +- .../Table/0.0.0-dev/src/IO/File_Read.enso | 2 +- .../src/Internal/Aggregate_Column_Helper.enso | 24 +- .../Filter_Condition_Helpers.enso | 2 +- .../0.0.0-dev/src/Internal/Java_Exports.enso | 6 +- .../src/Internal/Parse_Values_Helper.enso | 2 +- .../src/Internal/Problem_Builder.enso | 4 +- .../0.0.0-dev/src/Internal/Table_Helpers.enso | 17 +- .../Standard/Table/0.0.0-dev/src/Main.enso | 9 +- .../0.0.0-dev/src/File_Upload.enso | 8 +- .../Visualization/0.0.0-dev/src/Geo_Map.enso | 4 +- .../0.0.0-dev/src/Histogram.enso | 8 +- .../Visualization/0.0.0-dev/src/Id.enso | 27 +- .../Visualization/0.0.0-dev/src/Main.enso | 10 +- .../0.0.0-dev/src/SQL/Visualization.enso | 5 +- .../0.0.0-dev/src/Scatter_Plot.enso | 39 +- .../0.0.0-dev/src/Table/Visualization.enso | 10 +- test/Table_Tests/src/Column_Spec.enso | 24 +- .../src/Database/Codegen_Spec.enso | 12 +- .../Helpers/Fake_Test_Connection.enso | 23 +- .../src/Database/Postgres_Spec.enso | 55 ++- .../src/Database/Redshift_Spec.enso | 11 +- .../Table_Tests/src/Database/SQLite_Spec.enso | 9 +- test/Visualization_Tests/src/SQL_Spec.enso | 5 +- test/Visualization_Tests/src/Table_Spec.enso | 4 +- .../src/Visualization_Spec.enso | 6 +- 79 files changed, 1232 insertions(+), 1380 deletions(-) create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Statement.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Type.enso delete mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Context.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Expression.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/From_Spec.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Internal_Column.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Join_Kind.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Nulls_Order.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Order_Descriptor.enso create mode 100644 distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Query.enso rename distribution/lib/Standard/Table/0.0.0-dev/src/Excel/{Range.enso => Excel_Range.enso} (100%) rename distribution/lib/Standard/Table/0.0.0-dev/src/Excel/{Section.enso => Excel_Section.enso} (82%) rename distribution/lib/Standard/Table/0.0.0-dev/src/{Data => Internal}/Filter_Condition_Helpers.enso (98%) diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Client_Certificate.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Client_Certificate.enso index a217b6afe01..f5ac036ebec 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Client_Certificate.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Client_Certificate.enso @@ -1,9 +1,5 @@ from Standard.Base import all -# TODO Dubious constructor export -from project.Connection.Client_Certificate.Client_Certificate import all -from project.Connection.Client_Certificate.Client_Certificate export all - type Client_Certificate ## Creates a new Client_Certificate object. @@ -11,7 +7,7 @@ type Client_Certificate - cert_file: path to the client certificate file. - key_file: path to the client key file. - key_password: password for the client key file. - Client_Certificate_Data cert_file:(File|Text) key_file:(File|Text) (key_password:Text='') + Value cert_file:(File|Text) key_file:(File|Text) (key_password:Text='') ## PRIVATE Creates the JDBC properties for the client certificate. diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection.enso index 67f9dc813ab..48c1935f501 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection.enso @@ -1,25 +1,23 @@ from Standard.Base import all -import Standard.Database.Internal.IR -import Standard.Database.Data.SQL -import Standard.Database.Data.SQL_Query -import Standard.Database.Data.Table as Database_Table - -import Standard.Table.Data.Table as Materialized_Table from Standard.Table import Column_Selector, Column_Name_Mapping +import Standard.Table.Data.Table.Table as Materialized_Table -from Standard.Database.Data.SQL import SQL_Type, Statement, Statement_Data -from Standard.Database.Internal.JDBC_Connection import create_table_statement, handle_sql_errors -from Standard.Database.Internal.Result_Set import read_column, result_set_to_table -from Standard.Database.Errors import SQL_Error +import project.Data.SQL_Query.SQL_Query +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Data.Table as Database_Table +import project.Internal.IR.Context.Context +import project.Internal.IR.Expression.Expression +import project.Internal.IR.Query.Query + +from project.Internal.Result_Set import read_column, result_set_to_table +from project.Internal.JDBC_Connection import create_table_statement, handle_sql_errors +from project.Errors import SQL_Error polyglot java import java.lang.UnsupportedOperationException polyglot java import java.util.UUID -# TODO Dubious constructor export -from project.Connection.Connection.Connection import all -from project.Connection.Connection.Connection export all - type Connection ## PRIVATE @@ -29,7 +27,7 @@ type Connection - jdbc_connection: the resource managing the underlying JDBC connection. - dialect: the dialect associated with the database we are connected to. - Connection_Data jdbc_connection dialect + Value jdbc_connection dialect ## Closes the connection releasing the underlying database resources immediately instead of waiting for them to be automatically released. @@ -94,7 +92,7 @@ type Connection - schema: The schema name to search in (defaults to current schema). - types: The table types to search for. The list of possible values can be obtained using the `table_types` method. - all_fields: Return all the fields in the metadata table. - tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table.Table + tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table tables self name_like=Nothing database=self.database schema=self.schema types=Nothing all_fields=False = types_array = if types.is_nothing then Nothing else types.to_array name_map = Map.from_vector [["TABLE_CAT", "Database"], ["TABLE_SCHEM", "Schema"], ["TABLE_NAME", "Name"], ["TABLE_TYPE", "Type"], ["REMARKS", "Description"], ["TYPE_CAT", "Type Database"], ["TYPE_SCHEM", "Type Schema"], ["TYPE_NAME", "Type Name"]] @@ -121,11 +119,11 @@ type Connection SQL_Query.Raw_SQL raw_sql -> columns = self.jdbc_connection.fetch_columns raw_sql name = if alias == "" then (UUID.randomUUID.to_text) else alias - ctx = IR.context_for_query raw_sql name + ctx = Context.for_query raw_sql name Database_Table.make_table self name columns ctx SQL_Query.Table_Name name -> - ctx = IR.context_for_table name (if alias == "" then name else alias) - columns = self.jdbc_connection.fetch_columns (self.dialect.generate_sql (IR.Select_All ctx)) + ctx = Context.for_table name (if alias == "" then name else alias) + columns = self.jdbc_connection.fetch_columns (self.dialect.generate_sql (Query.Select_All ctx)) Database_Table.make_table self name columns ctx ## Execute the query and load the results into memory as a Table. @@ -134,13 +132,13 @@ type Connection - query: name of the table or sql statement to query. If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - limit: the maximum number of rows to return. - read : Text | SQL_Query -> Text -> Integer | Nothing -> Materialized_Table.Table + read : Text | SQL_Query -> Text -> Integer | Nothing -> Materialized_Table read self query limit=Nothing = self.query query . read max_rows=limit ## PRIVATE Internal read function for a statement with optional types. - read_statement : Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table.Table + read_statement : SQL_Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table read_statement self statement expected_types=Nothing = self.jdbc_connection.with_prepared_statement statement stmt-> result_set_to_table stmt.executeQuery expected_types @@ -152,9 +150,9 @@ type Connection returns 0 for other types of queries (like creating or altering tables). Arguments: - - query: either raw SQL code as Text or an instance of SQL.Statement + - query: either raw SQL code as Text or an instance of SQL_Statement representing the query to execute. - execute_update : Text | SQL.Statement -> Integer + execute_update : Text | SQL_Statement -> Integer execute_update self query = self.jdbc_connection.with_prepared_statement query stmt-> Panic.catch UnsupportedOperationException stmt.executeLargeUpdate _-> @@ -177,15 +175,15 @@ type Connection usually not be visible to other connections. - batch_size: Specifies how many rows should be uploaded in a single batch. - upload_table : Text -> Materialized_Table.Table -> Boolean -> Integer -> Database_Table.Table + upload_table : Text -> Materialized_Table -> Boolean -> Integer -> Database_Table.Table upload_table self name table temporary=True batch_size=1000 = Panic.recover Illegal_State_Error_Data <| create_sql = create_table_statement name table temporary create_table = self.execute_update create_sql db_table = if create_table.is_error then create_table else self.query (SQL_Query.Table_Name name) if db_table.is_error.not then - pairs = db_table.internal_columns.map col->[col.name, IR.Constant col.sql_type Nothing] - insert_query = self.dialect.generate_sql <| IR.Insert name pairs + pairs = db_table.internal_columns.map col->[col.name, Expression.Constant col.sql_type Nothing] + insert_query = self.dialect.generate_sql <| Query.Insert name pairs insert_template = insert_query.prepare.first self.jdbc_connection.load_table insert_template db_table table batch_size diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection_Options.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection_Options.enso index 46e36b8e75f..f8e0db840f2 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection_Options.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Connection_Options.enso @@ -1,12 +1,9 @@ from Standard.Base import all -# TODO Dubious constructor export -from project.Connection.Connection_Options.Connection_Options import all -from project.Connection.Connection_Options.Connection_Options export all type Connection_Options ## Hold a set of key value pairs used to configure the connection. - Connection_Options_Data options:Vector=[] + Value options:Vector=[] ## Merge the base set of options with the overrides in this object. merge : Vector -> Vector diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Credentials.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Credentials.enso index 07cefa61adb..f50a660b8bf 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Credentials.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Credentials.enso @@ -1,9 +1,5 @@ from Standard.Base import all -# TODO Dubious constructor export -from project.Connection.Credentials.Credentials import all -from project.Connection.Credentials.Credentials export all - type Credentials ## Simple username and password type. Username_And_Password username:Text password:Text diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Database.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Database.enso index 159c70ae5bf..6a37da3d5f8 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Database.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Database.enso @@ -1,13 +1,12 @@ from Standard.Base import all -from Standard.Database.Connection.Connection_Options import Connection_Options, Connection_Options_Data +import project.Connection.Connection_Options.Connection_Options +import project.Connection.Postgres_Options.Postgres_Options +import project.Connection.SQLite_Options.SQLite_Options +import project.Connection.Redshift_Options.Redshift_Options +import project.Connection.Connection.Connection -from Standard.Database.Connection.Postgres_Options import Postgres_Options -from Standard.Database.Connection.SQLite_Options import SQLite_Options -from Standard.Database.Connection.Redshift_Options import Redshift_Options - -from Standard.Database.Connection.Connection import Connection -from Standard.Database.Errors import SQL_Error +from project.Errors import SQL_Error ## UNSTABLE @@ -17,5 +16,5 @@ from Standard.Database.Errors import SQL_Error - details: Connection_Details to use to connect. - options: Any overriding options to use. connect : (Postgres_Options|SQLite_Options|Redshift_Options) -> Connection_Options -> Connection ! SQL_Error -connect details options=Connection_Options_Data = +connect details options=Connection_Options.Value = details.connect options diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Postgres_Options.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Postgres_Options.enso index 37dde32b5d4..bc1018e7b13 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Postgres_Options.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Postgres_Options.enso @@ -1,24 +1,17 @@ from Standard.Base import all - from Standard.Base.Data.Numbers import Parse_Error_Data -import Standard.Database.Internal.Postgres.Postgres_Connection -import Standard.Database.Connection.Connection_Options - -from Standard.Database.Connection.Credentials import Credentials, Username_And_Password - -import Standard.Database.Connection.SSL_Mode -from Standard.Database.Connection.SSL_Mode import all - -import Standard.Database.Connection.Client_Certificate - -import Standard.Database.Internal.Postgres.Pgpass +import project.Connection.Client_Certificate.Client_Certificate +import project.Connection.Connection_Options.Connection_Options +import project.Connection.Credentials.Credentials +import project.Connection.SSL_Mode.SSL_Mode +import project.Internal.Postgres.Postgres_Connection +import project.Internal.Postgres.Pgpass polyglot java import org.postgresql.Driver -# TODO Dubious constructor export -from project.Connection.Postgres_Options.Postgres_Options import all -from project.Connection.Postgres_Options.Postgres_Options export all +from project.Connection.Postgres_Options.Postgres_Options import Postgres +from project.Connection.Postgres_Options.Postgres_Options export Postgres type Postgres_Options ## Connect to a PostgreSQL database. @@ -29,9 +22,9 @@ type Postgres_Options - database: The database to connect to. If empty, the default database will be used. - schema: The schema to connect to. If empty, the default schema will be used. - credentials: The credentials to use for the connection (defaults to PGPass or No Authentication). - - use_ssl: Whether to use SSL (defaults to `Prefer`). + - use_ssl: Whether to use SSL (defaults to `SSL_Mode.Prefer`). - client_cert: The client certificate to use or `Nothing` if not needed. - Postgres (host:Text=default_postgres_host) (port:Integer=default_postgres_port) (database:Text=default_postgres_database) (schema:Text="") (credentials:(Credentials|Nothing)=Nothing) (use_ssl:SSL_Mode=Prefer) (client_cert:(Client_Certificate|Nothing)=Nothing) + Postgres (host:Text=default_postgres_host) (port:Integer=default_postgres_port) (database:Text=default_postgres_database) (schema:Text="") (credentials:(Credentials|Nothing)=Nothing) (use_ssl:SSL_Mode=SSL_Mode.Prefer) (client_cert:(Client_Certificate|Nothing)=Nothing) ## Build the Connection resource. @@ -45,7 +38,7 @@ type Postgres_Options ## Cannot use default argument values as gets in an infinite loop if you do. make_new database schema = - Postgres self.host self.port (database.if_nothing self.database) (schema.if_nothing self.schema) self.credentials self.use_ssl self.client_cert . connect options + Postgres_Options.Postgres self.host self.port (database.if_nothing self.database) (schema.if_nothing self.schema) self.credentials self.use_ssl self.client_cert . connect options Postgres_Connection.create self.jdbc_url properties make_new @@ -70,7 +63,7 @@ type Postgres_Options Pgpass.read self.host self.port self.database username Pair_Data username password -> [Pair_Data 'user' username, Pair_Data 'password' password] - Username_And_Password username password -> + Credentials.Username_And_Password username password -> [Pair_Data 'user' username, Pair_Data 'password' password] ssl_properties = ssl_mode_to_jdbc_properties self.use_ssl @@ -85,13 +78,13 @@ type Postgres_Options connection. ssl_mode_to_jdbc_properties : SSL_Mode -> [Pair Text Text] ssl_mode_to_jdbc_properties use_ssl = case use_ssl of - Disable -> [] - Prefer -> [Pair_Data 'sslmode' 'prefer'] - Require -> [Pair_Data 'sslmode' 'require'] - Verify_CA cert_file -> + SSL_Mode.Disable -> [] + SSL_Mode.Prefer -> [Pair_Data 'sslmode' 'prefer'] + SSL_Mode.Require -> [Pair_Data 'sslmode' 'require'] + SSL_Mode.Verify_CA cert_file -> if cert_file.is_nothing then [Pair_Data 'sslmode' 'verify-ca'] else [Pair_Data 'sslmode' 'verify-ca', Pair_Data 'sslrootcert' (File.new cert_file).absolute.path] - Full_Verification cert_file -> + SSL_Mode.Full_Verification cert_file -> if cert_file.is_nothing then [Pair_Data 'sslmode' 'verify-full'] else [Pair_Data 'sslmode' 'verify-full', Pair_Data 'sslrootcert' (File.new cert_file).absolute.path] diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Redshift_Options.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Redshift_Options.enso index d3560f2b88b..84dc2daf1ec 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Redshift_Options.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/Redshift_Options.enso @@ -1,22 +1,20 @@ from Standard.Base import all -import Standard.Database.Data.Dialect -import Standard.Database.Internal.JDBC_Connection -import Standard.Database.Connection.Connection -from Standard.Database.Connection.Credentials import Credentials, Username_And_Password -import Standard.Database.Connection.Connection_Options -import Standard.Database.Connection.SSL_Mode -from Standard.Database.Connection.SSL_Mode import all -import Standard.Database.Connection.Client_Certificate -import Standard.Database.Internal.Postgres.Pgpass +import project.Connection.Client_Certificate.Client_Certificate +import project.Connection.Connection.Connection +import project.Connection.Connection_Options.Connection_Options +import project.Connection.Credentials.Credentials +import project.Connection.SSL_Mode.SSL_Mode +import project.Data.Dialect +import project.Internal.JDBC_Connection +import project.Internal.Postgres.Pgpass polyglot java import com.amazon.redshift.jdbc.Driver polyglot java import java.util.Properties polyglot java import org.enso.database.JDBCProxy -# TODO Dubious constructor export -from project.Connection.Redshift_Options.Redshift_Options import all -from project.Connection.Redshift_Options.Redshift_Options export all +from project.Connection.Redshift_Options.Redshift_Options import Redshift +from project.Connection.Redshift_Options.Redshift_Options export Redshift type Redshift_Options ## Connect to a AWS Redshift database. @@ -26,9 +24,9 @@ type Redshift_Options - port: The port of the database server (defaults to 5432). - schema: The schema to connect to (if not provided or empty, the default schema will be used). - credentials: The credentials to use for the connection (defaults to PGPass or No Authentication). - - use_ssl: Whether to use SSL (defaults to `Require`). + - use_ssl: Whether to use SSL (defaults to `SSL_Mode.Require`). - client_cert: The client certificate to use or `Nothing` if not needed. - Redshift (host:Text) (port:Integer=5439) (schema:Text='') (credentials:Credentials|AWS_Credential|Nothing=Nothing) (use_ssl:(Disable|Require|Verify_CA|Full_Verification)=Require) (client_cert:Client_Certificate|Nothing=Nothing) + Redshift (host:Text) (port:Integer=5439) (schema:Text='') (credentials:Credentials|AWS_Credential|Nothing=Nothing) (use_ssl:SSL_Mode=SSL_Mode.Require) (client_cert:Client_Certificate|Nothing=Nothing) ## Build the Connection resource. @@ -44,14 +42,13 @@ type Redshift_Options java_props.setProperty pair.first pair.second jdbc_connection = JDBC_Connection.create self.jdbc_url properties - Connection.Connection_Data jdbc_connection Dialect.redshift + Connection.Value jdbc_connection Dialect.redshift ## Provides the jdbc url for the connection. jdbc_url : Text jdbc_url self = prefix = case self.credentials of - AWS_Profile _ _ -> 'jdbc:redshift:iam://' - AWS_Key _ _ _ -> 'jdbc:redshift:iam://' + _ : AWS_Credential -> 'jdbc:redshift:iam://' _ -> 'jdbc:redshift://' prefix + self.host + ':' + self.port.to_text + (if self.schema == '' then '' else '/' + self.schema) @@ -60,11 +57,11 @@ type Redshift_Options jdbc_properties self = credentials = case self.credentials of Nothing -> Pgpass.read self.host self.port self.schema - AWS_Profile db_user profile -> + AWS_Credential.Profile db_user profile -> [Pair_Data 'user' db_user] + (if profile == '' then [] else [Pair_Data 'profile' profile]) - AWS_Key db_user access_key secret_access_key -> + AWS_Credential.Key db_user access_key secret_access_key -> [Pair_Data 'user' db_user, Pair_Data 'AccessKeyID' access_key, Pair_Data 'SecretAccessKey' secret_access_key] - Username_And_Password username password -> + Credentials.Username_And_Password username password -> [Pair_Data 'user' username, Pair_Data 'password' password] ## Disabled as Redshift SSL settings are different to PostgreSQL. @@ -75,17 +72,13 @@ type Redshift_Options credentials + ssl_properties + cert_properties -# TODO Dubious constructor export -from project.Connection.Redshift_Options.AWS_Credential import all -from project.Connection.Redshift_Options.AWS_Credential export all - type AWS_Credential ## Access Redshift using IAM via an AWS profile. Arguments: - db_user: Redshift username to connect as. - profile: AWS profile name (if empty uses default). - AWS_Profile db_user:Text profile:Text='' + Profile db_user:Text profile:Text='' ## Access Redshift using IAM via an AWS access key ID and secret access key. @@ -93,4 +86,4 @@ type AWS_Credential - db_user: Redshift username to connect as. - access_key: AWS access key ID. - secret_access_key: AWS secret access key. - AWS_Key db_user:Text access_key:Text secret_access_key:Text + Key db_user:Text access_key:Text secret_access_key:Text diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SQLite_Options.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SQLite_Options.enso index 66f2c8e7854..a16a64d7481 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SQLite_Options.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SQLite_Options.enso @@ -1,11 +1,10 @@ from Standard.Base import all -import Standard.Database.Internal.SQLite.SQLite_Connection -import Standard.Database.Connection.Connection_Options +import project.Connection.Connection_Options +import project.Internal.SQLite.SQLite_Connection -# TODO Dubious constructor export -from project.Connection.SQLite_Options.SQLite_Options import all -from project.Connection.SQLite_Options.SQLite_Options export all +from project.Connection.SQLite_Options.SQLite_Options import SQLite +from project.Connection.SQLite_Options.SQLite_Options export SQLite type SQLite_Options ## Connect to a SQLite DB File or InMemory DB. diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SSL_Mode.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SSL_Mode.enso index 06f8d3359ac..4878a290a92 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SSL_Mode.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Connection/SSL_Mode.enso @@ -1,9 +1,5 @@ from Standard.Base import all -# TODO Dubious constructor export -from project.Connection.SSL_Mode.SSL_Mode import all -from project.Connection.SSL_Mode.SSL_Mode export all - type SSL_Mode ## Do not use SSL for the connection. Disable diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Column.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Column.enso index 555b7f83e58..35fd7200406 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Column.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Column.enso @@ -1,22 +1,19 @@ from Standard.Base import all -import Standard.Database.Internal.Helpers -import Standard.Database.Internal.IR -from Standard.Database.Data.Table import Table, freshen_columns -from Standard.Table import Filter_Condition - -import Standard.Table.Data.Column.Column as Materialized_Column -import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector -import Standard.Table.Data.Sort_Column.Sort_Column +from Standard.Table import Sort_Column, Sort_Column_Selector import Standard.Table.Data.Value_Type.Value_Type +import Standard.Table.Data.Column.Column as Materialized_Column -from Standard.Database.Data.SQL import SQL_Type, Statement -from Standard.Database.Data.Table import Integrity_Error -from Standard.Database.Errors import Unsupported_Database_Operation_Error +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.Helpers +import project.Internal.IR.Context.Context +import project.Internal.IR.Expression.Expression +import project.Internal.IR.Internal_Column.Internal_Column -# TODO Dubious constructor export -from project.Data.Column.Column import all -from project.Data.Column.Column export all +from project.Data.Table import Table, freshen_columns + +from project.Errors import Unsupported_Database_Operation_Error type Column @@ -37,7 +34,7 @@ type Column which they come. Combined expressions must come from the same context - they must both have the same filtering, grouping etc. rules applied to be able to be combined. - Column_Data name:Text connection:Connection sql_type:SQL_Type expression:IR.Expression context:IR.Context + Value name:Text connection:Connection sql_type:SQL_Type expression:Expression context:Context ## UNSTABLE @@ -72,7 +69,7 @@ type Column Converts this column into a single-column table. to_table : Table to_table self = - Table.Table_Data self.name self.connection [self.as_internal] self.context + Table.Value self.name self.connection [self.as_internal] self.context ## UNSTABLE @@ -81,7 +78,7 @@ type Column Arguments: - max_rows: specifies a maximum amount of rows to fetch; if not set, all available rows are fetched. - read : (Nothing | Integer) -> Materialized_Column.Column + read : (Nothing | Integer) -> Materialized_Column read self max_rows=Nothing = self.to_table.read max_rows . at self.name @@ -113,7 +110,7 @@ type Column ## UNSTABLE Returns an SQL statement that will be used for materializing this column. - to_sql : Statement + to_sql : SQL_Statement to_sql self = self.to_table.to_sql ## PRIVATE @@ -134,18 +131,18 @@ type Column make_binary_op self op_kind operand new_type=Nothing operand_type=Nothing = actual_new_type = new_type.if_nothing self.sql_type case operand of - Column_Data _ _ _ other_expr _ -> + Column.Value _ _ _ other_expr _ -> case Helpers.check_integrity self operand of False -> Error.throw <| Unsupported_Database_Operation_Error "Cannot compare columns coming from different contexts. Only columns of a single table can be compared." True -> - new_expr = IR.Operation op_kind [self.expression, other_expr] - Column_Data self.name self.connection actual_new_type new_expr self.context + new_expr = Expression.Operation op_kind [self.expression, other_expr] + Column.Value self.name self.connection actual_new_type new_expr self.context _ -> actual_operand_type = operand_type.if_nothing self.sql_type - other = IR.make_constant actual_operand_type operand - new_expr = IR.Operation op_kind [self.expression, other] - Column_Data self.name self.connection actual_new_type new_expr self.context + other = Expression.Constant actual_operand_type operand + new_expr = Expression.Operation op_kind [self.expression, other] + Column.Value self.name self.connection actual_new_type new_expr self.context ## PRIVATE @@ -158,8 +155,8 @@ type Column make_unary_op : Text -> Text -> (SQL_Type | Nothing) -> Column make_unary_op self op_kind new_type=Nothing = actual_new_type = new_type.if_nothing self.sql_type - new_expr = IR.Operation op_kind [self.expression] - Column_Data self.name self.connection actual_new_type new_expr self.context + new_expr = Expression.Operation op_kind [self.expression] + Column.Value self.name self.connection actual_new_type new_expr self.context ## UNSTABLE @@ -430,7 +427,7 @@ type Column case is_used_in_index of True -> Error.throw <| Illegal_State_Error_Data "Cannot rename the column to "+new_name+", because it has an index with the same name." False -> - Column_Data new_name self.connection self.sql_type self.expression self.context + Column.Value new_name self.connection self.sql_type self.expression self.context ## UNSTABLE @@ -521,8 +518,8 @@ type Column contains self other = self.make_binary_op "contains" other new_type=SQL_Type.boolean ## PRIVATE - as_internal : IR.Internal_Column - as_internal self = IR.Internal_Column_Data self.name self.sql_type self.expression + as_internal : Internal_Column + as_internal self = Internal_Column.Value self.name self.sql_type self.expression ## PRIVATE @@ -537,7 +534,7 @@ type Column make_aggregate : Column -> Text -> Text -> SQL_Type -> Column make_aggregate column operation name_suffix="_agg" new_type=Nothing = actual_new_type = new_type.if_nothing column.sql_type - expr = IR.Operation operation [column.expression] + expr = Expression.Operation operation [column.expression] case Helpers.ensure_name_is_sane name_suffix of True -> new_name = column.name + name_suffix @@ -554,18 +551,18 @@ make_aggregate column operation name_suffix="_agg" new_type=Nothing = - expected_type: The expected SQL type of the column. - expr: The expression for the query. - context: The context in which the query exists. -lift_aggregate : Text -> Connection -> SQL_Type -> IR.Expression -> IR.Context -> Column +lift_aggregate : Text -> Connection -> SQL_Type -> Expression -> Context -> Column lift_aggregate new_name connection expected_type expr context = # TODO [RW] This is a simple workaround for #1643 - we always wrap the # aggregate into a subquery, thus making it safe to use it everywhere. A # more complex solution may be adopted at some point. ixes = freshen_columns [new_name] context.meta_index - col = IR.Internal_Column_Data new_name expected_type expr + col = Internal_Column.Value new_name expected_type expr setup = context.as_subquery new_name+"_sub" [[col], ixes] subquery = setup.first cols = setup.second new_col = cols.first.first new_ixes = cols.second - new_ctx = IR.subquery_as_ctx subquery . set_index new_ixes - Column_Data new_name connection new_col.sql_type new_col.expression new_ctx + new_ctx = Context.for_subquery subquery . set_index new_ixes + Column.Value new_name connection new_col.sql_type new_col.expression new_ctx diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Dialect.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Dialect.enso index f5af25524ac..e39f40a01ef 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Dialect.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Dialect.enso @@ -1,12 +1,15 @@ from Standard.Base import all - import Standard.Base.Error.Common as Errors + from Standard.Table import Aggregate_Column -from Standard.Database.Data.SQL import Statement, SQL_Type -import Standard.Database.Internal.IR -import Standard.Database.Internal.Postgres.Postgres_Dialect -import Standard.Database.Internal.Redshift.Redshift_Dialect -import Standard.Database.Internal.SQLite.SQLite_Dialect + +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.IR.Internal_Column.Internal_Column +import project.Internal.IR.Order_Descriptor.Order_Descriptor +import project.Internal.Postgres.Postgres_Dialect +import project.Internal.Redshift.Redshift_Dialect +import project.Internal.SQLite.SQLite_Dialect ## PRIVATE @@ -23,7 +26,7 @@ type Dialect ## PRIVATE A function which generates SQL code from the internal representation according to the specific dialect. - generate_sql : Query -> Statement + generate_sql : Query -> SQL_Statement generate_sql self = Errors.unimplemented "This is an interface only." ## PRIVATE @@ -39,7 +42,7 @@ type Dialect One of the purposes of this method is to verify if the expected ordering settings are supported by the given database backend. - prepare_order_descriptor : IR.Internal_Column -> Sort_Direction -> Text_Ordering -> IR.Order_Descriptor + prepare_order_descriptor : Internal_Column -> Sort_Direction -> Text_Ordering -> Order_Descriptor prepare_order_descriptor self = Errors.unimplemented "This is an interface only." ## PRIVATE diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL.enso index 8524b9ebe5d..f136469d184 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL.enso @@ -2,13 +2,14 @@ from Standard.Base import all import Standard.Table.Internal.Vector_Builder.Vector_Builder -polyglot java import java.sql.Types +import project.Data.SQL_Type.SQL_Type +import project.Data.SQL_Statement.SQL_Statement ## UNSTABLE Creates a Builder representing and empty code fragment. empty : Builder -empty = Builder_Data (Vector_Builder.empty) +empty = Builder.Value (Vector_Builder.empty) ## UNSTABLE @@ -19,8 +20,8 @@ empty = Builder_Data (Vector_Builder.empty) - text: The raw SQL code. code : Text -> Builder code text = - vec = if text.is_empty then [] else [SQL_Code_Part text] - Builder_Data (Vector_Builder.from_vector vec) + vec = if text.is_empty then [] else [SQL_Fragment.Code_Part text] + Builder.Value (Vector_Builder.from_vector vec) ## UNSTABLE @@ -31,7 +32,7 @@ code text = - object: The object to be interpolated into the query as if it has the type given by `sql_type`. interpolation : SQL_Type -> Any -> Builder -interpolation sql_type object = Builder_Data (Vector_Builder.from_vector [SQL_Interpolation sql_type object]) +interpolation sql_type object = Builder.Value (Vector_Builder.from_vector [SQL_Fragment.Interpolation sql_type object]) ## UNSTABLE @@ -43,133 +44,19 @@ interpolation sql_type object = Builder_Data (Vector_Builder.from_vector [SQL_In join : Builder | Text -> Vector Builder -> Builder join separator statements = sep = case separator of - Builder_Data _ -> separator + Builder.Value _ -> separator _ -> code separator if statements.length == 0 then empty else (1.up_to statements.length . fold (statements.at 0) acc-> i-> acc ++ sep ++ statements.at i) -# TODO Dubious constructor export -from project.Data.SQL.SQL_Type import all -from project.Data.SQL.SQL_Type export all - -## Represents an internal SQL data-type. -type SQL_Type - - ## Represents an internal SQL data-type. - - Arguments: - - typeid: a numerical type id, as defined in `java.sql.Types`. - - name: a database-specific type name, used for pretty printing. - SQL_Type_Data typeid name - - == self that = case that of - SQL_Type_Data that_id _ -> - self.typeid == that_id - _ -> False - - ## The SQL representation of `Boolean` type. - boolean : SQL_Type - boolean = SQL_Type_Data Types.BOOLEAN "BOOLEAN" - - ## The SQL representation of `Integer` type. - integer : SQL_Type - integer = SQL_Type_Data Types.INTEGER "INTEGER" - - ## The SQL representation of the `BIGINT` type. - bigint : SQL_Type - bigint = SQL_Type_Data Types.BIGINT "BIGINT" - - ## The SQL representation of the `SMALLINT` type. - smallint : SQL_Type - smallint = SQL_Type_Data Types.SMALLINT "SMALLINT" - - ## The SQL type representing decimal numbers. - decimal : SQL_Type - decimal = SQL_Type_Data Types.DECIMAL "DECIMAL" - - ## The SQL type representing decimal numbers. - real : SQL_Type - real = SQL_Type_Data Types.REAL "REAL" - - ## The SQL type representing double-precision floating-point numbers. - double : SQL_Type - double = SQL_Type_Data Types.DOUBLE "DOUBLE PRECISION" - - ## The SQL type representing a general numeric type. - numeric : SQL_Type - numeric = SQL_Type_Data Types.NUMERIC "NUMERIC" - - ## The SQL type representing one of the suppported textual types. - varchar : SQL_Type - varchar = SQL_Type_Data Types.VARCHAR "VARCHAR" - - ## UNSTABLE - The SQL type representing one of the suppported textual types. - - It seems that JDBC treats the `TEXT` and `VARCHAR` types as interchangeable. - text : SQL_Type - text = SQL_Type_Data Types.VARCHAR "VARCHAR" - - ## The SQL type representing a binary object. - blob : SQL_Type - blob = SQL_Type_Data Types.BLOB "BLOB" - - ## PRIVATE - - Returns True if this type represents an integer. - - It only handles the standard types so it may return false negatives for - non-standard ones. - is_definitely_integer : Boolean - is_definitely_integer self = - [Types.INTEGER, Types.BIGINT, Types.SMALLINT, Types.TINYINT].contains self.typeid - - ## PRIVATE - - Returns True if this type represents a boolean. - - It only handles the standard types so it may return false negatives for - non-standard ones. - is_definitely_boolean : Boolean - is_definitely_boolean self = - [Types.BOOLEAN, Types.BIT].contains self.typeid - - ## PRIVATE - - Returns True if this type represents a floating point number. - - It only handles the standard types so it may return false negatives for - non-standard ones. - is_definitely_double : Boolean - is_definitely_double self = - [Types.FLOAT, Types.DOUBLE, Types.REAL].contains self.typeid - - ## PRIVATE - Returns True if this type represents a Text. - is_definitely_text : Boolean - is_definitely_text self = - [Types.VARCHAR, Types.LONGVARCHAR, Types.NVARCHAR, Types.LONGNVARCHAR].contains self.typeid - - ## PRIVATE - Returns True if this type represents a Text, using heuristics that may - match more possible types. - is_likely_text : Boolean - is_likely_text self = - self.is_definitely_text || self.name.contains "text" Text_Matcher.Case_Insensitive - - -# TODO Dubious constructor export -from project.Data.SQL.SQL_Fragment import all -from project.Data.SQL.SQL_Fragment export all - ## UNSTABLE A fragment of a SQL query. - It can either be a SQL_Code_Part that represents raw SQL code or - SQL_Interpolation which represents an object that will be interpolated into - the query. + It can either be a SQL_Fragment.Code_Part that represents raw SQL code or + SQL_Fragment.Interpolation which represents an object that will be + interpolated into the query. type SQL_Fragment ## UNSTABLE @@ -178,7 +65,7 @@ type SQL_Fragment Arguments: - code: A fragment of SQL code. - SQL_Code_Part code:Text + Code_Part code:Text ## UNSTABLE @@ -189,90 +76,7 @@ type SQL_Fragment - sql_type: The expected SQL type of `object`. - object: A value that will be interpolated into the query, interpreted as having the type `sql_type`. - SQL_Interpolation sql_type:SQL_Type object:Any - -# TODO Dubious constructor export -from project.Data.SQL.Statement import all -from project.Data.SQL.Statement export all - -type Statement - - ## UNSTABLE - - Represents a built SQL statement. - - Arguments: - - internal_fragments: A vector of SQL code fragments. - - The statement consists of SQL code with parameters and values that will be - interpolated for these parameters. - Statement_Data (internal_fragments:(Vector SQL_Fragment)) - - ## UNSTABLE - - A vector of code fragments. - - Consists of two types of values: - - SQL_Code_Part, representing parts of raw SQL code and - - SQL_Interpolation, representing objects that will be interpolated in - between the SQL code. - fragments : Vector SQL_Fragment - fragments self = self.internal_fragments - - ## UNSAFE - UNSTABLE - ADVANCED - - This function returns a raw SQL string for the query, manually handling - the interpolation that is normally handled by the database engine itself. - - It should be used EXTREMELY carefully - the returned SQL code should - always be read by a human to ensure that it does what is expected before - executing it in any REPLs or other database interfaces. - - It should NEVER be used in production code. - unsafe_to_raw_sql : Text - unsafe_to_raw_sql self = - strings = self.internal_fragments . map <| case _ of - SQL_Code_Part code -> code - # TODO at some point we may try more sophisticated serialization based on data type - SQL_Interpolation _ obj -> case obj of - Number -> obj.to_text - _ -> "'" + obj.to_text.replace "'" "''" + "'" - strings.join "" - - ## UNSTABLE - - Returns a pair consisting of the SQL code with holes for values and - a list for values that should be substituted. - # prepare : [Text, Vector Any] - prepare self = - to_code fragment = case fragment of - SQL_Code_Part code -> code - SQL_Interpolation _ _ -> "?" - to_subst fragment = case fragment of - SQL_Code_Part _ -> [] - SQL_Interpolation typ obj -> [[obj, typ]] - sql = self.fragments.map to_code . join "" - substitutions = self.fragments.flat_map to_subst - [sql, substitutions] - - ## UNSTABLE - - Returns a JSON representation of the statement. - to_json : Json - to_json self = - jsonify fragment = case fragment of - SQL_Code_Part code -> Json.from_pairs [["sql_code", code]] - SQL_Interpolation typ obj -> - inner = Json.from_pairs [["value", obj], ["expected_sql_type", typ.name]] - Json.from_pairs [["sql_interpolation", inner]] - fragments = Json.Array (self.internal_fragments.map jsonify) - Json.from_pairs [["query", fragments]] - -# TODO Dubious constructor export -from project.Data.SQL.Builder import all -from project.Data.SQL.Builder export all + Interpolation sql_type:SQL_Type object:Any type Builder @@ -285,7 +89,7 @@ type Builder It can be used to concatenate parts of SQL code in O(1) time and at the end build the actual query in linear time. - Builder_Data (fragments:(Vector_Builder SQL_Fragment)) + Value (fragments:(Vector_Builder SQL_Fragment)) ## UNSTABLE @@ -295,8 +99,8 @@ type Builder - other: The code fragment to append to `self`. ++ : Builder -> Builder ++ self other = case other of - text : Text -> if text == "" then self else Builder_Data (self.fragments ++ (code text).fragments) - _ -> Builder_Data (self.fragments ++ other.fragments) + text : Text -> if text == "" then self else Builder.Value (self.fragments ++ (code text).fragments) + _ -> Builder.Value (self.fragments ++ other.fragments) ## UNSTABLE @@ -307,10 +111,10 @@ type Builder ## UNSTABLE Builds a SQL statement. - build : Statement + build : SQL_Statement build self = fragments = optimize_fragments self.fragments.build - Statement_Data fragments + SQL_Statement.Value fragments ## UNSTABLE @@ -329,7 +133,7 @@ type Builder prefix_if_present : Text | Builder -> Builder prefix_if_present self prefix = pref = case prefix of - Builder_Data _ -> prefix + _ : Builder -> prefix _ -> code prefix if self.is_empty then self else pref++self @@ -344,25 +148,24 @@ optimize_fragments : Vector SQL_Fragment -> Vector SQL_Fragment optimize_fragments fragments = builder = Vector.new_builder go elem = - last_part = State.get SQL_Code_Part + last_part = State.get SQL_Fragment.Code_Part case elem of - SQL_Code_Part code -> + SQL_Fragment.Code_Part code -> new_part = case last_part of - Nothing -> SQL_Code_Part code - SQL_Code_Part other -> SQL_Code_Part other+code - State.put SQL_Code_Part new_part - SQL_Interpolation _ _ -> + Nothing -> SQL_Fragment.Code_Part code + SQL_Fragment.Code_Part other -> SQL_Fragment.Code_Part other+code + State.put SQL_Fragment.Code_Part new_part + SQL_Fragment.Interpolation _ _ -> case last_part of Nothing -> Nothing - SQL_Code_Part _ -> + SQL_Fragment.Code_Part _ -> builder.append last_part - State.put SQL_Code_Part Nothing + State.put SQL_Fragment.Code_Part Nothing builder.append elem - State.run SQL_Code_Part Nothing <| + State.run SQL_Fragment.Code_Part Nothing <| fragments.each go - last_part = State.get SQL_Code_Part + last_part = State.get SQL_Fragment.Code_Part case last_part of Nothing -> Nothing - SQL_Code_Part _ -> builder.append last_part + SQL_Fragment.Code_Part _ -> builder.append last_part builder.to_vector - diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Query.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Query.enso index aba0ed147e9..90589680c8f 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Query.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Query.enso @@ -1,9 +1,5 @@ from Standard.Base import Text -# TODO Dubious constructor export -from project.Data.SQL_Query.SQL_Query import all -from project.Data.SQL_Query.SQL_Query export all - type SQL_Query ## Query a whole table or view. Table_Name name:Text diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Statement.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Statement.enso new file mode 100644 index 00000000000..ad3e6a67bfb --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Statement.enso @@ -0,0 +1,78 @@ +from Standard.Base import all + +import project.Data.SQL.SQL_Fragment + +type SQL_Statement + + ## UNSTABLE + + Represents a built SQL statement. + + Arguments: + - internal_fragments: A vector of SQL code fragments. + + The statement consists of SQL code with parameters and values that will be + interpolated for these parameters. + Value (internal_fragments:(Vector SQL_Fragment)) + + ## UNSTABLE + + A vector of code fragments. + + Consists of two types of values: + - SQL_Fragment.Code_Part, representing parts of raw SQL code and + - SQL_Fragment.Interpolation, representing objects that will be + interpolated in between the SQL code. + fragments : Vector SQL_Fragment + fragments self = self.internal_fragments + + ## UNSAFE + UNSTABLE + ADVANCED + + This function returns a raw SQL string for the query, manually handling + the interpolation that is normally handled by the database engine itself. + + It should be used EXTREMELY carefully - the returned SQL code should + always be read by a human to ensure that it does what is expected before + executing it in any REPLs or other database interfaces. + + It should NEVER be used in production code. + unsafe_to_raw_sql : Text + unsafe_to_raw_sql self = + strings = self.internal_fragments . map <| case _ of + SQL_Fragment.Code_Part code -> code + # TODO at some point we may try more sophisticated serialization based on data type + SQL_Fragment.Interpolation _ obj -> case obj of + Number -> obj.to_text + _ -> "'" + obj.to_text.replace "'" "''" + "'" + strings.join "" + + ## UNSTABLE + + Returns a pair consisting of the SQL code with holes for values and + a list for values that should be substituted. + # prepare : [Text, Vector Any] + prepare self = + to_code fragment = case fragment of + SQL_Fragment.Code_Part code -> code + SQL_Fragment.Interpolation _ _ -> "?" + to_subst fragment = case fragment of + SQL_Fragment.Code_Part _ -> [] + SQL_Fragment.Interpolation typ obj -> [[obj, typ]] + sql = self.fragments.map to_code . join "" + substitutions = self.fragments.flat_map to_subst + [sql, substitutions] + + ## UNSTABLE + + Returns a JSON representation of the statement. + to_json : Json + to_json self = + jsonify fragment = case fragment of + SQL_Fragment.Code_Part code -> Json.from_pairs [["sql_code", code]] + SQL_Fragment.Interpolation typ obj -> + inner = Json.from_pairs [["value", obj], ["expected_sql_type", typ.name]] + Json.from_pairs [["sql_interpolation", inner]] + fragments = Json.Array (self.internal_fragments.map jsonify) + Json.from_pairs [["query", fragments]] diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Type.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Type.enso new file mode 100644 index 00000000000..55b97825496 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/SQL_Type.enso @@ -0,0 +1,108 @@ +from Standard.Base import all + +polyglot java import java.sql.Types + +## Represents an internal SQL data-type. +type SQL_Type + + ## Represents an internal SQL data-type. + + Arguments: + - typeid: a numerical type id, as defined in `java.sql.Types`. + - name: a database-specific type name, used for pretty printing. + Value typeid name + + == self that = case that of + SQL_Type.Value that_id _ -> + self.typeid == that_id + _ -> False + + ## The SQL representation of `Boolean` type. + boolean : SQL_Type + boolean = SQL_Type.Value Types.BOOLEAN "BOOLEAN" + + ## The SQL representation of `Integer` type. + integer : SQL_Type + integer = SQL_Type.Value Types.INTEGER "INTEGER" + + ## The SQL representation of the `BIGINT` type. + bigint : SQL_Type + bigint = SQL_Type.Value Types.BIGINT "BIGINT" + + ## The SQL representation of the `SMALLINT` type. + smallint : SQL_Type + smallint = SQL_Type.Value Types.SMALLINT "SMALLINT" + + ## The SQL type representing decimal numbers. + decimal : SQL_Type + decimal = SQL_Type.Value Types.DECIMAL "DECIMAL" + + ## The SQL type representing decimal numbers. + real : SQL_Type + real = SQL_Type.Value Types.REAL "REAL" + + ## The SQL type representing double-precision floating-point numbers. + double : SQL_Type + double = SQL_Type.Value Types.DOUBLE "DOUBLE PRECISION" + + ## The SQL type representing a general numeric type. + numeric : SQL_Type + numeric = SQL_Type.Value Types.NUMERIC "NUMERIC" + + ## The SQL type representing one of the suppported textual types. + varchar : SQL_Type + varchar = SQL_Type.Value Types.VARCHAR "VARCHAR" + + ## UNSTABLE + The SQL type representing one of the suppported textual types. + + It seems that JDBC treats the `TEXT` and `VARCHAR` types as interchangeable. + text : SQL_Type + text = SQL_Type.Value Types.VARCHAR "VARCHAR" + + ## The SQL type representing a binary object. + blob : SQL_Type + blob = SQL_Type.Value Types.BLOB "BLOB" + + ## PRIVATE + + Returns True if this type represents an integer. + + It only handles the standard types so it may return false negatives for + non-standard ones. + is_definitely_integer : Boolean + is_definitely_integer self = + [Types.INTEGER, Types.BIGINT, Types.SMALLINT, Types.TINYINT].contains self.typeid + + ## PRIVATE + + Returns True if this type represents a boolean. + + It only handles the standard types so it may return false negatives for + non-standard ones. + is_definitely_boolean : Boolean + is_definitely_boolean self = + [Types.BOOLEAN, Types.BIT].contains self.typeid + + ## PRIVATE + + Returns True if this type represents a floating point number. + + It only handles the standard types so it may return false negatives for + non-standard ones. + is_definitely_double : Boolean + is_definitely_double self = + [Types.FLOAT, Types.DOUBLE, Types.REAL].contains self.typeid + + ## PRIVATE + Returns True if this type represents a Text. + is_definitely_text : Boolean + is_definitely_text self = + [Types.VARCHAR, Types.LONGVARCHAR, Types.NVARCHAR, Types.LONGNVARCHAR].contains self.typeid + + ## PRIVATE + Returns True if this type represents a Text, using heuristics that may + match more possible types. + is_likely_text : Boolean + is_likely_text self = + self.is_definitely_text || self.name.contains "text" Text_Matcher.Case_Insensitive 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 9c7f0287341..189dc42ada5 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 @@ -1,28 +1,29 @@ from Standard.Base import all from Standard.Base.Error.Problem_Behavior import Report_Warning -import Standard.Database.Internal.Helpers -import Standard.Database.Internal.Aggregate_Helper -import Standard.Database.Internal.IR -from Standard.Database.Data.SQL_Query import Raw_SQL -from Standard.Database.Data.SQL import Statement, SQL_Type - -from Standard.Table import Auto_Detect, Aggregate_Column, Data_Formatter, Column_Name_Mapping, Sort_Column_Selector, Sort_Column, Match_Columns, Position -from Standard.Table.Data.Column import get_item_string +from Standard.Table import Auto_Detect, Aggregate_Column, Data_Formatter, Column_Name_Mapping, Column_Selector, Sort_Column_Selector, Sort_Column, Match_Columns, Position import Standard.Table.Data.Table.Table as Materialized_Table -from Standard.Table.Data.Table import print_table -from Standard.Table.Data.Filter_Condition_Helpers import make_filter_column - -from Standard.Table.Errors import No_Index_Set_Error, No_Such_Column_Error, No_Such_Column_Error_Data -from Standard.Table.Data.Column_Selector import Column_Selector - import Standard.Table.Internal.Java_Exports import Standard.Table.Internal.Table_Helpers import Standard.Table.Internal.Problem_Builder.Problem_Builder import Standard.Table.Internal.Aggregate_Column_Helper +from Standard.Table.Data.Column import get_item_string +from Standard.Table.Data.Table import print_table +from Standard.Table.Internal.Filter_Condition_Helpers import make_filter_column +from Standard.Table.Errors import No_Index_Set_Error, No_Such_Column_Error, No_Such_Column_Error_Data + +import project.Data.Column.Column +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.Helpers +import project.Internal.Aggregate_Helper +import project.Internal.IR.Context.Context +import project.Internal.IR.Expression.Expression +import project.Internal.IR.From_Spec.From_Spec +import project.Internal.IR.Internal_Column.Internal_Column +import project.Internal.IR.Join_Kind.Join_Kind +import project.Internal.IR.Query.Query -from Standard.Database.Data.Column import Column, Column_Data -from Standard.Database.Internal.IR import Internal_Column, Internal_Column_Data from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data polyglot java import java.sql.JDBCType @@ -39,7 +40,7 @@ type Table - connection: The connection with which the table is associated. - internal_columns: The internal representation of the table columns. - context: The context associated with this table. - Table_Data name:Text connection:Connection (internal_columns:(Vector Internal_Column)) context:IR.Context + Value name:Text connection:Connection (internal_columns:(Vector Internal_Column)) context:IR.Context ## UNSTABLE @@ -335,7 +336,7 @@ type Table _ : Text -> Panic.rethrow (self.at column) _ -> if Helpers.check_integrity self column then column else - Panic.throw (Integrity_Error_Data "Column "+column.name) + Panic.throw (Integrity_Error.Error "Column "+column.name) ## ALIAS Filter Rows @@ -385,7 +386,7 @@ type Table _ : Column -> mask filter_column = case Helpers.check_integrity self filter_column of False -> - Error.throw (Integrity_Error_Data "Column "+filter_column.name) + Error.throw (Integrity_Error.Error "Column "+filter_column.name) True -> new_filters = self.context.where_filters + [filter_column.expression] new_ctx = self.context.set_where_filters new_filters @@ -401,7 +402,7 @@ type Table ## PRIVATE with_no_rows self = - false_expression = IR.Operation "=" [IR.Constant SQL_Type.integer 1, IR.Constant SQL_Type.integer 2] + false_expression = Expression.Operation "=" [Expression.Constant SQL_Type.integer 1, Expression.Constant SQL_Type.integer 2] new_filters = self.context.where_filters + [false_expression] new_ctx = self.context.set_where_filters new_filters self.updated_context new_ctx @@ -483,7 +484,7 @@ type Table case is_used_in_index of True -> Error.throw <| Illegal_State_Error_Data "Cannot override column "+name+", because it is used as an index. Remove the index or use a different name." False -> - new_col = Internal_Column_Data name column.sql_type column.expression + new_col = Internal_Column.Value name column.sql_type column.expression replace = self.internal_columns.exists (c -> c.name == name) case replace of True -> @@ -659,7 +660,7 @@ type Table Panic.rethrow (Helpers.ensure_name_is_sane left_suffix && Helpers.ensure_name_is_sane right_suffix) if left_suffix == right_suffix then Panic.throw <| Illegal_State_Error_Data "left_suffix must be different from right_suffix" - kind = if drop_unmatched then IR.Join_Inner else IR.Join_Left + kind = if drop_unmatched then Join_Kind.Inner else Join_Kind.Left # Prepare the left and right pairs of indices along which the join will be performed. left_join_index : Vector Internal_Column @@ -719,12 +720,12 @@ type Table new_columns = left_renamed_columns + right_renamed_columns on_exprs = left_new_join_index.zip right_new_join_index l-> r-> - IR.Operation "=" [l.expression, r.expression] - new_from = IR.Join kind left_subquery right_subquery on_exprs + Expression.Operation "=" [l.expression, r.expression] + new_from = From_Spec.Join kind left_subquery right_subquery on_exprs new_limit = Nothing - new_ctx = IR.Context_Data new_from [] [] [] new_index new_limit + new_ctx = Context.Value new_from [] [] [] new_index new_limit - Table.Table_Data new_table_name self.connection new_columns new_ctx + Table.Value new_table_name self.connection new_columns new_ctx ## ALIAS group, summarize @@ -763,7 +764,7 @@ type Table agg = p.second new_name = p.first Aggregate_Helper.make_aggregate_column self agg new_name . catch - partitioned = results.partition (_.is_a Internal_Column_Data) + partitioned = results.partition (_.is_a Internal_Column.Value) ## When working on join we may encounter further issues with having aggregate columns exposed directly, it may be useful to re-use the `lift_aggregate` method to push the aggregates into a @@ -793,11 +794,11 @@ type Table ## DEPRECATED Will be replaced with `Incomplete_Columns` selector (to be used with `remove_columns`). drop_missing_columns : Table drop_missing_columns self = - rows_expr = IR.Operation "COUNT_ROWS" [] + rows_expr = Expression.Operation "COUNT_ROWS" [] all_rows_column_name = "row_count" - make_count_expr expr = IR.Operation "COUNT" [expr] + make_count_expr expr = Expression.Operation "COUNT" [expr] cols = self.internal_columns.map (c -> [c.name, make_count_expr c.expression]) - query = IR.Select [[all_rows_column_name, rows_expr]]+cols self.context + query = Query.Select [[all_rows_column_name, rows_expr]]+cols self.context sql = self.connection.dialect.generate_sql query table = self.connection.read_statement sql all_rows = table.at all_rows_column_name . at 0 @@ -808,15 +809,15 @@ type Table ## Returns the amount of rows in this table. row_count : Integer row_count self = if self.internal_columns.is_empty then 0 else - expr = IR.Operation "COUNT_ROWS" [] + expr = Expression.Operation "COUNT_ROWS" [] column_name = "row_count" ## We need to keep some column in the subquery which will determine if the query is performing regular selection or aggregation. To avoid computing too much we do not pass all the columns but only the first one. setup = self.context.as_subquery self.name [[self.internal_columns.first]] - new_ctx = IR.subquery_as_ctx setup.first - query = IR.Select [[column_name, expr]] new_ctx + new_ctx = Context.for_subquery setup.first + query = Query.Select [[column_name, expr]] new_ctx sql = self.connection.dialect.generate_sql query table = self.connection.read_statement sql table.at column_name . at 0 @@ -859,13 +860,13 @@ type Table ## UNSTABLE Returns an SQL statement that will be used for materializing this table. - to_sql : Statement + to_sql : SQL_Statement to_sql self = cols = self.internal_columns.map (c -> [c.name, c.expression]) case cols.is_empty of True -> Error.throw <| Unsupported_Database_Operation_Error_Data "Cannot generate SQL for a table with no columns." False -> - query = IR.Select cols self.context + query = Query.Select cols self.context self.connection.dialect.generate_sql query ## Returns a Table describing this table's contents. @@ -881,10 +882,10 @@ type Table Naively wrapping each column in a `COUNT(...)` will not always work as aggregates cannot be nested. setup = self.context.as_subquery self.name [self.internal_columns] - new_ctx = IR.subquery_as_ctx setup.first + new_ctx = Context.for_subquery setup.first new_columns = setup.second.first.map column-> - [column.name, IR.Operation "COUNT" [column.expression]] - query = IR.Select new_columns new_ctx + [column.name, Expression.Operation "COUNT" [column.expression]] + query = Query.Select new_columns new_ctx self.connection.dialect.generate_sql query count_table = self.connection.read_statement count_query counts = if cols.is_empty then [] else count_table.columns.map c-> c.at 0 @@ -904,7 +905,7 @@ type Table # these distinctness assumptions, to avoid this renaming. ixes = freshen_columns [internal.name] self.context.meta_index new_ctx = self.context.set_index ixes - Column_Data internal.name self.connection internal.sql_type internal.expression new_ctx + Column.Value internal.name self.connection internal.sql_type internal.expression new_ctx ## PRIVATE @@ -913,7 +914,7 @@ type Table Arguments: - columns: The columns with which to update this table. updated_columns : Vector Internal_Column -> Table - updated_columns self internal_columns = Table.Table_Data self.name self.connection internal_columns self.context + updated_columns self internal_columns = Table.Value self.name self.connection internal_columns self.context ## PRIVATE @@ -922,7 +923,7 @@ type Table Arguments: - ctx: The new context for this table. updated_context : Context -> Table - updated_context self ctx = Table.Table_Data self.name self.connection self.internal_columns ctx + updated_context self ctx = Table.Value self.name self.connection self.internal_columns ctx ## PRIVATE @@ -932,7 +933,7 @@ type Table - ctx: The new context for this table. - internal_columns: The new columns to include in the table. updated_context_and_columns : Context -> Vector Internal_Column -> Table - updated_context_and_columns self ctx internal_columns = Table.Table_Data self.name self.connection internal_columns ctx + updated_context_and_columns self ctx internal_columns = Table.Value self.name self.connection internal_columns ctx ## PRIVATE @@ -956,12 +957,12 @@ type Table insert : Vector Any -> Nothing insert self values = table_name = case self.context.from_spec of - IR.From_Table name _ -> name + From_Spec.From_Table name _ -> name _ -> Error.throw <| Illegal_State_Error_Data "Inserting can only be performed on tables as returned by `query`, any further processing is not allowed." # TODO [RW] before removing the PRIVATE tag, add a check that no bad stuff was done to the table as described above pairs = self.internal_columns.zip values col-> value-> - [col.name, IR.Constant col.sql_type value] - query = self.connection.dialect.generate_sql <| IR.Insert table_name pairs + [col.name, Expression.Constant col.sql_type value] + query = self.connection.dialect.generate_sql <| Query.Insert table_name pairs affected_rows = self.connection.execute_update query case affected_rows == 1 of False -> Error.throw <| Illegal_State_Error_Data "The update unexpectedly affected "+affected_rows.to_text+" rows." @@ -1016,21 +1017,17 @@ type Table Write a database table to a CSV file. import Standard.Examples - import Standard.Database + from Standard.Database import all example_to_csv = connection = Database.connect (SQLite (File.new "db.sqlite")) - table = connection.query (Table_Name "Table") + table = connection.query (SQL_Query.Table_Name "Table") table.write (enso_project.data / "example_csv_output.csv") write : File|Text -> File_Format -> Existing_File_Behavior -> Match_Columns -> Problem_Behavior -> Nothing ! Column_Mismatch | Illegal_Argument_Error | File_Not_Found | IO_Error write self path format=Auto_Detect on_existing_file=Existing_File_Behavior.Backup match_columns=Match_Columns.By_Name on_problems=Report_Warning = # TODO This should ideally be done in a streaming manner, or at least respect the row limits. self.read.write path format on_existing_file match_columns on_problems -# TODO Dubious constructor export -from project.Data.Table.Integrity_Error import all -from project.Data.Table.Integrity_Error export all - type Integrity_Error ## UNSTABLE @@ -1039,7 +1036,7 @@ type Integrity_Error contexts. To use columns from different tables, you must first join them. - Integrity_Error_Data object_description + Error object_description # Return a readable description of this error. to_text : Text @@ -1057,11 +1054,11 @@ type Integrity_Error - table_name: The name of the table to get. - columns: The names of the columns to get. - ctx: The context to use for the table. -# make_table : Connection -> Text -> Vector [Text, SQL_Type] -> IR.Context -> Table -make_table : Connection -> Text -> Vector -> IR.Context -> Table +# make_table : Connection -> Text -> Vector [Text, SQL_Type] -> Context -> Table +make_table : Connection -> Text -> Vector -> Context -> Table make_table connection table_name columns ctx = - cols = columns.map (p -> Internal_Column_Data p.first p.second (IR.Column table_name p.first)) - Table.Table_Data table_name connection cols ctx + cols = columns.map (p -> Internal_Column.Value p.first p.second (Expression.Column table_name p.first)) + Table.Value table_name connection cols ctx ## PRIVATE diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Aggregate_Helper.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Aggregate_Helper.enso index 2bf3c749264..1640e4c50c7 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Aggregate_Helper.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Aggregate_Helper.enso @@ -1,9 +1,12 @@ from Standard.Base import all hiding First, Last from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all -import Standard.Database.Internal.IR -from Standard.Database.Data.SQL import SQL_Type -from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data + +import project.Data.SQL_Type.SQL_Type +import project.Internal.IR.Expression.Expression +import project.Internal.IR.Internal_Column.Internal_Column + +from project.Errors import Unsupported_Database_Operation_Error_Data ## PRIVATE Creates an `Internal_Column` that computes the specified statistic. @@ -11,57 +14,57 @@ from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data The provided `aggregate` is assumed to contain only already resolved columns. You may need to transform it with `resolve_aggregate` first. -make_aggregate_column : Table -> Aggregate_Column -> Text -> IR.Internal_Column +make_aggregate_column : Table -> Aggregate_Column -> Text -> Internal_Column make_aggregate_column table aggregate new_name = sql_type = table.connection.dialect.resolve_target_sql_type aggregate expression = make_expression aggregate table.connection.dialect - IR.Internal_Column_Data new_name sql_type expression + Internal_Column.Value new_name sql_type expression ## PRIVATE Creates an Internal Representation of the expression that computes a requested statistic. -make_expression : Aggregate_Column -> Dialect -> IR.Expression +make_expression : Aggregate_Column -> Dialect -> Expression make_expression aggregate dialect = is_non_empty_selector v = if v.is_nothing then False else v.columns.not_empty case aggregate of Group_By c _ -> c.expression - Count _ -> IR.Operation "COUNT_ROWS" [] + Count _ -> Expression.Operation "COUNT_ROWS" [] Count_Distinct columns _ ignore_nothing -> if columns.is_empty then Error.throw (Illegal_Argument_Error "Count_Distinct must have at least one column.") else case ignore_nothing of - True -> IR.Operation "COUNT_DISTINCT" (columns.map .expression) - False -> IR.Operation "COUNT_DISTINCT_INCLUDE_NULL" (columns.map .expression) - Count_Not_Nothing c _ -> IR.Operation "COUNT" [c.expression] - Count_Nothing c _ -> IR.Operation "COUNT_IS_NULL" [c.expression] - Count_Not_Empty c _ -> IR.Operation "COUNT_NOT_EMPTY" [c.expression] - Count_Empty c _ -> IR.Operation "COUNT_EMPTY" [c.expression] - Percentile p c _ -> IR.Operation "PERCENTILE" [IR.Constant SQL_Type.double p, c.expression] - Mode c _ -> IR.Operation "MODE" [c.expression] + True -> Expression.Operation "COUNT_DISTINCT" (columns.map .expression) + False -> Expression.Operation "COUNT_DISTINCT_INCLUDE_NULL" (columns.map .expression) + Count_Not_Nothing c _ -> Expression.Operation "COUNT" [c.expression] + Count_Nothing c _ -> Expression.Operation "COUNT_IS_NULL" [c.expression] + Count_Not_Empty c _ -> Expression.Operation "COUNT_NOT_EMPTY" [c.expression] + Count_Empty c _ -> Expression.Operation "COUNT_EMPTY" [c.expression] + Percentile p c _ -> Expression.Operation "PERCENTILE" [Expression.Constant SQL_Type.double p, c.expression] + Mode c _ -> Expression.Operation "MODE" [c.expression] First c _ ignore_nothing order_by -> case is_non_empty_selector order_by of False -> Error.throw (Unsupported_Database_Operation_Error_Data "`First` aggregation requires at least one `order_by` column.") True -> order_bys = order_by.columns.map c-> dialect.prepare_order_descriptor c.column.as_internal c.direction Text_Ordering.Default case ignore_nothing of - False -> IR.Operation "FIRST" [c.expression]+order_bys - True -> IR.Operation "FIRST_NOT_NULL" [c.expression]+order_bys + False -> Expression.Operation "FIRST" [c.expression]+order_bys + True -> Expression.Operation "FIRST_NOT_NULL" [c.expression]+order_bys Last c _ ignore_nothing order_by -> case is_non_empty_selector order_by of False -> Error.throw (Unsupported_Database_Operation_Error_Data "`Last` aggregation requires at least one `order_by` column.") True -> order_bys = order_by.columns.map c-> dialect.prepare_order_descriptor c.column.as_internal c.direction Text_Ordering.Default case ignore_nothing of - False -> IR.Operation "LAST" [c.expression]+order_bys - True -> IR.Operation "LAST_NOT_NULL" [c.expression]+order_bys - Maximum c _ -> IR.Operation "MAX" [c.expression] - Minimum c _ -> IR.Operation "MIN" [c.expression] - Shortest c _ -> IR.Operation "SHORTEST" [c.expression] - Longest c _ -> IR.Operation "LONGEST" [c.expression] + False -> Expression.Operation "LAST" [c.expression]+order_bys + True -> Expression.Operation "LAST_NOT_NULL" [c.expression]+order_bys + Maximum c _ -> Expression.Operation "MAX" [c.expression] + Minimum c _ -> Expression.Operation "MIN" [c.expression] + Shortest c _ -> Expression.Operation "SHORTEST" [c.expression] + Longest c _ -> Expression.Operation "LONGEST" [c.expression] Standard_Deviation c _ population -> case population of - True -> IR.Operation "STDDEV_POP" [c.expression] - False -> IR.Operation "STDDEV_SAMP" [c.expression] + True -> Expression.Operation "STDDEV_POP" [c.expression] + False -> Expression.Operation "STDDEV_SAMP" [c.expression] Concatenate c _ separator prefix suffix quote_char -> - base_args = [c.expression, IR.Constant SQL_Type.text separator, IR.Constant SQL_Type.text prefix, IR.Constant SQL_Type.text suffix] + base_args = [c.expression, Expression.Constant SQL_Type.text separator, Expression.Constant SQL_Type.text prefix, Expression.Constant SQL_Type.text suffix] case quote_char.is_empty of - True -> IR.Operation "CONCAT" base_args - False -> IR.Operation "CONCAT_QUOTE_IF_NEEDED" base_args+[IR.Constant SQL_Type.text quote_char] - Sum c _ -> IR.Operation "SUM" [c.expression] - Average c _ -> IR.Operation "AVG" [c.expression] - Median c _ -> IR.Operation "MEDIAN" [c.expression] + True -> Expression.Operation "CONCAT" base_args + False -> Expression.Operation "CONCAT_QUOTE_IF_NEEDED" base_args+[Expression.Constant SQL_Type.text quote_char] + Sum c _ -> Expression.Operation "SUM" [c.expression] + Average c _ -> Expression.Operation "AVG" [c.expression] + Median c _ -> Expression.Operation "MEDIAN" [c.expression] diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Base_Generator.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Base_Generator.enso index a85487da471..2dd95b3ac5c 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Base_Generator.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Base_Generator.enso @@ -1,15 +1,17 @@ from Standard.Base import all -import Standard.Database.Internal.IR +import project.Data.SQL +import project.Data.SQL.Builder +import project.Internal.IR.Context.Context +import project.Internal.IR.Expression.Expression +import project.Internal.IR.From_Spec.From_Spec +import project.Internal.IR.Join_Kind.Join_Kind +import project.Internal.IR.Order_Descriptor.Order_Descriptor +import project.Internal.IR.Nulls_Order.Nulls_Order +import project.Internal.IR.Query.Query +from project.Data.SQL import code -from Standard.Database.Data.SQL import Builder, code -import Standard.Database.Data.SQL - -from Standard.Database.Errors import Unsupported_Database_Operation_Error - -# TODO Dubious constructor export -from project.Internal.Base_Generator.Internal_Dialect import all -from project.Internal.Base_Generator.Internal_Dialect export all +from project.Errors import Unsupported_Database_Operation_Error type Internal_Dialect @@ -26,7 +28,7 @@ type Internal_Dialect identifier name in such a way that it can be used in the query; that usually consists of wrapping the name in quotes and escaping any quotes within it. - Internal_Dialect_Data (operation_map:(Map Text (Vector (Builder->Builder)))) (wrap_identifier:(Text->Builder)) + Value (operation_map:(Map Text (Vector (Builder->Builder)))) (wrap_identifier:(Text->Builder)) ## PRIVATE @@ -37,7 +39,7 @@ type Internal_Dialect extend_with : Vector Any -> Internal_Dialect extend_with self mappings = new_map = mappings.fold self.operation_map (m -> el -> m.insert (el.at 0) (el.at 1)) - Internal_Dialect_Data new_map self.wrap_identifier + Internal_Dialect.Value new_map self.wrap_identifier ## PRIVATE @@ -173,7 +175,7 @@ base_dialect = counts = [fun "COUNT", ["COUNT_ROWS", make_constant "COUNT(*)"]] nulls = [["ISNULL", make_right_unary_op "IS NULL"], ["FILLNULL", make_function "COALESCE"]] base_map = Map.from_vector (arith + logic + compare + agg + nulls + counts) - Internal_Dialect_Data base_map wrap_in_quotes + Internal_Dialect.Value base_map wrap_in_quotes ## PRIVATE @@ -182,16 +184,16 @@ base_dialect = Arguments: - dialect: The SQL dialect in which the expression is being generated. - expr: The expression to generate SQL code for. -generate_expression : Internal_Dialect -> IR.Expression -> Builder +generate_expression : Internal_Dialect -> Expression | Order_Descriptor -> Builder generate_expression dialect expr = case expr of - IR.Column origin name -> + Expression.Column origin name -> dialect.wrap_identifier origin ++ '.' ++ dialect.wrap_identifier name - IR.Constant sql_type value -> SQL.interpolation sql_type value - IR.Operation kind arguments -> + Expression.Constant sql_type value -> SQL.interpolation sql_type value + Expression.Operation kind arguments -> op = dialect.operation_map.get_or_else kind (Error.throw <| Unsupported_Database_Operation_Error kind) parsed_args = arguments.map (generate_expression dialect) op parsed_args - IR.Order_Descriptor_Data _ _ _ _ -> generate_order dialect expr + _ : Order_Descriptor -> generate_order dialect expr ## PRIVATE @@ -215,22 +217,22 @@ alias dialect name = - from_spec: A description of the FROM clause. generate_from_part : Internal_Dialect -> From_Spec -> Builder generate_from_part dialect from_spec = case from_spec of - IR.From_Table name as_name -> + From_Spec.From_Table name as_name -> dialect.wrap_identifier name ++ alias dialect as_name - IR.From_Query raw_sql as_name -> + From_Spec.From_Query raw_sql as_name -> code raw_sql . paren ++ alias dialect as_name - IR.Join kind left_spec right_spec on -> + From_Spec.Join kind left_spec right_spec on -> left = generate_from_part dialect left_spec right = generate_from_part dialect right_spec prefix = case kind of - IR.Join_Inner -> "INNER JOIN" - IR.Join_Left -> "LEFT JOIN" - IR.Join_Right -> "RIGHT JOIN" - IR.Join_Cross -> "CROSS JOIN" + Join_Kind.Inner -> "INNER JOIN" + Join_Kind.Left -> "LEFT JOIN" + Join_Kind.Right -> "RIGHT JOIN" + Join_Kind.Cross -> "CROSS JOIN" ons = SQL.join " AND " (on.map (generate_expression dialect)) . prefix_if_present " ON " left ++ (" " + prefix + " ") ++ right ++ ons - IR.Sub_Query columns context as_name -> - sub = generate_query dialect (IR.Select columns context) + From_Spec.Sub_Query columns context as_name -> + sub = generate_query dialect (Query.Select columns context) sub.paren ++ alias dialect as_name ## PRIVATE @@ -247,8 +249,8 @@ generate_order dialect order_descriptor = Sort_Direction.Descending -> " DESC" nulls_suffix = case order_descriptor.nulls_order of Nothing -> "" - IR.Nulls_First -> " NULLS FIRST" - IR.Nulls_Last -> " NULLS LAST" + Nulls_Order.First -> " NULLS FIRST" + Nulls_Order.Last -> " NULLS LAST" collation = case order_descriptor.collation of Nothing -> "" collation_name -> ' COLLATE "' + collation_name + '"' @@ -263,7 +265,7 @@ generate_order dialect order_descriptor = Arguments: - dialect: The SQL dialect for which the code is being generated. - ctx: A description of the SELECT clause. -generate_select_context : Internal_Dialect -> IR.Context -> Builder +generate_select_context : Internal_Dialect -> Context -> Builder generate_select_context dialect ctx = gen_exprs exprs = exprs.map (generate_expression dialect) from_part = generate_from_part dialect ctx.from_spec @@ -301,15 +303,15 @@ generate_insert_query dialect table_name pairs = Arguments: - dialect: The SQL dialect for which the code is being generated. - query: An IR describing the query. -generate_query : Internal_Dialect -> IR.Query -> Builder +generate_query : Internal_Dialect -> Query -> Builder generate_query dialect query = case query of - IR.Select columns ctx -> + Query.Select columns ctx -> gen_column pair = (generate_expression dialect pair.second) ++ alias dialect pair.first cols = SQL.join ", " (columns.map gen_column) code "SELECT " ++ cols ++ generate_select_context dialect ctx - IR.Select_All ctx -> + Query.Select_All ctx -> code "SELECT * " ++ generate_select_context dialect ctx - IR.Insert table_name pairs -> + Query.Insert table_name pairs -> generate_insert_query dialect table_name pairs _ -> Error.throw <| Unsupported_Database_Operation_Error "Unsupported query type." diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Helpers.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Helpers.enso index 430aa4e5e82..49824c9f57d 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Helpers.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Helpers.enso @@ -1,7 +1,7 @@ from Standard.Base import all -from Standard.Database.Data.Table import Table -from Standard.Database.Data.Column import Column +import project.Data.Table.Table +import project.Data.Column.Column polyglot java import java.util.regex.Pattern @@ -36,10 +36,6 @@ unify_vector_singleton x = case x of _ : Vector.Vector -> x _ -> [x] -# TODO Dubious constructor export -from project.Internal.Helpers.Unsupported_Name_Error import all -from project.Internal.Helpers.Unsupported_Name_Error export all - ## UNSTABLE Signals that a name for a column or table is not supported. @@ -50,8 +46,8 @@ from project.Internal.Helpers.Unsupported_Name_Error export all Currently the names can only include ASCII letters, numbers and the underscore. This is a temporary limitation simplifying name handling. It will be removed in a future version. -type Unsupported_Name_Error - Unsupported_Name_Error_Data text +type Unsupported_Name + Error text ## PRIVATE @@ -77,5 +73,5 @@ ensure_name_is_sane name = is_safe = Pattern.matches "[A-Za-z_0-9]+" name if is_safe then True else - Error.throw <| Unsupported_Name_Error_Data (name + " is not a valid name for a column. Please use english letters, numbers and underscore only.") + Error.throw <| Unsupported_Name.Error (name + " is not a valid name for a column. Please use english letters, numbers and underscore only.") diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR.enso deleted file mode 100644 index 17564e5c2b9..00000000000 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR.enso +++ /dev/null @@ -1,451 +0,0 @@ -from Standard.Base import all -from Standard.Database.Data.SQL import SQL_Type - -# TODO Dubious constructor export -from project.Internal.IR.Expression import all -from project.Internal.IR.Expression export all - -## PRIVATE - - The internal representation of an SQL expression which can be a column - reference, an interpolated constant or an operation that combines other - expressions. -type Expression - - ## PRIVATE - - The internal representation of an SQL expression that gets a value from a - column. - - Arguments: - - origin: the name of the entity (table or sub-query) that this column - originates from, it corresponds to the `alias` field in `from_spec`. - - name: the name of the column directly in the table or its alias in a - sub-query. - Column (origin : Text) (name : Text) - - ## PRIVATE - - The internal representation of an SQL expression which is a constant to - be interpolated when building the query. - - Arguments: - - sql_type: The SQL type that this object is going to be serialized to. - It is usually inferred from the expression's context. - - value: the value to be interpolated; it should be a simple Number, Text - or other types that are serializable for JDBC. - Constant (sql_type : SQL_Type) (value : Any) - - ## PRIVATE - - The internal representation of an SQL expression built from an operation - and sub-expressions. - - Arguments: - - kind: the name of the operation, these can be both functions or infix - operators, the actual implementation is determined by a specific - dialect. - - expressions: a list of expressions which are arguments to the operation - different operations support different amounts of arguments. - Operation (kind : Text) (expressions : Vector Expression) - -# TODO Dubious constructor export -from project.Internal.IR.Internal_Column import all -from project.Internal.IR.Internal_Column export all - -type Internal_Column - ## PRIVATE - - An internal column structure. - - Arguments: - - name: The column name. - - sql_type: The SQL type of the column. - - expression: An expression for applying to the column. - Internal_Column_Data name sql_type expression - - ## PRIVATE - - Rename the internal column. - - Arguments: - - new_name: The new name for the column. - rename : Text -> Internal_Column - rename self new_name = Internal_Column_Data new_name self.sql_type self.expression - -# TODO Dubious constructor export -from project.Internal.IR.Context import all -from project.Internal.IR.Context export all - -## PRIVATE - - A context associated with an SQL query. -type Context - - ## PRIVATE - - A context associated with an SQL query. - - The expressions can only be computed in a context which specifies from where - their columns come and set filters and other settings for processing the - query. - - Arguments: - - from_spec: the sources for the query, see `From_Spec` for more - details. - - where_filters: a list of expressions for filtering - only the rows - for which these expressions evaluate to true are included in the - result. - - orders: a list of ordering expressions, for each entry an ORDER BY - clause is added. - - groups: a list of grouping expressions, for each entry a GROUP BY is - added, the resulting query can then directly include only the - grouped-by columns or aggregate expressions. - - meta_index: a list of internal columns to use for joining or grouping. - - limit: an optional maximum number of elements that the equery should - return. - Context_Data (from_spec : From_Spec) (where_filters : Vector Expression) (orders : Vector Order_Descriptor) (groups : Vector Expression) (meta_index : Vector Internal_Column) (limit : Nothing | Integer) - - ## PRIVATE - - Returns a copy of the context with changed `meta_index`. - - Arguments: - - new_index: The new index to set in the query. - set_index : Vector Internal_Column -> Context - set_index self new_index = - Context_Data self.from_spec self.where_filters self.orders self.groups new_index self.limit - - ## PRIVATE - - Returns a copy of the context with changed `where_filters`. - - Arguments: - - new_filters: The new filters to set in the query. - set_where_filters : Vector Expression -> Context - set_where_filters self new_filters = - Context_Data self.from_spec new_filters self.orders self.groups self.meta_index self.limit - - ## PRIVATE - - Returns a copy of the context with changed `orders`. - - Arguments: - - new_orders: The new ordering clauses to set in the query. - set_orders : Vector Order_Descriptor -> Context - set_orders self new_orders = - Context_Data self.from_spec self.where_filters new_orders self.groups self.meta_index self.limit - - ## PRIVATE - - Returns a copy of the context with added `orders`. - - The orderings are modified in such a way that the newly added ordering - takes precedence, but if any orderings were already present they are also - taken into account to break ties within the new ordering. - - In practice this means, that the old orderings are preserved, but the new - ones are added to the beginning of the list so that they take precedence. - - Arguments: - - new_orders: The new ordering clauses to add to the query. - add_orders : Vector Order_Descriptor -> Context - add_orders self new_orders = - Context_Data self.from_spec self.where_filters new_orders+self.orders self.groups self.meta_index self.limit - - ## PRIVATE - - Returns a copy of the context with changed `groups`. - - Arguments: - - new_groups: The new grouping clauses to set in the query. - set_groups : Vector Expression -> Context - set_groups self new_groups = - Context_Data self.from_spec self.where_filters self.orders new_groups self.meta_index self.limit - - ## PRIVATE - - Returns a copy of the context with changed `limit`. - - Arguments: - - new_limit: The new limit clauses to set in the query. - set_limit : (Nothing | Integer) -> Context - set_limit self new_limit = - Context_Data self.from_spec self.where_filters self.orders self.groups self.meta_index new_limit - - ## PRIVATE - - 'Lifts' this context into a subquery, so that the original context (with all filters etc.) is - encapsulated within the subquery and all external references passed as the second argument, - refer directly to that subquery. - - It takes a list of lists of columns that should be included in that subquery (this can for - example the list of regular columns, the list of indices etc.) - It assumes that columns on these lists all have unique names. - - It returns a new context and the lists transformed in such a way that each column corresponds - to one from the original list but it is valid in the new context. - - This is useful as a preprocessing step between combining queries, for example in a join. - # as_subquery : Text -> Vector (Vector Internal_Column) -> [IR.Sub_Query, Vector (Vector Internal_Column)] - as_subquery : Text -> Vector Any -> Vector - as_subquery self alias column_lists = - rewrite_internal_column : Internal_Column -> Internal_Column - rewrite_internal_column column = - Internal_Column_Data column.name column.sql_type (IR.Column alias column.name) - - new_columns = column_lists.map columns-> - columns.map rewrite_internal_column - - encapsulated_columns = column_lists.flat_map columns-> - columns.map column-> [column.name, column.expression] - new_from = IR.Sub_Query encapsulated_columns self alias - - [new_from, new_columns] - - -# TODO Dubious constructor export -from project.Internal.IR.From_Spec import all -from project.Internal.IR.From_Spec export all - -## PRIVATE - - Used as part of the context, specifies the sources of the query. -type From_Spec - ## PRIVATE - - A query source that takes data directly from a table in the - database. - - Arguments: - - table_name: the full name identifying the table in the database. - - alias: the name upon which the table can be referred to in other - parts of the query, this is especially useful for example in - self-joins, allowing to differentiate between different instances of - the same table. - From_Table (table_name : Text) (alias : Text) - - ## PRIVATE - - A query source that holds a raw SQL statement. - - Arguments: - - raw_sql: the raw SQL code of a query used as a source for this table. - - alias: the name upon which the table can be referred to in other - parts of the query, this is especially useful for example in - self-joins, allowing to differentiate between different instances of - the same table. - From_Query (raw_sql : Text) (alias : Text) - - ## PRIVATE - - A query source that performs a join operation on two sources. - - Arguments: - - kind: the kind of the join. - - left_spec: the left data source to be joined - - right_spec: the right data source to be joined - - on: a list of expressions that will be used as join conditions, these - are usually be equalities between expressions from the left and right - sources. - Join (kind : Join_Kind) (left_spec : From_Spec) (right_spec : From_Spec) (on : Vector Expression) - - ## PRIVATE - - A query source consisting of a sub-query. - - Arguments: - - columns: a list of pairs; each first element is the alias for the - column created in the sub-query and the second element is the - expression to be computed. - - context: the context for the sub-query. - - alias: the name upon which the results of this sub-query can be - referred to in other parts of the query. - Sub_Query (columns : Vector (Pair Text Expression)) (context : Context) (alias : Text) - -# TODO Dubious constructor export -from project.Internal.IR.Join_Kind import all -from project.Internal.IR.Join_Kind export all - -## PRIVATE - - The kind of the join operation. -type Join_Kind - ## PRIVATE - - Inner join. - - The result will contain only rows that had a match in both left and right - source. - Join_Inner - - ## PRIVATE - - Left join. - - The result will contain all rows from the left source. Some of them may - be duplicated if they have multiple matches on the right. If a row from - the left source has no match on the right, it will be present exactly - once in the result and the fields corresponding to the right source will - be set to NULL. - Join_Left - - ## PRIVATE - - Right join. - - The result will contain all rows from the right source. Some of them may - be duplicated if they have multiple matches on the left. If a row from - the right source has no match on the left, it will be present exactly - once in the result and the fields corresponding to the left source will - be set to NULL. - Join_Right - - ## PRIVATE - - Cross join. - - The result will contain a cross product of rows from the left source with - the right source. Its `on` list should be empty, instead `where_filters` - in the query can be used to filter the results. - Join_Cross - -# TODO Dubious constructor export -from project.Internal.IR.Order_Descriptor import all -from project.Internal.IR.Order_Descriptor export all - -## PRIVATE -type Order_Descriptor - Order_Descriptor_Data (expression : Expression) (direction : Sort_Direction) (nulls_order : Nothing | Nulls_Order = Nothing) (collation : Nothing | Text = Nothing) - -# TODO Dubious constructor export -from project.Internal.IR.Nulls_Order import all -from project.Internal.IR.Nulls_Order export all - -## PRIVATE - - Specifies how null values should be handled within the ordering. -type Nulls_Order - - ## PRIVATE - - Null values are included before any other values in the ordering. - Nulls_First - - ## PRIVATE - - Null values are included after all other values in the ordering. - Nulls_Last - -# TODO Dubious constructor export -from project.Internal.IR.Query import all -from project.Internal.IR.Query export all - -## PRIVATE - - Describes a full SQL query. -type Query - - ## PRIVATE - - A Select SQL query. - - Arguments: - - expressions: List of pairs specifying the columns to materialize; each - is a pair whose first element is the name of the materialized column - and the second element is the expression to compute. - - context: The query context, see `Context` for more detail. - Select (expressions : Vector (Pair Text Expression)) (context : Context) - - ## PRIVATE - - A Select SQL query that gets all columns in a table. - - Arguments: - - context: The query context, see `Context` for more detail. - Select_All context - - ## PRIVATE - - An Insert SQL query that inserts a single row to the table. - - Arguments: - - table_name: The name of the table to insert to. - - pairs: A list of pairs consisting of a column name and and expression. - Insert table_name pairs - -## PRIVATE - - Creates a query context that just fetches data from a table, without any - additional processing. - - Arguments: - - table_name: The name of the table for which the context is being created. - - alias: An alias name to use for table within the query. -context_for_table : Text -> Text -> Context -context_for_table table_name alias=table_name = - Context_Data (From_Table table_name alias) [] [] [] [] Nothing - -## PRIVATE - - Creates a query context that runs a raw SQL query. - - Arguments: - - raw_sql: The name of the table for which the context is being created. - - alias: An alias name to use for table within the query. -context_for_query : Text -> Text -> Context -context_for_query raw_sql alias = - Context_Data (From_Query raw_sql alias) [] [] [] [] Nothing - -## PRIVATE - - Creates a Context from a Sub_Query. - - Arguments: - - subquery: The subquery to lift into a context. -subquery_as_ctx : Sub_Query -> Context -subquery_as_ctx subquery = - Context_Data subquery [] [] [] [] Nothing - -## PRIVATE - - Creates an expression which is a simple constant to be interpolated. - - Arguments: - - sql_type: The SQL type of the value. - - x: The value to turn into a constant. -make_constant : SQL_Type -> Any -> Expression -make_constant sql_type x = - Constant sql_type x - -## PRIVATE - - A helper function to subsitute names tables inside of expressions. - - Arguments: - - old_origin: The old table name. - - new_origin: The new table name. - - expr: The expression in which the substitution should be performed. - - It is used for example when renaming a table during a join. -substitute_origin : Text -> Text -> Expression -> Expression -substitute_origin old_origin new_origin expr = case expr of - Column origin name -> - if origin == old_origin then Column new_origin name else expr - Constant _ _ -> expr - Operation kind exprs -> - Operation kind (exprs.map (substitute_origin old_origin new_origin)) - -## PRIVATE - - Lifts a function mapping expressions into a function mapping internal columns - which applies the original function to their expressions, leaving other - fields as-is. - - Arguments: - - f: The function to map over expressions. - - col: The column over which to apply `f`. -lift_expression_map : (Expression -> Expression) -> Internal_Column -> Internal_Column -lift_expression_map f col = - Internal_Column_Data col.name col.sql_type (f col.expression) - diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Context.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Context.enso new file mode 100644 index 00000000000..9a96e6ad722 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Context.enso @@ -0,0 +1,164 @@ +from Standard.Base import all + +import project.Internal.IR.Expression.Expression +import project.Internal.IR.From_Spec.From_Spec +import project.Internal.IR.Internal_Column.Internal_Column +import project.Internal.IR.Order_Descriptor.Order_Descriptor + +## PRIVATE + + A context associated with an SQL query. +type Context + ## PRIVATE + + Creates a query context that just fetches data from a table, without any + additional processing. + + Arguments: + - table_name: The name of the table for which the context is being created. + - alias: An alias name to use for table within the query. + for_table : Text -> Text -> Context + for_table table_name alias=table_name = + Context.Value (From_Spec.From_Table table_name alias) [] [] [] [] Nothing + + ## PRIVATE + + Creates a query context that runs a raw SQL query. + + Arguments: + - raw_sql: The name of the table for which the context is being created. + - alias: An alias name to use for table within the query. + for_query : Text -> Text -> Context + for_query raw_sql alias = + Context.Value (From_Spec.From_Query raw_sql alias) [] [] [] [] Nothing + + ## PRIVATE + + Creates a Context from a Sub_Query. + + Arguments: + - subquery: The subquery to lift into a context. + for_subquery : Sub_Query -> Context + for_subquery subquery = + Context.Value subquery [] [] [] [] Nothing + + ## PRIVATE + + A context associated with an SQL query. + + The expressions can only be computed in a context which specifies from where + their columns come and set filters and other settings for processing the + query. + + Arguments: + - from_spec: the sources for the query, see `From_Spec` for more + details. + - where_filters: a list of expressions for filtering - only the rows + for which these expressions evaluate to true are included in the + result. + - orders: a list of ordering expressions, for each entry an ORDER BY + clause is added. + - groups: a list of grouping expressions, for each entry a GROUP BY is + added, the resulting query can then directly include only the + grouped-by columns or aggregate expressions. + - meta_index: a list of internal columns to use for joining or grouping. + - limit: an optional maximum number of elements that the equery should + return. + Value (from_spec : From_Spec) (where_filters : Vector Expression) (orders : Vector Order_Descriptor) (groups : Vector Expression) (meta_index : Vector Internal_Column) (limit : Nothing | Integer) + + ## PRIVATE + + Returns a copy of the context with changed `meta_index`. + + Arguments: + - new_index: The new index to set in the query. + set_index : Vector Internal_Column -> Context + set_index self new_index = + Context.Value self.from_spec self.where_filters self.orders self.groups new_index self.limit + + ## PRIVATE + + Returns a copy of the context with changed `where_filters`. + + Arguments: + - new_filters: The new filters to set in the query. + set_where_filters : Vector Expression -> Context + set_where_filters self new_filters = + Context.Value self.from_spec new_filters self.orders self.groups self.meta_index self.limit + + ## PRIVATE + + Returns a copy of the context with changed `orders`. + + Arguments: + - new_orders: The new ordering clauses to set in the query. + set_orders : Vector Order_Descriptor -> Context + set_orders self new_orders = + Context.Value self.from_spec self.where_filters new_orders self.groups self.meta_index self.limit + + ## PRIVATE + + Returns a copy of the context with added `orders`. + + The orderings are modified in such a way that the newly added ordering + takes precedence, but if any orderings were already present they are also + taken into account to break ties within the new ordering. + + In practice this means, that the old orderings are preserved, but the new + ones are added to the beginning of the list so that they take precedence. + + Arguments: + - new_orders: The new ordering clauses to add to the query. + add_orders : Vector Order_Descriptor -> Context + add_orders self new_orders = + Context.Value self.from_spec self.where_filters new_orders+self.orders self.groups self.meta_index self.limit + + ## PRIVATE + + Returns a copy of the context with changed `groups`. + + Arguments: + - new_groups: The new grouping clauses to set in the query. + set_groups : Vector Expression -> Context + set_groups self new_groups = + Context.Value self.from_spec self.where_filters self.orders new_groups self.meta_index self.limit + + ## PRIVATE + + Returns a copy of the context with changed `limit`. + + Arguments: + - new_limit: The new limit clauses to set in the query. + set_limit : (Nothing | Integer) -> Context + set_limit self new_limit = + Context.Value self.from_spec self.where_filters self.orders self.groups self.meta_index new_limit + + ## PRIVATE + + 'Lifts' this context into a subquery, so that the original context (with all filters etc.) is + encapsulated within the subquery and all external references passed as the second argument, + refer directly to that subquery. + + It takes a list of lists of columns that should be included in that subquery (this can for + example the list of regular columns, the list of indices etc.) + It assumes that columns on these lists all have unique names. + + It returns a new context and the lists transformed in such a way that each column corresponds + to one from the original list but it is valid in the new context. + + This is useful as a preprocessing step between combining queries, for example in a join. + # as_subquery : Text -> Vector (Vector Internal_Column) -> [From_Spec.Sub_Query, Vector (Vector Internal_Column)] + as_subquery : Text -> Vector Any -> Vector + as_subquery self alias column_lists = + rewrite_internal_column : Internal_Column -> Internal_Column + rewrite_internal_column column = + Internal_Column.Value column.name column.sql_type (Expression.Column alias column.name) + + new_columns = column_lists.map columns-> + columns.map rewrite_internal_column + + encapsulated_columns = column_lists.flat_map columns-> + columns.map column-> [column.name, column.expression] + new_from = From_Spec.Sub_Query encapsulated_columns self alias + + [new_from, new_columns] diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Expression.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Expression.enso new file mode 100644 index 00000000000..4ebf104aa3e --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Expression.enso @@ -0,0 +1,46 @@ +from Standard.Base import all + +import project.Data.SQL_Type.SQL_Type + +## PRIVATE + + The internal representation of an SQL expression which can be a column + reference, an interpolated constant or an operation that combines other + expressions. +type Expression + ## PRIVATE + + The internal representation of an SQL expression that gets a value from a + column. + + Arguments: + - origin: the name of the entity (table or sub-query) that this column + originates from, it corresponds to the `alias` field in `from_spec`. + - name: the name of the column directly in the table or its alias in a + sub-query. + Column (origin : Text) (name : Text) + + ## PRIVATE + + The internal representation of an SQL expression which is a constant to + be interpolated when building the query. + + Arguments: + - sql_type: The SQL type that this object is going to be serialized to. + It is usually inferred from the expression's context. + - value: the value to be interpolated; it should be a simple Number, Text + or other types that are serializable for JDBC. + Constant (sql_type : SQL_Type) (value : Any) + + ## PRIVATE + + The internal representation of an SQL expression built from an operation + and sub-expressions. + + Arguments: + - kind: the name of the operation, these can be both functions or infix + operators, the actual implementation is determined by a specific + dialect. + - expressions: a list of expressions which are arguments to the operation + different operations support different amounts of arguments. + Operation (kind : Text) (expressions : Vector Expression) diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/From_Spec.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/From_Spec.enso new file mode 100644 index 00000000000..40ba84fb8f1 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/From_Spec.enso @@ -0,0 +1,60 @@ +from Standard.Base import all + +import project.Internal.IR.Context.Context +import project.Internal.IR.Expression.Expression +import project.Internal.IR.Join_Kind.Join_Kind + +## PRIVATE + + Used as part of the context, specifies the sources of the query. +type From_Spec + ## PRIVATE + + A query source that takes data directly from a table in the + database. + + Arguments: + - table_name: the full name identifying the table in the database. + - alias: the name upon which the table can be referred to in other + parts of the query, this is especially useful for example in + self-joins, allowing to differentiate between different instances of + the same table. + From_Table (table_name : Text) (alias : Text) + + ## PRIVATE + + A query source that holds a raw SQL statement. + + Arguments: + - raw_sql: the raw SQL code of a query used as a source for this table. + - alias: the name upon which the table can be referred to in other + parts of the query, this is especially useful for example in + self-joins, allowing to differentiate between different instances of + the same table. + From_Query (raw_sql : Text) (alias : Text) + + ## PRIVATE + + A query source that performs a join operation on two sources. + + Arguments: + - kind: the kind of the join. + - left_spec: the left data source to be joined + - right_spec: the right data source to be joined + - on: a list of expressions that will be used as join conditions, these + are usually be equalities between expressions from the left and right + sources. + Join (kind : Join_Kind) (left_spec : From_Spec) (right_spec : From_Spec) (on : Vector Expression) + + ## PRIVATE + + A query source consisting of a sub-query. + + Arguments: + - columns: a list of pairs; each first element is the alias for the + column created in the sub-query and the second element is the + expression to be computed. + - context: the context for the sub-query. + - alias: the name upon which the results of this sub-query can be + referred to in other parts of the query. + Sub_Query (columns : Vector (Pair Text Expression)) (context : Context) (alias : Text) diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Internal_Column.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Internal_Column.enso new file mode 100644 index 00000000000..db734304d81 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Internal_Column.enso @@ -0,0 +1,24 @@ +from Standard.Base import all + +import project.Data.SQL_Type.SQL_Type +import project.Internal.IR.Expression.Expression + +type Internal_Column + ## PRIVATE + + An internal column structure. + + Arguments: + - name: The column name. + - sql_type: The SQL type of the column. + - expression: An expression for applying to the column. + Value name:Text sql_type:SQL_Type expression:Expression + + ## PRIVATE + + Rename the internal column. + + Arguments: + - new_name: The new name for the column. + rename : Text -> Internal_Column + rename self new_name = Internal_Column.Value new_name self.sql_type self.expression diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Join_Kind.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Join_Kind.enso new file mode 100644 index 00000000000..3d89eea8ce3 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Join_Kind.enso @@ -0,0 +1,44 @@ +from Standard.Base import all + +## PRIVATE + + The kind of the join operation. +type Join_Kind + ## PRIVATE + + Inner join. + + The result will contain only rows that had a match in both left and right + source. + Inner + + ## PRIVATE + + Left join. + + The result will contain all rows from the left source. Some of them may + be duplicated if they have multiple matches on the right. If a row from + the left source has no match on the right, it will be present exactly + once in the result and the fields corresponding to the right source will + be set to NULL. + Left + + ## PRIVATE + + Right join. + + The result will contain all rows from the right source. Some of them may + be duplicated if they have multiple matches on the left. If a row from + the right source has no match on the left, it will be present exactly + once in the result and the fields corresponding to the left source will + be set to NULL. + Right + + ## PRIVATE + + Cross join. + + The result will contain a cross product of rows from the left source with + the right source. Its `on` list should be empty, instead `where_filters` + in the query can be used to filter the results. + Cross diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Nulls_Order.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Nulls_Order.enso new file mode 100644 index 00000000000..9079b552927 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Nulls_Order.enso @@ -0,0 +1,16 @@ +from Standard.Base import all + +## PRIVATE + + Specifies how null values should be handled within the ordering. +type Nulls_Order + + ## PRIVATE + + Null values are included before any other values in the ordering. + First + + ## PRIVATE + + Null values are included after all other values in the ordering. + Last diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Order_Descriptor.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Order_Descriptor.enso new file mode 100644 index 00000000000..e899c311cdd --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Order_Descriptor.enso @@ -0,0 +1,8 @@ +from Standard.Base import all + +import project.Internal.IR.Expression.Expression +import project.Internal.IR.Nulls_Order.Nulls_Order + +## PRIVATE +type Order_Descriptor + Value (expression : Expression) (direction : Sort_Direction) (nulls_order : Nothing | Nulls_Order = Nothing) (collation : Nothing | Text = Nothing) diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Query.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Query.enso new file mode 100644 index 00000000000..543bc257310 --- /dev/null +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Query.enso @@ -0,0 +1,37 @@ +from Standard.Base import all + +import project.Internal.IR.Context.Context +import project.Internal.IR.Expression.Expression + +## PRIVATE + + Describes a full SQL query. +type Query + + ## PRIVATE + + A Select SQL query. + + Arguments: + - expressions: List of pairs specifying the columns to materialize; each + is a pair whose first element is the name of the materialized column + and the second element is the expression to compute. + - context: The query context, see `Context` for more detail. + Select (expressions : Vector (Pair Text Expression)) (context : Context) + + ## PRIVATE + + A Select SQL query that gets all columns in a table. + + Arguments: + - context: The query context, see `Context` for more detail. + Select_All context + + ## PRIVATE + + An Insert SQL query that inserts a single row to the table. + + Arguments: + - table_name: The name of the table to insert to. + - pairs: A list of pairs consisting of a column name and and expression. + Insert table_name pairs diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/JDBC_Connection.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/JDBC_Connection.enso index a2f0fdd8712..edfe446abc3 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/JDBC_Connection.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/JDBC_Connection.enso @@ -1,15 +1,18 @@ from Standard.Base import all - import Standard.Base.Runtime.Resource from Standard.Base.Runtime.Resource import Managed_Resource -import Standard.Database.Data.SQL -from Standard.Database.Data.SQL import SQL_Type, SQL_Type_Data, Statement, Statement_Data -from Standard.Database.Errors import SQL_Error, SQL_Error_Data, SQL_Timeout_Error, SQL_Timeout_Error_Data -import Standard.Database.Internal.Base_Generator import Standard.Table.Data.Storage.Storage -import Standard.Database.Data.Table as Database_Table -import Standard.Table.Data.Table as Materialized_Table +import Standard.Table.Data.Table.Table as Materialized_Table + +import project.Data.SQL +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.Base_Generator + +import project.Data.Table.Table as Database_Table + +from project.Errors import SQL_Error, SQL_Error_Data, SQL_Timeout_Error, SQL_Timeout_Error_Data polyglot java import java.util.Properties @@ -20,13 +23,9 @@ polyglot java import java.sql.SQLTimeoutException polyglot java import org.enso.database.JDBCProxy -# TODO Dubious constructor export -from project.Internal.JDBC_Connection.JDBC_Connection import all -from project.Internal.JDBC_Connection.JDBC_Connection export all - type JDBC_Connection ## PRIVATE - JDBC_Connection_Data connection_resource + Value connection_resource ## PRIVATE Closes the connection releasing the underlying database resources @@ -61,7 +60,7 @@ type JDBC_Connection Runs the provided action with a prepared statement, adding contextual information to any thrown SQL errors. - with_prepared_statement : Text | Statement -> (PreparedStatement -> Any) -> Any + with_prepared_statement : Text | SQL_Statement -> (PreparedStatement -> Any) -> Any with_prepared_statement self query action = prepare template holes = self.connection_resource.with java_connection-> stmt = java_connection.prepareStatement template @@ -76,7 +75,7 @@ type JDBC_Connection case query of _ : Text -> go query [] - Statement_Data _ -> + SQL_Statement.Value _ -> compiled = query.prepare go compiled.first compiled.second @@ -84,7 +83,7 @@ type JDBC_Connection Given a prepared statement, gets the column names and types for the result set. - fetch_columns : Text | Statement -> Any + fetch_columns : Text | SQL_Statement -> Any fetch_columns self statement = self.with_prepared_statement statement stmt-> metadata = stmt.executeQuery.getMetaData @@ -93,7 +92,7 @@ type JDBC_Connection name = metadata.getColumnName ix+1 typeid = metadata.getColumnType ix+1 typename = metadata.getColumnTypeName ix+1 - [name, SQL_Type_Data typeid typename] + [name, SQL_Type.Value typeid typename] Vector.new metadata.getColumnCount resolve_column @@ -101,7 +100,7 @@ type JDBC_Connection Given an insert query template and the associated Database_Table, and a Materialized_Table of data, load to the database. - load_table : Text -> Database_Table.Table -> Materialized_Table.Table -> Integer -> Nothing + load_table : Text -> Database_Table -> Materialized_Table -> Integer -> Nothing load_table self insert_template db_table table batch_size = db_types = db_table.internal_columns.map .sql_type self.with_connection java_connection-> @@ -142,7 +141,7 @@ create url properties = handle_sql_errors <| java_connection = JDBCProxy.getConnection url java_props resource = Managed_Resource.register java_connection close_connection - JDBC_Connection_Data resource + JDBC_Connection.Value resource ## PRIVATE @@ -182,7 +181,7 @@ set_statement_values stmt holes = ## PRIVATE Given a Materialized_Table, create a SQL statement to build the table. -create_table_statement : Text -> Materialized_Table.Table -> Boolean -> Statement +create_table_statement : Text -> Materialized_Table -> Boolean -> SQL_Statement create_table_statement name table temporary = column_types = table.columns.map col-> default_storage_type col.storage_type column_names = table.columns.map .name diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Pgpass.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Pgpass.enso index 671a83ffaec..83ba5726a24 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Pgpass.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Pgpass.enso @@ -35,13 +35,9 @@ read host port database username=Nothing = Nothing -> [] entry -> [Pair_Data 'user' entry.username, Pair_Data 'password' entry.password] -# TODO Dubious constructor export -from project.Internal.Postgres.Pgpass.Pgpass_Entry import all -from project.Internal.Postgres.Pgpass.Pgpass_Entry export all - type Pgpass_Entry ## PRIVATE - Pgpass_Entry_Data host port database username password + Value host port database username password ## PRIVATE matches : Text -> Text|Integer -> Text -> Text -> Boolean @@ -88,7 +84,7 @@ parse_file file = if line.starts_with "#" || line.is_empty then Nothing else elements = parse_line line if elements.length != 5 then Nothing else - Pgpass_Entry_Data (elements.at 0) (elements.at 1) (elements.at 2) (elements.at 3) (elements.at 4) + Pgpass_Entry.Value (elements.at 0) (elements.at 1) (elements.at 2) (elements.at 3) (elements.at 4) File.read_text file . lines . map parse . filter (x -> x.is_nothing.not) diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Connection.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Connection.enso index 7bbf3ee297e..5c00a3a5e06 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Connection.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Connection.enso @@ -1,22 +1,18 @@ from Standard.Base import all -from Standard.Database.Data.SQL import SQL_Type, Statement -import Standard.Database.Data.SQL_Query +import Standard.Table.Data.Table.Table as Materialized_Table -import Standard.Database.Internal.JDBC_Connection -import Standard.Database.Data.Dialect -from Standard.Database.Connection.Connection import Connection_Data +import project.Connection.Connection.Connection +import project.Data.Dialect +import project.Data.SQL_Query.SQL_Query +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Data.Table.Table as Database_Table +import project.Internal.JDBC_Connection -import Standard.Database.Data.Table as Database_Table -import Standard.Table.Data.Table as Materialized_Table +from project.Internal.Result_Set import read_column -from Standard.Database.Errors import SQL_Error - -from Standard.Database.Internal.Result_Set import read_column - -# TODO Dubious constructor export -from project.Internal.Postgres.Postgres_Connection.Postgres_Connection import all -from project.Internal.Postgres.Postgres_Connection.Postgres_Connection export all +from project.Errors import SQL_Error type Postgres_Connection @@ -27,7 +23,7 @@ type Postgres_Connection Arguments: - connection: the underlying connection. - make_new: a function that returns a new connection. - Postgres_Connection_Data connection make_new + Value connection make_new ## Closes the connection releasing the underlying database resources immediately instead of waiting for them to be automatically released. @@ -85,7 +81,7 @@ type Postgres_Connection - schema: The schema name to search in (defaults to current schema). - types: The table types to search for. The list of values can be obtained using the `table_types` method. - all_fields: Return all the fields in the metadata table. - tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table.Table + tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table tables self name_like=Nothing database=self.database schema=self.schema types=Nothing all_fields=False = self.connection.tables name_like database schema types all_fields @@ -95,7 +91,7 @@ type Postgres_Connection - query: name of the table or sql statement to query. If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - alias: optionally specify a friendly alias for the query. - query : Text | SQL_Query -> Text -> Database_Table.Table + query : Text | SQL_Query -> Text -> Database_Table query self query alias="" = self.connection.query query alias ## Execute the query and load the results into memory as a Table. @@ -104,12 +100,12 @@ type Postgres_Connection - query: name of the table or sql statement to query. If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - limit: the maximum number of rows to return. - read : Text | SQL_Query -> Integer | Nothing -> Materialized_Table.Table + read : Text | SQL_Query -> Integer | Nothing -> Materialized_Table read self query limit=Nothing = self.connection.read query limit ## PRIVATE Internal read function for a statement with optional types. - read_statement : Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table.Table + read_statement : SQL_Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table read_statement self statement expected_types=Nothing = self.connection.read_statement statement expected_types @@ -120,9 +116,9 @@ type Postgres_Connection returns 0 for other types of queries (like creating or altering tables). Arguments: - - query: either raw SQL code as Text or an instance of Statement + - query: either raw SQL code as Text or an instance of SQL_Statement representing the query to execute. - execute_update : Text | Statement -> Integer + execute_update : Text | SQL_Statement -> Integer execute_update self query = self.connection.execute_update query @@ -143,7 +139,7 @@ type Postgres_Connection usually not be visible to other connections. - batch_size: Specifies how many rows should be uploaded in a single batch. - upload_table : Text -> Materialized_Table.Table -> Boolean -> Integer -> Database_Table.Table + upload_table : Text -> Materialized_Table -> Boolean -> Integer -> Database_Table upload_table self name table temporary=True batch_size=1000 = Panic.recover Illegal_State_Error <| self.connection.upload_table name table temporary batch_size @@ -158,4 +154,4 @@ type Postgres_Connection create : Text -> Vector -> (Text -> Text -> Postgres_Connection) -> Postgres_Connection create url properties make_new = jdbc_connection = JDBC_Connection.create url properties - Postgres_Connection_Data (Connection_Data jdbc_connection Dialect.postgres) make_new + Postgres_Connection.Value (Connection.Value jdbc_connection Dialect.postgres) make_new diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Dialect.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Dialect.enso index 079db720a31..5b950260643 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Dialect.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Postgres/Postgres_Dialect.enso @@ -1,24 +1,26 @@ from Standard.Base import all hiding First, Last - import Standard.Base.Error.Common as Errors + from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all -from Standard.Database.Data.SQL import SQL_Type, Statement, code -import Standard.Database.Data.SQL -import Standard.Database.Data.Dialect -import Standard.Database.Internal.Base_Generator -import Standard.Database.Internal.IR -from Standard.Database.Errors import Unsupported_Database_Operation_Error + +import project.Data.SQL +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.Base_Generator +import project.Internal.IR.Expression.Expression +import project.Internal.IR.Internal_Column.Internal_Column +import project.Internal.IR.Order_Descriptor.Order_Descriptor +import project.Internal.IR.Nulls_Order.Nulls_Order + +from project.Data.SQL import code +from project.Errors import Unsupported_Database_Operation_Error ## PRIVATE The dialect of PostgreSQL databases. -postgres : Dialect +postgres : Postgres_Dialect postgres = - Postgres_Dialect_Data make_internal_generator_dialect - -# TODO Dubious constructor export -from project.Internal.Postgres.Postgres_Dialect.Postgres_Dialect import all -from project.Internal.Postgres.Postgres_Dialect.Postgres_Dialect export all + Postgres_Dialect.Value make_internal_generator_dialect ## PRIVATE @@ -27,7 +29,7 @@ type Postgres_Dialect ## PRIVATE The dialect of PostgreSQL databases. - Postgres_Dialect_Data internal_generator_dialect + Value internal_generator_dialect ## PRIVATE Name of the dialect. @@ -37,7 +39,7 @@ type Postgres_Dialect ## PRIVATE A function which generates SQL code from the internal representation according to the specific dialect. - generate_sql : Query -> Statement + generate_sql : Query -> SQL_Statement generate_sql self query = Base_Generator.generate_query self.internal_generator_dialect query . build @@ -54,7 +56,7 @@ type Postgres_Dialect One of the purposes of this method is to verify if the expected ordering settings are supported by the given database backend. - prepare_order_descriptor : IR.Internal_Column -> Sort_Direction -> Text_Ordering -> IR.Order_Descriptor + prepare_order_descriptor : Internal_Column -> Sort_Direction -> Text_Ordering -> Order_Descriptor prepare_order_descriptor self internal_column sort_direction text_ordering = make_order_descriptor internal_column sort_direction text_ordering @@ -225,23 +227,23 @@ contains = Base_Generator.lift_binary_op "contains" make_contains_expr ## PRIVATE make_order_descriptor internal_column sort_direction text_ordering = nulls = case sort_direction of - Sort_Direction.Ascending -> IR.Nulls_First - Sort_Direction.Descending -> IR.Nulls_Last + Sort_Direction.Ascending -> Nulls_Order.First + Sort_Direction.Descending -> Nulls_Order.Last case internal_column.sql_type.is_likely_text of True -> ## In the future we can modify this error to suggest using a custom defined collation. if text_ordering.sort_digits_as_numbers then Error.throw (Unsupported_Database_Operation_Error "Natural ordering is currently not supported. You may need to materialize the Table to perform this operation.") else case text_ordering.case_sensitivity of Nothing -> - IR.Order_Descriptor_Data internal_column.expression sort_direction nulls_order=nulls collation=Nothing + Order_Descriptor.Value internal_column.expression sort_direction nulls_order=nulls collation=Nothing Case_Sensitivity.Sensitive -> - IR.Order_Descriptor_Data internal_column.expression sort_direction nulls_order=nulls collation="ucs_basic" + Order_Descriptor.Value internal_column.expression sort_direction nulls_order=nulls collation="ucs_basic" Case_Sensitivity.Insensitive locale -> case locale == Locale.default of False -> Error.throw (Unsupported_Database_Operation_Error "Case insensitive ordering with custom locale is currently not supported. You may need to materialize the Table to perform this operation.") True -> - upper = IR.Operation "UPPER" [internal_column.expression] - folded_expression = IR.Operation "LOWER" [upper] - IR.Order_Descriptor_Data folded_expression sort_direction nulls_order=nulls collation=Nothing + upper = Expression.Operation "UPPER" [internal_column.expression] + folded_expression = Expression.Operation "LOWER" [upper] + Order_Descriptor.Value folded_expression sort_direction nulls_order=nulls collation=Nothing False -> - IR.Order_Descriptor_Data internal_column.expression sort_direction nulls_order=nulls collation=Nothing + Order_Descriptor.Value internal_column.expression sort_direction nulls_order=nulls collation=Nothing diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Redshift/Redshift_Dialect.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Redshift/Redshift_Dialect.enso index 46fd4f21e05..3a1682d6c2d 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Redshift/Redshift_Dialect.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Redshift/Redshift_Dialect.enso @@ -2,21 +2,20 @@ from Standard.Base import all from Standard.Table import Aggregate_Column -from Standard.Database.Data.SQL import SQL_Type, Statement -import Standard.Database.Data.Dialect -import Standard.Database.Internal.Postgres.Postgres_Dialect -import Standard.Database.Internal.Base_Generator +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.Base_Generator +import project.Internal.IR.Internal_Column.Internal_Column +import project.Internal.IR.Order_Descriptor.Order_Descriptor +import project.Internal.Postgres.Postgres_Dialect + ## PRIVATE The dialect for Redshift connections. -redshift : Dialect +redshift : Redshift_Dialect redshift = - Redshift_Dialect_Data Postgres_Dialect.make_internal_generator_dialect - -# TODO Dubious constructor export -from project.Internal.Redshift.Redshift_Dialect.Redshift_Dialect import all -from project.Internal.Redshift.Redshift_Dialect.Redshift_Dialect export all + Redshift_Dialect.Value Postgres_Dialect.make_internal_generator_dialect ## PRIVATE @@ -25,7 +24,7 @@ type Redshift_Dialect ## PRIVATE The dialect for Redshift connections. - Redshift_Dialect_Data internal_generator_dialect + Value internal_generator_dialect ## PRIVATE Name of the dialect. @@ -35,7 +34,7 @@ type Redshift_Dialect ## PRIVATE A function which generates SQL code from the internal representation according to the specific dialect. - generate_sql : Query -> Statement + generate_sql : Query -> SQL_Statement generate_sql self query = Base_Generator.generate_query self.internal_generator_dialect query . build @@ -53,6 +52,6 @@ type Redshift_Dialect One of the purposes of this method is to verify if the expected ordering settings are supported by the given database backend. - prepare_order_descriptor : IR.Internal_Column -> Sort_Direction -> Text_Ordering -> IR.Order_Descriptor + prepare_order_descriptor : Internal_Column -> Sort_Direction -> Text_Ordering -> Order_Descriptor prepare_order_descriptor self internal_column sort_direction text_ordering = Postgres_Dialect.make_order_descriptor internal_column sort_direction text_ordering diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Result_Set.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Result_Set.enso index b57bd64cdd7..f35b9728e87 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Result_Set.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Result_Set.enso @@ -1,9 +1,10 @@ from Standard.Base import all -import Standard.Table.Data.Table as Materialized_Table -import Standard.Table.Data.Column as Materialized_Column +import Standard.Table.Data.Table.Table as Materialized_Table +import Standard.Table.Data.Column.Column as Materialized_Column import Standard.Table.Internal.Java_Exports -from Standard.Database.Data.SQL import SQL_Type, SQL_Type_Data + +import project.Data.SQL_Type.SQL_Type polyglot java import java.sql.ResultSet @@ -24,7 +25,7 @@ read_column result_set column_name = ## PRIVATE Converts a ResultSet into a Materialized_Table. -result_set_to_table : ResultSet -> (Vector | Nothing) -> Materialized_Table.Table +result_set_to_table : ResultSet -> (Vector | Nothing) -> Materialized_Table result_set_to_table result_set expected_types=Nothing = metadata = result_set.getMetaData ncols = metadata.getColumnCount @@ -33,7 +34,7 @@ result_set_to_table result_set expected_types=Nothing = Vector.new ncols ix-> typeid = metadata.getColumnType ix+1 name = metadata.getColumnTypeName ix+1 - SQL_Type_Data typeid name + SQL_Type.Value typeid name column_builders = column_types.map typ-> create_builder typ go has_next = if has_next.not then Nothing else @@ -43,7 +44,7 @@ result_set_to_table result_set expected_types=Nothing = go result_set.next columns = column_builders.zip column_names builder-> name-> builder.make_column name - Materialized_Table.Table.new columns + Materialized_Table.new columns ## PRIVATE @@ -130,7 +131,7 @@ type Builder Argument: - name: The name of the column. - make_column : Text -> Materialized_Column.Column + make_column : Text -> Materialized_Column make_column self name = storage = self.java_builder.seal Java_Exports.make_column name storage diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Connection.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Connection.enso index e37e19c0f0d..3e8349a3ca5 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Connection.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Connection.enso @@ -1,20 +1,16 @@ from Standard.Base import all -from Standard.Database.Data.SQL import SQL_Type, Statement -import Standard.Database.Data.SQL_Query +import Standard.Table.Data.Table.Table as Materialized_Table -import Standard.Database.Internal.JDBC_Connection -import Standard.Database.Data.Dialect -from Standard.Database.Connection.Connection import Connection_Data +import project.Data.SQL_Query.SQL_Query +import project.Data.SQL_Type.SQL_Type +import project.Internal.JDBC_Connection +import project.Data.Dialect +import project.Connection.Connection.Connection +import project.Data.Table.Table as Database_Table -import Standard.Database.Data.Table as Database_Table -import Standard.Table.Data.Table as Materialized_Table - -from Standard.Database.Errors import SQL_Error - -# TODO Dubious constructor export -from project.Internal.SQLite.SQLite_Connection.SQLite_Connection import all -from project.Internal.SQLite.SQLite_Connection.SQLite_Connection export all +import project.Data.SQL_Statement.SQL_Statement +from project.Errors import SQL_Error type SQLite_Connection ## PRIVATE @@ -23,7 +19,7 @@ type SQLite_Connection Arguments: - connection: the underlying connection. - SQLite_Connection_Data connection + Value connection ## Closes the connection releasing the underlying database resources immediately instead of waiting for them to be automatically released. @@ -78,7 +74,7 @@ type SQLite_Connection - schema: The schema name to search in (defaults to current schema). - types: The table types to search for. The list of values can be obtained using the `table_types` method. - all_fields: Return all the fields in the metadata table. - tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table.Table + tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table tables self name_like=Nothing database=self.database schema=self.schema types=Nothing all_fields=False = self.connection.tables name_like database schema types all_fields @@ -88,7 +84,7 @@ type SQLite_Connection - query: name of the table or sql statement to query. If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - alias: optionally specify a friendly alias for the query. - query : Text | SQL_Query -> Text -> Database_Table.Table + query : Text | SQL_Query -> Text -> Database_Table query self query alias="" = self.connection.query query alias ## Execute the query and load the results into memory as a Table. @@ -97,12 +93,12 @@ type SQLite_Connection - query: name of the table or sql statement to query. If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - limit: the maximum number of rows to return. - read : Text | SQL_Query -> Integer | Nothing -> Materialized_Table.Table + read : Text | SQL_Query -> Integer | Nothing -> Materialized_Table read self query limit=Nothing = self.connection.read query limit ## PRIVATE Internal read function for a statement with optional types. - read_statement : Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table.Table + read_statement : SQL_Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table read_statement self statement expected_types=Nothing = self.connection.read_statement statement expected_types @@ -113,9 +109,9 @@ type SQLite_Connection returns 0 for other types of queries (like creating or altering tables). Arguments: - - query: either raw SQL code as Text or an instance of Statement + - query: either raw SQL code as Text or an instance of SQL_Statement representing the query to execute. - execute_update : Text | Statement -> Integer + execute_update : Text | SQL_Statement -> Integer execute_update self query = self.connection.execute_update query @@ -136,7 +132,7 @@ type SQLite_Connection usually not be visible to other connections. - batch_size: Specifies how many rows should be uploaded in a single batch. - upload_table : Text -> Materialized_Table.Table -> Boolean -> Integer -> Database_Table.Table + upload_table : Text -> Materialized_Table -> Boolean -> Integer -> Database_Table upload_table self name table temporary=True batch_size=1000 = Panic.recover Illegal_State_Error <| self.connection.upload_table name table temporary batch_size @@ -150,4 +146,4 @@ type SQLite_Connection create : Text -> Vector -> SQLite_Connection create url properties = jdbc_connection = JDBC_Connection.create url properties - SQLite_Connection_Data (Connection_Data jdbc_connection Dialect.sqlite) + SQLite_Connection.Value (Connection.Value jdbc_connection Dialect.sqlite) diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Dialect.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Dialect.enso index ee56c8ec015..208dc4b6de8 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Dialect.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Internal/SQLite/SQLite_Dialect.enso @@ -1,23 +1,23 @@ from Standard.Base import all hiding First, Last from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all -import Standard.Database.Data.SQL -from Standard.Database.Data.SQL import SQL_Type, Statement, code -import Standard.Database.Data.Dialect -import Standard.Database.Internal.Base_Generator -import Standard.Database.Internal.IR -from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data + +import project.Data.SQL +import project.Data.SQL_Statement.SQL_Statement +import project.Data.SQL_Type.SQL_Type +import project.Internal.Base_Generator +import project.Internal.IR.Internal_Column.Internal_Column +import project.Internal.IR.Order_Descriptor.Order_Descriptor + +from project.Data.SQL import code +from project.Errors import Unsupported_Database_Operation_Error_Data ## PRIVATE The dialect of SQLite databases. -sqlite : Dialect +sqlite : SQLite_Dialect sqlite = - SQLite_Dialect_Data make_internal_generator_dialect - -# TODO Dubious constructor export -from project.Internal.SQLite.SQLite_Dialect.SQLite_Dialect import all -from project.Internal.SQLite.SQLite_Dialect.SQLite_Dialect export all + SQLite_Dialect.Value make_internal_generator_dialect ## PRIVATE @@ -26,7 +26,7 @@ type SQLite_Dialect ## PRIVATE The dialect of SQLite databases. - SQLite_Dialect_Data internal_generator_dialect + Value internal_generator_dialect ## PRIVATE Name of the dialect. @@ -36,7 +36,7 @@ type SQLite_Dialect ## PRIVATE A function which generates SQL code from the internal representation according to the specific dialect. - generate_sql : Query -> Statement + generate_sql : Query -> SQL_Statement generate_sql self query = Base_Generator.generate_query self.internal_generator_dialect query . build @@ -53,22 +53,22 @@ type SQLite_Dialect One of the purposes of this method is to verify if the expected ordering settings are supported by the given database backend. - prepare_order_descriptor : IR.Internal_Column -> Sort_Direction -> Text_Ordering -> IR.Order_Descriptor + prepare_order_descriptor : Internal_Column -> Sort_Direction -> Text_Ordering -> Order_Descriptor prepare_order_descriptor self internal_column sort_direction text_ordering = case internal_column.sql_type.is_likely_text of True -> if text_ordering.sort_digits_as_numbers then Error.throw (Unsupported_Database_Operation_Error_Data "Natural ordering is not supported by the SQLite backend. You may need to materialize the Table to perform this operation.") else case text_ordering.case_sensitivity of Nothing -> - IR.Order_Descriptor_Data internal_column.expression sort_direction collation=Nothing + Order_Descriptor.Value internal_column.expression sort_direction collation=Nothing Case_Sensitivity.Sensitive -> - IR.Order_Descriptor_Data internal_column.expression sort_direction collation="BINARY" + Order_Descriptor.Value internal_column.expression sort_direction collation="BINARY" Case_Sensitivity.Insensitive locale -> case locale == Locale.default of False -> Error.throw (Unsupported_Database_Operation_Error_Data "Case insensitive ordering with custom locale is not supported by the SQLite backend. You may need to materialize the Table to perform this operation.") True -> - IR.Order_Descriptor_Data internal_column.expression sort_direction collation="NOCASE" + Order_Descriptor.Value internal_column.expression sort_direction collation="NOCASE" False -> - IR.Order_Descriptor_Data internal_column.expression sort_direction collation=Nothing + Order_Descriptor.Value internal_column.expression sort_direction collation=Nothing ## PRIVATE make_internal_generator_dialect = 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 ea21f8f2729..44cc0309fcc 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 @@ -1,23 +1,24 @@ -import Standard.Database.Data.SQL_Query -import Standard.Database.Connection.Database +import project.Connection.Database -import Standard.Database.Connection.Credentials -import Standard.Database.Connection.Client_Certificate -import Standard.Database.Connection.SSL_Mode -import Standard.Database.Connection.Connection_Options +import project.Connection.Credentials.Credentials +import project.Connection.Client_Certificate.Client_Certificate +import project.Connection.SSL_Mode.SSL_Mode +import project.Connection.Connection_Options.Connection_Options -import Standard.Database.Connection.Postgres_Options -import Standard.Database.Connection.SQLite_Options -import Standard.Database.Connection.Redshift_Options +import project.Connection.Postgres_Options +import project.Connection.SQLite_Options +import project.Connection.Redshift_Options +import project.Data.SQL_Query.SQL_Query -export Standard.Database.Connection.SSL_Mode +export project.Connection.Credentials.Credentials -from Standard.Database.Connection.Credentials export Credentials, Username_And_Password -from Standard.Database.Connection.Client_Certificate export Client_Certificate -from Standard.Database.Connection.Connection_Options export Connection_Options +export project.Connection.SSL_Mode.SSL_Mode +export project.Connection.Client_Certificate.Client_Certificate +export project.Connection.Connection_Options.Connection_Options -from Standard.Database.Connection.Database export connect -from Standard.Database.Connection.Postgres_Options export Postgres_Options, Postgres -from Standard.Database.Connection.SQLite_Options export SQLite_Options, SQLite, In_Memory -from Standard.Database.Connection.Redshift_Options export Redshift_Options, Redshift, AWS_Profile, AWS_Key -from Standard.Database.Data.SQL_Query export SQL_Query, Table_Name, Raw_SQL +export project.Connection.Database +export project.Data.SQL_Query.SQL_Query + +from project.Connection.Postgres_Options export Postgres_Options, Postgres +from project.Connection.SQLite_Options export SQLite_Options, In_Memory, SQLite +from project.Connection.Redshift_Options export Redshift_Options, Redshift, AWS_Credential diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Aggregate_Column.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Aggregate_Column.enso index c6a812f48c3..7c07ea9eaf8 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Aggregate_Column.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Aggregate_Column.enso @@ -1,8 +1,8 @@ from Standard.Base import all -import Standard.Table.Data.Column.Column -import Standard.Table.Data.Column_Selector.Column_Selector -import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector +import project.Data.Column.Column +import project.Data.Column_Selector.Column_Selector +import project.Data.Sort_Column_Selector.Sort_Column_Selector ## Defines an Aggregate Column type Aggregate_Column diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Column.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Column.enso index 077347d833b..12aadbdfc37 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Column.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Column.enso @@ -2,10 +2,10 @@ from Standard.Base import all import Standard.Base.Data.Ordering.Comparator import Standard.Base.Data.Index_Sub_Range -import Standard.Table.Data.Table.Table -from Standard.Table.Data.Table import print_table -import Standard.Table.Data.Storage.Storage -import Standard.Table.Data.Value_Type.Value_Type +import project.Data.Table.Table +import project.Data.Storage.Storage +import project.Data.Value_Type.Value_Type +from project.Data.Table import print_table from project.Errors import No_Index_Set_Error @@ -751,7 +751,7 @@ type Column storage_type : Storage storage_type self = tp = self.java_column.getStorage.getType - storage_types.at tp . catch Index_Out_Of_Bounds_Error _-> + Storage.types.at tp . catch Index_Out_Of_Bounds_Error _-> Panic.throw (Illegal_State_Error "Unknown storage type: "+tp.to_text) ## UNSTABLE TODO this is a prototype that will be revisited later on @@ -1139,20 +1139,6 @@ run_vectorized_unary_op column name fallback_fn = rs = s.map name fallback_fn Column.Column_Data (Java_Column.new "Result" ix rs) -## PRIVATE - Enumerates storage types in a way that is consistent with - `org.enso.table.data.Storage.Storage`, i.e. - `storage_type.at org.enso.table.data.Storage.Storage.LONG` will yield the - corresponding `Storage.Integer`. -storage_types : Vector Storage -storage_types = [Storage.Any, Storage.Integer, Storage.Decimal, Storage.Text, Storage.Boolean, Storage.Date, Storage.Time_Of_Day, Storage.Date_Time] - -## PRIVATE - - Keep this in sync with `org.enso.table.data.Storage.Storage.STRING` -storage_type_string : Integer -storage_type_string = 3 - ## PRIVATE A helper function for converting a column storage to JSON. diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Data_Formatter.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Data_Formatter.enso index b9f127c3f5a..cdbee2fb294 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Data_Formatter.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Data_Formatter.enso @@ -1,10 +1,9 @@ from Standard.Base import all import Standard.Base.Error.Common as Errors -import Standard.Table.Data.Column_Type_Selection.Auto -import Standard.Table.Data.Storage.Storage - -import Standard.Table.Internal.Parse_Values_Helper +import project.Data.Column_Type_Selection.Auto +import project.Data.Storage.Storage +import project.Internal.Parse_Values_Helper polyglot java import org.enso.table.parsing.IntegerParser polyglot java import org.enso.table.parsing.DecimalParser diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Sort_Column_Selector.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Sort_Column_Selector.enso index e75d479b2d0..e8abcc2ffe1 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Sort_Column_Selector.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Sort_Column_Selector.enso @@ -1,7 +1,7 @@ from Standard.Base import all -import Standard.Table.Data.Column.Column -import Standard.Table.Data.Sort_Column.Sort_Column +import project.Data.Column.Column +import project.Data.Sort_Column.Sort_Column type Sort_Column_Selector By_Name (columns : Vector (Sort_Column.Name | Text)) (matcher:Matcher=Text_Matcher.Case_Sensitive) diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Storage.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Storage.enso index 507d127e73e..e0293912434 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Storage.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Storage.enso @@ -24,3 +24,11 @@ type Storage ## A column storing arbitrary data. Any + + ## PRIVATE + Enumerates storage types in a way that is consistent with + `org.enso.table.data.Storage.Storage`, i.e. + `storage_type.at org.enso.table.data.Storage.Storage.LONG` will yield the + corresponding `Storage.Integer`. + types : Vector Storage + types = [Storage.Any, Storage.Integer, Storage.Decimal, Storage.Text, Storage.Boolean, Storage.Date, Storage.Time_Of_Day, Storage.Date_Time] 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 c0aafbc4720..7103c8a3383 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 @@ -6,30 +6,26 @@ import Standard.Base.Data.Ordering.Comparator import Standard.Base.Data.Text.Case import Standard.Base.System.Platform -import Standard.Table.Data.Column.Column -from Standard.Table.Data.Filter_Condition_Helpers import make_filter_column +import project.Data.Column.Column +import project.Data.Column_Name_Mapping.Column_Name_Mapping +import project.Data.Column_Selector.Column_Selector +import project.Data.Data_Formatter.Data_Formatter +import project.Data.Match_Columns.Match_Columns +import project.Data.Position.Position +import project.Data.Sort_Column_Selector.Sort_Column_Selector +import project.Data.Sort_Column.Sort_Column +import project.Data.Aggregate_Column.Aggregate_Column +import project.Internal.Table_Helpers +import project.Internal.Aggregate_Column_Helper +import project.Internal.Parse_Values_Helper +import project.Internal.Problem_Builder.Problem_Builder +import project.IO.Auto_Detect.Auto_Detect -import Standard.Table.Internal.Table_Helpers -import Standard.Table.Internal.Aggregate_Column_Helper -import Standard.Table.Internal.Parse_Values_Helper -import Standard.Table.Internal.Problem_Builder.Problem_Builder +from project.Data.Column_Type_Selection import Column_Type_Selection, Auto +from project.Delimited.Delimited_Format import Delimited +from project.Internal.Filter_Condition_Helpers import make_filter_column +from project.Errors import Missing_Input_Columns, Column_Indexes_Out_Of_Range, Duplicate_Type_Selector, No_Index_Set_Error, No_Such_Column_Error, No_Such_Column_Error_Data, No_Input_Columns_Selected, No_Output_Columns -import Standard.Table.IO.Auto_Detect.Auto_Detect - -from Standard.Table.Delimited.Delimited_Format import Delimited_Format, Delimited - -import Standard.Table.Data.Column_Selector.Column_Selector -from Standard.Table.Data.Column_Type_Selection import Column_Type_Selection, Auto -import Standard.Table.Data.Data_Formatter.Data_Formatter -from Standard.Table.Errors import Missing_Input_Columns, Column_Indexes_Out_Of_Range, Duplicate_Type_Selector, No_Index_Set_Error, No_Such_Column_Error, No_Such_Column_Error_Data, No_Input_Columns_Selected, No_Output_Columns -import Standard.Table.Data.Match_Columns.Match_Columns - -from Standard.Table.Data.Column_Name_Mapping import Column_Name_Mapping -import Standard.Table.Data.Position.Position -import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector -import Standard.Table.Data.Sort_Column.Sort_Column - -import Standard.Table.Data.Aggregate_Column.Aggregate_Column import Standard.Visualization polyglot java import org.enso.table.data.table.Table as Java_Table diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table_Conversions.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table_Conversions.enso index be08867e9bf..614dcaa253c 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table_Conversions.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Table_Conversions.enso @@ -2,16 +2,16 @@ from Standard.Base import all from Standard.Base.Error.Problem_Behavior import Report_Warning import project.Data.Table.Table -import project.Errors - -from project.Delimited.Delimited_Format import Delimited_Format, Delimited import project.Delimited.Delimited_Reader import project.Delimited.Delimited_Writer +from project.Delimited.Delimited_Format import Delimited_Format, Delimited +from project.Errors import unimplemented + Table.from (that : Text) (format:Delimited_Format = Delimited '\t') (on_problems:Problem_Behavior=Report_Warning) = if format.is_a Delimited then Delimited_Reader.read_text that format on_problems else - Errors.unimplemented "Table.from for fixed-width files is not yet implemented." + unimplemented "Table.from for fixed-width files is not yet implemented." Text.from (that : Table) (format:Delimited_Format = Delimited '\t') = if format.is_a Delimited then Delimited_Writer.write_text that format else - Errors.unimplemented "Text.from for fixed-width files is not yet implemented." + unimplemented "Text.from for fixed-width files is not yet implemented." diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Value_Type.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Value_Type.enso index 4f0ba5f989c..3a970d78080 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Value_Type.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Value_Type.enso @@ -4,7 +4,7 @@ from Standard.Base import all -from Standard.Table.Errors import Invalid_Value_Type +from project.Errors import Invalid_Value_Type ## Type to represent the different sizes of integer or float possible within a database. type Bits 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 0f40a9e1ae1..d5309052088 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 @@ -1,11 +1,11 @@ from Standard.Base import all -from Standard.Table.Data.Table import Table -from Standard.Table.Data.Data_Formatter import Data_Formatter -from Standard.Table.Data.Match_Columns import Match_Columns -import Standard.Table.Delimited.Delimited_Reader -import Standard.Table.Delimited.Delimited_Writer -import Standard.Table.Delimited.Quote_Style.Quote_Style +import project.Data.Table.Table +import project.Data.Data_Formatter.Data_Formatter +import project.Data.Match_Columns.Match_Columns +import project.Delimited.Delimited_Reader +import project.Delimited.Delimited_Writer +import project.Delimited.Quote_Style.Quote_Style from project.Delimited.Delimited_Format.Delimited_Format import Delimited from project.Delimited.Delimited_Format.Delimited_Format export Delimited diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Reader.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Reader.enso index ecbe6b62756..d99ee6d5ebb 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Reader.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Reader.enso @@ -2,12 +2,12 @@ from Standard.Base import all import Standard.Base.Error.Common as Errors from Standard.Base.Error.Problem_Behavior import Ignore, Report_Error -import Standard.Table.Data.Table.Table -import Standard.Table.Data.Data_Formatter.Data_Formatter -import Standard.Table.Delimited.Delimited_Format.Delimited_Format -import Standard.Table.Delimited.Quote_Style.Quote_Style +import project.Data.Table.Table +import project.Data.Data_Formatter.Data_Formatter +import project.Delimited.Delimited_Format.Delimited_Format +import project.Delimited.Quote_Style.Quote_Style -from Standard.Table.Errors import Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, Invalid_Row_Data, Mismatched_Quote, Parser_Error, Additional_Invalid_Rows_Data +from project.Errors import Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, Invalid_Row_Data, Mismatched_Quote, Parser_Error, Additional_Invalid_Rows_Data polyglot java import org.enso.base.encoding.NewlineDetector polyglot java import org.enso.table.read.DelimitedReader diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Writer.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Writer.enso index 00bc8ceb99d..259c36ba581 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Writer.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Delimited/Delimited_Writer.enso @@ -2,14 +2,15 @@ from Standard.Base import all import Standard.Base.System import Standard.Base.Error.Common as Errors -from Standard.Table.Data.Table import Table -from Standard.Table.Errors import Duplicate_Output_Column_Names, Invalid_Output_Column_Names, Invalid_Row, Mismatched_Quote, Parser_Error, Additional_Invalid_Rows, Column_Count_Mismatch, Column_Name_Mismatch -from Standard.Table.Data.Data_Formatter import Data_Formatter -from Standard.Table.Data.Storage import Storage -from Standard.Table.Delimited.Delimited_Format import Delimited_Format -from Standard.Table.Delimited.Quote_Style import Quote_Style -from Standard.Table.Delimited.Delimited_Reader import Detected_Headers, detect_metadata -from Standard.Table.Data.Match_Columns import Match_Columns +import project.Data.Table.Table +import project.Data.Data_Formatter.Data_Formatter +import project.Data.Match_Columns.Match_Columns +import project.Data.Storage.Storage +import project.Delimited.Delimited_Format.Delimited_Format +import project.Delimited.Quote_Style.Quote_Style + +from project.Delimited.Delimited_Reader import Detected_Headers, detect_metadata +from project.Errors import Duplicate_Output_Column_Names, Invalid_Output_Column_Names, Invalid_Row, Mismatched_Quote, Parser_Error, Additional_Invalid_Rows, Column_Count_Mismatch, Column_Name_Mismatch polyglot java import org.enso.table.write.DelimitedWriter polyglot java import org.enso.table.write.WriteQuoteBehavior diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Format.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Format.enso index 067e39faf14..dbab7b320cd 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Format.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Format.enso @@ -1,10 +1,10 @@ from Standard.Base import all -import Standard.Table.Data.Table.Table +import project.Data.Table.Table +import project.Excel.Excel_Reader +import project.Excel.Excel_Writer -from Standard.Table.Excel.Section import Excel_Section, Worksheet, Sheet_Names, Range_Names -import Standard.Table.Excel.Excel_Reader -import Standard.Table.Excel.Excel_Writer +from project.Excel.Excel_Section import Excel_Section, Worksheet, Sheet_Names, Range_Names from project.Excel.Excel_Format.Excel_Format import Excel from project.Excel.Excel_Format.Excel_Format export Excel diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Range.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Range.enso similarity index 100% rename from distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Range.enso rename to distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Range.enso diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Reader.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Reader.enso index 98a0c96b83c..58c8714378a 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Reader.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Reader.enso @@ -1,12 +1,11 @@ from Standard.Base import all import Standard.Base.System.File.Option -import Standard.Table.Data.Table.Table -import Standard.Table.Excel.Range.Excel_Range +import project.Data.Table.Table +import project.Excel.Excel_Range.Excel_Range -from Standard.Table.Excel.Section import Excel_Section, Sheet_Names, Range_Names, Worksheet, Cell_Range - -from Standard.Table.Errors import Invalid_Location_Data, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data +from project.Excel.Excel_Section import Excel_Section, Sheet_Names, Range_Names, Worksheet, Cell_Range +from project.Errors import Invalid_Location_Data, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data polyglot java import org.enso.table.excel.ExcelHeaders polyglot java import org.enso.table.read.ExcelReader diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Section.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Section.enso similarity index 82% rename from distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Section.enso rename to distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Section.enso index ee51842a233..2bce587bcf8 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Section.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Section.enso @@ -1,9 +1,9 @@ from Standard.Base import all -import Standard.Table.Excel.Range.Excel_Range +import project.Excel.Excel_Range.Excel_Range -from project.Excel.Section.Excel_Section import all -from project.Excel.Section.Excel_Section export all +from project.Excel.Excel_Section.Excel_Section import all +from project.Excel.Excel_Section.Excel_Section export all type Excel_Section ## Gets a list of sheets within a workbook. diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Writer.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Writer.enso index 7bb2f0b686d..a220fde8a1d 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Writer.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Writer.enso @@ -1,13 +1,12 @@ from Standard.Base import all -import Standard.Table.Data.Table +import project.Data.Table +import project.Data.Match_Columns.Match_Columns +import project.Excel.Excel_Range.Excel_Range -from Standard.Table.Excel.Excel_Reader import handle_reader, make_java_headers -from Standard.Table.Excel.Section import Worksheet, Cell_Range -import Standard.Table.Excel.Range.Excel_Range - -from Standard.Table.Errors import Invalid_Location_Data, Range_Exceeded_Data, Existing_Data_Data, Column_Count_Mismatch, Column_Name_Mismatch -import Standard.Table.Data.Match_Columns.Match_Columns +from project.Excel.Excel_Reader import handle_reader, make_java_headers +from project.Excel.Excel_Section import Worksheet, Cell_Range +from project.Errors import Invalid_Location_Data, Range_Exceeded_Data, Existing_Data_Data, Column_Count_Mismatch, Column_Name_Mismatch polyglot java import org.enso.table.read.ExcelReader polyglot java import org.enso.table.write.ExcelWriter diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/IO/Auto_Detect.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/IO/Auto_Detect.enso index 9ed769a5c38..9a47bbcfcda 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/IO/Auto_Detect.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/IO/Auto_Detect.enso @@ -1,8 +1,8 @@ from Standard.Base import Any, Problem_Behavior, Nothing, Error, Panic, Meta, File, File_Format, Plain_Text_Format, Bytes from Standard.Base.Error.Common import Unsupported_File_Type, Unsupported_File_Type_Data, No_Such_Method_Error_Data, Illegal_Argument_Error_Data -import Standard.Table.Delimited.Delimited_Format.Delimited_Format -import Standard.Table.Excel.Excel_Format.Excel_Format +import project.Delimited.Delimited_Format.Delimited_Format +import project.Excel.Excel_Format.Excel_Format ## PRIVATE Set of File_Format types for read files. diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/IO/File_Read.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/IO/File_Read.enso index 6ae2b95ac7a..706858d7e43 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/IO/File_Read.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/IO/File_Read.enso @@ -2,7 +2,7 @@ from Standard.Base import Any, Text, Problem_Behavior, Nothing, Error, Panic, Me from Standard.Base.Error.Problem_Behavior import Report_Warning from Standard.Base.Error.Common import Unsupported_File_Type_Data, No_Such_Method_Error_Data, Illegal_Argument_Error_Data -import Standard.Table.IO.Auto_Detect.Auto_Detect +import project.IO.Auto_Detect.Auto_Detect ## ALIAS Read Text File, Read File diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Aggregate_Column_Helper.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Aggregate_Column_Helper.enso index 0060116d473..b20bbfaaff3 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Aggregate_Column_Helper.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Aggregate_Column_Helper.enso @@ -1,20 +1,16 @@ from Standard.Base import all hiding First, Last - -import Standard.Table.Data.Column.Column - -from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all -import Standard.Table.Data.Column_Selector.Column_Selector - -import Standard.Table.Internal.Problem_Builder.Problem_Builder -import Standard.Table.Internal.Unique_Name_Strategy.Unique_Name_Strategy -import Standard.Table.Internal.Table_Helpers - -import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector -import Standard.Table.Data.Sort_Column.Sort_Column - import Standard.Base.Data.Ordering.Comparator -from Standard.Table.Errors import Missing_Input_Columns_Data, Column_Indexes_Out_Of_Range, No_Output_Columns, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, Invalid_Aggregation_Data, Floating_Point_Grouping_Data, Unquoted_Delimiter_Data, Additional_Warnings_Data +import project.Data.Column.Column +import project.Data.Column_Selector.Column_Selector +import project.Data.Sort_Column.Sort_Column +import project.Data.Sort_Column_Selector.Sort_Column_Selector +import project.Internal.Problem_Builder.Problem_Builder +import project.Internal.Table_Helpers +import project.Internal.Unique_Name_Strategy.Unique_Name_Strategy + +from project.Data.Aggregate_Column.Aggregate_Column import all +from project.Errors import Missing_Input_Columns_Data, Column_Indexes_Out_Of_Range, No_Output_Columns, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, Invalid_Aggregation_Data, Floating_Point_Grouping_Data, Unquoted_Delimiter_Data, Additional_Warnings_Data polyglot java import org.enso.table.aggregations.Aggregator polyglot java import org.enso.table.aggregations.Concatenate as ConcatenateAggregator diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Filter_Condition_Helpers.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Filter_Condition_Helpers.enso similarity index 98% rename from distribution/lib/Standard/Table/0.0.0-dev/src/Data/Filter_Condition_Helpers.enso rename to distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Filter_Condition_Helpers.enso index 18616aafc40..d28302c770a 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Filter_Condition_Helpers.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Filter_Condition_Helpers.enso @@ -1,6 +1,6 @@ from Standard.Base import all -from Standard.Table.Data.Value_Type import Value_Type +import project.Data.Value_Type.Value_Type from Standard.Base.Data.Filter_Condition.Filter_Condition import all diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Java_Exports.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Java_Exports.enso index 2258312052a..b8044647fa5 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Java_Exports.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Java_Exports.enso @@ -1,9 +1,9 @@ from Standard.Base import all -import Standard.Table.Data.Column.Column -polyglot java import org.enso.table.data.table.Column as Java_Column +import project.Data.Column.Column +import project.Data.Table.Table -import Standard.Table.Data.Table.Table +polyglot java import org.enso.table.data.table.Column as Java_Column polyglot java import org.enso.table.data.table.Table as Java_Table polyglot java import org.enso.table.data.index.DefaultIndex diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Parse_Values_Helper.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Parse_Values_Helper.enso index b1695720d04..1a1cc6b36ef 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Parse_Values_Helper.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Parse_Values_Helper.enso @@ -1,6 +1,6 @@ from Standard.Base import all -from Standard.Table.Errors import Invalid_Format_Data, Leading_Zeros_Data +from project.Errors import Invalid_Format_Data, Leading_Zeros_Data polyglot java import org.enso.table.parsing.problems.InvalidFormat polyglot java import org.enso.table.parsing.problems.LeadingZeros 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 2029071bf00..3e4a8fd3cf9 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 @@ -2,9 +2,9 @@ from Standard.Base import all from Standard.Base.Error.Problem_Behavior import Report_Warning import Standard.Base.Runtime.Ref -import Standard.Table.Internal.Vector_Builder.Vector_Builder +import project.Internal.Vector_Builder.Vector_Builder -from Standard.Table.Errors import Missing_Input_Columns_Data, Column_Indexes_Out_Of_Range_Data, No_Output_Columns, Duplicate_Column_Selectors_Data, Input_Indices_Already_Matched_Data, Too_Many_Column_Names_Provided, Duplicate_Output_Column_Names, Invalid_Output_Column_Names, Column_Matched_By_Multiple_Selectors_Data +from project.Errors import Missing_Input_Columns_Data, Column_Indexes_Out_Of_Range_Data, No_Output_Columns, Duplicate_Column_Selectors_Data, Input_Indices_Already_Matched_Data, Too_Many_Column_Names_Provided, Duplicate_Output_Column_Names, Invalid_Output_Column_Names, Column_Matched_By_Multiple_Selectors_Data type Problem_Builder Value oob_indices duplicate_column_selectors input_indices_already_matched missing_input_columns other diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Table_Helpers.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Table_Helpers.enso index 4d50b0a8825..6e0406b067f 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Table_Helpers.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Table_Helpers.enso @@ -4,14 +4,15 @@ import Standard.Base.Data.Ordering.Vector_Lexicographic_Order from Standard.Base.Data.Text.Text_Ordering import Text_Ordering from Standard.Base.Error.Problem_Behavior import Report_Warning -import Standard.Table.Data.Position.Position -from Standard.Table.Errors import Missing_Input_Columns_Data, No_Output_Columns, Too_Many_Column_Names_Provided_Data, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, No_Input_Columns_Selected -import Standard.Table.Data.Column_Selector.Column_Selector -import Standard.Table.Data.Column_Name_Mapping.Column_Name_Mapping -import Standard.Table.Internal.Unique_Name_Strategy.Unique_Name_Strategy -import Standard.Table.Internal.Problem_Builder.Problem_Builder -import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector -import Standard.Table.Data.Sort_Column.Sort_Column +import project.Data.Position.Position +import project.Data.Column_Name_Mapping.Column_Name_Mapping +import project.Data.Column_Selector.Column_Selector +import project.Data.Sort_Column_Selector.Sort_Column_Selector +import project.Data.Sort_Column.Sort_Column +import project.Internal.Problem_Builder.Problem_Builder +import project.Internal.Unique_Name_Strategy.Unique_Name_Strategy + +from project.Errors import Missing_Input_Columns_Data, No_Output_Columns, Too_Many_Column_Names_Provided_Data, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, No_Input_Columns_Selected polyglot java import java.util.HashSet diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Main.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Main.enso index e4a832aef13..b0f8c8b676b 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Main.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Main.enso @@ -20,8 +20,8 @@ import project.Delimited.Quote_Style.Quote_Style import project.Delimited.Delimited_Format import project.Data.Table_Conversions -import project.Excel.Section -import project.Excel.Range.Excel_Range +import project.Excel.Excel_Section +import project.Excel.Excel_Range.Excel_Range import project.Excel.Excel_Format export project.Data.Table.Table @@ -33,7 +33,6 @@ export project.Data.Column_Name_Mapping.Column_Name_Mapping export project.Data.Match_Columns.Match_Columns export project.Data.Position.Position export project.Data.Aggregate_Column.Aggregate_Column -export project.Data.Filter_Condition.Filter_Condition export project.IO.File_Read export project.IO.Auto_Detect.Auto_Detect @@ -43,8 +42,8 @@ from project.Delimited.Delimited_Format export Delimited_Format, Delimited export project.Data.Table_Conversions from project.Excel.Excel_Format export Excel_Format, Excel -from project.Excel.Section export Excel_Section, Sheet_Names, Range_Names, Worksheet, Cell_Range -export project.Excel.Range.Excel_Range +from project.Excel.Excel_Section export Excel_Section, Sheet_Names, Range_Names, Worksheet, Cell_Range +export project.Excel.Excel_Range.Excel_Range export project.Data.Data_Formatter.Data_Formatter diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/File_Upload.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/File_Upload.enso index 5a5884b894c..d0bdafb3078 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/File_Upload.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/File_Upload.enso @@ -9,16 +9,12 @@ from Standard.Base import all - `path`: The path to which the file is being uploaded. file_uploading : (File.File | Text) -> File.File ! File_Being_Uploaded file_uploading path = - err = File_Being_Uploaded_Data <| case path of + err = File_Being_Uploaded.Value <| case path of _ : Text -> path _ : File.File -> path.path _ -> "" Error.throw err -# TODO Dubious constructor export -from project.File_Upload.File_Being_Uploaded import all -from project.File_Upload.File_Being_Uploaded export all - ## UNSTABLE Represents that a file is being uploaded to the given `file_path`. @@ -26,4 +22,4 @@ from project.File_Upload.File_Being_Uploaded export all Arguments: - file_path: The path at which the file is being uploaded. type File_Being_Uploaded - File_Being_Uploaded_Data file_path + Value file_path diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Geo_Map.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Geo_Map.enso index d5009f7987a..9b6d25d1b9f 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Geo_Map.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Geo_Map.enso @@ -1,8 +1,8 @@ from Standard.Base import all from Standard.Table import Table -import Standard.Test -import Standard.Visualization.Helpers + +import project.Helpers ## PRIVATE diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Histogram.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Histogram.enso index 70bf1dff6a9..2a3f08f80f1 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Histogram.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Histogram.enso @@ -1,7 +1,7 @@ from Standard.Base import all from Standard.Table import Table, Column -import Standard.Visualization.Helpers +import project.Helpers ## PRIVATE @@ -23,7 +23,7 @@ Table.value_column self = type Update ## PRIVATE - Update_Data values label + Value values label ## PRIVATE @@ -43,12 +43,12 @@ from_table table = col = table.value_column label = col.name.catch_ Nothing values = col.to_vector.catch_ [] - Update.Update_Data values label + Update.Value values label ## PRIVATE from_vector : Vector -> Update from_vector vector = - Update.Update_Data vector Nothing + Update.Value vector Nothing ## PRIVATE from_value : Any -> Update diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Id.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Id.enso index 1f0ff9c02b4..579e0ece8f9 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Id.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Id.enso @@ -1,16 +1,13 @@ from Standard.Base import all import Standard.Base -# TODO Dubious constructor export -from project.Id.Id import all -from project.Id.Id export all - ## An ID used by the visualization system to identify different ways of displaying data. type Id ## A builtin visulization, implemented in the graphical interface and not imported from any library. Builtin name + ## A visualization implemented in a library. Library project name @@ -18,8 +15,8 @@ type Id interface. to_json self = project = case self of - Builtin _ -> Nothing - Library project _ -> + Id.Builtin _ -> Nothing + Id.Library project _ -> full_name = project.namespace + "." + project.name Base.Json.from_pairs [["name", full_name]] Base.Json.from_pairs [["library", project], ["name", self.name]] @@ -29,56 +26,56 @@ type Id An identifier for the builtin JSON visualization json : Id -json = Builtin "JSON" +json = Id.Builtin "JSON" ## UNSTABLE ADVANCED An identifier for the builtin Scatter Plot visualization scatter_plot : Id -scatter_plot = Builtin "Scatter Plot" +scatter_plot = Id.Builtin "Scatter Plot" ## UNSTABLE ADVANCED An identifier for the builtin Histogram visualization histogram : Id -histogram = Builtin "Histogram" +histogram = Id.Builtin "Histogram" ## UNSTABLE ADVANCED An identifier for the builtin Heatmap visualization heatmap : Id -heatmap = Builtin "Heatmap" +heatmap = Id.Builtin "Heatmap" ## UNSTABLE ADVANCED An identifier for the builtin Table visualization table : Id -table = Builtin "Table" +table = Id.Builtin "Table" ## UNSTABLE ADVANCED An identifier for the builtin SQL Query visualization sql_query : Id -sql_query = Builtin "SQL Query" +sql_query = Id.Builtin "SQL Query" ## UNSTABLE ADVANCED An identifier for the builtin Geo Map visualization geo_map : Id -geo_map = Builtin "Geo Map" +geo_map = Id.Builtin "Geo Map" ## UNSTABLE ADVANCED An identifier for the builtin Image visualization image : Id -image = Builtin "Image" +image = Id.Builtin "Image" ## UNSTABLE ADVANCED @@ -97,7 +94,7 @@ image = Builtin "Image" example_id = Visualization.Id.from_module Base "My Visualization" from_module module visualization_name = - Library module.enso_project visualization_name + Id.Library module.enso_project visualization_name ## UNSTABLE ADVANCED diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso index 1857d0c13c6..c4f1b376dd1 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso @@ -1,8 +1,8 @@ from Standard.Base import all -import Standard.Visualization.File_Upload -import Standard.Visualization.Id -import Standard.Visualization.Preprocessor +import project.File_Upload +import project.Id +import project.Preprocessor -from Standard.Visualization.File_Upload export file_uploading -export Standard.Visualization.Id +from project.File_Upload export file_uploading +export project.Id diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/SQL/Visualization.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/SQL/Visualization.enso index a5dd182a171..d4ac72f8ea6 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/SQL/Visualization.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/SQL/Visualization.enso @@ -1,7 +1,8 @@ from Standard.Base import all -from Standard.Database.Data.SQL import SQL_Type -import Standard.Visualization.Helpers +import Standard.Database.Data.SQL_Type.SQL_Type + +import project.Helpers ## PRIVATE diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Scatter_Plot.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Scatter_Plot.enso index b03652ba092..9ee2654ff0e 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Scatter_Plot.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Scatter_Plot.enso @@ -1,9 +1,9 @@ from Standard.Base import all +from Standard.Base.Data.Index_Sub_Range import Sample from Standard.Table import Table, Column -import Standard.Visualization.Helpers -from Standard.Base.Data.Index_Sub_Range import Sample +import project.Helpers ## PRIVATE @@ -23,10 +23,6 @@ axis_field = 'axis' label_field : Text label_field = 'label' -# TODO Dubious constructor export -from project.Scatter_Plot.Point_Data import all -from project.Scatter_Plot.Point_Data export all - ## PRIVATE Represents a recognized point data field for a scatter plot visualization. @@ -54,7 +50,7 @@ type Point_Data Returns all recognized point data fields. all_fields : Vector - all_fields = [X,Y,Color,Shape,Label,Size] + all_fields = [Point_Data.X, Point_Data.Y, Point_Data.Color, Point_Data.Shape, Point_Data.Label, Point_Data.Size] ## PRIVATE recognized_names : Vector @@ -71,9 +67,9 @@ type Point_Data ## PRIVATE fallback_column : Table -> Column ! No_Fallback_Column fallback_column self table = case self of - X -> table.index.catch_ <| Point_Data.iota table.row_count - Y -> - x_column = X.lookup_in table + Point_Data.X -> table.index.catch_ <| Point_Data.iota table.row_count + Point_Data.Y -> + x_column = Point_Data.X.lookup_in table candidates = table.all_columns is_good_enough c = c.is_numeric && c.name != x_column.name is_good c = is_good_enough c && (self.is_recognized c).not @@ -124,8 +120,8 @@ Table.axes self = col_name = field.lookup_in self . name label = Json.from_pairs [[label_field, col_name]] [field.name, label] - x_axis = describe_axis X - y_axis = describe_axis Y + x_axis = describe_axis Point_Data.X + y_axis = describe_axis Point_Data.Y is_valid axis_pair = label = axis_pair.at 1 label.is_valid && (self.all_columns.length > 0) @@ -136,7 +132,7 @@ Table.axes self = Vector.Vector.point_data : Vector -> Object Vector.Vector.point_data self = self.map_with_index <| i-> elem-> - Json.from_pairs [[X.name,i],[Y.name,elem]] + Json.from_pairs [[Point_Data.X.name, i], [Point_Data.Y.name, elem]] ## PRIVATE bound_data bounds data = case bounds of @@ -153,12 +149,8 @@ bound_data bounds data = case bounds of min_x<=x && x<=max_x && min_y<=y && y<=max_y -# TODO Dubious constructor export -from project.Scatter_Plot.Extreme import all -from project.Scatter_Plot.Extreme export all - type Extreme - Extreme_Data min_x max_x min_y max_y + Value min_x max_x min_y max_y ## PRIVATE limit_data limit data = case limit of @@ -172,11 +164,11 @@ limit_data limit data = case limit of new_min_y = if y current.min_y.second > y point then [idx, point] else current.min_y new_max_x = if x current.max_x.second < x point then [idx, point] else current.max_x new_max_y = if y current.max_y.second < y point then [idx, point] else current.max_y - Extreme_Data new_min_x new_max_x new_min_y new_max_y + Extreme.Value new_min_x new_max_x new_min_y new_max_y first = [0, data.first] - bounds = case data.fold_with_index (Extreme_Data first first first first) update_extreme of - Extreme_Data min_x max_x min_y max_y -> [min_x, max_x, min_y, max_y] + bounds = case data.fold_with_index (Extreme.Value first first first first) update_extreme of + Extreme.Value min_x max_x min_y max_y -> [min_x, max_x, min_y, max_y] _ -> [] extreme = Map.from_vector bounds . values @@ -199,9 +191,9 @@ json_from_vector vec bounds limit = ## PRIVATE - Default preprocessor for the scatterplot visualization. + Default preprocessor for the scatter-plot visualization. - Generates JSON text describing the scatterplot visualization. + Generates JSON text describing the scatter-plot visualization. Arguments: - value: the value to be visualized. @@ -214,4 +206,3 @@ process_to_json_text value bounds=Nothing limit=Nothing = _ -> json_from_vector value.to_vector bounds limit json.to_text - diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso index 5b061743a33..dadbb51837e 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso @@ -7,7 +7,7 @@ import Standard.Database.Data.Column.Column as Database_Column import Standard.Table.Data.Column_Selector.Column_Selector -import Standard.Visualization.Helpers +import project.Helpers # TODO add an initial offset to fully support lazy visualizations @@ -22,7 +22,7 @@ import Standard.Visualization.Helpers In case of Database backed data, it materializes a fragment of the data. prepare_visualization : Any -> Integer -> Json prepare_visualization x max_rows=1000 = Helpers.recover_errors <| case x of - Dataframe_Table.Table_Data _ -> + _ : Dataframe_Table -> dataframe = x.take (First max_rows) all_rows_count = x.row_count included_rows = dataframe.row_count @@ -30,7 +30,7 @@ prepare_visualization x max_rows=1000 = Helpers.recover_errors <| case x of Dataframe_Column.from_vector "" (Vector.new included_rows i->i) make_json dataframe [index] all_rows_count - Database_Table.Table_Data _ _ _ _ -> + _ : Database_Table -> # Materialize a table with indices as normal columns (because dataframe does not support multi-indexing). df = x.reset_index.read max_rows # Then split into actual columns and indices. @@ -40,9 +40,9 @@ prepare_visualization x max_rows=1000 = Helpers.recover_errors <| case x of make_json vis_df indices all_rows_count # We display columns as 1-column tables. - Dataframe_Column.Column_Data _ -> + _ : Dataframe_Column -> prepare_visualization x.to_table max_rows - Database_Column.Column_Data _ _ _ _ _ -> + _ : Database_Column -> prepare_visualization x.to_table max_rows # TODO [RW] Should we truncate Vectors? diff --git a/test/Table_Tests/src/Column_Spec.enso b/test/Table_Tests/src/Column_Spec.enso index be8ef57463a..94504c6eae7 100644 --- a/test/Table_Tests/src/Column_Spec.enso +++ b/test/Table_Tests/src/Column_Spec.enso @@ -1,6 +1,6 @@ from Standard.Base import all from Standard.Table import Column -import Standard.Table.Data.Column as Column_Module +import Standard.Table.Data.Column.Empty_Error import Standard.Table.Data.Storage.Storage import Standard.Examples @@ -13,14 +13,14 @@ spec = Test.group "Columns" <| empty_column = Column.from_vector "Test" [] Test.specify "should correctly map storage types" <| - Column_Module.storage_types.at Java_Storage.Type.LONG . should_equal Storage.Integer - Column_Module.storage_types.at Java_Storage.Type.DOUBLE . should_equal Storage.Decimal - Column_Module.storage_types.at Java_Storage.Type.STRING . should_equal Storage.Text - Column_Module.storage_types.at Java_Storage.Type.BOOL . should_equal Storage.Boolean - Column_Module.storage_types.at Java_Storage.Type.OBJECT . should_equal Storage.Any - Column_Module.storage_types.at Java_Storage.Type.DATE . should_equal Storage.Date - Column_Module.storage_types.at Java_Storage.Type.TIME_OF_DAY . should_equal Storage.Time_Of_Day - Column_Module.storage_types.at Java_Storage.Type.DATE_TIME . should_equal Storage.Date_Time + Storage.types.at Java_Storage.Type.LONG . should_equal Storage.Integer + Storage.types.at Java_Storage.Type.DOUBLE . should_equal Storage.Decimal + Storage.types.at Java_Storage.Type.STRING . should_equal Storage.Text + Storage.types.at Java_Storage.Type.BOOL . should_equal Storage.Boolean + Storage.types.at Java_Storage.Type.OBJECT . should_equal Storage.Any + Storage.types.at Java_Storage.Type.DATE . should_equal Storage.Date + Storage.types.at Java_Storage.Type.TIME_OF_DAY . should_equal Storage.Time_Of_Day + Storage.types.at Java_Storage.Type.DATE_TIME . should_equal Storage.Date_Time Test.specify "should allow getting specific elements" <| test_column.at 0 . should_equal 1 @@ -48,12 +48,12 @@ spec = Test.group "Columns" <| Test.specify "should be able to get the first / head element" <| test_column.first . should_equal 1 test_column.head . should_equal 1 - empty_column.first.should_fail_with Column_Module.Empty_Error - empty_column.head.should_fail_with Column_Module.Empty_Error + empty_column.first.should_fail_with Empty_Error + empty_column.head.should_fail_with Empty_Error Test.specify "should be able to get the last element" <| test_column.last . should_equal 6 - empty_column.last.should_fail_with Column_Module.Empty_Error + empty_column.last.should_fail_with Empty_Error Test.specify "should be able to be reversed" <| expected_1 = Column.from_vector "Test" [6, 4, 2, 5, 3, 1] diff --git a/test/Table_Tests/src/Database/Codegen_Spec.enso b/test/Table_Tests/src/Database/Codegen_Spec.enso index aa8260e91f4..9d2bda76e2a 100644 --- a/test/Table_Tests/src/Database/Codegen_Spec.enso +++ b/test/Table_Tests/src/Database/Codegen_Spec.enso @@ -5,8 +5,8 @@ from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all from Standard.Table.Errors import No_Input_Columns_Selected, Missing_Input_Columns_Data, No_Such_Column_Error_Data from Standard.Database import all -from Standard.Database.Data.SQL import SQL_Type import Standard.Database.Data.Dialect +import Standard.Database.Data.SQL_Type.SQL_Type from Standard.Database.Data.Table import combine_names, fresh_names from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data @@ -25,7 +25,7 @@ spec = table3 = ["T3", [["A", int], ["E", bool], ["F", int]]] tables = Map.from_vector [table1, table2, table3] Fake_Test_Connection.make Dialect.sqlite tables - t1 = test_connection.query (Table_Name "T1") + t1 = test_connection.query (SQL_Query.Table_Name "T1") Test.group "[Codegen] JSON serialization" <| Test.specify "should serialize Tables and Columns to their SQL representation" <| q1 = t1.filter (t1.at "A" == 42) . to_json @@ -99,8 +99,8 @@ spec = c2.to_sql.prepare . should_equal ['SELECT "T1"."B" AS "B" FROM "T1" AS "T1" WHERE ("T1"."A" = "T1"."C")', []] Test.group "[Codegen] Joining Tables" <| - t2 = test_connection.query (Table_Name "T2") - t3 = test_connection.query (Table_Name "T3") + t2 = test_connection.query (SQL_Query.Table_Name "T2") + t3 = test_connection.query (SQL_Query.Table_Name "T3") Test.specify "should allow joining tables index-on-index" <| r1 = t1.set_index 'A' . join (t2.set_index 'D') r1.to_sql.prepare . should_equal ['SELECT "T1"."B" AS "B", "T1"."C" AS "C", "T2"."E" AS "E", "T2"."F" AS "F" FROM (SELECT "T1"."B" AS "B", "T1"."C" AS "C", "T1"."A" AS "A", "T1"."A" AS "A_1" FROM "T1" AS "T1") AS "T1" LEFT JOIN (SELECT "T2"."E" AS "E", "T2"."F" AS "F", "T2"."D" AS "D" FROM "T2" AS "T2") AS "T2" ON ("T1"."A_1" = "T2"."D")', []] @@ -123,8 +123,8 @@ spec = table2 = ["T2", [["X", int], ["A", int], ["B", int]]] tables = Map.from_vector [table1, table2] Fake_Test_Connection.make Dialect.sqlite tables - t1 = connection.query (Table_Name "T1") - t2 = connection.query (Table_Name "T2") + t1 = connection.query (SQL_Query.Table_Name "T1") + t2 = connection.query (SQL_Query.Table_Name "T2") (t1.set_index "X").join (t2.set_index "X") . should_fail_with Illegal_State_Error_Data Test.specify "should ensure that name suffixes are distinct" <| diff --git a/test/Table_Tests/src/Database/Helpers/Fake_Test_Connection.enso b/test/Table_Tests/src/Database/Helpers/Fake_Test_Connection.enso index cb6dbd4b8da..f75f6a94cca 100644 --- a/test/Table_Tests/src/Database/Helpers/Fake_Test_Connection.enso +++ b/test/Table_Tests/src/Database/Helpers/Fake_Test_Connection.enso @@ -1,10 +1,11 @@ from Standard.Base import all -import Standard.Table.Data.Table as Materialized_Table -from Standard.Database import SQL_Query, Raw_SQL, Table_Name +import Standard.Table.Data.Table.Table as Materialized_Table +from Standard.Database import SQL_Query import Standard.Database.Data.Table as Database_Table -from Standard.Database.Data.SQL import Statement, SQL_Type -import Standard.Database.Internal.IR +import Standard.Database.Data.SQL_Statement.SQL_Statement +import Standard.Database.Data.SQL_Type.SQL_Type +import Standard.Database.Internal.IR.Context.Context type Fake_Test_Connection # type Fake_Test_Connection.Value (tables : Map Text (Vector [Text, SQL_Type])) (dialect : Text) @@ -16,14 +17,14 @@ type Fake_Test_Connection - query: name of the table or sql statement to query. If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - alias: optionally specify a friendly alias for the query. - query : Text | SQL_Query -> Text -> Database_Table + query : Text | SQL_Query -> Text -> Database_Table.Table query self query alias="" = case query of - Text -> self.query (Table_Name query) alias - Raw_SQL _ -> + Text -> self.query (SQL_Query.Table_Name query) alias + SQL_Query.Raw_SQL _ -> Error.throw (Illegal_Argument_Error "Cannot query a fake connection with raw SQL") - Table_Name name -> + SQL_Query.Table_Name name -> columns = self.tables.get name - Database_Table.make_table self name columns (IR.context_for_table name) + Database_Table.make_table self name columns (Context.for_table name) ## Execute the query and load the results into memory as a Table. @@ -32,7 +33,7 @@ type Fake_Test_Connection If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query. - alias: optionally specify a friendly alias for the query. - limit: the maximum number of rows to return (default 1000). - read : Text | SQL_Query -> Text -> Integer | Nothing -> Materialized_Table.Table + read : Text | SQL_Query -> Text -> Integer | Nothing -> Materialized_Table read self _ _="" _=Nothing = Error.throw "Materialization not supported on fake connection." @@ -41,7 +42,7 @@ type Fake_Test_Connection close self = Nothing ## PRIVATE - execute_update : Text | Statement -> Integer + execute_update : Text | SQL_Statement -> Integer execute_update self _ = Error.throw "Materialization not supported on fake connection." diff --git a/test/Table_Tests/src/Database/Postgres_Spec.enso b/test/Table_Tests/src/Database/Postgres_Spec.enso index 3c8365175da..cbff943f1d2 100644 --- a/test/Table_Tests/src/Database/Postgres_Spec.enso +++ b/test/Table_Tests/src/Database/Postgres_Spec.enso @@ -7,11 +7,10 @@ from Standard.Base.System.Process.Exit_Code import Exit_Success from Standard.Table import Table from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all hiding First -import Standard.Database -from Standard.Database import all +from Standard.Database import Database, Postgres, SQL_Query, Credentials, SSL_Mode from Standard.Database.Errors import SQL_Error -from Standard.Database.Data.SQL import SQL_Type -from Standard.Database.Internal.Postgres.Pgpass import Pgpass_Entry_Data +import Standard.Database.Data.SQL_Type.SQL_Type + import Standard.Database.Internal.Postgres.Pgpass import Standard.Test @@ -39,14 +38,14 @@ postgres_specific_spec connection db_name pending = Test.specify "should allow changing schema" <| new_connection = connection.set_schema "information_schema" - new_schema = new_connection.read (Raw_SQL "SELECT current_schema()") . at 0 . to_vector . first + new_schema = new_connection.read (SQL_Query.Raw_SQL "SELECT current_schema()") . at 0 . to_vector . first new_schema . should_equal "information_schema" databases = connection.databases.filter d->((d!=db_name) && (d!='rdsadmin')) pending_database = if databases.length != 0 then Nothing else "Cannot tests changing database unless two databases defined." Test.specify "should allow changing database" pending=pending_database <| new_connection = connection.set_database databases.first - new_database = new_connection.read (Raw_SQL "SELECT current_database()") . at 0 . to_vector . first + new_database = new_connection.read (SQL_Query.Raw_SQL "SELECT current_database()") . at 0 . to_vector . first new_database . should_equal databases.first Test.group "[PostgreSQL] Tables and Table Types" <| @@ -91,7 +90,7 @@ postgres_specific_spec connection db_name pending = Test.group "[PostgreSQL] Info" pending=pending <| tinfo = Name_Generator.random_name "Tinfo" connection.execute_update 'CREATE TEMPORARY TABLE "'+tinfo+'" ("strs" VARCHAR, "ints" INTEGER, "bools" BOOLEAN, "reals" REAL, "doubles" DOUBLE PRECISION)' - t = connection.query (Table_Name tinfo) + t = connection.query (SQL_Query.Table_Name tinfo) t.insert ["a", Nothing, False, 1.2, 0.000000000001] t.insert ["abc", Nothing, Nothing, 1.3, Nothing] t.insert ["def", 42, True, 1.4, 10] @@ -118,7 +117,7 @@ postgres_specific_spec connection db_name pending = Test.group "[PostgreSQL] Table.aggregate should correctly infer result types" pending=pending <| name = Name_Generator.random_name "Ttypes" connection.execute_update 'CREATE TEMPORARY TABLE "'+name+'" ("txt" VARCHAR, "i1" SMALLINT, "i2" INT, "i3" BIGINT, "i4" NUMERIC, "r1" REAL, "r2" DOUBLE PRECISION, "bools" BOOLEAN)' - t = connection.query (Table_Name name) + t = connection.query (SQL_Query.Table_Name name) Test.specify "Concatenate, Shortest and Longest" <| r = t.aggregate [Concatenate "txt", Shortest "txt", Longest "txt"] r.columns.at 0 . sql_type . should_equal SQL_Type.text @@ -198,27 +197,27 @@ table_spec = ssl_pending = if ca_cert_file.is_nothing then "PostgreSQL SSL test not configured." else Nothing Test.group "[PostgreSQL] SSL connectivity tests" pending=ssl_pending <| Test.specify "should connect without ssl parameter" <| - Database.connect (Postgres db_host db_port db_name credentials=(Username_And_Password db_user db_password)) . should_succeed + Database.connect (Postgres db_host db_port db_name credentials=(Credentials.Username_And_Password db_user db_password)) . should_succeed Test.specify "should connect, requiring SSL" <| - Database.connect (Postgres db_host db_port db_name credentials=(Username_And_Password db_user db_password) use_ssl=SSL_Mode.Require) . should_succeed + Database.connect (Postgres db_host db_port db_name credentials=(Credentials.Username_And_Password db_user db_password) use_ssl=SSL_Mode.Require) . should_succeed Test.specify "should connect be able to verify the certificate" <| - Database.connect (Postgres db_host db_port db_name credentials=(Username_And_Password db_user db_password) use_ssl=(SSL_Mode.Verify_CA ca_cert_file)) . should_succeed + Database.connect (Postgres db_host db_port db_name credentials=(Credentials.Username_And_Password db_user db_password) use_ssl=(SSL_Mode.Verify_CA ca_cert_file)) . should_succeed ## Default certificate should not accept the self signed certificate. - ca_fail = Database.connect (Postgres db_host db_port db_name credentials=(Username_And_Password db_user db_password) use_ssl=SSL_Mode.Verify_CA) + ca_fail = Database.connect (Postgres db_host db_port db_name credentials=(Credentials.Username_And_Password db_user db_password) use_ssl=SSL_Mode.Verify_CA) ca_fail.is_error . should_equal True ca_fail.catch SQL_Error . is_a SQL_Error . should_equal True Test.specify "should connect be able to verify the host name against the certificate" <| - Database.connect (Postgres db_host db_port db_name credentials=(Username_And_Password db_user db_password) use_ssl=(SSL_Mode.Full_Verification ca_cert_file)) . should_succeed + Database.connect (Postgres db_host db_port db_name credentials=(Credentials.Username_And_Password db_user db_password) use_ssl=(SSL_Mode.Full_Verification ca_cert_file)) . should_succeed alternate_host = Environment.get "ENSO_DATABASE_TEST_ALTERNATE_HOST" . if_nothing <| if db_host == "127.0.0.1" then "localhost" else Nothing pending_alternate = if alternate_host.is_nothing then "Alternative host name not configured." else Nothing Test.specify "should fail to connect with alternate host name not valid in certificate" pending=pending_alternate <| - ca_fail = Database.connect (Postgres alternate_host db_port db_name credentials=(Username_And_Password db_user db_password) use_ssl=(SSL_Mode.Full_Verification ca_cert_file)) + ca_fail = Database.connect (Postgres alternate_host db_port db_name credentials=(Credentials.Username_And_Password db_user db_password) use_ssl=(SSL_Mode.Full_Verification ca_cert_file)) ca_fail.is_error . should_equal True ca_fail.catch SQL_Error . is_a SQL_Error . should_equal True @@ -228,7 +227,7 @@ table_spec = connection = Error.throw message run_tests connection pending=message False -> - connection = Database.connect (Postgres (db_host_port.at 0) db_port db_name credentials=(Username_And_Password db_user db_password)) + connection = Database.connect (Postgres (db_host_port.at 0) db_port db_name credentials=(Credentials.Username_And_Password db_user db_password)) run_tests connection db_name @@ -240,18 +239,18 @@ pgpass_spec = Test.group "[PostgreSQL] .pgpass" <| Test.specify "should correctly parse the file, including escapes, blank lines and comments" <| result = Pgpass.parse_file pgpass_file result.length . should_equal 12 - e1 = Pgpass_Entry_Data "localhost" "5432" "postgres" "postgres" "postgres" - e2 = Pgpass_Entry_Data "192.168.4.0" "1234" "foo" "bar" "baz" - e3 = Pgpass_Entry_Data "host with : semicolons in it? what?" "*" "*" "*" "well yes, that is possible, the :password: can contain those as well" - e4 = Pgpass_Entry_Data ":" ":" ":" ":" ":" - e5 = Pgpass_Entry_Data "you can escape an escape too: see \\" "*" "*" "*" "yes it is possible" - e6 = Pgpass_Entry_Data "other escapes like \n or \? " "*" "*" "*" "are just parsed as-is" - e7 = Pgpass_Entry_Data "a trailing escape character" "*" "*" "*" "is treated as a regular slash\" - e8 = Pgpass_Entry_Data "passwords should preserve leading space" "*" "*" "*" " pass" - e9 = Pgpass_Entry_Data "\:" "*" "*" "*" "\:" - e10 = Pgpass_Entry_Data "::1" "*" "database_name" "user_that_has_no_password" "" - e11 = Pgpass_Entry_Data "*" "*" "*" "*" "fallback_password" - e12 = Pgpass_Entry_Data "order_matters" "1234" "this" "will_still_match_the_fallback_password" "not_this_one" + e1 = Pgpass.Pgpass_Entry.Value "localhost" "5432" "postgres" "postgres" "postgres" + e2 = Pgpass.Pgpass_Entry.Value "192.168.4.0" "1234" "foo" "bar" "baz" + e3 = Pgpass.Pgpass_Entry.Value "host with : semicolons in it? what?" "*" "*" "*" "well yes, that is possible, the :password: can contain those as well" + e4 = Pgpass.Pgpass_Entry.Value ":" ":" ":" ":" ":" + e5 = Pgpass.Pgpass_Entry.Value "you can escape an escape too: see \\" "*" "*" "*" "yes it is possible" + e6 = Pgpass.Pgpass_Entry.Value "other escapes like \n or \? " "*" "*" "*" "are just parsed as-is" + e7 = Pgpass.Pgpass_Entry.Value "a trailing escape character" "*" "*" "*" "is treated as a regular slash\" + e8 = Pgpass.Pgpass_Entry.Value "passwords should preserve leading space" "*" "*" "*" " pass" + e9 = Pgpass.Pgpass_Entry.Value "\:" "*" "*" "*" "\:" + e10 = Pgpass.Pgpass_Entry.Value "::1" "*" "database_name" "user_that_has_no_password" "" + e11 = Pgpass.Pgpass_Entry.Value "*" "*" "*" "*" "fallback_password" + e12 = Pgpass.Pgpass_Entry.Value "order_matters" "1234" "this" "will_still_match_the_fallback_password" "not_this_one" entries = [e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12] result.should_equal entries @@ -313,7 +312,7 @@ connection_setup_spec = Test.group "[PostgreSQL] Connection setup" <| add_ssl props = props+[Pair_Data 'sslmode' 'prefer'] Test.specify "should use the given credentials" <| - c = Postgres credentials=(Username_And_Password "myuser" "mypass") + c = Postgres credentials=(Credentials.Username_And_Password "myuser" "mypass") c.jdbc_url . should_equal "jdbc:postgresql://localhost:5432" c.jdbc_properties . should_equal <| add_ssl [Pair_Data "user" "myuser", Pair_Data "password" "mypass"] diff --git a/test/Table_Tests/src/Database/Redshift_Spec.enso b/test/Table_Tests/src/Database/Redshift_Spec.enso index 6953ef9d663..ef16e19f5ca 100644 --- a/test/Table_Tests/src/Database/Redshift_Spec.enso +++ b/test/Table_Tests/src/Database/Redshift_Spec.enso @@ -3,8 +3,7 @@ import Standard.Base.Runtime.Ref from Standard.Table import Table -import Standard.Database -from Standard.Database import all +from Standard.Database import Database, Redshift, AWS_Credential, SQL_Query import Standard.Test @@ -17,7 +16,7 @@ redshift_specific_spec connection pending = Test.group "[Redshift] Info" pending=pending <| tinfo = Name_Generator.random_name "Tinfo" connection.execute_update 'CREATE TEMPORARY TABLE "'+tinfo+'" ("strs" VARCHAR, "ints" INTEGER, "bools" BOOLEAN, "reals" REAL)' - t = connection.query (Table_Name tinfo) + t = connection.query (SQL_Query.Table_Name tinfo) t.insert ["a", Nothing, False, 1.2] t.insert ["abc", Nothing, Nothing, 1.3] t.insert ["def", 42, True, 1.4] @@ -82,7 +81,7 @@ connect_via_json_config = db_name = uri.at 2 user = creds.get 'db_user' - Redshift db_uri db_port db_name credentials=(AWS_Key user access_key secret_key) + Redshift db_uri db_port db_name credentials=(AWS_Credential.Key user access_key secret_key) connect_via_aws_environment db_host_port = db_host_port_split = uri_parse db_host_port @@ -94,8 +93,8 @@ connect_via_aws_environment db_host_port = access_key = Environment.get "AWS_ACCESS_KEY_ID" secret_key = Environment.get "AWS_SECRET_ACCESS_KEY" - credentials = if (access_key.is_nothing || secret_key.is_nothing) then AWS_Profile db_user (Environment.get "AWS_PROFILE" . if_nothing '') else - AWS_Key db_user access_key secret_key + credentials = if (access_key.is_nothing || secret_key.is_nothing) then AWS_Credential.Profile db_user (Environment.get "AWS_PROFILE" . if_nothing '') else + AWS_Credential.Key db_user access_key secret_key Redshift db_uri db_port db_name credentials=credentials diff --git a/test/Table_Tests/src/Database/SQLite_Spec.enso b/test/Table_Tests/src/Database/SQLite_Spec.enso index 9bfe2c14a3d..ac3dfbeda9b 100644 --- a/test/Table_Tests/src/Database/SQLite_Spec.enso +++ b/test/Table_Tests/src/Database/SQLite_Spec.enso @@ -3,8 +3,7 @@ import Standard.Base.Runtime.Ref from Standard.Table import Table -import Standard.Database -from Standard.Database import all +from Standard.Database import Database, SQLite, In_Memory, SQL_Query from Standard.Database.Errors import SQL_Error_Data import Standard.Test @@ -67,17 +66,17 @@ sqlite_specific_spec connection = Test.group "[SQLite] Error Handling" <| Test.specify "should wrap errors" <| - connection.read (Raw_SQL "foobar") . should_fail_with SQL_Error_Data + connection.read (SQL_Query.Raw_SQL "foobar") . should_fail_with SQL_Error_Data connection.execute_update "foobar" . should_fail_with SQL_Error_Data - action = connection.read (Raw_SQL "SELECT A FROM undefined_table") + action = connection.read (SQL_Query.Raw_SQL "SELECT A FROM undefined_table") action . should_fail_with SQL_Error_Data action.catch.to_text . should_equal "There was an SQL error: '[SQLITE_ERROR] SQL error or missing database (no such table: undefined_table)'. [Query was: SELECT A FROM undefined_table]" Test.group "[SQLite] Metadata" <| tinfo = Name_Generator.random_name "Tinfo" connection.execute_update 'CREATE TABLE "'+tinfo+'" ("strs" VARCHAR, "ints" INTEGER, "bools" BOOLEAN, "reals" REAL)' - t = connection.query (Table_Name tinfo) + t = connection.query (SQL_Query.Table_Name tinfo) t.insert ["a", Nothing, False, 1.2] t.insert ["abc", Nothing, Nothing, 1.3] t.insert ["def", 42, True, 1.4] diff --git a/test/Visualization_Tests/src/SQL_Spec.enso b/test/Visualization_Tests/src/SQL_Spec.enso index bf336748fae..48081156aa2 100644 --- a/test/Visualization_Tests/src/SQL_Spec.enso +++ b/test/Visualization_Tests/src/SQL_Spec.enso @@ -1,7 +1,6 @@ from Standard.Base import all -from Standard.Database import all -import Standard.Database +from Standard.Database import Database, SQLite, SQL_Query import Standard.Visualization.SQL.Visualization as Visualization @@ -9,7 +8,7 @@ import Standard.Test visualization_spec connection = connection.execute_update 'CREATE TABLE "T" ("A" VARCHAR, "B" INTEGER, "C" INTEGER)' - t = connection.query (Table_Name "T") + t = connection.query (SQL_Query.Table_Name "T") Test.group "SQL Visualization" <| Test.specify "should provide type metadata for interpolations" <| q = t.filter ((t.at "B" == 2) && (t.at "A" == True)) . at "C" diff --git a/test/Visualization_Tests/src/Table_Spec.enso b/test/Visualization_Tests/src/Table_Spec.enso index 5c11010f5f1..5843ed753ca 100644 --- a/test/Visualization_Tests/src/Table_Spec.enso +++ b/test/Visualization_Tests/src/Table_Spec.enso @@ -3,7 +3,7 @@ from Standard.Base import all from Standard.Table import Table, Aggregate_Column from Standard.Database import SQLite -import Standard.Database +from Standard.Database import Database import Standard.Database.Data.Table.Table as Database_Table import Standard.Visualization.Table.Visualization as Visualization @@ -32,7 +32,7 @@ visualization_spec connection = Test.group "Table Visualization" <| Test.specify "should wrap internal errors" <| - bad_table = Database_Table.Table_Data Nothing Nothing Nothing Nothing + bad_table = Database_Table.Value Nothing Nothing Nothing Nothing vis = Visualization.prepare_visualization bad_table 2 json = Json.from_pairs [["error", "Method `meta_index` of Nothing could not be found."]] vis . should_equal json.to_text diff --git a/test/Visualization_Tests/src/Visualization_Spec.enso b/test/Visualization_Tests/src/Visualization_Spec.enso index c9288b180a5..48c005acebd 100644 --- a/test/Visualization_Tests/src/Visualization_Spec.enso +++ b/test/Visualization_Tests/src/Visualization_Spec.enso @@ -6,11 +6,11 @@ import Standard.Visualization import Standard.Test -from Standard.Visualization.File_Upload import File_Being_Uploaded_Data +import Standard.Visualization.File_Upload.File_Being_Uploaded spec = Test.group "File uploads" <| Test.specify "should be able to be signalled as uploading" <| - Visualization.file_uploading "file" . should_fail_with File_Being_Uploaded_Data + Visualization.file_uploading "file" . should_fail_with File_Being_Uploaded.Value Test.specify "should work whether a textual or file path is provided" <| result_file = Visualization.file_uploading Examples.csv . catch @@ -18,5 +18,3 @@ spec = Test.group "File uploads" <| result_text = Visualization.file_uploading Examples.csv_path . catch result_text.file_path . should_equal Examples.csv_path - -