Skip to content
Snippets Groups Projects
Commit dfe3e963 authored by Cam Saül's avatar Cam Saül Committed by GitHub
Browse files

Merge pull request #3858 from crate/m/subcolumns-information-schema

CrateDB: display nested object as columns
parents f234f92e 208121e1
No related branches found
No related tags found
No related merge requests found
......@@ -15,4 +15,8 @@ Starting in v0.18.0 Metabase provides a driver for connecting to CrateDB directl
3. Click the `Save` button. Done.
Metabase will now begin inspecting your CrateDB Dataset and finding any tables and fields to build up a sense for the schema. Give it a little bit of time to do its work and then you're all set to start querying.
\ No newline at end of file
Metabase will now begin inspecting your CrateDB Dataset and finding any tables and fields to build up a sense for the schema. Give it a little bit of time to do its work and then you're all set to start querying.
### Known limitations
* Columns/Fields of type `object_array` are deactivated and not exposed. However, their nested fields are listed and also supported for queries.
\ No newline at end of file
(ns metabase.driver.crate
(:require [clojure.java.jdbc :as jdbc]
[clojure.tools.logging :as log]
[honeysql.core :as hsql]
[metabase.driver :as driver]
[metabase.driver.crate.util :as crate-util]
[metabase.driver.generic-sql :as sql]
[metabase.util :as u]))
[metabase.util :as u])
(:import java.sql.DatabaseMetaData))
(def ^:private ^:const column->base-type
"Map of Crate column types -> Field base types
......@@ -55,6 +57,39 @@
(defn- string-length-fn [field-key]
(hsql/call :char_length field-key))
(defn- describe-table-fields
[database, driver, {:keys [schema name]}]
(let [columns (jdbc/query
(sql/db->jdbc-connection-spec database)
[(format "select column_name, data_type as type_name
from information_schema.columns
where table_name like '%s' and table_schema like '%s'
and data_type != 'object_array'" name schema)])] ; clojure jdbc can't handle fields of type "object_array" atm
(set (for [{:keys [column_name type_name]} columns]
(merge {:name column_name
:custom {:column-type type_name}
:base-type (or (column->base-type (keyword type_name))
(do (log/warn (format "Don't know how to map column type '%s' to a Field base_type, falling back to :type/*." type_name))
:type/*))})))))
(defn- add-table-pks
[^DatabaseMetaData metadata, table]
(let [pks (->> (.getPrimaryKeys metadata nil nil (:name table))
jdbc/result-set-seq
(mapv :column_name)
set)]
(update table :fields (fn [fields]
(set (for [field fields]
(if-not (contains? pks (:name field))
field
(assoc field :pk? true))))))))
(defn- describe-table [driver database table]
(sql/with-metadata [metadata driver database]
(->> (describe-table-fields database driver table)
(assoc (select-keys table [:name :schema]) :fields)
;; find PKs and mark them
(add-table-pks metadata))))
(defrecord CrateDriver []
clojure.lang.Named
......@@ -65,6 +100,7 @@
(merge (sql/IDriverSQLDefaultsMixin)
{:can-connect? (u/drop-first-arg can-connect?)
:date-interval crate-util/date-interval
:describe-table describe-table
:details-fields (constantly [{:name "hosts"
:display-name "Hosts"
:default "localhost:5432"}])
......@@ -75,6 +111,8 @@
:column->base-type (u/drop-first-arg column->base-type)
:string-length-fn (u/drop-first-arg string-length-fn)
:date crate-util/date
:quote-style (constantly :crate)
:field->alias (constantly nil)
:unix-timestamp->timestamp crate-util/unix-timestamp->timestamp
:current-datetime-fn (constantly now)}))
......
......@@ -21,6 +21,23 @@
(intern 'honeysql.format 'quote-fns
(assoc quote-fns :h2 (comp s/upper-case ansi-quote-fn))))
(defn- str-insert
"Insert c in string s at index i."
[s c i]
(str c (subs s 0 i) c (subs s i)))
(defn- crate-column-identifier
[^CharSequence s]
(let [idx (s/index-of s "[")]
(if (nil? idx)
(str \" s \")
(str-insert s "\"" idx))))
;; `:crate` quote style that correctly quotes nested column identifiers
(let [quote-fns @(resolve 'honeysql.format/quote-fns)]
(->> (assoc quote-fns :crate crate-column-identifier)
(intern 'honeysql.format 'quote-fns)))
;; register the `extract` function with HoneySQL
;; (hsql/format (hsql/call :extract :a :b)) -> "extract(a from b)"
(defmethod hformat/fn-handler "extract" [_ unit expr]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment