Project dependencies

[walkable "1.2.0-SNAPSHOT"]

Walkable is a plugin for Pathom.

Pathom is a Clojure library designed to provide a collection of helper functions to support Clojure(script) graph parsers using om.next graph syntax.

Don't worry if you don't know how Pathom works yet: Understanding Pathom is not required unless you use advanced features.

Required namespaces

(require '[com.wsscode.pathom.core :as p])
(require '[walkable.sql-query-builder :as sqb])

Depends on which DBMS you're targeting, you'll also need to require a specific namespace:

;; Postgres
(require 'walkable.sql-query-builder.impl.postgres)

or:

;; Sqlite
(require 'walkable.sql-query-builder.impl.sqlite)

but don't require both!

Mysql and other DBMSes don't require such specific namespaces.

Build the parser

First of all, you need to build pathom "parser" with walkable's sqb/pull-entities (or sqb/async-pull-entities)

Walkable comes with two versions: synchronous (for Clojure) and asynchronous (for both Clojure and Clojurescript).

Sync version
Async version
(def sync-parser
  (p/parser
    {::p/plugins
     [(p/env-plugin
        {::p/reader
        ;; walkable's main worker
         [sqb/pull-entities
         ;; pathom's entity reader
          p/map-reader]})]}))
(def async-parser
  (p/async-parser
    {::p/plugins
     [(p/env-plugin
        {::p/reader
        ;; walkable's main worker
         [sqb/async-pull-entities
         ;; pathom's entity reader
          p/map-reader]})]}))

Define the floor-plan

Then you need to define your floor-plan and compile it

;; both sync and async versions
(require '[walkable.sql-query-builder.floor-plan :as floor-plan])
(def compiled-floor-plan
  (floor-plan/compile-floor-plan
    {:emitter      ...
     :true-columns ...
     :idents       ...
     :joins        ...
     ...           ...}))

Details about the floor-plan is here.

Run your EQL queries

Ready! It's time to benefit:

Sync version:

(require '[clojure.java.jdbc :as jdbc])

(let [my-query     [{:people/all [:person/name]}]
      my-db        {:dbtype   "mysql"
                    :dbname   "clojure_test"
                    :user     "test_user"
                    :password "test_password"}
      my-run-query jdbc/query]
  (sync-parser {::sqb/sql-db     my-db
                ::sqb/run-query  my-run-query
                ::sqb/floor-plan compiled-floor-plan}
               my-query))

where my-run-query and my-db is any pair of a function plus a database instance (even a pair of mock ones!) that work together like this:

(my-run-query my-db ["select * from fruit where color = ?" "red"])
;; => [{:id 1, :color "red"} {:id 3, :color "red"} ...]

(my-run-query my-db ["select * from fruit"])
;; => [{:id 1, :color "red"} {:id 2, :color "blue"} ...]

Async version, Clojure JVM:

(require '[clojure.java.jdbc :as jdbc])
(require '[clojure.core.async :refer [go promise-chan put! >! <!]])

(let [my-query     [{:people/all [:person/name]}]
      my-db        {:dbtype   "mysql"
                    :dbname   "clojure_test"
                    :user     "test_user"
                    :password "test_password"}
      my-run-query (fn [db q]
                     (let [ch (promise-chan)]
                       (let [result (jdbc/query db q)]
                         (put! ch rersult))
                       ch))]
  (go
    (println
      (<! (async-parser
            {::sqb/sql-db     my-db
             ::sqb/run-query  my-run-query
             ::sqb/floor-plan compiled-floor-plan}
            my-query)))))

As you can see, my-run-query and my-db are similar to those in sync version, except that my-run-query doesn't return the result directly but in a channel.

For Nodejs, you'll need to convert between Javascript and Clojure data structure. The file dev.cljs has examples using sqlite3 node module.

Please see the file dev.clj (or its nodejs version dev.cljs) for executable examples. Consult config.edn for SQL migrations for those examples.

results matching ""

    No results matching ""