Skip to content

Commit

Permalink
Refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
niwinz committed Jul 8, 2019
1 parent e6ab111 commit fd9ea23
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 311 deletions.
17 changes: 17 additions & 0 deletions CHANGES.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
= Changelog

== 2.0.0

Date: unreleased

BREAKING CHANGES:
- `suricatta.format` namespace is removed
- `suricatta.dsl` namespace is removed
- dbspec connection format is removed (now only the simplest methods
are supported: `DataSource` instance and URL.
- `cursor->lazyseq` is renamed to `cursor->seq`
- New and simplfied method for add type extensions (see docs).

Other changes:
- Many performance improvements on standart queries.
- Many performance improvements on lazy fetching.


== 1.3.1

Date: 2016-12-25
Expand Down
11 changes: 2 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,16 @@ High level sql toolkit for clojure (backed by jooq library)
Put suricatta on your dependency list:

```clojure
[funcool/suricatta "1.3.1"]
[funcool/suricatta "2.0.0"]
[com.h2database/h2 "1.4.191"] ;; For this example only
```

Define a valid dbspec hashmap:

```clojure
(def dbspec {:subprotocol "h2"
:subname "mem:"})
```

Connect to the database and execute a query:

```clojure
(require '[suricatta.core :as sc])

(with-open [ctx (sc/context dbspec)]
(with-open [ctx (sc/context "h2:mem:")]
(sc/fetch ctx "select x from system_range(1, 2);"))
;; => [{:x 1} {:x 2}]
```
Expand Down
26 changes: 13 additions & 13 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{:deps {org.clojure/clojure {:mvn/version "1.10.1"}
org.jooq/jooq {:mvn/version "3.11.11"}}

:paths ["src"]
:aliases
{:dev {:extra-deps {com.bhauman/rebel-readline {:mvn/version "0.1.4"}
org.clojure/tools.namespace {:mvn/version "0.3.0"}
org.postgresql/postgresql {:mvn/version "42.2.6"}
com.h2database/h2 {:mvn/version "1.4.199"}
cheshire/cheshire {:mvn/version "5.8.1"}}
:extra-paths ["test"]}
:repl {:main-opts ["-m" "rebel-readline.main"]}
:ancient {:main-opts ["-m" "deps-ancient.deps-ancient"]
:extra-deps {deps-ancient {:mvn/version "RELEASE"}}}
:test {:main-opts ["-m" "user"]}
}}
:aliases {:dev {:extra-deps {com.bhauman/rebel-readline {:mvn/version "0.1.4"}
org.clojure/tools.namespace {:mvn/version "0.3.0"}
org.postgresql/postgresql {:mvn/version "42.2.6"}
com.h2database/h2 {:mvn/version "1.4.199"}
cheshire/cheshire {:mvn/version "5.8.1"}}
:extra-paths ["test"]}
:bench {:extra-deps {seancorfield/next.jdbc {:mvn/version "1.0.1"}
criterium/criterium {:mvn/version "0.4.5"}}}
:repl {:main-opts ["-m" "rebel-readline.main"]}
:ancient {:main-opts ["-m" "deps-ancient.deps-ancient"]
:extra-deps {deps-ancient {:mvn/version "RELEASE"}}}
:test {:main-opts ["-m" "user"]}
}}



131 changes: 30 additions & 101 deletions doc/content.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= suricatta documentation
Andrey Antukh, <niwi@niwi.nz>
1.3.1
2.0.0
:toc: left
:!numbered:
:source-highlighter: pygments
Expand Down Expand Up @@ -50,62 +50,33 @@ management, transaction isolation flags and sql rendering dialect.

You can create a **context** from:

- a hash-map dbspec format (plain connection params).
- a datasource instance (connection pool).
- a link:http://funcool.github.io/clojure.jdbc/latest/[clojure.jdbc] connection
instance.
- a valid jdbc url

