From 1f451b47c3c5c35e17026b97eb9ce56f960e70b8 Mon Sep 17 00:00:00 2001 From: "Clark C. Evans" Date: Fri, 16 May 2025 13:39:34 -0500 Subject: [PATCH 1/3] reflect includes table_catalog --- src/reflect.jl | 51 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/reflect.jl b/src/reflect.jl index d90a7570..8aa30477 100644 --- a/src/reflect.jl +++ b/src/reflect.jl @@ -2,25 +2,31 @@ const default_reflect_clause = FROM(:c => (:information_schema, :columns)) |> - WHERE(FUN("=", (:c, :table_schema), VAR(:schema))) |> - ORDER((:c, :table_schema), (:c, :table_name), (:c, :ordinal_position)) |> - SELECT(:schema => (:c, :table_schema), + WHERE(FUN(:and, FUN("=", (:c, :table_catalog), VAR(:catalog)), + FUN("=", (:c, :table_schema), VAR(:schema)) + )) |> + ORDER((:c, :table_catalog), (:c, :table_schema), (:c, :table_name), (:c, :ordinal_position)) |> + SELECT(:catalog => (:c, :table_catalog), + :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")), + WHERE(FUN(:and, FUN("=", (:c, :table_catalog), FUN(:coalesce, VAR(:catalog), FUN(:current_catalog))), + FUN("=", (:c, :table_schema), FUN(:coalesce, VAR(:schema), FUN(:current_schema))), 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), + ORDER((:c, :table_catalog), (:c, :table_schema), (:c, :table_name), (:c, :ordinal_position)) |> + SELECT(:catalog => (:c, :table_catalog), + :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")))) |> ORDER((:c, :table_schema), (:c, :table_name), (:c, :ordinal_position)) |> - SELECT(:schema => (:c, :table_schema), + SELECT(:catalog => missing, + :schema => (:c, :table_schema), :name => (:c, :table_name), :column => (:c, :column_name)) const postgresql_reflect_clause = @@ -32,7 +38,8 @@ const postgresql_reflect_clause = FUN(">", (:a, :attnum), 0), FUN(:not, (:a, :attisdropped)))) |> ORDER((:n, :nspname), (:c, :relname), (:a, :attnum)) |> - SELECT(:schema => (:n, :nspname), + SELECT(:catalog => missing, + :schema => (:n, :nspname), :name => (:c, :relname), :column => (:a, :attname)) const redshift_reflect_clause = postgresql_reflect_clause @@ -42,7 +49,8 @@ const sqlite_reflect_clause = WHERE(FUN(:and, FUN(:in, (:sm, :type), "table", "view"), FUN(:not_like, (:sm, :name), "sqlite_%"))) |> ORDER((:sm, :name), (:pti, :cid)) |> - SELECT(:schema => missing, + SELECT(:catalog => missing, + :schema => missing, :name => (:sm, :name), :column => (:pti, :name)) const sqlserver_reflect_clause = @@ -52,7 +60,8 @@ const sqlserver_reflect_clause = WHERE(FUN(:and, FUN("=", (:s, :name), FUN(:coalesce, VAR(:schema), "dbo")), FUN(:in, (:o, :type), "U", "V"))) |> ORDER((:s, :name), (:o, :name), (:c, :column_id)) |> - SELECT(:schema => (:s, :name), + SELECT(:catalog => missing, + :schema => (:s, :name), :name => (:o, :name), :column => (:c, :name)) const standard_reflect_clauses = [ @@ -92,10 +101,10 @@ Parameter `dialect` specifies the target [`SQLDialect`](@ref). If not set, `dialect` will be inferred from the type of the connection object. """ -function reflect(conn; schema = nothing, dialect = nothing, cache = default_cache_maxsize) +function reflect(conn; catalog = nothing, schema = nothing, dialect = nothing, cache = default_cache_maxsize) dialect = dialect === nothing ? SQLDialect(typeof(conn)) : convert(SQLDialect, dialect) sql = reflect_sql(dialect) - params = pack(sql, (; schema = something(schema, missing))) + params = pack(sql, (; catalog = something(catalog, missing), schema = something(schema, missing))) stmt = DBInterface.prepare(conn, String(sql)) cr = DBInterface.execute(stmt, params) SQLCatalog(tables = tables_from_column_list(Tables.rows(cr)), @@ -106,22 +115,30 @@ end function tables_from_column_list(rows) tables = SQLTable[] qualifiers = Symbol[] - schema = name = nothing + catalog = schema = name = nothing columns = Symbol[] - for (s, n, c) in rows + for (g, s, n, c) in rows + g = g !== missing ? Symbol(g) : nothing s = s !== missing ? Symbol(s) : nothing n = Symbol(n) c = Symbol(c) - if s === schema && n === name + if g === catalog && s === schema && n === name push!(columns, c) else if !isempty(columns) t = SQLTable(qualifiers = qualifiers, name = name, columns = columns) push!(tables, t) end - if s !== schema - qualifiers = s !== nothing ? [s] : Symbol[] + if s !== schema || g !== catalog + qualifiers = Symbol[] + if !isnothing(g) + push!(qualifiers, g) + end + if !isnothing(s) + push!(qualifiers, s) + end end + catalog = g schema = s name = n columns = [c] From 996ee6fb316d3cf397fc0d11d6147b0d0cb964ba Mon Sep 17 00:00:00 2001 From: Kyrylo Simonov Date: Sun, 18 May 2025 17:21:57 -0500 Subject: [PATCH 2/3] Update reflect() docstring --- src/reflect.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/reflect.jl b/src/reflect.jl index 8aa30477..69c5270c 100644 --- a/src/reflect.jl +++ b/src/reflect.jl @@ -86,15 +86,16 @@ reflect_sql(d::SQLDialect) = """ reflect(conn; + catalog = nothing, schema = nothing, dialect = nothing, cache = $default_cache_maxsize)::SQLCatalog Retrieve the information about available database tables. -The function returns a [`SQLCatalog`](@ref) object. The catalog -will be populated with the tables from the given database `schema`, or, -if parameter `schema` is not set, from the default database schema +The function returns a [`SQLCatalog`](@ref) object. The catalog will be +populated with the tables from the given database `catalog` and `schema`. +If these parameters are not set, the default catalog and schema are assumed (e.g., schema `public` for PostgreSQL). Parameter `dialect` specifies the target [`SQLDialect`](@ref). If not set, From 669d33bb32a713a994c351efaa2cb82af9596c20 Mon Sep 17 00:00:00 2001 From: Kyrylo Simonov Date: Sun, 18 May 2025 17:27:14 -0500 Subject: [PATCH 3/3] DBInterface.connect(): add catalog parameter --- src/connections.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/connections.jl b/src/connections.jl index fa068f25..dc1da7af 100644 --- a/src/connections.jl +++ b/src/connections.jl @@ -62,6 +62,7 @@ const DB = SQLConnection """ DBInterface.connect(DB{RawConnType}, args...; + catalog = nothing, schema = nothing, dialect = nothing, cache = $default_cache_maxsize, @@ -75,13 +76,13 @@ Extra parameters `args` and `kws` are passed to the call: DBInterface.connect(RawConnType, args...; kws...) """ function DBInterface.connect(::Type{SQLConnection{RawConnType}}, args...; + catalog = nothing, schema = nothing, dialect = nothing, cache = default_cache_maxsize, kws...) where {RawConnType} raw = DBInterface.connect(RawConnType, args...; kws...) - catalog = reflect(raw, schema = schema, dialect = dialect, cache = cache) - SQLConnection{RawConnType}(raw, catalog = catalog) + SQLConnection{RawConnType}(raw; catalog = reflect(raw; catalog, schema, dialect, cache)) end """