Skip to content
Snippets Groups Projects
Commit e5b34121 authored by Cam Saul's avatar Cam Saul
Browse files

thou can setteth thy timezones

parent 889b2912
No related branches found
No related tags found
No related merge requests found
......@@ -66,7 +66,8 @@
[lein-bikeshed "0.2.0"] ; Linting
[lein-expectations "0.0.8"] ; run unit tests with 'lein expectations'
[lein-instant-cheatsheet "2.1.1"] ; use awesome instant cheatsheet created by yours truly w/ 'lein instant-cheatsheet'
[lein-marginalia "0.8.0"]] ; generate documentation with 'lein marg'
[lein-marginalia "0.8.0"] ; generate documentation with 'lein marg'
[refactor-nrepl "1.0.1"]]
:jvm-opts ["-Dlogfile.path=target/log"
"-Xms1024m" ; give JVM a decent heap size to start with
"-Xmx2048m" ; hard limit of 2GB so we stop hitting the 4GB container limit on CircleCI
......
......@@ -3,13 +3,13 @@
(:import com.metabase.corvus.api.ApiException)
(:require [clojure.java.jdbc :as jdbc]
[clojure.tools.logging :as log]
[korma.core :as korma]
korma.db
(korma [core :as korma]
db)
[metabase.db :refer [sel]]
[metabase.driver.generic-sql.util :refer :all]
[metabase.models.database :refer [Database]]))
(def class->base-type
(def ^:const class->base-type
"Map of classes returned from DB call to metabase.models.field/base-types"
{java.lang.Boolean :BooleanField
java.lang.Double :FloatField
......@@ -22,6 +22,18 @@
java.sql.Date :DateField
java.sql.Timestamp :DateTimeField})
(def ^:dynamic *timezone->set-timezone-sql*
" This function is called whenever `timezone` is specified in a native query, at the beginning of
the DB transaction.
If implemented, it should take a timestamp like `\"US/Pacific\"` and return a SQL
string that can be executed to set the timezone within the context of a transaction,
e.g. `\"SET LOCAL timezone to 'US/Pacific'\"`.
Because not all DB engines support timestamps (e.g., H2), the default implementation is a no-op.
Engines that *do* support timestamps (e.g., Postgres) should override this function."
(fn [_]))
(defn- value->base-type
"Attempt to match a value we get back from the DB with the corresponding base-type`."
[v]
......@@ -29,6 +41,7 @@
(or (class->base-type (type v))
(throw (ApiException. (int 500) (format "Missing base type mapping for %s in metabase.driver.generic-sql.native/class->base-type. Please add an entry."
(str (type v))))))))
(defn process-and-run
"Process and run a native (raw SQL) QUERY."
{:arglists '([query])}
......@@ -36,11 +49,18 @@
database-id :database :as query}]
{:pre [(string? sql)
(integer? database-id)]}
(log/debug "QUERY: " query)
(log/debug "QUERY: \n"
(with-out-str (clojure.pprint/pprint query)))
(try (let [db (-> (sel :one Database :id database-id)
korma-db
korma.db/get-connection)
[columns & [first-row :as rows]] (jdbc/query db sql :as-arrays? true)]
[columns & [first-row :as rows]] (jdbc/with-db-transaction [conn db :read-only? true]
;; If timezone is specified in the Query and the driver supports setting the timezone then execute SQL to set it
(when-let [timezone (-> query :native :timezone)]
(when-let [set-timezone-sql (*timezone->set-timezone-sql* timezone)]
(log/debug "Setting timezone to:" timezone)
(jdbc/db-do-prepared conn set-timezone-sql)))
(jdbc/query conn sql :as-arrays? true))]
{:status :completed
:row_count (count rows)
:data {:rows rows
......@@ -55,3 +75,7 @@
(re-find #"^(.*);") ; the user already knows the SQL, and error code is meaningless
second) ; so just return the part of the exception that is relevant
(.getMessage e))})))
(def db (delay (-> (sel :one Database :id 1)
korma-db
korma.db/get-connection)))
......@@ -19,7 +19,7 @@
query-is-cumulative-sum?
apply-cumulative-sum)
(def ^{:dynamic true, :private true} *query*
(def ^:dynamic ^:private *query*
"Query dictionary that we're currently processing"
nil)
......
(ns metabase.driver.postgres.query-processor
(:require [metabase.driver.generic-sql.query-processor :as generic]
(:require (metabase.driver.generic-sql [native :as native]
[query-processor :as generic])
[metabase.driver :refer [process-and-run]]))
(defmethod process-and-run :postgres [query]
(generic/process-and-run query))
(binding [native/*timezone->set-timezone-sql* (fn [timezone]
(format "SET LOCAL timezone TO '%s';" timezone))]
(generic/process-and-run query)))
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