Skip to content

Commit 0d0269e

Browse files
authored
Merge pull request #30 from tegonal/dev/TRD_update_to_metabase_0.46.0
Dev/trd update to metabase 0.46.0
2 parents d06ce9e + 29f8ccc commit 0d0269e

File tree

3 files changed

+78
-95
lines changed

3 files changed

+78
-95
lines changed

deps.edn

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,27 @@
11
{
2-
:paths [
3-
; in case you get the error `All dirs should be absolute`, you forgot to define an absolute project-dir like so:
4-
; clojure -X:build :project-dir "\"$(pwd)\""
5-
"src"
6-
"resources"
7-
]
2+
:paths [
3+
; in case you get the error `All dirs should be absolute`, you forgot to define an absolute project-dir like so:
4+
; clojure -X:build :project-dir "\"$(pwd)\""
5+
"src"
6+
"resources"
7+
]
88

9-
:deps {
10-
org.clojure/clojure {:mvn/version "1.11.1"}
11-
expectations/clojure-test {:mvn/version "1.2.1"}
12-
; replace also the version in metabase-plugin.yaml
13-
metabase/metabase-core {:git/url "https://github.com/metabase/metabase.git" :git/tag "v0.45.3" :git/sha "070f57b"}
14-
metabase/build-drivers {:git/url "https://github.com/metabase/metabase.git" :git/tag "v0.45.3" :git/sha "070f57b" :deps/root "bin/build-drivers"}
15-
}
9+
:deps { org.clojure/core.logic {:mvn/version "1.0.0"}
10+
com.github.seancorfield/honeysql {:mvn/version "2.4.1011"}
11+
}
1612

17-
;; These are needed for the Athena and Redshift drivers in order to build them. Maven repos from subprojects do not
13+
;; These are needed for the Athena and Redshift drivers in order to build them. Maven repos from subprojects do not
1814
;; get copied over -- see
1915
;; https://ask.clojure.org/index.php/10726/deps-manifest-dependencies-respect-repos-dependent-project
2016
:mvn/repos
2117
{"athena" {:url "https://s3.amazonaws.com/maven-athena"}
2218
"redshift" {:url "https://s3.amazonaws.com/redshift-maven-repository/release"}}
2319

24-
; build the driver with `clojure -X:build :project-dir "\"$(pwd)\""`
25-
:aliases {
26-
:build {
27-
:exec-fn build-drivers.build-driver/build-driver!
28-
:exec-args {:driver :teradata
29-
:project-dir "."
30-
:target-dir "./target"}
31-
20+
; build the driver with `clojure -X:build :project-dir "\"$(pwd)\""`
21+
:aliases
22+
{:dev
23+
{:extra-deps
24+
{ io.github.metabase/metabase { :git/tag "v0.46.0", :git/sha "0ca7df3" } }
25+
}
3226
}
33-
; We don't want to include metabase nor clojure in the uber jar
34-
:oss {:replace-deps {} }
35-
36-
:test {:extra-paths ["test"]
37-
:extra-deps {io.github.cognitect-labs/test-runner
38-
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}
39-
:main-opts ["-m" "cognitect.test-runner"]
40-
:exec-fn cognitect.test-runner.api/test}
41-
}
4227
}

resources/metabase-plugin.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
info:
22
name: Metabase Teradata Driver
33
# also replace the version in deps.edn if you change the metabase version here
4-
version: 1.1.0-metabase-v0.45.3-teradata-jdbc-17.10
4+
version: 1.1.0-metabase-v0.46.0-teradata-jdbc-17.10
55
description: Allows Metabase to connect to Teradata databases. Community Supported driver.
66
dependencies:
77
- class: com.teradata.jdbc.TeraDriver
@@ -37,7 +37,7 @@ driver:
3737
- additional-options
3838
- placeholder: e.g. COPLAST=OFF
3939
# required in order that `Choose when syncs and scans happen` shows up in database options afterwards
40-
# (during first time setup, you only see `Periodically refingerprint tables` in metabase v0.45.3
40+
# (during first time setup, you only see `Periodically refingerprint tables` in metabase v0.46.0
4141
# the option `Choose when syncs and scans happen` only shows up later in admin -> Database -> advanced options)
4242
- default-advanced-options
4343
connection-properties-include-tunnel-config: false

src/metabase/driver/teradata.clj

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
[medley.core :as m]
66
[clojure.tools.logging :as log]
77
[clojure.java.jdbc :as jdbc]
8-
[honeysql.core :as hsql]
98
[java-time :as t]
109
[metabase
1110
[driver :as driver]
@@ -20,10 +19,8 @@
2019
[metabase.driver.sql-jdbc.sync.describe-table :as sql-jdbc.describe-table]
2120
[metabase.driver.sql.query-processor :as sql.qp]
2221
[metabase.driver.sql.util.deduplicate :as deduplicateutil]
23-
[metabase.query-processor.util :as qputil]
24-
[metabase.util
25-
[honeysql-extensions :as hx]
26-
[i18n :refer [trs]]])
22+
[metabase.util.i18n :refer [trs]]
23+
[metabase.util.honey-sql-2 :as h2x])
2724
(:import [java.sql Connection DatabaseMetaData ResultSet Types PreparedStatement]
2825
[java.time OffsetDateTime OffsetTime]
2926
[java.util Calendar TimeZone]))
@@ -86,6 +83,10 @@
8683
(keyword "timestamp with timezone") :type/DateTime
8784
(keyword "timestamp without timezone") :type/DateTime}, column-type))
8885

