CREATE DATABASE / DROP DATABASE token-driven parser plus the
db-from-template helper used to wire a server-level config
template to a per-database config.
JSqlParser 5.x has no AST class for either statement (returns
UnsupportedStatement), so we hand-parse before JSqlParser sees
the SQL. The grammar accepted is:
CREATE DATABASE name [WITH] [(] [k [=] v [,]]* [)] DROP DATABASE [IF EXISTS] name [WITH (FORCE)]
name is either a bare identifier or a quoted identifier
("..."). Option values are 'string', "ident", number,
true|false, or a bare identifier.
Datahike-aware option keys are translated into datahike config:
BACKEND -> [:store :backend] keyword STORE_ID -> [:store :id] string PATH -> [:store :path] string (file backend) HOST / PORT / USER / -> [:store :*] string|long PASSWORD / DBNAME (pg backend) SCHEMA_FLEXIBILITY -> :schema-flexibility keyword KEEP_HISTORY -> :keep-history? boolean INDEX -> :index :datahike.index/<value>
PostgreSQL-only option keys (OWNER, TEMPLATE, ENCODING, LC_COLLATE, LC_CTYPE, LOCALE, LOCALE_PROVIDER, ICU_LOCALE, ICU_RULES, COLLATION_VERSION, TABLESPACE, ALLOW_CONNECTIONS, CONNECTION_LIMIT, IS_TEMPLATE, OID, STRATEGY, REFRESH_COLLATION_VERSION) are silently accepted with a NOTICE so pg_dump output round-trips.
Unknown option names raise :syntax-error.
CREATE DATABASE / DROP DATABASE token-driven parser plus the
`db-from-template` helper used to wire a server-level config
template to a per-database config.
JSqlParser 5.x has no AST class for either statement (returns
`UnsupportedStatement`), so we hand-parse before JSqlParser sees
the SQL. The grammar accepted is:
CREATE DATABASE name [WITH] [(] [k [=] v [,]]* [)]
DROP DATABASE [IF EXISTS] name [WITH (FORCE)]
`name` is either a bare identifier or a quoted identifier
("..."). Option values are 'string', "ident", number,
true|false, or a bare identifier.
Datahike-aware option keys are translated into datahike config:
BACKEND -> [:store :backend] keyword
STORE_ID -> [:store :id] string
PATH -> [:store :path] string (file backend)
HOST / PORT / USER / -> [:store :*] string|long
PASSWORD / DBNAME (pg backend)
SCHEMA_FLEXIBILITY -> :schema-flexibility keyword
KEEP_HISTORY -> :keep-history? boolean
INDEX -> :index :datahike.index/<value>
PostgreSQL-only option keys (OWNER, TEMPLATE, ENCODING, LC_COLLATE,
LC_CTYPE, LOCALE, LOCALE_PROVIDER, ICU_LOCALE, ICU_RULES,
COLLATION_VERSION, TABLESPACE, ALLOW_CONNECTIONS, CONNECTION_LIMIT,
IS_TEMPLATE, OID, STRATEGY, REFRESH_COLLATION_VERSION) are silently
accepted with a NOTICE so pg_dump output round-trips.
Unknown option names raise `:syntax-error`.(db-delete-from-template _server-template)Build an :on-delete-database hook that mirrors db-from-template:
release the conn and delete ITS backing store.
The store is the one the conn was opened on, read from the conn.
Rebuilding it from the template, as this did, gave an in-memory store
a FRESH random :id (ensure-store-id), so delete-database
deleted a store that never existed -- silently, under the catch --
and the dropped database stayed in the memory backend's registry,
reachable for the life of the process. pg_regress creates and drops a
fixture database per file; a run kept every one of them, about 400k
datoms each, and that is why its harness restarted the server every
30 files.
Build an `:on-delete-database` hook that mirrors `db-from-template`: release the conn and delete ITS backing store. The store is the one the conn was opened on, read from the conn. Rebuilding it from the template, as this did, gave an in-memory store a FRESH random `:id` (`ensure-store-id`), so `delete-database` deleted a store that never existed -- silently, under the catch -- and the dropped database stayed in the memory backend's registry, reachable for the life of the process. pg_regress creates and drops a fixture database per file; a run kept every one of them, about 400k datoms each, and that is why its harness restarted the server every 30 files.
(db-from-template server-template)Build an :on-create-database hook from a server-level config
template. The returned fn receives [db-name parsed-options],
merges options over the template, interpolates {{name}},
ensures a UUID :id, then runs d/create-database and
d/connect and returns the connection.
Example template: {:store {:backend :memory} :schema-flexibility :write :keep-history? false}
With {{name}} interpolation:
{:store {:backend :file :path "/var/lib/dh/{{name}}"}
:schema-flexibility :write}
Build an `:on-create-database` hook from a server-level config
template. The returned fn receives `[db-name parsed-options]`,
merges options over the template, interpolates `{{name}}`,
ensures a UUID `:id`, then runs `d/create-database` and
`d/connect` and returns the connection.
Example template:
{:store {:backend :memory}
:schema-flexibility :write
:keep-history? false}
With `{{name}}` interpolation:
{:store {:backend :file :path "/var/lib/dh/{{name}}"}
:schema-flexibility :write}(ensure-value-caps cfg)Default a server-created database to UNBOUNDED value sizes unless the operator's template says otherwise.
Datahike leaves value-size caps opt-in and warns once per
create-database that they are unset. The nudge is aimed at Datalog
applications; for a PostgreSQL surrogate the answer is not the
:value-caps :default preset, because that is Datomic parity — 4096
characters for a string — and PostgreSQL's text is bounded only by
the 1GB varlena limit. Adopting the preset would reject values a real
PostgreSQL accepts, so we record the unbounded choice explicitly
(:max-string-length 0 disables the cap) rather than inherit a
silent 4096.
An operator who wants caps sets them in the template and keeps them.
Default a server-created database to UNBOUNDED value sizes unless the operator's template says otherwise. Datahike leaves value-size caps opt-in and warns once per `create-database` that they are unset. The nudge is aimed at Datalog applications; for a PostgreSQL surrogate the answer is not the `:value-caps :default` preset, because that is Datomic parity — 4096 characters for a string — and PostgreSQL's `text` is bounded only by the 1GB varlena limit. Adopting the preset would reject values a real PostgreSQL accepts, so we record the unbounded choice explicitly (`:max-string-length 0` disables the cap) rather than inherit a silent 4096. An operator who wants caps sets them in the template and keeps them.
(options->config server-template options)Apply parsed options on top of server-template. Returns
{:config datahike-config :notices [str ...]}.
Throws :syntax-error on an unknown non-pg option.
Apply parsed options on top of `server-template`. Returns
{:config datahike-config :notices [str ...]}.
Throws `:syntax-error` on an unknown non-pg option.(parse-create-database toks)Parse a tokenised CREATE DATABASE statement. Returns: {:db-name str :if-not-exists? bool :options [[lower-case-key value] ...]}
The grammar is intentionally lenient — WITH is optional, (...)
is optional, = between key and value is optional, , between
pairs is optional. Each option value is decoded as the right
Clojure type (string for 'literal', long for digits, boolean for
true/false, raw string otherwise).
Parse a tokenised CREATE DATABASE statement. Returns:
{:db-name str
:if-not-exists? bool
:options [[lower-case-key value] ...]}
The grammar is intentionally lenient — `WITH` is optional, `(...)`
is optional, `=` between key and value is optional, `,` between
pairs is optional. Each option value is decoded as the right
Clojure type (string for 'literal', long for digits, boolean for
true/false, raw string otherwise).(parse-drop-database toks)Parse a tokenised DROP DATABASE statement. Returns: {:db-name str :if-exists? bool}
WITH (FORCE) is silently accepted but ignored — Datahike
connections are released as part of the drop regardless.
Parse a tokenised DROP DATABASE statement. Returns:
{:db-name str :if-exists? bool}
`WITH (FORCE)` is silently accepted but ignored — Datahike
connections are released as part of the drop regardless.(tokenize sql)Tokenize a SQL string into a vector of [kind text-or-value] pairs. Tokens: :ident :string :num :bool :eq :comma :lparen :rparen :semicolon.
Tokenize a SQL string into a vector of [kind text-or-value] pairs. Tokens: :ident :string :num :bool :eq :comma :lparen :rparen :semicolon.
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 |