У меня есть функция для получения метаданных JDBC через clojure-sql
(ns relink
(:require
[clojure.contrib.sql :as sql]
[clojure.string :as str]
))
(let [db-host "localhost"
db-port 1433
db-name "databasename"]
(def db {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
:subprotocol "sqlserver"
:subname (str "//" db-host ":" db-port)
:databasename db-name
:user "user"
:password "password"}))
(defn get-table-metadata
"Take database spec, return all table names from the database metadata"
[db]
(sql/with-connection db
(doall
(resultset-seq
(.getTables
(.getMetaData (sql/connection))
nil nil "%" (into-array '("TABLE")))))))
(get-table-metadata db)
Теперь я хочу расширить эту функцию для использования других метаданных SQL, заключив вызов метода java в функцию clojure в качестве параметра, чтобы он выглядел примерно так:
(get-sql-metadata db .getTables nil nil "%" (into-array '("TABLE")))
Похоже, что сделать это невозможно без помещения (.getMetaData (sql / connection)) внутри параметра функции.
(get-sql-metadata db #(.getTables (.getMetaData (sql/connection)) nil nil "%" (into-array '("TABLE"))))
Однако я хотел бы абстрагироваться от функции get-sql-metadata, поскольку она одинакова для всех вызовов методов метаданных.
Я пытался переписать часть в resultset-seq с помощью нотаций doto, .., -> и (., Но не смог заставить ни одну из них работать.
Что я пропустил?
UPDATE:
Следующее решение работает, но требуется взлом. Я не могу поверить, что необходимо отражение в str-invoke, поэтому я не буду публиковать его как ответ.
(defn str-invoke [instance method-str & args]
(clojure.lang.Reflector/invokeInstanceMethod
instance
method-str
(to-array args)))
(defn get-sql-metadata
"Take database spec, metadata method (as string) and method parameters"
[db method & args]
(sql/with-connection db
(doall
(resultset-seq
(apply str-invoke
(.getMetaData (sql/connection))
method args)))))
(get-sql-metadata db "getTables" nil nil "%" (into-array '("TABLE")))
Проблема, похоже, в том, что apply необходимо, но нельзя использовать на. форма.