无法使用Korma(Clojure)连接到Heroku上的postgresql DB

时间:2012-11-01 11:01:15

标签: postgresql heroku clojure korma

我在Heroku的配置设置中解析postgresql uri。但我似乎无法让它发挥作用。任何帮助将不胜感激,我可能会错过一些直接的东西。

以下是使用的代码。

(def dev-db-info
  {:db "dbname"
   :user "username"})

(defn parse-db-uri
  [uri]
  (drop 1 (split uri #"://|:|@|/")))

(defn create-map-from-uri
  [uri]
  (let [parsed (parse-db-uri uri)]
  (zipmap [:user :password :host :port :db] parsed)))

(defn db-info
  []
  (if production?
    (create-map-from-uri (System/getenv "DATABASE_URL"))
    dev-db-info))

(defdb connected-db
   (postgres (db-info)))

我从uri检索的地图如下所示:

{:db "dbname"
 :port "5662"
 :host "ec2-url.compute-1.amazonaws.com"
 :password "pwd"
 :user "username"}

我收到以下错误:

Connections could not be acquired from the underlying database!

编辑:

我已经放弃使用Korma,并转而使用Clojure.JDBC 0.2.3,它支持“connection-uri”,因此支持与db的ssl连接。 Korma目前不支持这一点。我将在Github上提交一个问题以允许这种连接方法。

4 个答案:

答案 0 :(得分:5)

编辑: 没有理由再使用[org.clojars.ccfontes/korma "0.3.0-beta12-pgssl"]了。阅读this以了解更多相关信息。另外,请忽略以下说明。

添加了postgres SSL支持。

project.clj插入: [org.clojars.ccfontes/korma "0.3.0-beta12-pgssl"]

在heroku上定义与postgres数据库的连接:

(ns app.db
    (:require [clojure.java.jdbc :as sql]
              [korma.db :as db]
              [clojure.string :as string])
    (:import (java.net URI)))

    (defn set-app-pg-db! [mode]
      (let [db-uri (java.net.URI. (System/getenv "DATABASE_URL"))]
        (->> (string/split (.getUserInfo db-uri) #":")
          (#(identity {:db (last (string/split (System/getenv "DATABASE_URL") #"\/"))
                       :host (.getHost db-uri)
                       :port (.getPort db-uri)
                       :user (% 0)
                       :password (% 1)
                       :ssl true
                       :sslfactory (when (= mode :dev) "org.postgresql.ssl.NonValidatingFactory")}))
          (db/postgres)
          (db/defdb app-pg-db))))

该修补程序使用Tomcat JDBC Connection Pool及其配置示例作为连接池,因此它可能不太适合每个人的需求,而且这只是一个黑客攻击。理想情况下,原始的Korma项目应该整合这些变化或其他可能的解决方案。

非常感谢来自其他人的一些反馈,因为它仅在我自己的项目中进行过测试。感谢。

答案 1 :(得分:1)

实际上解决方案非常简单,只能在本地运行:

(defn- convert-db-uri [db-uri]
  (let [[_ user password host port db] (re-matches #"postgres://(?:(.+):(.*)@)?([^:]+)(?::(\d+))?/(.+)" db-uri)]
    {
      :user user
      :password password
      :host host
      :port (or port 80)
      :db db
    }))

(def db-spec (postgres
               (convert-db-uri
                (config/get "DATABASE_URL"))))

其中DATABASE_URL是“postgres:// user:pw @ host:port / dbname?ssl = true& sslfactory = org.postgresql.ssl.NonValidatingFactory”

似乎db名称将SSL参数转发给底层驱动程序,它只是起作用。

这是:

[korma "0.3.0-beta9"]
[org.clojure/java.jdbc "0.1.3"]
[postgresql/postgresql "9.1-901.jdbc4"]

答案 2 :(得分:1)

在您的编辑中,您提到切换到clojure.java.jdbc,因为它允许您使用连接URI启用SSL。您可以使用korma使用korma.db / defdb函数使用相同的技术,它允许您提供自己的连接URL并使用如下查询字符串启用SSL:

(defdb korma-db {:classname "org.postgresql.Driver"
                 :subprotocol "postgresql"
                 :subname "//localhost:5432/test?ssl=true"
                 :user "my-username"
                 :password "my-password"})

答案 3 :(得分:0)

FWIW,这是我用来从Heroku的DATABASE_URL得到一个clojure.java.jdbc db-spec(我认为是Korma想要的)的代码。

(def db-uri (java.net.URI. (System/getenv "DATABASE_URL")))

(def user-and-password (clojure.string/split (.getUserInfo db-uri) #":"))

(def db
  {:classname "org.postgresql.Driver"
   :subprotocol "postgresql"
   :user (get user-and-password 0)
   :password (get user-and-password 1) ; may be nil
   :subname (if (= -1 (.getPort db-uri))
              (format "//%s%s" (.getHost db-uri) (.getPath db-uri))
              (format "//%s:%s%s" (.getHost db-uri) (.getPort db-uri) (.getPath db-uri)))})