Skip to content

Commit 73ee3ae

Browse files
authored
Merge pull request #8 from gizmodata/main
Re-added username/password auth. Fixed issue when selecting Date/Tim…
2 parents 64d2de2 + ceb542f commit 73ee3ae

File tree

2 files changed

+96
-52
lines changed

2 files changed

+96
-52
lines changed

resources/metabase-plugin.yaml

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,63 @@ info:
33
version: 1.0.0-SNAPSHOT-1.0.0
44
description: Allows Metabase to connect to databases via the Apache Arrow Flight SQL JDBC driver.
55

6+
# contact-info belongs at the top level (not inside driver)
7+
contact-info:
8+
name: Metabase FlightSQL Driver
9+
address: https://github.com/J0hnG4lt/metabase-flightsql-driver/issues
10+
611
driver:
712
name: arrow-flight-sql
813
display-name: Arrow Flight SQL
914
lazy-load: true
1015
parent: sql-jdbc
16+
1117
connection-properties:
12-
- name: host
13-
display-name: Host
14-
placeholder: "localhost"
15-
required: true
16-
- name: port
17-
display-name: Port
18-
placeholder: "443"
19-
required: true
18+
# Use built-in host; override placeholder if you want
19+
- merge:
20+
- host
21+
- { placeholder: "localhost" }
22+
23+
# Use built-in port; override placeholder
24+
- merge:
25+
- port
26+
- { placeholder: "443" }
27+
28+
# Username is custom (built-in is 'user'); that's fine
29+
- name: username
30+
display-name: Username (optional)
31+
required: false
32+
33+
# Built-in password; just make it optional in UI
34+
- merge:
35+
- password
36+
- { display-name: "Password (optional)", required: false }
37+
38+
# Token is a NEW field (do not use merge here)
2039
- name: token
2140
display-name: Token (optional)
2241
type: secret
42+
required: false
43+
2344
- name: useEncryption
2445
display-name: Use Encryption
2546
type: boolean
2647
default: false
48+
2749
- name: disableCertificateVerification
28-
display-name: Disable Cerificate Verification
50+
display-name: Disable Certificate Verification
2951
type: boolean
3052
default: true
53+
54+
# Advanced section helpers are literal strings
3155
- advanced-options-start
3256
- merge:
3357
- additional-options
34-
- placeholder: "threadPoolSize=1"
58+
- { placeholder: "threadPoolSize=1" }
3559
- default-advanced-options
3660

3761
init:
3862
- step: load-namespace
39-
namespace: metabase.driver.arrow-flight-sql
63+
namespace: metabase.driver.arrow-flight-sql
4064
- step: register-jdbc-driver
4165
class: org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver

src/metabase/driver/arrow_flight_sql.clj

Lines changed: 61 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
...
66
"
77
(:import
8-
(java.sql PreparedStatement Timestamp)
9-
(java.time LocalDateTime)
10-
(java.time LocalDate LocalTime OffsetDateTime)
8+
(java.sql PreparedStatement Timestamp Types Date Time)
9+
(java.time LocalDate LocalTime LocalDateTime OffsetDateTime)
1110
)
1211
(:require
1312
;; String manipulation functions.
@@ -34,10 +33,6 @@
3433

3534
))
3635