86+
(defmethod sql.qp/honey-sql-version :teradata
87+
[_driver]
88+
2)
89+
8990
(defn- dbnames-set
9091
"Transform the string of databases to a set of strings."
9192
[dbnames]
@@ -212,73 +213,68 @@
212213
teradata-spec
213214
(sql-jdbc.common/handle-additional-options details-map, :seperator-style :comma)))
214215

215-
;; trunc always returns a date in Teradata
216-
(defn- date-trunc [unit expr] (hsql/call :trunc expr (hx/literal unit)))
217-
218-
(defn- timestamp-trunc [unit expr] (hsql/call :to_timestamp
219-
(hsql/call :to_char
220-
expr
221-
unit) unit))
222-
223-
(defn- extract [unit expr] (hsql/call :extract unit expr))
224-
225-
(def ^:private extract-integer (comp hx/->integer extract))
226-
227-
(def ^:private ^:const one-day (hsql/raw "INTERVAL '1' DAY"))
228-
229-
(def ^:private ^:const now (hsql/raw "CURRENT_TIMESTAMP"))
230-
231-
(defmethod sql.qp/date [:teradata :default] [_ _ expr] expr)
232-
(defmethod sql.qp/date [:teradata :minute] [_ _ expr] (timestamp-trunc (hsql/raw "'yyyy-mm-dd hh24:mi'") expr))
233-
(defmethod sql.qp/date [:teradata :minute-of-hour] [_ _ expr] (extract-integer :minute expr))
234-
(defmethod sql.qp/date [:teradata :hour] [_ _ expr] (timestamp-trunc (hsql/raw "'yyyy-mm-dd hh24'") expr))
235-
(defmethod sql.qp/date [:teradata :hour-of-day] [_ _ expr] (extract-integer :hour expr))
236-
(defmethod sql.qp/date [:teradata :day] [_ _ expr] (hx/->date expr))
237-
(defmethod sql.qp/date [:teradata :day-of-week] [driver _ expr] (hx/inc (hx/- (sql.qp/date driver :day expr)
238-
(sql.qp/date driver :week expr))))
239-
(defmethod sql.qp/date [:teradata :day-of-month] [_ _ expr] (extract-integer :day expr))
240-
(defmethod sql.qp/date [:teradata :day-of-year] [driver _ expr] (hx/inc (hx/- (sql.qp/date driver :day expr) (date-trunc :year expr))))
241-
(defmethod sql.qp/date [:teradata :week] [_ _ expr] (date-trunc :day expr)) ; Same behaviour as with Oracle.
242-
(defmethod sql.qp/date [:teradata :week-of-year] [_ _ expr] (hx/inc (hx// (hx/- (date-trunc :iw expr)
243-
(date-trunc :iy expr))
244-
7)))
245-
(defmethod sql.qp/date [:teradata :month] [_ _ expr] (date-trunc :mm expr))
246-
(defmethod sql.qp/date [:teradata :month-of-year] [_ _ expr] (extract-integer :month expr))
247-
(defmethod sql.qp/date [:teradata :quarter] [_ _ expr] (date-trunc :q expr))
248-
(defmethod sql.qp/date [:teradata :quarter-of-year] [driver _ expr] (hx// (hx/+ (sql.qp/date driver :month-of-year (sql.qp/date driver :quarter expr)) 2) 3))
249-
(defmethod sql.qp/date [:teradata :year] [_ _ expr] (date-trunc :year expr))
216+
(defn- trunc [format-template v]
217+
[:trunc v (h2x/literal format-template)])
218+
219+
(def ^:private ^:const one-day [:raw "INTERVAL '1' DAY"])
220+
221+
(def ^:private ^:const now [:raw "CURRENT_TIMESTAMP"])
222+
223+
(defmethod sql.qp/date [:teradata :default] [_ _ expr] expr)
224+
(defmethod sql.qp/date [:teradata :minute] [_ _ expr] (:to_timestamp (:raw "'yyyy-mm-dd hh24:mi'") expr))
225+
(defmethod sql.qp/date [:teradata :minute-of-hour] [_ _ expr] [::h2x/extract :minute expr])
226+
(defmethod sql.qp/date [:teradata :hour] [_ _ expr] (:to_timestamp (:raw "'yyyy-mm-dd hh24'") expr))
227+
(defmethod sql.qp/date [:teradata :hour-of-day] [_ _ expr] [::h2x/extract :hour expr])
228+
(defmethod sql.qp/date [:teradata :day] [_ _ expr] (h2x/->date expr))
229+
(defmethod sql.qp/date [:teradata :day-of-week] [driver _ expr] (h2x/inc (h2x/- (sql.qp/date driver :day expr)
230+
(sql.qp/date driver :week expr))))
231+
(defmethod sql.qp/date [:teradata :day-of-month] [_ _ expr] [::h2x/extract :day expr])
232+
(defmethod sql.qp/date [:teradata :day-of-year] [driver _ expr] (h2x/inc (h2x/- (sql.qp/date driver :day expr) (trunc :year expr))))
233+
(defmethod sql.qp/date [:teradata :week] [_ _ expr] (trunc :day expr)) ; Same behaviour as with Oracle.
234+
(defmethod sql.qp/date [:teradata :week-of-year] [_ _ expr] (h2x/inc (h2x// (h2x/- (trunc :iw expr)
235+
(trunc :iy expr))
236+
7)))
237+
(defmethod sql.qp/date [:teradata :month] [_ _ expr] (trunc :month expr))
238+
(defmethod sql.qp/date [:teradata :month-of-year] [_ _ expr] [::h2x/extract :month expr])
239+
(defmethod sql.qp/date [:teradata :quarter] [_ _ expr] (trunc :q expr))
240+
(defmethod sql.qp/date [:teradata :quarter-of-year] [driver _ expr] (h2x// (h2x/+ (sql.qp/date driver :month-of-year (sql.qp/date driver :quarter expr)) 2) 3))
241+
(defmethod sql.qp/date [:teradata :year] [_ _ expr] (trunc :year expr))
250242

251243
(defn- num-to-interval [unit amount]
252-
(hsql/raw (format "INTERVAL '%d' %s" (int (Math/abs amount)) (name unit))))
244+
[:raw (format "INTERVAL '%d' %s" (int (Math/abs amount)) (name unit))])
253245

254246
(defmethod sql.qp/add-interval-honeysql-form :teradata [_ hsql-form amount unit]
255-
(let [op (if (>= amount 0) hx/+ hx/-)]
256-
(op (if
257-
(= unit :month)
258-
(date-trunc :month hsql-form)
259-
(hx/->timestamp hsql-form))
260-
(case unit
261-
:second (num-to-interval :second amount)
262-
:minute (num-to-interval :minute amount)
263-
:hour (num-to-interval :hour amount)
264-
:day (num-to-interval :day amount)
265-
:week (num-to-interval :day (* amount 7))
266-
:month (num-to-interval :month amount)
267-
:quarter (num-to-interval :month (* amount 3))
268-
:year (num-to-interval :year amount)))))
247+
(let [op (if (>= amount 0) h2x/+ h2x/-)]
248+
(op (if (= unit :month)
249+
(trunc :month hsql-form)
250+
(h2x/->timestamp hsql-form))
251+
(case unit
252+
:second (num-to-interval :second amount)
253+
:minute (num-to-interval :minute amount)
254+
:hour (num-to-interval :hour amount)
255+
:day (num-to-interval :day amount)
256+
:week (num-to-interval :day (* amount 7))
257+
:month (num-to-interval :month amount)
258+
:quarter (num-to-interval :month (* amount 3))
259+
:year (num-to-interval :year amount)))))
260+
261+
(def ^:private timestamp-types
262+
#{"timestamp" "timestamp with time zone" "timestamp with local time zone"})
269263

270264
(defmethod sql.qp/unix-timestamp->honeysql [:teradata :seconds] [_ _ field-or-value]
271-
(hsql/call :to_timestamp field-or-value))
265+
(:to_timestamp field-or-value))
272266

273267
(defmethod sql.qp/unix-timestamp->honeysql [:teradata :milliseconds] [_ _ field-or-value]
274-
(sql.qp/unix-timestamp->honeysql (hx// field-or-value 1000) :seconds))
268+
(sql.qp/unix-timestamp->honeysql (h2x// field-or-value 1000) :seconds))
275269

276-
(defmethod sql.qp/apply-top-level-clause [:teradata :limit] [_ _ honeysql-form {value :limit}]
277-
(update (assoc honeysql-form :modifiers [(format "TOP %d" value)]) :select deduplicateutil/deduplicate-identifiers))
270+
(defmethod sql.qp/apply-top-level-clause [:teradata :limit]
271+
[_ _ honeysql-form {value :limit}]
272+
(update honeysql-form :select deduplicateutil/deduplicate-identifiers)
273+
)
278274

279275
(defmethod sql.qp/apply-top-level-clause [:teradata :page] [_ _ honeysql-form {{:keys [items page]} :page}]
280-
(assoc honeysql-form :offset (hsql/raw (format "QUALIFY ROW_NUMBER() OVER (%s) BETWEEN %d AND %d"
281-
(first (hsql/format (select-keys honeysql-form [:order-by])
276+
(assoc honeysql-form :offset (:raw (format "QUALIFY ROW_NUMBER() OVER (%s) BETWEEN %d AND %d"
277+
(first (format (select-keys honeysql-form [:order-by])
282278
:allow-dashed-names? true
283279
:quoting :ansi))
284280
(inc (* items (dec page)))
@@ -386,7 +382,9 @@
386382

387383
(defmethod driver/execute-reducible-query :teradata
388384
[driver query context respond]
389-
((get-method driver/execute-reducible-query :sql-jdbc) driver (cleanup-query query) context respond))
385+
(
386+
(get-method driver/execute-reducible-query :sql-jdbc) driver (cleanup-query query) context respond)
387+
)
390388

391389
(defmethod sql.qp/current-datetime-honeysql-form :teradata [_] now)
392390

0 commit comments

Comments
 (0)