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

Move Korma spec functions to metabase.db.spec :honey_pot:

parent 2e3c676f
No related branches found
No related tags found
No related merge requests found
......@@ -25,7 +25,6 @@
(defendpoint GET "/recent_views"
"Get the list of 15 things the current user has been viewing most recently."
[]
;; use a custom Korma query because we are doing some groupings and aggregations
;; expected output of the query is a single row per unique model viewed by the current user
;; including a `:max_ts` which has the most recent view timestamp of the item and `:cnt` which has total views
;; and we order the results by most recently viewed then hydrate the basic details of the model
......
......@@ -91,7 +91,7 @@
(print (color/blue \.))
(flush)
(k/insert e (k/values (if (= e DashboardCard)
;; mini-HACK to fix korma/h2 lowercasing these couple attributes
;; mini-HACK to fix h2 lowercasing these couple attributes
;; luckily this is the only place in our schema where we have camel case names
(mapv #(set/rename-keys % {:sizex :sizeX, :sizey :sizeY}) chunk)
chunk))))
......
......@@ -8,11 +8,11 @@
(honeysql [core :as hsql]
[format :as hformat]
[helpers :as h])
(korma [core :as k]
[db :as kdb])
[korma.db :as kdb]
[medley.core :as m]
[ring.util.codec :as codec]
[metabase.config :as config]
[metabase.db.spec :as dbspec]
[metabase.models.interface :as models]
[metabase.util :as u]
metabase.util.honeysql-extensions) ; this needs to be loaded so the `:h2` quoting style gets added
......@@ -87,15 +87,15 @@
:password (config/config-str :mb-db-pass)}))))
(defn jdbc-details
"Takes our own MB details map and formats them properly for connection details for Korma / JDBC."
"Takes our own MB details map and formats them properly for connection details for JDBC."
[db-details]
{:pre [(map? db-details)]}
;; TODO: it's probably a good idea to put some more validation here and be really strict about what's in `db-details`
(case (:type db-details)
:h2 (kdb/h2 (assoc db-details :naming {:keys s/lower-case
:fields s/upper-case}))
:mysql (kdb/mysql (assoc db-details :db (:dbname db-details)))
:postgres (kdb/postgres (assoc db-details :db (:dbname db-details)))))
:h2 (dbspec/h2 (assoc db-details :naming {:keys s/lower-case
:fields s/upper-case}))
:mysql (dbspec/mysql (assoc db-details :db (:dbname db-details)))
:postgres (dbspec/postgres (assoc db-details :db (:dbname db-details)))))
;; ## MIGRATE
......@@ -188,7 +188,7 @@
(throw (java.lang.Exception. "Database requires manual upgrade."))))
(log/info "Database Migrations Current ... ✅")
;; Establish our 'default' Korma DB Connection
;; Establish our 'default' DB Connection
(kdb/default-connection (kdb/create-db (jdbc-details db-details)))
;; Do any custom code-based migrations now that the db structure is up to date
......@@ -269,7 +269,7 @@
(def ^:private ^:dynamic *call-count*
"Atom used as a counter for DB calls when enabled.
This number isn't *perfectly* accurate, only mostly; DB calls made directly to JDBC or via old korma patterns won't be logged."
This number isn't *perfectly* accurate, only mostly; DB calls made directly to JDBC won't be logged."
nil)
(defn do-with-call-counting
......
(ns metabase.db.spec
"Functions for creating JDBC DB specs for a given engine.")
(defn postgres
"Create a database specification for a postgres database. Opts should include
keys for :db, :user, and :password. You can also optionally set host and
port."
[{:keys [host port db make-pool?]
:or {host "localhost", port 5432, db "", make-pool? true}
:as opts}]
(merge {:classname "org.postgresql.Driver" ; must be in classpath
:subprotocol "postgresql"
:subname (str "//" host ":" port "/" db)
:make-pool? make-pool?}
(dissoc opts :host :port :db)))
(defn mysql
"Create a database specification for a mysql database. Opts should include keys
for :db, :user, and :password. You can also optionally set host and port.
Delimiters are automatically set to \"`\"."
[{:keys [host port db make-pool?]
:or {host "localhost", port 3306, db "", make-pool? true}
:as opts}]
(merge {:classname "com.mysql.jdbc.Driver" ; must be in classpath
:subprotocol "mysql"
:subname (str "//" host ":" port "/" db)
:delimiters "`"
:make-pool? make-pool?}
(dissoc opts :host :port :db)))
(defn mssql
"Create a database specification for a mssql database. Opts should include keys
for :db, :user, and :password. You can also optionally set host and port."
[{:keys [user password db host port make-pool?]
:or {user "dbuser", password "dbpassword", db "", host "localhost", port 1433, make-pool? true}
:as opts}]
(merge {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver" ; must be in classpath
:subprotocol "sqlserver"
:subname (str "//" host ":" port ";database=" db ";user=" user ";password=" password)
:make-pool? make-pool?}
(dissoc opts :host :port :db)))
(defn sqlite3
"Create a database specification for a SQLite3 database. Opts should include a
key for :db which is the path to the database file."
[{:keys [db make-pool?]
:or {db "sqlite.db", make-pool? true}
:as opts}]
(merge {:classname "org.sqlite.JDBC" ; must be in classpath
:subprotocol "sqlite"
:subname db
:make-pool? make-pool?}
(dissoc opts :db)))
(defn h2
"Create a database specification for a h2 database. Opts should include a key
for :db which is the path to the database file."
[{:keys [db make-pool?]
:or {db "h2.db", make-pool? true}
:as opts}]
(merge {:classname "org.h2.Driver" ; must be in classpath
:subprotocol "h2"
:subname db
:make-pool? make-pool?}
(dissoc opts :db)))
......@@ -5,10 +5,9 @@
[clojure.tools.logging :as log]
(honeysql [core :as hsql]
[helpers :as h])
[korma.db :as kdb]
(metabase [config :as config]
[db :as db]
[driver :as driver])
[metabase.config :as config]
[metabase.db :as db]
[metabase.driver :as driver]
[metabase.driver.generic-sql :as sql]
[metabase.driver.generic-sql.query-processor :as sqlqp]
(metabase.models [database :refer [Database]]
......
......@@ -53,10 +53,10 @@
"Given a `Database` DETAILS-MAP, return a JDBC connection spec.")
(current-datetime-fn [this]
"*OPTIONAL*. Korma form that should be used to get the current `DATETIME` (or equivalent). Defaults to `:%now`.")
"*OPTIONAL*. HoneySQL form that should be used to get the current `DATETIME` (or equivalent). Defaults to `:%now`.")
(date [this, ^Keyword unit, field-or-value]
"Return a korma form for truncating a date or timestamp field or value to a given resolution, or extracting a date component.")
"Return a HoneySQL form for truncating a date or timestamp field or value to a given resolution, or extracting a date component.")
(excluded-schemas ^java.util.Set [this]
"*OPTIONAL*. Set of string names of schemas to skip syncing tables from.")
......@@ -73,9 +73,9 @@
Return `nil` to prevent FIELD from being aliased.")
(prepare-value [this, ^Value value]
"*OPTIONAL*. Prepare a value (e.g. a `String` or `Integer`) that will be used in a korma form. By default, this returns VALUE's `:value` as-is, which
"*OPTIONAL*. Prepare a value (e.g. a `String` or `Integer`) that will be used in a HoneySQL form. By default, this returns VALUE's `:value` as-is, which
is eventually passed as a parameter in a prepared statement. Drivers such as BigQuery that don't support prepared statements can skip this
behavior by returning a korma `raw` form instead, or other drivers can perform custom type conversion as appropriate.")
behavior by returning a HoneySQL `raw` form instead, or other drivers can perform custom type conversion as appropriate.")
(quote-style ^clojure.lang.Keyword [this]
"*OPTIONAL*. Return the quoting style that should be used by [HoneySQL](https://github.com/jkk/honeysql) when building a SQL statement.
......@@ -99,7 +99,7 @@
(hsql/call :length (hx/cast :VARCHAR field-key))")
(unix-timestamp->timestamp [this, field-or-value, ^Keyword seconds-or-milliseconds]
"Return a korma form appropriate for converting a Unix timestamp integer field or value to an proper SQL `Timestamp`.
"Return a HoneySQL form appropriate for converting a Unix timestamp integer field or value to an proper SQL `Timestamp`.
SECONDS-OR-MILLISECONDS refers to the resolution of the int in question and with be either `:seconds` or `:milliseconds`."))
......@@ -159,7 +159,7 @@
(defn escape-field-name
"Escape dots in a field name so Korma doesn't get confused and separate them. Returns a keyword."
"Escape dots in a field name so HoneySQL doesn't get confused and separate them. Returns a keyword."
^clojure.lang.Keyword [k]
(keyword (hx/escape-dots (name k))))
......@@ -439,7 +439,7 @@
(defn- db->korma-db
"Return a Korma DB spec for Metabase DATABASE."
"Return a DB spec for Metabase DATABASE."
[{:keys [details engine], :as database}]
(let [spec (connection-details->spec (driver/engine->driver engine) details)]
(assoc (create-db spec)
......@@ -453,7 +453,7 @@
(name (hx/escape-dots (name s))))))))
(defn korma-entity
"Return a Korma entity for [DB and] TABLE.
"Return a entity for [DB and] TABLE.
(-> (Table :id 100)
korma-entity
......
......@@ -2,8 +2,8 @@
;; TODO - This namespace should be reworked to use `u/drop-first-arg` like newer drivers
(:require [clojure.string :as s]
[honeysql.core :as hsql]
[korma.db :as kdb]
[metabase.db :as db]
[metabase.db.spec :as dbspec]
[metabase.driver :as driver]
[metabase.driver.generic-sql :as sql]
[metabase.util :as u]
......@@ -104,8 +104,8 @@
"ACCESS_MODE_DATA" "r"}))))
(defn- connection-details->spec [_ details]
(kdb/h2 (if db/*allow-potentailly-unsafe-connections* details
(update details :db connection-string-set-safe-options))))
(dbspec/h2 (if db/*allow-potentailly-unsafe-connections* details
(update details :db connection-string-set-safe-options))))
(defn- unix-timestamp->timestamp [_ expr seconds-or-milliseconds]
......
......@@ -2,7 +2,7 @@
(:require (clojure [set :as set]
[string :as s])
[honeysql.core :as hsql]
[korma.db :as kdb]
[metabase.db.spec :as dbspec]
[metabase.driver :as driver]
[metabase.driver.generic-sql :as sql]
[metabase.util :as u]
......@@ -58,7 +58,7 @@
(defn- connection-details->spec [details]
(-> details
(set/rename-keys {:dbname :db})
kdb/mysql
dbspec/mysql
(update :subname #(str % connection-args-string (when-not (:ssl details)
"&useSSL=false"))))) ; newer versions of MySQL will complain if you don't explicitly disable SSL
......
......@@ -5,7 +5,7 @@
[string :as s])
[clojure.tools.logging :as log]
[honeysql.core :as hsql]
[korma.db :as kdb]
[metabase.db.spec :as dbspec]
[metabase.driver :as driver]
[metabase.driver.generic-sql :as sql]
[metabase.util :as u]
......@@ -103,7 +103,7 @@
ssl-params
disable-ssl-params))
(rename-keys {:dbname :db})
kdb/postgres))
dbspec/postgres))
(defn- unix-timestamp->timestamp [expr seconds-or-milliseconds]
(case seconds-or-milliseconds
......
......@@ -2,16 +2,16 @@
"Amazon Redshift Driver."
(:require [clojure.java.jdbc :as jdbc]
[honeysql.core :as hsql]
[korma.db :as kdb]
(metabase [config :as config]
[driver :as driver])
[metabase.config :as config]
[metabase.db.spec :as dbspec]
[metabase.driver :as driver]
(metabase.driver [generic-sql :as sql]
[postgres :as postgres])
[metabase.util :as u]
[metabase.util.honeysql-extensions :as hx]))
(defn- connection-details->spec [details]
(kdb/postgres (merge details postgres/ssl-params))) ; always connect to redshift over SSL
(dbspec/postgres (merge details postgres/ssl-params))) ; always connect to redshift over SSL
(defn- date-interval [unit amount]
(hsql/call :+ :%getdate (hsql/raw (format "INTERVAL '%d %s'" (int amount) (name unit)))))
......
......@@ -2,8 +2,8 @@
(:require [clojure.set :as set]
(honeysql [core :as hsql]
[format :as hformat])
[korma.db :as kdb]
[metabase.config :as config]
[metabase.db.spec :as dbspec]
[metabase.driver :as driver]
[metabase.driver.generic-sql :as sql]
[metabase.util :as u]
......@@ -143,7 +143,7 @@
(merge (sql/ISQLDriverDefaultsMixin)
{:active-tables sql/post-filtered-active-tables
:column->base-type (sql/pattern-based-column->base-type pattern->type)
:connection-details->spec (u/drop-first-arg kdb/sqlite3)
:connection-details->spec (u/drop-first-arg dbspec/sqlite3)
:current-datetime-fn (constantly (hsql/raw "datetime('now')"))
:date (u/drop-first-arg date)
:prepare-value (u/drop-first-arg prepare-value)
......
......@@ -295,7 +295,7 @@
:tag (symbol (str (namespace-munge *ns*) \. instance))
:arglists ''([] [id] [& kvs])
:doc (or docstr
(format "Korma entity for '%s' table; instance of %s." (name table-name) instance)))
(format "Entity for '%s' table; instance of %s." (name table-name) instance)))
(-> (k/create-entity ~(name entity))
(k/table ~table-name)
(assoc ::entity true)
......
......@@ -54,11 +54,8 @@
(driver/register-driver! :sync-test (SyncTestDriver.))
(def ^:private users-table (delay (Table, :name "USERS")))
(def ^:private venues-table (delay (Table (id :venues))))
(def ^:private korma-users-table (delay (korma-entity @users-table)))
(def ^:private users-name-field (delay (Field (id :users :name))))
(def ^:private venues-table (delay (Table (id :venues))))
(defn- table-details [table]
(into {} (-> (dissoc table :db :pk_field :field_values)
......
......@@ -52,7 +52,7 @@
;; Other optional methods
(korma-entity [this, ^DatabaseDefinition dbdef, ^TableDefinition tabledef]
"*Optional* Return a korma-entity for TABLEDEF.")
"*Optional* Return an entity for TABLEDEF.")
(prepare-identifier [this, ^String identifier]
"*OPTIONAL*. Prepare an identifier, such as a Table or Field name, when it is used in a SQL query.
......@@ -172,7 +172,7 @@
;; Oracle doesn't understand the normal syntax for inserting multiple rows at a time so we'll insert them one-at-a-time instead)
(defn load-data-get-rows
"Get a sequence of row maps for use in a korma `insert` when loading table data."
"Get a sequence of row maps for use in a `insert!` when loading table data."
[driver dbdef tabledef]
(let [fields-for-insert (mapv (comp keyword :field-name)
(:field-definitions tabledef))]
......
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