[next.jdbc]
Hi, for sqlite when returning from execute! of a query I need to convert all values that are under :uuid type column to be uuid instead of string when returned., I would like to do it in next.jdbc using builder-fn to apply a function based on the qualified keyword (that is returned) :table-name/column-name but I think ResultSet don't have that.
I've tried implementing it with using rs/builder-adapter rs/as-maps and using getTableName getColumnName and transform them into that qualified keyword by myself, but for sqlite I sometimes get empty string as a value for it so I can't join it with columnname to get qualified keyword like :table-name/table-column.
Although I have a feeling it is somehow possible as at the end I always get correct :table-name/column-name keyword for values returned by execute!
I'm doing like this:
(def uuid-column-names
"Column names that should be converted to UUIDs"
#{"id"})
(defn valid-uuid-string?
"Check if string is a valid UUID format"
[s]
(and (string? s) (try (java.util.UUID/fromString s) true (catch Exception _ false))))
(defn uuid-column-by-index-fn
"Convert UUID strings to UUID objects for specific columns"
[builder ^java.sql.ResultSet rs ^Integer i]
(let [rsmeta (:rsmeta builder)
col-name (.getColumnName rsmeta i)
val (.getObject rs i)]
(if (and (contains? uuid-column-names col-name) (valid-uuid-string? val))
(java.util.UUID/fromString val)
val)))
But what I would like to check is to check agains :table-name/column-name (as it's correctly always returned by the execute!).It feels like you should probably be using https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.3.1070/doc/getting-started/result-set-builders#readablecolumn
I must had some cache because it is working now and I always get tablename 🤷 And btw fully qualified kw is under :cols in builder here is working snippet if anyone had the same problem
(defn uuid-column-by-index-fn
[builder ^java.sql.ResultSet rs ^Integer i]
(let [val (.getObject rs i)
builder-cols (:cols builder)
col (when builder-cols (nth builder-cols (dec i) nil))]
(if (contains? sql-schema/uuid-columns col)
(try
(parse-uuid val)
(catch Exception e
(log/log! {:level :warn
:data {:e e
:val val
:col col}} "Parsing failed")
val))
val)))
(def uuid-transformer (rs/builder-adapter rs/as-maps uuid-column-by-index-fn))Glad you got it working. That seems more straightforward than the earlier code (and likely better for your specific use case -- where you have a known set of columns that should be coerced -- than a global protocol change). I assume none of those columns can be NULL?