From 0396095a3235631d61c8f195bfb4473307127503 Mon Sep 17 00:00:00 2001 From: Kyrylo Simonov Date: Sat, 7 Sep 2024 09:43:34 -0500 Subject: [PATCH] Reflect DuckDB using INFORMATION_SCHEMA --- src/dialects.jl | 21 +++++++++++---------- src/reflect.jl | 25 ++++++++++--------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/dialects.jl b/src/dialects.jl index d39915db..78c4235b 100644 --- a/src/dialects.jl +++ b/src/dialects.jl @@ -60,6 +60,7 @@ Properties and capabilities of a particular SQL dialect. Use `SQLDialect(name::Symbol)` to create one of the known dialects. The following names are recognized: +* `:duckdb` * `:mysql` * `:postgresql` * `:redshift` @@ -72,8 +73,9 @@ check the source code. Use `SQLDialect(ConnType::Type)` to detect the dialect based on the type of the database connection object. The following types are recognized: -* `LibPQ.Connection` +* `DuckDB.DB` * `MySQL.Connection` +* `LibPQ.Connection` * `SQLite.DB` # Examples @@ -137,6 +139,11 @@ end const default_dialect = SQLDialect() +const duckdb_dialect = + SQLDialect(name = :duckdb, + limit_style = LIMIT_STYLE.POSTGRESQL, + variable_prefix = '$', + variable_style = VARIABLE_STYLE.NUMBERED) const mysql_dialect = SQLDialect(name = :mysql, identifier_quotes = ('`', '`'), @@ -151,11 +158,6 @@ const postgresql_dialect = limit_style = LIMIT_STYLE.POSTGRESQL, variable_prefix = '$', variable_style = VARIABLE_STYLE.NUMBERED) -const duckdb_dialect = - SQLDialect(name = :duckdb, - limit_style = LIMIT_STYLE.POSTGRESQL, - variable_prefix = '$', - variable_style = VARIABLE_STYLE.NUMBERED) const redshift_dialect = SQLDialect(name = :redshift, concat_operator = Symbol("||"), @@ -186,14 +188,14 @@ const sqlserver_dialect = variable_prefix = '?', variable_style = VARIABLE_STYLE.POSITIONAL) const standard_dialects = [ + duckdb_dialect, mysql_dialect, postgresql_dialect, redshift_dialect, spark_dialect, sqlite_dialect, sqlserver_dialect, - default_dialect, - duckdb_dialect] + default_dialect] function SQLDialect(name::Symbol; kws...) for sd in standard_dialects @@ -213,10 +215,10 @@ end end const known_connection_types = [ + [:DuckDB, :DB] => :duckdb, [:MySQL, :Connection] => :mysql, [:LibPQ, :Connection] => :postgresql, [:SQLite, :DB] => :sqlite, - [:DuckDB, :DB] => :duckdb, ] function SQLDialect(@nospecialize ConnType::Type) @@ -288,4 +290,3 @@ end Base.show(io::IO, ::MIME"text/plain", d::SQLDialect) = pprint(io, d) - diff --git a/src/reflect.jl b/src/reflect.jl index 900dc3de..b2bb4d3b 100644 --- a/src/reflect.jl +++ b/src/reflect.jl @@ -7,6 +7,15 @@ const default_reflect_clause = SELECT(:schema => (:c, :table_schema), :name => (:c, :table_name), :column => (:c, :column_name)) +const duckdb_reflect_clause = + FROM(:c => (:information_schema, :columns)) |> + WHERE(FUN(:and, FUN("=", (:c, :table_schema), FUN(:coalesce, VAR(:schema), "main")), + FUN(:not_like, (:c, :table_name), "sqlite_%"), + FUN(:not_like, (:c, :table_name), "pragma_database_list"))) |> + ORDER((:c, :table_schema), (:c, :table_name), (:c, :ordinal_position)) |> + SELECT(:schema => (:c, :table_schema), + :name => (:c, :table_name), + :column => (:c, :column_name)) const mysql_reflect_clause = FROM(:c => (:information_schema, :columns)) |> WHERE(FUN("=", (:c, :table_schema), FUN(:coalesce, VAR(:schema), FUN("DATABASE ")))) |> @@ -26,19 +35,6 @@ const postgresql_reflect_clause = SELECT(:schema => (:n, :nspname), :name => (:c, :relname), :column => (:a, :attname)) -# same as postgresql, just the default schema is "main" instead of "public": -const duckdb_reflect_clause = - FROM(:n => (:pg_catalog, :pg_namespace)) |> - JOIN(:c => (:pg_catalog, :pg_class), on = FUN("=", (:n, :oid), (:c, :relnamespace))) |> - JOIN(:a => (:pg_catalog, :pg_attribute), on = FUN("=", (:c, :oid), (:a, :attrelid))) |> - WHERE(FUN(:and, FUN("=", (:n, :nspname), FUN(:coalesce, VAR(:schema), "main")), - FUN(:in, (:c, :relkind), "r", "v"), - FUN(">", (:a, :attnum), 0), - FUN(:not, (:a, :attisdropped)))) |> - ORDER((:n, :nspname), (:c, :relname), (:a, :attnum)) |> - SELECT(:schema => (:n, :nspname), - :name => (:c, :relname), - :column => (:a, :attname)) const redshift_reflect_clause = postgresql_reflect_clause const sqlite_reflect_clause = FROM(:sm => :sqlite_master) |> @@ -60,9 +56,9 @@ const sqlserver_reflect_clause = :name => (:o, :name), :column => (:c, :name)) const standard_reflect_clauses = [ + :duckdb => duckdb_reflect_clause, :mysql => mysql_reflect_clause, :postgresql => postgresql_reflect_clause, - :duckdb => duckdb_reflect_clause, :redshift => redshift_reflect_clause, :sqlite => sqlite_reflect_clause, :sqlserver => sqlserver_reflect_clause] @@ -137,4 +133,3 @@ function tables_from_column_list(rows) end tables end -