The zodiac.ext.sql/init function accepts a map with the following keys:
Connection pool configuration passed to HikariCP. Common options:
{:jdbcUrl "jdbc:postgresql://localhost:5432/mydb"
:username "myuser"
:password "mypassword"
:maxPoolSize 10}
See HikariCP configuration for all available options.
Options for result set handling, passed to next.jdbc. Defaults to next.jdbc/snake-kebab-opts which converts snake_case column names to :kebab-case keywords.
(require '[next.jdbc.result-set :as rs])
(z.sql/init {:spec {...}
:jdbc-options {:builder-fn rs/as-unqualified-maps}})
See next.jdbc options for details.
The key used to store the database connection in the Zodiac request context. Defaults to :zodiac.ext.sql/db.
;; Use a custom key
(z.sql/init {:spec {...}
:context-key :my-app/db})
;; Access in handler
(defn handler [{:keys [::z/context]}]
(let [db (:my-app/db context)]
...))
Helper to convert a DATABASE_URL environment variable format to a JDBC URL:
(z.sql/database-url->jdbcUrl "postgresql://user:pass@localhost:5432/mydb")
;; => "jdbc:postgresql://localhost:5432/mydb?user=user&password=pass"
Supports postgresql, postgres, mysql, sqlserver, and sqlite schemes.
zodiac-sql automatically reads database timestamps as java.time.Instant via next.jdbc.date-time/read-as-instant. No configuration needed.
SQLite requires special handling for PRAGMA settings like foreign_keys, which are disabled by default.
The simplest approach is to add pragma settings as query parameters in the JDBC URL:
(z.sql/init {:spec {:jdbcUrl "jdbc:sqlite:mydb.db?foreign_keys=ON"}})
;; Multiple pragmas
(z.sql/init {:spec {:jdbcUrl "jdbc:sqlite:mydb.db?foreign_keys=ON&cache_size=-2000&busy_timeout=5000"}})
Alternatively, use HikariCP's dataSourceProperties which are passed to the SQLite driver:
(z.sql/init {:spec {:jdbcUrl "jdbc:sqlite:mydb.db"
:dataSourceProperties {:foreign_keys "true"
:busy_timeout "5000"}}})
| Pragma | Default | Recommended | Description |
|---|---|---|---|
foreign_keys | OFF | ON | Enable foreign key constraint enforcement |
journal_mode | DELETE | WAL | Write-ahead logging for better concurrency |
busy_timeout | 0 | 5000 | Milliseconds to wait when database is locked |
synchronous | FULL | NORMAL | Balance durability vs performance |
cache_size | -2000 | -2000 | Negative = KB, positive = pages |
SQLite supports loadable extensions like SpatiaLite for geospatial queries or sqlite-vec for vector search.
Loading extensions requires two steps:
connectionInitSql(z.sql/init {:spec {:jdbcUrl "jdbc:sqlite:mydb.db?enable_load_extension=true"
:connectionInitSql "SELECT load_extension('/path/to/extension')"}})
Or using dataSourceProperties:
(z.sql/init {:spec {:jdbcUrl "jdbc:sqlite:mydb.db"
:dataSourceProperties {:enable_load_extension "true"}
:connectionInitSql "SELECT load_extension('/path/to/extension')"}})
Why connectionInitSql? HikariCP manages a pool of connections. Extensions must be loaded on each connection, and connectionInitSql runs automatically whenever HikariCP creates a new connection.
Multiple extensions:
{:connectionInitSql "SELECT load_extension('/path/to/ext1'); SELECT load_extension('/path/to/ext2')"}
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |