java.jdbc

make 'result-set-seq' accept customized result-set-read-column to support multi-database environment

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Using java.jdbc with postgres composite type, the common way is extend the IResultSetReadColumn protocol. When there are multiple databases in use, every database should specify it's own column reader.
Add option to 'result-set-seq' support custom function to replace IResultSetReadColumn may be a solution for this situation.

Activity

Hide
Sean Corfield added a comment -

The closest parallel with setting parameters would be to have a :read-columns option (to result-set-seq and upstream in several calling functions, as well as a per-database default in the db-spec itself).

Like :set-parameters, this :read-columns function would be expected to map over the metadata itself – it would be passed the result set object and the result set metadata object, and the default implementation would map over (range 1 (inc (.getColumnCount rsmeta))) and call (.getObject rs idx) and then convert that to Clojure based on the corresponding column in rsmeta.

That feels like a lot of "heavy lifting" but it's what folks have to do if they need per-database set-parameters behavior and it feels like the right approach (given a result set and its metadata, construct an entire row).

Would that solve your problem sufficiently?

Show
Sean Corfield added a comment - The closest parallel with setting parameters would be to have a :read-columns option (to result-set-seq and upstream in several calling functions, as well as a per-database default in the db-spec itself). Like :set-parameters, this :read-columns function would be expected to map over the metadata itself – it would be passed the result set object and the result set metadata object, and the default implementation would map over (range 1 (inc (.getColumnCount rsmeta))) and call (.getObject rs idx) and then convert that to Clojure based on the corresponding column in rsmeta. That feels like a lot of "heavy lifting" but it's what folks have to do if they need per-database set-parameters behavior and it feels like the right approach (given a result set and its metadata, construct an entire row). Would that solve your problem sufficiently?
Hide
Zhou Xiangtao added a comment -

@Sean Corfield

Yes, it would solve the problem. Is the result metadata will make the query execute twice? one for analysis metadata, another for execute the query with data. If so, the result metadata query operation take palpable time or not ? or use result set over result set metadata ?

Show
Zhou Xiangtao added a comment - @Sean Corfield Yes, it would solve the problem. Is the result metadata will make the query execute twice? one for analysis metadata, another for execute the query with data. If so, the result metadata query operation take palpable time or not ? or use result set over result set metadata ?
Hide
Sean Corfield added a comment -

The result-set-seq function already has both the metadata and the column data on hand – see this section of the code:

https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L405-L415

Currently the protocol supports a function that is passed the Object (column value), the metadata, and the 1-based column index (into the metadata). I'm suggesting a function that would be passed rs (the result set itself), rsmeta (the metadata), and idxs (the indices), and would return the row values. In the code above, row-values would change to something like:

row-values (fn [] (read-columns rs rsmeta))

And the default behavior would be:

(defn default-read-columns [rs rsmeta idxs]
  (map (fn [^Integer i] (result-set-read-column (.getObject rs i) rsmeta i)) idxs))

(this is slightly simpler than my comment above suggested a few weeks back).

Show
Sean Corfield added a comment - The result-set-seq function already has both the metadata and the column data on hand – see this section of the code: https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L405-L415 Currently the protocol supports a function that is passed the Object (column value), the metadata, and the 1-based column index (into the metadata). I'm suggesting a function that would be passed rs (the result set itself), rsmeta (the metadata), and idxs (the indices), and would return the row values. In the code above, row-values would change to something like:
row-values (fn [] (read-columns rs rsmeta))
And the default behavior would be:
(defn default-read-columns [rs rsmeta idxs]
  (map (fn [^Integer i] (result-set-read-column (.getObject rs i) rsmeta i)) idxs))
(this is slightly simpler than my comment above suggested a few weeks back).
Hide
Sean Corfield added a comment -

Will be in next release. An interim 0.6.2-SNAPSHOT release should be available on Sonatype shortly for testing.

Show
Sean Corfield added a comment - Will be in next release. An interim 0.6.2-SNAPSHOT release should be available on Sonatype shortly for testing.
Hide
Sean Corfield added a comment -

Closed by 0.7.0-alpha1 release.

Show
Sean Corfield added a comment - Closed by 0.7.0-alpha1 release.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: