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

Crate driver code cleanup :broken_heart:

parent e72be01a
Branches
Tags
No related merge requests found
(ns metabase.driver.crate
(:require [clojure.set :as set]
[korma.core :as k]
[metabase.driver :as driver]
(metabase.driver.crate [analyze :as analyze]
[native :as native]
[query-processor :as qp]
[util :as crate-util])
[metabase.driver.generic-sql :as sql]
(metabase.driver.crate [query-processor :as qp]
[util :as u]
[generic-sql :as gs]
[native :as n])
[korma.core :as k])
(:import (clojure.lang Named)))
[metabase.util :as u]))
(defn- column->base-type
(def ^:private ^:const column->base-type
"Map of Crate column types -> Field base types
Crate data types -> https://crate.io/docs/reference/sql/data_types.html"
[_ column-type]
({:integer :IntegerField
:string :TextField
:boolean :BooleanField
:byte :IntegerField
:short :IntegerField
:long :BigIntegerField
:float :FloatField
:double :FloatField
:ip :UnknownField
:timestamp :DateTimeField
:geo_shape :DictionaryField
:geo_point :ArrayField
:object :DictionaryField
:array :ArrayField
:object_array :ArrayField
:string_array :ArrayField
:integer_array :ArrayField
:float_array :ArrayField
:boolean_array :ArrayField
:byte_array :ArrayField
:timestamp_array :ArrayField
:short_array :ArrayField
:long_array :ArrayField
:double_array :ArrayField
:ip_array :ArrayField
:geo_shape_array :ArrayField
:geo_point_array :ArrayField
} column-type))
Crate data types -> https://crate.io/docs/reference/sql/data_types.html"
{:integer :IntegerField
:string :TextField
:boolean :BooleanField
:byte :IntegerField
:short :IntegerField
:long :BigIntegerField
:float :FloatField
:double :FloatField
:ip :UnknownField
:timestamp :DateTimeField
:geo_shape :DictionaryField
:geo_point :ArrayField
:object :DictionaryField
:array :ArrayField
:object_array :ArrayField
:string_array :ArrayField
:integer_array :ArrayField
:float_array :ArrayField
:boolean_array :ArrayField
:byte_array :ArrayField
:timestamp_array :ArrayField
:short_array :ArrayField
:long_array :ArrayField
:double_array :ArrayField
:ip_array :ArrayField
:geo_shape_array :ArrayField
:geo_point_array :ArrayField})
(def ^:private now (k/sqlfn :CURRENT_TIMESTAMP (k/raw 3)))
(defrecord CrateDriver []
Named
(getName [_] "Crate"))
(def ^:private ^:const now (k/sqlfn :CURRENT_TIMESTAMP (k/raw 3)))
(defn- crate-spec
[{:keys [hosts]
:or {hosts "//localhost:4300"}
:as opts}]
(merge {:classname "io.crate.client.jdbc.CrateDriver" ; must be in classpath
:or {hosts "//localhost:4300"}
:as opts}]
(merge {:classname "io.crate.client.jdbc.CrateDriver" ; must be in classpath
:subprotocol "crate"
:subname (str hosts)}
:subname (str hosts)}
(dissoc opts :hosts)))
(defn- connection-details->spec [_ details]
(crate-spec details))
(defn- can-connect [driver details]
(let [connection (connection-details->spec driver details)]
(= 1 (-> (k/exec-raw connection "select 1 from sys.cluster" :results)
(defn- can-connect? [details]
(let [connection-spec (crate-spec details)]
(= 1 (-> (k/exec-raw connection-spec "select 1 from sys.cluster" :results)
first
vals
first))))
(def CrateISQLDriverMixin
"Implementations of `ISQLDriver` methods for `CrateDriver`."
(merge (sql/ISQLDriverDefaultsMixin)
{:connection-details->spec connection-details->spec
:column->base-type column->base-type
:string-length-fn (constantly :CHAR_LENGTH)
:apply-filter qp/apply-filter
:date u/date
:unix-timestamp->timestamp u/unix-timestamp->timestamp
:current-datetime-fn (constantly now)}))
(extend CrateDriver
(defrecord CrateDriver []
clojure.lang.Named
(getName [_] "Crate"))
(u/strict-extend CrateDriver
driver/IDriver
(merge (sql/IDriverSQLDefaultsMixin)
{:details-fields (constantly [{:name "hosts"
:display-name "Hosts"
:default "//localhost:4300"}])
:can-connect? can-connect
:date-interval u/date-interval
:analyze-table gs/analyze-table
:process-native n/process-and-run
:can-connect? (u/drop-first-arg can-connect?)
:date-interval crate-util/date-interval
:analyze-table analyze/analyze-table
:process-native native/process-and-run
:features (fn [this]
(set/difference (sql/features this)
#{:foreign-keys}))})
sql/ISQLDriver CrateISQLDriverMixin)
sql/ISQLDriver
(merge (sql/ISQLDriverDefaultsMixin)
{:connection-details->spec (u/drop-first-arg crate-spec)
:column->base-type (u/drop-first-arg column->base-type)
:string-length-fn (constantly :CHAR_LENGTH)
:apply-filter qp/apply-filter
:date crate-util/date
:unix-timestamp->timestamp crate-util/unix-timestamp->timestamp
:current-datetime-fn (constantly now)}))
(driver/register-driver! :crate (CrateDriver.))
(ns metabase.driver.crate.generic-sql
(:require [metabase.driver.generic-sql :as sql]
[korma.core :as k]
(ns metabase.driver.crate.analyze
(:require [korma.core :as k]
[metabase.driver.generic-sql :as sql]
[metabase.models.field :as field]
[metabase.sync-database.analyze :as analyze]))
(defn- field-avg-length [_ field]
(defn- field-avg-length [field]
(or (some-> (sql/korma-entity (field/table field))
(k/select (k/aggregate (avg (k/sqlfn :CHAR_LENGTH
(sql/escape-field-name (:name field))))
......@@ -14,15 +14,15 @@
int)
0))
(defn- field-percent-urls [_ field]
(defn- field-percent-urls [field]
(or (let [korma-table (sql/korma-entity (field/table field))]
(when-let [total-non-null-count (:count (first (k/select korma-table
(k/aggregate (count (k/raw "*")) :count)
(k/where {(sql/escape-field-name (:name field)) [not= nil]}))))]
(k/aggregate (count (k/raw "*")) :count)
(k/where {(sql/escape-field-name (:name field)) [not= nil]}))))]
(when (> total-non-null-count 0)
(when-let [url-count (:count (first (k/select korma-table
(k/aggregate (count (k/raw "*")) :count)
(k/where {(sql/escape-field-name (:name field)) [like "http%://_%.__%"]}))))]
(k/aggregate (count (k/raw "*")) :count)
(k/where {(sql/escape-field-name (:name field)) [like "http%://_%.__%"]}))))]
(float (/ url-count total-non-null-count))))))
0.0))
......@@ -30,8 +30,8 @@
"Default implementation of `analyze-table` for SQL drivers."
[driver table new-table-ids]
((analyze/make-analyze-table driver
:field-avg-length-fn (partial field-avg-length driver)
:field-percent-urls-fn (partial field-percent-urls driver))
:field-avg-length-fn field-avg-length
:field-percent-urls-fn field-percent-urls)
driver
table
new-table-ids))
(ns metabase.driver.crate.native
(:require [clojure.java.jdbc :as jdbc]
[metabase.models.database :refer [Database]]
[clojure.tools.logging :as log]
[metabase.db :refer [sel]]
[metabase.driver.generic-sql :as sql]
[clojure.tools.logging :as log]
[metabase.util :as u]
[metabase.driver.generic-sql.native :as n]))
[metabase.driver.generic-sql.native :as n]
[metabase.models.database :refer [Database]]
[metabase.util :as u]))
(defn process-and-run
"Process and run a native (raw SQL) QUERY."
......
(ns metabase.driver.crate.query-processor
(:require [korma.core :as k]
(korma.sql [engine :as kengine]
[fns :as kfns])
[metabase.driver.generic-sql.query-processor :as qp]
[korma.sql.fns :as kfns]
[korma.sql.engine :as kengine]
[metabase.query-processor.interface :as i])
(:import (metabase.query_processor.interface ComparisonFilter CompoundFilter)))
(defn- rewrite-between
"Rewrite [:between <field> <min> <max>] -> [:and [:>= <field> <min>] [:<= <field> <max>]]"
[clause]
(i/strict-map->CompoundFilter {:compound-type :and :subclauses [(ComparisonFilter. :>= (:field clause) (:min-val clause))
(ComparisonFilter. :<= (:field clause) (:max-val clause))]}))
(i/strict-map->CompoundFilter {:compound-type :and
:subclauses [(i/strict-map->ComparisonFilter {:filter-type :>=
:field (:field clause)
:value (:min-val clause)})
(i/strict-map->ComparisonFilter {:filter-type :<=
:field (:field clause)
:value (:max-val clause)})]}))
(defn resolve-subclauses
"resolve filters recursively"
......@@ -21,7 +26,7 @@
(qp/filter-clause->predicate clause))
(case (:compound-type clause)
:and (apply kfns/pred-and (map resolve-subclauses (:subclauses clause)))
:or (apply kfns/pred-or (map resolve-subclauses (:subclauses clause)))
:or (apply kfns/pred-or (map resolve-subclauses (:subclauses clause)))
:not (kfns/pred-not (kengine/pred-map (qp/filter-subclause->predicate clause))))))
(defn apply-filter
......
(ns metabase.driver.crate.util
(:refer-clojure :exclude [second])
(:require [korma.sql.utils :as kutils]
[korma.core :as k]
(:require [korma.core :as k]
[korma.sql.utils :as kutils]
[metabase.driver.generic-sql.query-processor :as qp]
[metabase.util :as u]
[metabase.util.korma-extensions :as kx])
(:import (java.sql Timestamp)))
(:import java.sql.Timestamp))
(defn unix-timestamp->timestamp
"Converts datetime string to a valid timestamp"
......@@ -17,15 +17,15 @@
(defn- date-trunc
"date_trunc('interval', timezone, timestamp): truncates a timestamp to a given interval"
[unit expr]
(let [timezone (get-in qp/*query* [:settings :report-timezone])]
(if (= (nil? timezone) true)
(let [timezone (get-in qp/*query* [:settings :report-timezone])]
(if (nil? timezone)
(k/sqlfn :DATE_TRUNC (kx/literal unit) expr)
(k/sqlfn :DATE_TRUNC (kx/literal unit) timezone expr))))
(defn- date-format
"date_format('format_string', timezone, timestamp): formats the timestamp as string"
[fmt expr]
(let [timezone (get-in qp/*query* [:settings :report-timezone])]
(let [timezone (get-in qp/*query* [:settings :report-timezone])]
(if (nil? timezone)
(k/sqlfn :DATE_FORMAT fmt expr)
(k/sqlfn :DATE_FORMAT fmt timezone expr))))
......@@ -83,10 +83,10 @@
[_ unit amount]
(case unit
:quarter (recur nil :month (kx/* amount 3))
:year (k/raw (sql-interval year amount))
:month (k/raw (sql-interval month amount))
:week (k/raw (sql-interval week amount))
:day (k/raw (sql-interval day amount))
:hour (k/raw (sql-interval hour amount))
:minute (k/raw (sql-interval minute amount))
:second (k/raw (sql-interval second amount))))
:year (k/raw (sql-interval year amount))
:month (k/raw (sql-interval month amount))
:week (k/raw (sql-interval week amount))
:day (k/raw (sql-interval day amount))
:hour (k/raw (sql-interval hour amount))
:minute (k/raw (sql-interval minute amount))
:second (k/raw (sql-interval second amount))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment