|
5 | 5 | ... |
6 | 6 | " |
7 | 7 | (: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) |
11 | 10 | ) |
12 | 11 | (:require |
13 | 12 | ;; String manipulation functions. |
|
34 | 33 |
|
35 | 34 | )) |
36 | 35 |
|
37 | | -;; ---------------------------------------------------------------- |
38 | | -;; Register this driver as a JDBC-based driver with parent :sql-jdbc. |
39 | | -(driver/register! :arrow-flight-sql, :parent #{:sql-jdbc}) |
40 | | - |
41 | 36 | ;; ---------------------------------------------------------------- |
42 | 37 | ;; Define the display name for the Arrow Flight SQL driver. |
43 | 38 | (defmethod driver/display-name :arrow-flight-sql [_] |
|
69 | 64 | ;; ---------------------------------------------------------------- |
70 | 65 | (defmethod sql-jdbc.conn/connection-details->spec :arrow-flight-sql |
71 | 66 | [_ details] |
72 | | - (let [{:keys [host port token useEncryption disableCertificateVerification] |
| 67 | + (let [{:keys [host port token username user password useEncryption disableCertificateVerification] |
73 | 68 | :or {useEncryption true |
74 | 69 | 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))}))) |
108 | 112 |
|
109 | 113 | ;; ---------------------------------------------------------------- |
110 | 114 | ;; Test the connection to the Arrow Flight SQL database. |
|
159 | 163 | (some-> (.getTimestamp rs i) |
160 | 164 | .toLocalDateTime))) |
161 | 165 |
|
| 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 | + |
162 | 182 | ;; ---------------------------------------------------------------- |
163 | 183 | ;; Custom Schema Sync Implementations |
164 | 184 | ;; ---------------------------------------------------------------- |
|
0 commit comments