37-
;; ----------------------------------------------------------------
38-
;; Register this driver as a JDBC-based driver with parent :sql-jdbc.
39-
(driver/register! :arrow-flight-sql, :parent #{:sql-jdbc})
40-
4136
;; ----------------------------------------------------------------
4237
;; Define the display name for the Arrow Flight SQL driver.
4338
(defmethod driver/display-name :arrow-flight-sql [_]
@@ -69,42 +64,51 @@
6964
;; ----------------------------------------------------------------
7065
(defmethod sql-jdbc.conn/connection-details->spec :arrow-flight-sql
7166
[_ details]
72-
(let [{:keys [host port token useEncryption disableCertificateVerification]
67+
(let [{:keys [host port token username user password useEncryption disableCertificateVerification]
7368
:or {useEncryption true
7469
disableCertificateVerification false}} details
75-
;; URI-encode _only_ the raw token
76-
enc-token (when (and (string? token)
77-
(not (str/blank? token)))
78-
(codec/url-encode token))
79-
;; Manually assemble each key=value pair
80-
params (cond-> []
81-
enc-token (conj (str "authorization=Bearer%20" enc-token))
82-
true (conj (str "useEncryption=" useEncryption))
83-
true (conj (str "disableCertificateVerification="
84-
disableCertificateVerification)))
85-
qp (str/join "&" params)
86-
;; Build the full JDBC URI exactly as DBeaver would expect
87-
full-url (str "jdbc:arrow-flight-sql://"
88-
(or host "localhost")
89-
":"
90-
(or port 443)
91-
(when-not (str/blank? qp) (str "?" qp)))]
92-
;; Now split it into subprotocol + subname for the JDBC spec
93-
(let [scheme "jdbc:arrow-flight-sql:"
94-
subname (subs full-url (count scheme))]
95-
(-> {:classname "org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver"
96-
:subprotocol "arrow-flight-sql"
97-
:subname subname
98-
:cast (fn [col val]
99-
(if (and (= (:base-type col) :type/DateTime)
100-
(instance? java.sql.Timestamp val))
101-
(.toLocalDateTime ^java.sql.Timestamp val)
102-
val))}
103-
))))
104-
105-
106-
107-
70+
;; prefer :username (manifest) but fall back to :user
71+
username* (or (when (and (string? username) (not (str/blank? username))) username)
72+
(when (and (string? user) (not (str/blank? user))) user))
73+
74+
;; URL-encode only provided creds
75+
enc-token (when (and (string? token) (not (str/blank? token))) (codec/url-encode token))
76+
enc-user (when (and (string? username*) (not (str/blank? username*))) (codec/url-encode username*))
77+
enc-pass (when (and (string? password) (not (str/blank? password))) (codec/url-encode password))
78+
79+
;; Choose exactly ONE auth mode: token wins over user/pass
80+
auth-qps (cond
81+
enc-token [(str "authorization=Bearer%20" enc-token)]
82+
(and enc-user enc-pass) [(str "user=" enc-user)
83+
(str "password=" enc-pass)]
84+
:else [])
85+
86+
;; Build query params
87+
params (-> []
88+
(into auth-qps)
89+
(conj (str "useEncryption=" (boolean useEncryption)))
90+
(conj (str "disableCertificateVerification=" (boolean disableCertificateVerification))))
91+
qp (str/join "&" params)
92+
93+
;; Full JDBC URL
94+
full-url (str "jdbc:arrow-flight-sql://"
95+
(or host "localhost") ":"
96+
(or port 443)
97+
(when-not (str/blank? qp) (str "?" qp)))]
98+
(let [scheme "jdbc:arrow-flight-sql:"
99+
subname (subs full-url (count scheme))]
100+
{:classname "org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver"
101+
:subprotocol "arrow-flight-sql"
102+
:subname subname
103+
:cast (fn [col val]
104+
(case (:base-type col)
105+
:type/Date (if (instance? java.sql.Date val) (.toLocalDate ^java.sql.Date val) val)
106+
:type/Time (if (instance? java.sql.Time val) (.toLocalTime ^java.sql.Time val) val)
107+
:type/DateTime (cond
108+
(instance? java.sql.Timestamp val) (.toLocalDateTime ^java.sql.Timestamp val)
109+
(instance? java.time.OffsetDateTime val) (.toLocalDateTime ^java.time.OffsetDateTime val)
110+
:else val)
111+
val))})))
108112

109113
;; ----------------------------------------------------------------
110114
;; Test the connection to the Arrow Flight SQL database.
@@ -159,6 +163,22 @@
159163
(some-> (.getTimestamp rs i)
160164
.toLocalDateTime)))
161165

166+
;; ----------------------------------------------------------------
167+
;; Define a reader function for DATE columns.
168+
;; Retrieves a timestamp from the ResultSet and converts it to a local date.
169+
(defmethod sql-jdbc.execute/read-column-thunk
170+
[:arrow-flight-sql java.sql.Types/DATE]
171+
[_driver ^java.sql.ResultSet rs _rsmeta ^Integer i]
172+
(fn [] (some-> (.getDate rs i) .toLocalDate)))
173+
174+
;; ----------------------------------------------------------------
175+
;; Define a reader function for TIME columns.
176+
;; Retrieves a timestamp from the ResultSet and converts it to a local time.
177+
(defmethod sql-jdbc.execute/read-column-thunk
178+
[:arrow-flight-sql java.sql.Types/TIME]
179+
[_driver ^java.sql.ResultSet rs _rsmeta ^Integer i]
180+
(fn [] (some-> (.getTime rs i) .toLocalTime)))
181+
162182
;; ----------------------------------------------------------------
163183
;; Custom Schema Sync Implementations
164184
;; ----------------------------------------------------------------

0 commit comments

Comments
 (0)