sql

Mateusz Mazurczak 2025-09-19T15:29:42.204149Z

[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!).

seancorfield 2025-09-19T15:54:38.030889Z

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

Mateusz Mazurczak 2025-09-19T16:16:39.592999Z

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))

👍🏻 1
seancorfield 2025-09-19T19:42:20.077139Z

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?