Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Clojure插入PostgreSQL数组_Sql_Postgresql_Jdbc_Clojure - Fatal编程技术网

使用Clojure插入PostgreSQL数组

使用Clojure插入PostgreSQL数组,sql,postgresql,jdbc,clojure,Sql,Postgresql,Jdbc,Clojure,我找不到用Clojure插入Postgres数组类型的方法 (sql/insert! db :things {:animals ["cow" "pig"]}) 没有达到我的预期。错误消息: PSQLException Can't infer the SQL type to use for an instance of clojure.lang.PersistentVector. Use setObject() with an explicit Types value to specify th

我找不到用Clojure插入Postgres数组类型的方法

(sql/insert! db :things {:animals ["cow" "pig"]})
没有达到我的预期。错误消息:

PSQLException Can't infer the SQL type to use for an instance of clojure.lang.PersistentVector. Use setObject() with an explicit Types value to specify the type to use.  org.postgresql.jdbc2.AbstractJdbc2Statement.setObject (AbstractJdbc2Statement.java:1936)
即使是我能找到的最直接的SQL访问也不起作用:

(sql/execute! db "INSERT INTO things (animals) VALUES ('{\"cow\", \"pig\"}')")
我真的不知道这里发生了什么:

ClassCastException java.lang.Character cannot be cast to java.lang.String  clojure.java.jdbc/prepare-statement (jdbc.clj:419)
一定有可能吧?如果不是通过helper函数,则通过某种方式执行原始SQL。

使用insert!要插入字符串向量,必须(从字符串向量)创建一个实现java.sql.Array的对象。可以使用创建这样的对象

(def con (sql/get-connection db))

(def val-to-insert 
    (.createArrayOf con "varchar" (into-array String ["cow", "pig"]))

(sql/insert! db :things {:animals val-to-insert})

jdbc在said上的文档

您必须将sql字符串放入向量中才能使其工作

(sql/execute! db ["INSERT INTO things (animals) VALUES ('{\"cow\", \"pig\"}')"])

通过扩展两个协议,可以使clojure.java.jdbc在clojure向量和SQL数组之间自动转换。这可以通过您自己的代码完成:

(extend-protocol clojure.java.jdbc/ISQLParameter
  clojure.lang.IPersistentVector
  (set-parameter [v ^java.sql.PreparedStatement stmt ^long i]
    (let [conn (.getConnection stmt)
          meta (.getParameterMetaData stmt)
          type-name (.getParameterTypeName meta i)]
      (if-let [elem-type (when (= (first type-name) \_) (apply str (rest type-name)))]
        (.setObject stmt i (.createArrayOf conn elem-type (to-array v)))
        (.setObject stmt i v)))))

(extend-protocol clojure.java.jdbc/IResultSetReadColumn
  java.sql.Array
  (result-set-read-column [val _ _]
    (into [] (.getArray val))))
REPL示例:

user> (def db (clj-postgresql.core/pool :dbname "test"))
#'user/db
user> (clojure.java.jdbc/query db ["SELECT ?::text[], ?::int[]" ["foo" "bar"] [1 2 3]])
({:int4 [1 2 3], :text ["foo" "bar"]})

我目前正在开发一个库,它将自动支持PostgreSQL和PostGIS类型。尽管我一直在使用类似的策略,但仍有很多工作在进行中:

(defn vec->arr [array-vector]
  (.createArrayOf (j/get-connection db) "varchar" (into-array String array-vector)))

(extend-protocol j/ISQLValue
    clojure.lang.IPersistentVector
    (sql-value [v]
    (vec->arr v)))
(defn vec->arr [array-vector]
  (.createArrayOf (j/get-connection db) "varchar" (into-array String array-vector)))

(extend-protocol j/ISQLValue
    clojure.lang.IPersistentVector
    (sql-value [v]
    (vec->arr v)))