java.jdbc

Laziness on metadata-result results in closed resultset under Microsoft SQL

Details

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

Description

Getting a collection of tables, and then using these to get the columns inside the tables work swimmingly under Oracle, but throws an exception under Microsoft SQL (driver 4.0.2206.100)

CompilerException com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed., compiling:(form-init602030969958815921.clj:2:3)

 (def tables
    (jdbc/with-db-metadata [m db]
                           (->>
                             (jdbc/metadata-result  (.getTables m nil nil nil (into-array String ["TABLE"])))
                             (map :table_name)
                             doall)))

  (def columns
    (jdbc/with-db-metadata [m db]
                      (->>
                        tables
                        (mapcat #(jdbc/metadata-result (.getColumns m nil nil % nil)))
                        doall)))

The problem lies in the mapcat part. Using only map works fine, but there's no way to concat before the doall, since that results in the same exception.

Changing metadata-result from

(if (instance? java.sql.ResultSet rs-or-value)
    (result-set-seq rs-or-value :identifiers identifiers :as-arrays? as-arrays?)
    rs-or-value)

to

(if (instance? java.sql.ResultSet rs-or-value)
    (doall (result-set-seq rs-or-value :identifiers identifiers :as-arrays? as-arrays?))
   rs-or-value)

fixes things, but I'm not entirely sure of the consequences that would entail in case laziness would be intended.

Activity

Hide
Niels van Klaveren added a comment -

Giving metadata-result a result-set-fn parameter defaulting to either identity or doall would work, I guess.

(defn metadata-result
  "If the argument is a java.sql.ResultSet, turn it into a result-set-seq,
   else return it as-is. This makes working with metadata easier.
   Also accepts :identifiers and :as-arrays? to control how the ResultSet
   is transformed and returned. See query for more details."
  [rs-or-value & {:keys [identifiers as-arrays? result-set-fn]
                  :or {identifiers str/lower-case result-set-fn doall}}]
  (if (instance? java.sql.ResultSet rs-or-value)
    (result-set-fn (result-set-seq rs-or-value :identifiers identifiers :as-arrays? as-arrays?))
    rs-or-value))
Show
Niels van Klaveren added a comment - Giving metadata-result a result-set-fn parameter defaulting to either identity or doall would work, I guess.
(defn metadata-result
  "If the argument is a java.sql.ResultSet, turn it into a result-set-seq,
   else return it as-is. This makes working with metadata easier.
   Also accepts :identifiers and :as-arrays? to control how the ResultSet
   is transformed and returned. See query for more details."
  [rs-or-value & {:keys [identifiers as-arrays? result-set-fn]
                  :or {identifiers str/lower-case result-set-fn doall}}]
  (if (instance? java.sql.ResultSet rs-or-value)
    (result-set-fn (result-set-seq rs-or-value :identifiers identifiers :as-arrays? as-arrays?))
    rs-or-value))
Hide
Sean Corfield added a comment -

Yes, I think that is probably the right solution. I'll review it in the context of query etc and make sure it would create a consistent API. It might be worthwhile having :row-fn as well but I need to compare the functions and think carefully about the impact of those changes.

Thanx for spotting the problem!

Show
Sean Corfield added a comment - Yes, I think that is probably the right solution. I'll review it in the context of query etc and make sure it would create a consistent API. It might be worthwhile having :row-fn as well but I need to compare the functions and think carefully about the impact of those changes. Thanx for spotting the problem!
Hide
Sean Corfield added a comment -

Add :row-fn and :result-set-fn to metadata-result

Show
Sean Corfield added a comment - Add :row-fn and :result-set-fn to metadata-result
Sean Corfield made changes -
Field Original Value New Value
Resolution Completed [ 1 ]
Status Open [ 1 ] Resolved [ 5 ]

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: