Liking cljdoc? Tell your friends :D

toucan2.delete

Implementation of delete!.

Implementation of [[delete!]].
raw docstring

toucan2.execute

Code for executing queries and statements, and reducing their results.

The functions here meant for use on a regular basis are:

  • query -- resolve and compile a connectable, execute it using a connection from a connectable, and immediately fully realize the results.

  • query-one -- like query, but only realizes the first result.

  • reducible-query -- like query, but returns a [[clojure.lang.IReduceInit]] that can be reduced later rather than immediately realizing the results.

  • with-call-count -- helper macro to count the number of queries executed within a body.

Reducible query and pipeline.

Basic execution pipeline is something this

  1. [[reduce-impl]]
    1. resolve modelable => model with toucan2.model/with-model
    2. resolve queryable => query with toucan2.query/with-resolved-query
  2. reduce-uncompiled-query
    1. Compile query => compile-query with toucan2.compile/with-compiled-query
  3. reduce-compiled-query
    1. Open conn from connectable with toucan2.connection/with-connection
  4. reduce-compiled-query-with-connection
    1. Execute and reduce the query with the open connection.
Code for executing queries and statements, and reducing their results.

The functions here meant for use on a regular basis are:

* [[query]] -- resolve and compile a connectable, execute it using a connection from a connectable, and immediately
               fully realize the results.

* [[query-one]] -- like [[query]], but only realizes the first result.

* [[reducible-query]] -- like [[query]], but returns a [[clojure.lang.IReduceInit]] that can be reduced later rather
  than immediately realizing the results.

* [[with-call-count]] -- helper macro to count the number of queries executed within a `body`.

#### Reducible query and pipeline.

Basic execution pipeline is something this

1. [[reduce-impl]]
   1. resolve `modelable` => `model` with [[toucan2.model/with-model]]
   2. resolve `queryable` => `query` with [[toucan2.query/with-resolved-query]]
2. [[reduce-uncompiled-query]]
   1. Compile `query` => `compile-query` with [[toucan2.compile/with-compiled-query]]
3. [[reduce-compiled-query]]
   1. Open `conn` from `connectable` with [[toucan2.connection/with-connection]]
4. [[reduce-compiled-query-with-connection]]
   1. Execute and reduce the query with the open connection.
raw docstring

toucan2.magic-map

A map type that automatically applies key transforms to keys when you create the map, add values to it, and when you fetch values from it.

A map type that automatically applies key transforms to keys when you create the map, add values to it, and when you
fetch values from it.
raw docstring

toucan2.query

Query compilation pipeline is something like this:

Call something like [[toucan2.select/select]] with `modelable` and `unparsed-args`
↓
`modelable` is resolved to `model` with [[toucan2.model/with-model]]
↓
[[parse-args]] is used to parse args into a `parsed-args` map
↓
The `:queryable` key in parsed args is resolved and replaced with a `:query` by [[with-resolved-query]]
↓
[[build]] takes the `:query` in the parsed args and combines the other parsed args into it to build a
compilable query. The default backend builds a Honey SQL 2 query map
↓
some sort of reducible is returned.

<reducing the reducible>
↓
[[toucan2.compile/with-compiled-query]] compiles the built query (e.g. Honey SQL 2) into something that can be
executed natively (e.g. a `sql-args` vector)
↓
[[toucan2.connection/with-connection]] is used to get a connection from the current connectable, or the default
connectable for `model`, or the global default connectable
↓
Compiled query is executed with connection
Query compilation pipeline is something like this:

```
Call something like [[toucan2.select/select]] with `modelable` and `unparsed-args`
↓
`modelable` is resolved to `model` with [[toucan2.model/with-model]]
↓
[[parse-args]] is used to parse args into a `parsed-args` map
↓
The `:queryable` key in parsed args is resolved and replaced with a `:query` by [[with-resolved-query]]
↓
[[build]] takes the `:query` in the parsed args and combines the other parsed args into it to build a
compilable query. The default backend builds a Honey SQL 2 query map
↓
some sort of reducible is returned.

<reducing the reducible>
↓
[[toucan2.compile/with-compiled-query]] compiles the built query (e.g. Honey SQL 2) into something that can be
executed natively (e.g. a `sql-args` vector)
↓
[[toucan2.connection/with-connection]] is used to get a connection from the current connectable, or the default
connectable for `model`, or the global default connectable
↓
Compiled query is executed with connection
```
raw docstring

toucan2.tools.after

Shared low-level implementation for doing transformations to the results of different operations defined with toucan2.operation.

Shared low-level implementation for doing transformations to the results of different operations defined
with [[toucan2.operation]].
raw docstring

toucan2.tools.compile

Macros that can wrap a form and return the built query, compiled query, etc. without executing it.

Macros that can wrap a form and return the built query, compiled query, etc. without executing it.
raw docstring

toucan2.tools.disallow

No vars found in this namespace.

toucan2.tools.hydrate

hydrate adds one or more keys to an instance or instances using various hydration strategies, usually using one of the existing keys in those instances. A typical use case would be to take a sequence of orders and add :user keys to them based on their values of the foreign key :user-id.

hydrate is how you use the hydration facilities; everything else in this namespace is only for extending hydration to support your models.

Toucan 2 ships with several hydration strategies out of the box:

Automagic Batched Hydration (via model-for-automagic-hydration)

hydrate attempts to do a batched hydration where possible. If the key being hydrated is defined as one of some table's model-for-automagic-hydration, hydrate will do a batched toucan2.select/select if a corresponding key (by default, the same key suffixed by -id) is found in the objects being batch hydrated. The corresponding key can be customized by implementing fk-keys-for-automagic-hydration.

(hydrate [{:user_id 100}, {:user_id 101}] :user)

Since :user is a hydration key for :models/User, a single toucan2.select/select will used to fetch Users:

(db/select :models/User :id [:in #{100 101}])

The corresponding Users are then added under the key :user.

Function-Based Batched Hydration (via batched-hydrate methods)

If the key can't be hydrated auto-magically with the appropriate model-for-automagic-hydration, hydrate will attempt to do batched hydration if it can find a matching method for batched-hydrate. If a matching function is found, it is called with a collection of objects, e.g.

(m/defmethod hydrate/batched-hydrate [:default :fields]
  [_model _k rows]
  (let [id->fields (get-some-fields rows)]
    (for [row rows]
      (assoc row :fields (get id->fields (:id row))))))

Simple Hydration (via simple-hydrate methods)

If the key is not eligible for batched hydration, hydrate will look for a matching simple-hydrate method. simple-hydrate is called with a single row.

(m/defmethod simple-hydrate [:default :dashboard]
  [_model _k {:keys [dashboard-id], :as row}]
  (assoc row :dashboard (select/select-one :models/Dashboard :toucan/pk dashboard-id)))

Hydrating Multiple Keys

You can hydrate several keys at one time:

(hydrate {...} :a :b)
  -> {:a 1, :b 2}

Nested Hydration

You can do recursive hydration by listing keys inside a vector:

(hydrate {...} [:a :b])
  -> {:a {:b 1}}

The first key in a vector will be hydrated normally, and any subsequent keys will be hydrated inside the corresponding values for that key.

(hydrate {...}
         [:a [:b :c] :e])
  -> {:a {:b {:c 1} :e 2}}

Flowchart

If you're digging in to the details, this is a flowchart of how hydration works:

                      hydrate <-------------+
                        |                   |
                    hydrate-forms           |
                        | (for each form)   |
                    hydrate-one-form        | (recursively)
                        |                   |
             keyword? --+-- sequence?       |
                |             |             |
          hydrate-key   hydrate-key-seq ----+
                |
       (for each strategy) <--------+
        ::automagic-batched         |
        ::multimethod-batched       |
        ::multimethod-simple        | (try next strategy)
                |                   |
       can-hydrate-with-strategy?   |
                |                   |
         yes ---+--- no ------------+
          |
 hydrate-with-strategy
[[hydrate]] adds one or more keys to an instance or instances using various hydration strategies, usually using one of
the existing keys in those instances. A typical use case would be to take a sequence of `orders` and add `:user` keys
to them based on their values of the foreign key `:user-id`.

[[hydrate]] is how you *use* the hydration facilities; everything else in this namespace is only for extending
hydration to support your models.

Toucan 2 ships with several hydration strategies out of the box:

#### Automagic Batched Hydration (via [[model-for-automagic-hydration]])

[[hydrate]] attempts to do a *batched hydration* where possible. If the key being hydrated is defined as one of some
table's [[model-for-automagic-hydration]], `hydrate` will do a batched
[[toucan2.select/select]] if a corresponding key (by default, the same key suffixed by `-id`) is found in the
objects being batch hydrated. The corresponding key can be customized by
implementing [[fk-keys-for-automagic-hydration]].

```clj
(hydrate [{:user_id 100}, {:user_id 101}] :user)
```

Since `:user` is a hydration key for `:models/User`, a single [[toucan2.select/select]] will used to fetch Users:

```clj
(db/select :models/User :id [:in #{100 101}])
```

The corresponding Users are then added under the key `:user`.

#### Function-Based Batched Hydration (via [[batched-hydrate]] methods)

If the key can't be hydrated auto-magically with the appropriate [[model-for-automagic-hydration]],
[[hydrate]] will attempt to do batched hydration if it can find a matching method
for [[batched-hydrate]]. If a matching function is found, it is called with a collection of
objects, e.g.

```clj
(m/defmethod hydrate/batched-hydrate [:default :fields]
  [_model _k rows]
  (let [id->fields (get-some-fields rows)]
    (for [row rows]
      (assoc row :fields (get id->fields (:id row))))))
```

#### Simple Hydration (via [[simple-hydrate]] methods)

If the key is *not* eligible for batched hydration, [[hydrate]] will look for a matching
[[simple-hydrate]] method. `simple-hydrate` is called with a single row.

```clj
(m/defmethod simple-hydrate [:default :dashboard]
  [_model _k {:keys [dashboard-id], :as row}]
  (assoc row :dashboard (select/select-one :models/Dashboard :toucan/pk dashboard-id)))
```

#### Hydrating Multiple Keys

You can hydrate several keys at one time:

```clj
(hydrate {...} :a :b)
  -> {:a 1, :b 2}
```

#### Nested Hydration

You can do recursive hydration by listing keys inside a vector:

```clj
(hydrate {...} [:a :b])
  -> {:a {:b 1}}
```

The first key in a vector will be hydrated normally, and any subsequent keys will be hydrated *inside* the
corresponding values for that key.

```clj
(hydrate {...}
         [:a [:b :c] :e])
  -> {:a {:b {:c 1} :e 2}}
```

### Flowchart

If you're digging in to the details, this is a flowchart of how hydration works:

```
                      hydrate <-------------+
                        |                   |
                    hydrate-forms           |
                        | (for each form)   |
                    hydrate-one-form        | (recursively)
                        |                   |
             keyword? --+-- sequence?       |
                |             |             |
          hydrate-key   hydrate-key-seq ----+
                |
       (for each strategy) <--------+
        ::automagic-batched         |
        ::multimethod-batched       |
        ::multimethod-simple        | (try next strategy)
                |                   |
       can-hydrate-with-strategy?   |
                |                   |
         yes ---+--- no ------------+
          |
 hydrate-with-strategy
```
raw docstring

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close