.This is a default aspect of one dbspec.
[source,clojure]
----
(def dbspec {:subprotocol "postgresql"
:subname "//localhost:5432/dbname"
:user "username" ;; Optional
:password "password"} ;; Optional
----

==== Create Context from plain dbspec.
==== Create Context from jdbc url

.Example creating context from dbspec.
[source, clojure]
----
(require '[suricatta.core :as sc])
(with-open [ctx (sc/context {:subprotocol "h2"
:subname "mem:"})]
(do-something-with ctx))
----

==== Create Context from _clojure.jdbc_ connection.

.Example creating context from _clojure.jdbc_ connection instance.
[source, clojure]
----
(require '[jdbc.core :as jdbc])
(require '[suricatta.core :as sc])
(def dbspec {:subprotocol "h2"
:subname "mem:"})
(with-open [conn (jdbc/connection dbspec)
ctx (sc/context conn)]
(do-something ctx))
(with-open [ctx (sc/context "h2:mem:")]
(do-something-with ctx))
----

NOTE: when closing the _suricatta_ context, the wrapped connection will also be closed.


==== Create Context from DataSource.

DataSource is the preferd way to connect to the database in production enviroments
and is usually used to implement connection pools.

In our case we will use *hikaricp* as a datasource with a connection pool. Lets
start by adding hikari's dependency entry to your _project.clj_:
start by adding hikari's dependency entry to your _deps.edn_:

[source, clojure]
----
[hikari-cp "0.13.0" :exclusions [com.zaxxer/HikariCP]]
[com.zaxxer/HikariCP-java6 "2.2.5"]
hikari-cp/hikari-cp {:mvn/version "2.7.1"}
----

Now create the datasource instance:
Expand All @@ -114,19 +85,19 @@ Now create the datasource instance:
----
(require '[hikari-cp.core :as hikari])
(def ^javax.sql.Datasource
datasource (hikari/make-datasource
{:connection-timeout 30000
:idle-timeout 600000
:max-lifetime 1800000
:minimum-idle 10
:maximum-pool-size 10
:adapter "postgresql"
:username "username"
:password "password"
:database-name "database"
:server-name "localhost"
:port-number 5432}))
(def ^javax.sql.Datasource datasource
(hikari/make-datasource
{:connection-timeout 30000
:idle-timeout 600000
:max-lifetime 1800000
:minimum-idle 10
:maximum-pool-size 10
:adapter "postgresql"
:username "username"
:password "password"
:database-name "database"
:server-name "localhost"
:port-number 5432}))
----

Now, having a datasource instace, you can use it like plain dbspec for creating
Expand Down Expand Up @@ -276,7 +247,7 @@ sequence. Let's see one example:
(sc/atomic ctx
(with-open [cursor (sc/fetch-lazy ctx sql {:fetch-size 10})]
(doseq [item (sc/cursor->lazyseq cursor)]
(doseq [item (sc/cursor->seq cursor)]
(println item))))
;; This should print something similar to:
Expand All @@ -285,8 +256,8 @@ sequence. Let's see one example:
;; ...
----

The third parameter of `sc/fetch-lazy` function is the optional default fetch
size (currently 100.)
The third parameter of `sc/fetch-lazy` function is the optional. The
default fetch size is `128`.


=== Custom types
Expand Down Expand Up @@ -357,59 +328,16 @@ contains a work in progress of the new approach.

If you want play with that look tests code to see how it works.


== FAQ

=== Why I should use suricatta instead of clojure.jdbc or java.jdbc?
=== Why I should use suricatta instead of next.jdbc or java.jdbc?

Unlike any jdbc library, _suricatta_ works at a slightly higher level. It hides a
lot of idiosyncrasies of jdbc under a much *simpler, cleaner and less error prone
api*, with better resource management.


=== Where is the async support?

In previous version _suricatta_ it had come with asynchronous support using
core.async channels as response but since the version 0.4.0 it is removed because
core.async is not a proper abstraction for represent a promise.

In the jvm world, the proper promise abstraction is introduced in JDK8 so using
that abstraction will force people use JDK8, something that I don't want to do at
this moment.

The great news is that async support is stil very easy implement, so you can do
it in your own code base defining two additional functions. Here a code snippet
for it:

[source, clojure]
----
(require '[suricatta.core :as sc]
'[cats.monad.exception :as exc]
'[promissum.core :as p])
(defn execute
"Execute a query asynchronously returning a CompletableFuture."
([ctx q]
(execute ctx q {}))
([ctx q opts]
(let [act (.-act ctx)
fun #(% (exc/try-on (sc/execute ctx q)))]
(p/promise
(fn [deliver]
(send-off act (fn [_] (fun deliver))))))))
(defn fetch
"Execute a query asynchronously returning a CompletableFuture."
([ctx q]
(fetch ctx q {}))
([ctx q opts]
(let [act (.-act ctx)
fun #(% (exc/try-on (sc/fetch ctx q opts)))]
(p/promise
(fn [deliver]
(send-off act (fn [_] (fun deliver))))))))
----


=== Why another dsl? Is it just yet another dsl?

First _suricatta_ is not a dsl library, it's a sql toolkit, and one part of the
Expand All @@ -419,13 +347,14 @@ Secondly, _suricatta_'s dsl's don't intends to be a sql abstraction. The real
purpose of _suricatta_'s dsl is make SQL composable while still allowing use all or
almost all vendor specific sql constructions.


=== What are some suricatta use cases?

The _suricatta_ library is very flexible and it can be used in very different ways:

- You can build queries with _suricatta_ and execute them with _clojure.jdbc_.
- You can build queries with _suricatta_ and execute them with _next.jdbc_.
- You can use _suricatta_ for executing queries with string-based sql.
- You can combine the _suricatta_ library with _clojure.jdbc_.
- You can combine the _suricatta_ library with _next.jdbc_.
- And obviously, you can forget jdbc and use _suricatta_ for both purposes, building
and/or executing queries.

Expand Down Expand Up @@ -496,15 +425,15 @@ git clone https://github.com/funcool/suricatta

[source, text]
----
lein test
clojure -Adev:test
----

=== License

_suricatta_ is licensed under BSD (2-Clause) license:

----
Copyright (c) 2014-2015 Andrey Antukh <[email protected]>
Copyright (c) 2014-2019 Andrey Antukh <[email protected]>
All rights reserved.
Expand Down
37 changes: 37 additions & 0 deletions scripts/bench.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
;; HOW TO RUN: clojure -J-Xmx128m -Adev:bench scripts/bench.clj

(require '[criterium.core :as b])
(require '[next.jdbc :as jdbc])
(require '[next.jdbc.result-set :as jdbc-rs])
(require '[suricatta.core :as sc])

(def uri "jdbc:postgresql://127.0.0.1/test")

(def conn1 (jdbc/get-connection uri))
(def conn2 (sc/context uri))

(def sql1 "SELECT x FROM generate_series(1, 1000) as x;")

(defn test-next-jdbc1
[]
(let [result (jdbc/execute! conn1 [sql1] {:builder-fn jdbc-rs/as-unqualified-lower-maps})]
(with-out-str
(prn result))))

(defn test-suricatta1
[]
(let [result (sc/fetch conn2 sql1)]
(with-out-str
(prn result))))

(println "***** START: next.jdbc (1) *****")
;; (b/with-progress-reporting (b/quick-bench (test-next-jdbc1) :verbose))
(b/quick-bench (test-next-jdbc1))
(println "***** END: next.jdbc (1) *****")

(println "***** START: suricatta (1) *****")
;; (b/with-progress-reporting (b/quick-bench (test-suricatta1) :verbose))
(b/quick-bench (test-suricatta1))
(println "***** END: suricatta (1) *****")


Loading

0 comments on commit fd9ea23

Please sign in to comment.