diff --git a/distribution/std-lib/Database/src/Connection/Connection.enso b/distribution/std-lib/Database/src/Connection/Connection.enso index 590e7105d6367..adec0b29fa423 100644 --- a/distribution/std-lib/Database/src/Connection/Connection.enso +++ b/distribution/std-lib/Database/src/Connection/Connection.enso @@ -108,7 +108,7 @@ type JDBC_Connection _ -> Error.throw err ## PRIVATE - prepare_statement : Text | Sql.Statement -> Prepared_Statement + prepare_statement : Text | Sql.Statement -> PreparedStatement prepare_statement query = go template holes=[] = Managed_Resource.with this.connection_resource java_connection-> stmt = java_connection.prepareStatement template @@ -129,6 +129,9 @@ type JDBC_Connection go compiled.first compiled.second ## PRIVATE + + A helper function that fetches column names and sql types associated with + them for a table in the database. # fetch_columns : Text -> Vector [Text, Sql_Type] fetch_columns table_name = query = IR.Select_All (IR.make_ctx_from table_name) @@ -163,6 +166,8 @@ create_jdbc_connection url user=Nothing password=Nothing = here.wrap_sql_errors JDBC_Connection resource dialect ## PRIVATE + + This cannot be a closure due to limitations of Managed_Resource. close_connection connection = connection.close @@ -198,6 +203,9 @@ type Sql_Timeout_Error to_display_text = this.to_text ## PRIVATE + + Executes `action` and returns its result, catching any panics and if they are + coming from JDBC, wraps them with our own error types. wrap_sql_errors ~action = result = Panic.recover action result.catch err-> case err of diff --git a/distribution/std-lib/Database/src/Connection/Database.enso b/distribution/std-lib/Database/src/Connection/Database.enso index 960f1f7525fa8..01f7c43e87b34 100644 --- a/distribution/std-lib/Database/src/Connection/Database.enso +++ b/distribution/std-lib/Database/src/Connection/Database.enso @@ -1,11 +1,30 @@ from Base import all -import Database.Connection.Connection +from Database.Connection.Connection import all -connect : Text -> Nothing | Text -> Nothing | Text -> JDBC_Connection +## UNSTABLE + + Tries to connect to the database under a provided URL. + + Currently only SQLite databases are supported. + ## TODO [RW] finalize Postgres support + + Arguments: + - url: the URL to connect to, starting with `jdbc:...`. + - user: (optional) an username for authentication. + - password: (optional) a password for authentication. +connect : Text -> Nothing | Text -> Nothing | Text -> JDBC_Connection ! Sql_Error connect url user=Nothing password=Nothing = Connection.create_jdbc_connection url user password -open_sqlite_file : File -> Connection +## UNSTABLE + + Connects to an SQLite database in a file on the filesystem. + + It is an alternative to `connect` that resolves a path to the database file. + + Arguments: + - file: the path to the database. +open_sqlite_file : File -> JDBC_Connection ! Sql_Error open_sqlite_file file = url = "jdbc:sqlite:" + file.absolute.path here.connect url diff --git a/distribution/std-lib/Database/src/Data/Dialect.enso b/distribution/std-lib/Database/src/Data/Dialect.enso index e3ef5737be48e..ba1b7d9e3170e 100644 --- a/distribution/std-lib/Database/src/Data/Dialect.enso +++ b/distribution/std-lib/Database/src/Data/Dialect.enso @@ -96,5 +96,6 @@ sqlite = dialect = Base_Generator.base_dialect . extend_with my_mappings Dialect "sqlite" (query -> Base_Generator.generate_query dialect query . build) +## PRIVATE supported_dialects : Vector Dialect supported_dialects = [here.postgresql, here.sqlite] diff --git a/distribution/std-lib/Database/src/Data/Internal/Base_Generator.enso b/distribution/std-lib/Database/src/Data/Internal/Base_Generator.enso index 032d8a4d0a815..03feefd50c5d4 100644 --- a/distribution/std-lib/Database/src/Data/Internal/Base_Generator.enso +++ b/distribution/std-lib/Database/src/Data/Internal/Base_Generator.enso @@ -127,6 +127,10 @@ generate_expression dialect expr = case expr of parsed_args = arguments.map (here.generate_expression dialect) op parsed_args +## PRIVATE + + Adds an alias for the expression, applicable for expressions that represent + columns or sub-queries. alias : Internal_Dialect -> Text -> Sql.Builder alias dialect name = wrapped = dialect.wrap_identifier name diff --git a/distribution/std-lib/Database/src/Data/Internal/IR.enso b/distribution/std-lib/Database/src/Data/Internal/IR.enso index b460e7ab07bb0..00bc30118f9d2 100644 --- a/distribution/std-lib/Database/src/Data/Internal/IR.enso +++ b/distribution/std-lib/Database/src/Data/Internal/IR.enso @@ -304,6 +304,10 @@ substitute_origin old_origin new_origin expr = case expr of Operation kind (exprs.map (here.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. lift_expression_map : (Expression -> Expression) -> Internal_Column -> Internal_Column lift_expression_map f col = Internal_Column col.name col.sql_type (f col.expression) diff --git a/distribution/std-lib/Database/src/Data/Table.enso b/distribution/std-lib/Database/src/Data/Table.enso index d99320fcbdfd5..12895bd892437 100644 --- a/distribution/std-lib/Database/src/Data/Table.enso +++ b/distribution/std-lib/Database/src/Data/Table.enso @@ -411,6 +411,8 @@ type Table table.set_index ix_col_name ## PRIVATE + + Brings the index back as columns. reset_index : Table reset_index = new_cols = this.internal_columns_with_index @@ -458,6 +460,9 @@ type Table updated_context ctx = Table this.name this.connection this.internal_columns ctx ## PRIVATE + + Returns a vector that contains first the internal representations of all + indices and then all columns. internal_columns_with_index : Vector Internal_Column internal_columns_with_index = this.context.meta_index + this.internal_columns @@ -547,6 +552,22 @@ make_table connection table_name columns = cols = columns.map (p -> Internal_Column p.first p.second (IR.Column table_name p.first)) Table table_name connection cols ctx +## PRIVATE + + Renders an ASCII-art representation for a Table from a dataframe that + contains a fragment of the underlying data and count of all rows. + + Arguments: + - df: the materialized dataframe that contains the data to be displayed, it + should have no indices set. + - indices_count: indicates how many columns from the materialized dataframe + should be treated as indices in the display (index columns will be bold if + `format_terminal` is enabled). + - all_rows_count: the count of all rows in the underlying Table; if + `all_rows_count` is bigger than the amount of rows of `df`, an additional + line will be included that will say how many hidden rows there are. + - format_term: a boolean flag, specifying whether to use ANSI escape codes + for rich formatting in the terminal. display_dataframe : Materialized_Table.Table -> Integer -> Integer -> Boolean -> Text display_dataframe df indices_count all_rows_count format_terminal = cols = Vector.Vector df.java_table.getColumns diff --git a/distribution/std-lib/Table/src/Data/Table.enso b/distribution/std-lib/Table/src/Data/Table.enso index 54d1b3e7d11f2..cb59d4546059c 100644 --- a/distribution/std-lib/Table/src/Data/Table.enso +++ b/distribution/std-lib/Table/src/Data/Table.enso @@ -380,6 +380,9 @@ join tables = tables.reduce .join ## PRIVATE + + Ensures that the `txt` has at least `len` characters by appending spaces at + the end. pad txt len = true_len = txt.characters.length txt + (" ".repeat (len - true_len)) @@ -392,6 +395,18 @@ ansi_bold enabled txt = _ -> if enabled then '\e[1m' + txt + '\e[m' else txt ## PRIVATE + + A helper function for creating an ASCII-art representation of tabular data. + + Arguments: + - header: vector of names of columns in the table. + - rows: a vector of rows, where each row is a vector that contains a text + representation of each cell + - indices_count: the number specifying how many columns should be treated as + indices; this will make them in bold font if `format_term` is enabled. + - format_term: a boolean flag, specifying whether to use ANSI escape codes + for rich formatting in the terminal. +print_table : Vector Text -> (Vector (Vector Text)) -> Integer -> Boolean -> Text print_table header rows indices_count format_term = content_lengths = Vector.new header.length i-> max_row = 0.up_to rows.length . fold 0 a-> j-> Math.max a (rows.at j . at i . characters . length) diff --git a/distribution/std-lib/Test/src/Test.enso b/distribution/std-lib/Test/src/Test.enso index 8608c8a7e1b26..409037b8538c1 100644 --- a/distribution/std-lib/Test/src/Test.enso +++ b/distribution/std-lib/Test/src/Test.enso @@ -19,7 +19,7 @@ Spec.is_fail = this.behaviors.any .is_fail Suite.is_fail = this.specs.any .is_fail ## PRIVATE -type Finished_With_Error err stack_trace +type Finished_With_Error err stack_trace_text ## PRIVATE type Matched_On_Error err