From 886d1413751fa7b0de355b70bdef6b83ebf849e7 Mon Sep 17 00:00:00 2001 From: Alexander Oloo Date: Thu, 9 Nov 2023 21:09:17 +0200 Subject: [PATCH] update store-identity to correctly determine equivalence of configs (#26) * update store-identity to correctly determine equivalence of configs * bugfix: retain config --- build.clj | 2 +- deps.edn | 2 +- src/datahike_jdbc/core.clj | 37 +++++++++++++++------- test/datahike_jdbc/core_test.cljc | 52 +++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/build.clj b/build.clj index 567f809..dc2daa9 100644 --- a/build.clj +++ b/build.clj @@ -8,7 +8,7 @@ (def org "replikativ") (def lib 'io.replikativ/datahike-jdbc) (def current-commit (b/git-process {:git-args "rev-parse HEAD"})) -(def version (format "0.2.%s" (b/git-count-revs nil))) +(def version (format "0.3.%s" (b/git-count-revs nil))) (def class-dir "target/classes") (def basis (b/create-basis {:project "deps.edn"})) (def jar-file (format "target/%s-%s.jar" (name lib) version)) diff --git a/deps.edn b/deps.edn index e0ae974..6734285 100644 --- a/deps.edn +++ b/deps.edn @@ -1,6 +1,6 @@ {:deps {org.clojure/clojure {:mvn/version "1.11.1" :scope "provided"} io.replikativ/konserve-jdbc {:mvn/version "0.2.82"} - io.replikativ/datahike {:mvn/version "0.6.1552" :scope "provided"}} + io.replikativ/datahike {:mvn/version "0.6.1554" :scope "provided"}} :paths ["src"] :aliases {:test {:extra-paths ["test"] :extra-deps {lambdaisland/kaocha {:mvn/version "1.84.1335"} diff --git a/src/datahike_jdbc/core.clj b/src/datahike_jdbc/core.clj index b6cb89a..06ec7a6 100644 --- a/src/datahike_jdbc/core.clj +++ b/src/datahike_jdbc/core.clj @@ -2,28 +2,41 @@ (:require [datahike.store :refer [empty-store delete-store connect-store default-config config-spec release-store store-identity]] [datahike.config :refer [map-from-env]] [konserve-jdbc.core :as k] - [clojure.spec.alpha :as s])) + [next.jdbc.connection :as connection] + [clojure.spec.alpha :as s] + [clojure.string :as str])) + +(defn prepare-config [cfg] + ;; next.jdbc does not officially support the credentials in the format: driver://user:password@host/db + ;; connection/uri->db-spec makes is possible but is rough around the edges + ;; https://github.com/seancorfield/next-jdbc/issues/229 + (if (contains? cfg :jdbcUrl) + (merge + (dissoc cfg :jdbcUrl) + (-> cfg :jdbcUrl connection/uri->db-spec + (update :dbtype #(str/replace % #"postgres$" "postgresql")) + (update :port #(if (pos? %) % (-> connection/dbtypes (get (:dbtype %)) :port))))) + cfg)) (defmethod store-identity :jdbc [store-config] - (let [{:keys [jdbcUrl dbtype host port dbname table]} store-config] - (if jdbcUrl - [:jdbc jdbcUrl table] - [:jdbc dbtype host port dbname table]))) + ;; the store signature is made up of the dbtype, dbname, and table + (let [{:keys [dbtype _host _port dbname table]} (prepare-config store-config)] + [:jdbc dbtype dbname table])) (defmethod empty-store :jdbc [store-config] - (k/connect-store store-config)) + (k/connect-store (prepare-config store-config))) (defmethod delete-store :jdbc [store-config] - (k/delete-store store-config)) + (k/delete-store (prepare-config store-config))) (defmethod connect-store :jdbc [store-config] - (k/connect-store store-config)) + (k/connect-store (prepare-config store-config))) (defmethod default-config :jdbc [config] - (merge - (map-from-env :datahike-store-config {:dbtype "h2:mem" - :dbname "datahike"}) - config)) + ;; with the introduction of the store-identity config data should derived from inputs and not set to default values + (let [env-config (prepare-config (map-from-env :datahike-store-config {})) + passed-config (prepare-config config)] + (merge env-config passed-config))) (s/def :datahike.store.jdbc/backend #{:jdbc}) (s/def :datahike.store.jdbc/dbtype #{"h2" "h2:mem" "hsqldb" "jtds:sqlserver" "mysql" "oracle:oci" "oracle:thin" "postgresql" "redshift" "sqlite" "sqlserver"}) diff --git a/test/datahike_jdbc/core_test.cljc b/test/datahike_jdbc/core_test.cljc index 82d5ee5..d720e2a 100644 --- a/test/datahike_jdbc/core_test.cljc +++ b/test/datahike_jdbc/core_test.cljc @@ -183,3 +183,55 @@ (d/delete-database config2) (is (not (d/database-exists? config))) (is (not (d/database-exists? config2)))))) + +(deftest ^:integration test-signature + (let [config {:store {:backend :jdbc + :dbtype "postgresql" + :host "localhost" + :dbname "config-test" + :user "alice" + :password "foo" + :table "samezies"} + :schema-flexibility :read + :keep-history? false} + config2 {:store {:backend :jdbc + :jdbcUrl "postgresql://alice:foo@localhost/config-test" + :table "samezies"} + :schema-flexibility :read + :keep-history? false} + config3 {:store {:backend :jdbc + :jdbcUrl "postgresql://alice:foo@127.0.0.1/config-test" + :table "samezies"} + :schema-flexibility :read + :keep-history? false} + config4 {:store {:backend :jdbc + :jdbcUrl "postgresql://alice:foo@127.0.0.1/config-test" + :table "different"} + :schema-flexibility :read + :keep-history? false} + _ (d/delete-database config)] + (is (not (d/database-exists? config))) + (let [_ (d/create-database config) + conn (d/connect config) + conn2 (d/connect config2) + conn3 (d/connect config2)] + (is (not (d/database-exists? config4))) + + (d/transact conn [{:db/id 1, :name "Ivan", :age 15} + {:db/id 2, :name "Petr", :age 37} + {:db/id 3, :name "Ivan", :age 37} + {:db/id 4, :age 15}]) + (is (= (d/q '[:find ?e :where [?e :name]] @conn2) + #{[3] [2] [1]})) + + (is (= (d/q '[:find ?e :where [?e :name]] @conn3) + #{[3] [2] [1]})) + + (d/release conn) + (is (d/database-exists? config)) + (is (d/database-exists? config2)) + (is (d/database-exists? config3)) + (d/delete-database config) + (is (not (d/database-exists? config))) + (is (not (d/database-exists? config2))) + (is (not (d/database-exists? config3)))))) \ No newline at end of file