Skip to content

Commit f179df3

Browse files
authored
Merge pull request #11 from databendcloud/feat/support-metabase-0.49x
feat: support metabase 0.49.x
2 parents 6a43d82 + 2feffb2 commit f179df3

File tree

6 files changed

+110
-97
lines changed

6 files changed

+110
-97
lines changed

.github/workflows/check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
uses: actions/checkout@v2
4040
with:
4141
repository: metabase/metabase
42-
ref: v0.47.4
42+
ref: v0.49.12
4343

4444
- name: Checkout Driver Repo
4545
uses: actions/checkout@v2

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,16 @@ You should see a message on startup similar to:
6060
2019-05-07 23:27:32 INFO plugins.lazy-loaded-driver :: Registering lazy loading driver :databend...
6161
2019-05-07 23:27:32 INFO metabase.driver :: Registered driver :databend (parents: #{:sql-jdbc}) 🚚
6262
```
63+
64+
## Choosing the Right Version
65+
66+
| Metabase Release | Driver Version |
67+
|------------------|----------------|
68+
| 0.37.x | 0.0.1 |
69+
| 0.38.1+ | 0.0.2 |
70+
| 0.41.2 | 0.0.3 |
71+
| 0.41.3.1 | 0.0.4 |
72+
| 0.42.x | 0.0.5 |
73+
| 0.44.x | 0.0.6 |
74+
| 0.47.7+ | 0.0.7 |
75+
| 0.49.x | 0.0.8 |

repo/com/databend/metabase-core/maven-metadata.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
<groupId>com.databend</groupId>
44
<artifactId>metabase-core</artifactId>
55
<versioning>
6-
<release>1.40</release>
6+
<release>1.41</release>
77
<versions>
88
<version>1.40</version>
9+
<version>1.41</version>
910
</versions>
10-
<lastUpdated>20240527063529</lastUpdated>
11+
<lastUpdated>20240528085732</lastUpdated>
1112
</versioning>
1213
</metadata>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
02403d0fcb09a53437e4ab2986dd388f
1+
f5ab9f9594372558da4228baacdbb718
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
516a620a9e4ba200bf6527030341c8c5eee491d7
1+
344de6db540a64af1dd9f9d602aef2c1fccbc83f

src/metabase/driver/databend.clj

Lines changed: 91 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
(:require [clojure.java.jdbc :as jdbc]
55
[clojure.string :as str]
66
[clojure.tools.logging :as log]
7-
[honeysql [core :as hsql] [format :as hformat]]
7+
[honey.sql :as sql]
88
[java-time :as t]
99
[medley.core :as m]
1010
[metabase [config :as config] [driver :as driver] [util :as u]]
1111
[metabase.driver.ddl.interface :as ddl.i]
12+
[metabase.driver.sql :as driver.sql]
1213
[metabase.driver.sql.util :as sql.u]
1314
[metabase.driver.sql-jdbc [common :as sql-jdbc.common]
1415
[connection :as sql-jdbc.conn] [execute :as sql-jdbc.execute]
@@ -18,10 +19,8 @@
1819
[metabase.driver.sql-jdbc.sync.common :as common]
1920
[metabase.driver.sql-jdbc.execute.legacy-impl :as legacy]
2021
[metabase.driver.sql-jdbc.sync.interface :as i]
21-
[metabase.mbql.schema :as mbql.s]
22-
[metabase.mbql.util :as mbql.u]
22+
[metabase.util.honey-sql-2 :as h2x]
2323
[metabase.util.date-2 :as u.date]
24-
[metabase.util.honeysql-extensions :as hx]
2524
[metabase.util.ssh :as ssh]
2625
[schema.core :as s])
2726

@@ -78,10 +77,8 @@
7877

7978
(def ^:private default-connection-details
8079
{:classname "com.databend.jdbc.DatabendDriver", :subprotocol "databend", :user "root", :password "root", :dbname "default",:host "localhost", :port "8000", :ssl false})
81-
(def ^:private product-name "metabase/1.4.0")
82-
83-
(defmethod sql-jdbc.conn/connection-details->spec :databend
84-
[_ details]
80+
(def ^:private product-name "metabase/1.4.1")
81+
(defn- connection-details->spec* [details]
8582
;; ensure defaults merge on top of nils
8683
(let [details (reduce-kv (fn [m k v] (assoc m k (or v (k default-connection-details))))
8784
default-connection-details
@@ -99,11 +96,32 @@
9996
(sql-jdbc.common/handle-additional-options details :separator-style :url))
10097
))
10198

99+
(defmethod sql-jdbc.conn/connection-details->spec :databend
100+
[_ details]
101+
(connection-details->spec* details))
102102

103103
; Testing the databend database connection
104-
(defmethod driver/can-connect? :databend [driver details]
105-
(let [connection (sql-jdbc.conn/connection-details->spec driver (ssh/include-ssh-tunnel! details))]
106-
(= 1 (first (vals (first (jdbc/query connection ["SELECT 1"])))))))
104+
(defmethod driver/can-connect? :databend
105+
[driver details]
106+
(if config/is-test?
107+
(try
108+
;; Default SELECT 1 is not enough for Metabase test suite,
109+
;; as it works slightly differently than expected there
110+
(let [spec (sql-jdbc.conn/connection-details->spec driver details)
111+
db (or (:dbname details) (:db details) "default")]
112+
(sql-jdbc.execute/do-with-connection-with-options
113+
driver spec nil
114+
(fn [^java.sql.Connection conn]
115+
(let [stmt (.prepareStatement conn "SELECT count(*) > 0 FROM system.databases WHERE name = ?")
116+
_ (.setString stmt 1 db)
117+
rset (.executeQuery stmt)]
118+
(when (.next rset)
119+
(.getBoolean rset 1))))))
120+
(catch Throwable e
121+
(log/error e "An exception during Databend connectivity check")
122+
false))
123+
;; During normal usage, fall back to the default implementation
124+
(sql-jdbc.conn/can-connect? driver details)))
107125

108126

109127
(def ^:private allowed-table-types
@@ -184,57 +202,53 @@
184202

185203
(defn- to-start-of-year
186204
[expr]
187-
(hsql/call :to_start_of_year (hsql/call :TO_DATETIME expr)))
205+
[:'to_start_of_year expr])
188206

189207
(defn- to-day-of-year
190208
[expr]
191-
(hsql/call :to_day_of_year (hsql/call :TO_DATETIME expr)))
209+
[:'to_day_of_year expr])
192210

193211

194212
(defn- to-start-of-week
195213
[expr]
196214
;; The first day of a week can be Sunday or Monday, which is specified by the argument mode.
197215
;; Here we use Sunday as default
198-
(hsql/call :to_start_of_week expr))
216+
[:'to_start_of_week expr])
199217

200218
(defn- to-start-of-minute
201219
[expr]
202-
(hsql/call :to_start_of_minute (hsql/call :TO_DATETIME expr)))
220+
[:'to_start_of_minute expr])
203221

204222
(defn- to-start-of-hour
205223
[expr]
206-
(hsql/call :to_start_of_hour (hsql/call :TO_DATETIME expr)))
224+
[:'to_start_of_hour expr])
207225

208-
(defn- to-hour [expr] (hsql/call :to_hour (hsql/call :TO_DATETIME expr)))
226+
(defn- to-hour [expr] [:'to_hour expr])
209227

210-
(defn- to-minute [expr] (hsql/call :to_minute (hsql/call :TO_DATETIME expr)))
228+
(defn- to-minute [expr] [:'to_minute expr])
211229

212-
(defn- to-day [expr] (hsql/call :to_date expr))
213230

214231
(defmethod sql.qp/date [:databend :day-of-week]
215232
[_ _ expr]
216-
(sql.qp/adjust-day-of-week :databend (hsql/call :to_day_of_week expr)))
233+
(sql.qp/adjust-day-of-week :databend [:'to_day_of_week expr]))
217234

218235
(defn- to-day-of-month
219236
[expr]
220-
(hsql/call :to_day_of_month (hsql/call :TO_DATETIME expr)))
237+
[:'to_day_of_month expr])
221238

222239
(defn- to-start-of-month
223240
[expr]
224-
(hsql/call :to_start_of_month (hsql/call :TO_DATETIME expr)))
241+
[:'to_start_of_month expr])
225242

226243
(defn- to-start-of-quarter
227244
[expr]
228-
(hsql/call :to_start_of_quarter (hsql/call :TO_DATETIME expr)))
245+
[:'to_start_of_quarter expr])
229246

230247
(defmethod sql.qp/date [:databend :default] [_ _ expr] expr)
231248
(defmethod sql.qp/date [:databend :minute]
232249
[_ _ expr]
233250
(to-start-of-minute expr))
234251

235-
; Return an appropriate HoneySQL form for converting a Unix timestamp integer field or value to a proper SQL Timestamp.
236-
;(defmethod sql.qp/unix-timestamp->honeysql [:databend :seconds] [_ _ expr] (hsql/call :to_timestamp expr))
237-
238252
(defmethod sql.qp/date [:databend :minute-of-hour]
239253
[_ _ expr]
240254
(to-minute expr))
@@ -249,17 +263,16 @@
249263
(defmethod sql.qp/date [:databend :month] [_ _ expr] (to-start-of-month expr))
250264
(defmethod sql.qp/date [:databend :year] [_ _ expr] (to-start-of-year expr))
251265

252-
(defmethod sql.qp/date [:databend :day] [_ _ expr] (to-day expr))
253266
(defmethod sql.qp/date [:databend :week]
254267
[driver _ expr]
255268
(sql.qp/adjust-start-of-week driver to-start-of-week expr))
256269
(defmethod sql.qp/date [:databend :quarter]
257270
[_ _ expr]
258271
(to-start-of-quarter expr))
259272

260-
;(defmethod sql.qp/unix-timestamp->honeysql [:databend :seconds]
261-
; [_ _ expr]
262-
; (hsql/call :TO_DATETIME expr))
273+
(defmethod sql.qp/unix-timestamp->honeysql [:databend :seconds]
274+
[_ _ expr]
275+
(h2x/->datetime expr))
263276

264277
(defmethod unprepare/unprepare-value [:databend LocalDate]
265278
[_ t]
@@ -288,84 +301,59 @@
288301

289302
(defmethod sql.qp/->honeysql [:databend :log]
290303
[driver [_ field]]
291-
(hsql/call :log10 (sql.qp/->honeysql driver field)))
292-
293-
(defmethod hformat/fn-handler "quantile"
294-
[_ field p]
295-
(str "quantile(" (hformat/to-sql p) ")(" (hformat/to-sql field) ")"))
304+
[:'log10 (sql.qp/->honeysql driver field)])
296305

297306
; call REGEXP_SUBSTR function when regex-match-first is called
298307
(defmethod sql.qp/->honeysql [:databend :regex-match-first]
299308
[driver [_ arg pattern]]
300-
(let [arg-sql (hformat/to-sql (sql.qp/->honeysql driver arg))
301-
pattern-sql (sql.u/escape-sql (sql.qp/->honeysql driver pattern) :ansi)
302-
sql-string (str "REGEXP_SUBSTR(" arg-sql ", '" pattern-sql "')")]
303-
(hsql/raw sql-string)))
309+
[:'extract (sql.qp/->honeysql driver arg) pattern])
310+
311+
(defmethod sql.qp/->honeysql [:databend :stddev]
312+
[driver [_ field]]
313+
[:'stddevPop (sql.qp/->honeysql driver field)])
304314

315+
(defmethod sql.qp/->honeysql [:databend :median]
316+
[driver [_ field]]
317+
[:'median (sql.qp/->honeysql driver field)])
318+
319+
(defn- args->float64
320+
[args]
321+
(map (fn [arg] [:'to_float64 (sql.qp/->honeysql :databend arg)]) args))
322+
323+
(defmethod sql.qp/->float :databend
324+
[_ value]
325+
[:'to_float64 value])
326+
(defmethod sql.qp/->honeysql [:databend :substring]
327+
[driver [_ arg start length]]
328+
(let [str [:'toString (sql.qp/->honeysql driver arg)]]
329+
(if length
330+
[:'substr str
331+
(sql.qp/->honeysql driver start)
332+
(sql.qp/->honeysql driver length)]
333+
[:'substr str
334+
(sql.qp/->honeysql driver start)])))
305335

306336
;; metabase.query-processor-test.count-where-test
307337
;; metabase.query-processor-test.share-test
308338
(defmethod sql.qp/->honeysql [:databend :count-where]
309339
[driver [_ pred]]
310-
(hsql/call :case
311-
(hsql/call :>
312-
(hsql/call :count) 0)
313-
(hsql/call :sum
314-
(hsql/call :case (sql.qp/->honeysql driver pred) 1.0 :else 0.0))
315-
:else nil))
340+
[:case
341+
[:> [:'count] 0]
342+
[:sum [:case (sql.qp/->honeysql driver pred) 1 :else 0]]
343+
:else nil])
344+
316345

317346
(defmethod sql.qp/quote-style :databend [_] :mysql)
318347

319348
(defmethod sql.qp/add-interval-honeysql-form :databend
320349
[_ dt amount unit]
321-
(hx/+ (hx/->timestamp dt)
322-
(hsql/raw (format "INTERVAL %d %s" (int amount) (name unit)))))
323-
324-
;; The following lines make sure we call lowerUTF8 instead of lower
325-
(defn- databend-like-clause
326-
[driver field value options]
327-
(if (get options :case-sensitive true)
328-
[:like field (sql.qp/->honeysql driver value)]
329-
[:like (hsql/call :lowerUTF8 field)
330-
(sql.qp/->honeysql driver (update value 1 str/lower-case))]))
331-
332-
(s/defn ^:private update-string-value :- mbql.s/value
333-
[value :- (s/constrained mbql.s/value #(string? (second %)) "string value") f]
334-
(update value 1 f))
335-
336-
(defmethod sql.qp/->honeysql [:databendd :starts-with]
337-
[driver [_ field value options]]
338-
(databend-like-clause driver
339-
(sql.qp/->honeysql driver field)
340-
(update-string-value value #(str % \%))
341-
options))
342-
343-
(defmethod sql.qp/->honeysql [:databend :contains]
344-
[driver [_ field value options]]
345-
(databend-like-clause driver
346-
(sql.qp/->honeysql driver field)
347-
(update-string-value value #(str \% % \%))
348-
options))
349-
350-
(defmethod sql.qp/->honeysql [:databend :ends-with]
351-
[driver [_ field value options]]
352-
(databend-like-clause driver
353-
(sql.qp/->honeysql driver field)
354-
(update-string-value value #(str \% %))
355-
options))
350+
(h2x/+ dt [:raw (format "INTERVAL %d %s" (int amount) (name unit))]))
356351

357352

358353
(defmethod sql.qp/cast-temporal-byte [:databend :Coercion/ISO8601->Time]
359354
[_driver _special_type expr]
360-
(hx/->timestamp expr))
355+
(h2x/->timestamp expr))
361356

362-
;(defmethod sql-jdbc.execute/read-column-thunk [:databend Types/TIMESTAMP]
363-
; [_ ^ResultSet rs ^ResultSetMetaData _ ^Integer i]
364-
; (fn []
365-
; (let [r (.getObject rs i LocalDateTime)]
366-
; (cond (nil? r) nil
367-
; (= (.toLocalDate r) (t/local-date 1970 1 1)) (.toLocalTime r)
368-
; :else r))))
369357

370358
(defmethod sql-jdbc.execute/read-column-thunk [:databend Types/TIMESTAMP_WITH_TIMEZONE]
371359
[_ ^ResultSet rs ^ResultSetMetaData _ ^Integer i]
@@ -405,10 +393,17 @@
405393

406394
(defmethod driver/display-name :databend [_] "Databend")
407395

408-
(defmethod driver/supports? [:databend :standard-deviation-aggregations] [_ _] true)
409-
(defmethod driver/supports? [:databend :set-timezone] [_ _] true)
410-
(defmethod driver/supports? [:databend :foreign-keys] [_ _] false)
411-
(defmethod driver/supports? [:databend :test/jvm-timezone-setting] [_ _] false)
396+
(doseq [[feature supported?] {:standard-deviation-aggregations true
397+
:foreign-keys false
398+
:set-timezone false
399+
:convert-timezone false
400+
:test/jvm-timezone-setting false
401+
:connection-impersonation false
402+
:schemas true
403+
:datetime-diff true
404+
:upload-with-auto-pk false}]
405+
406+
(defmethod driver/database-supports? [:databend feature] [_driver _feature _db] supported?))
412407

413408
(defmethod sql-jdbc.sync/db-default-timezone :databend
414409
[_ spec]
@@ -420,3 +415,7 @@
420415

421416
(defmethod ddl.i/format-name :databend [_ table-or-field-name]
422417
(str/replace table-or-field-name #"-" "_"))
418+
419+
(defmethod driver.sql/set-role-statement :databend
420+
[_ role]
421+
(format "SET ROLE %s;" role))

0 commit comments

Comments
 (0)