kura_driver behaviour (kura v2.0.6)

View Source

Pluggable database driver behaviour.

A kura_driver implementation is the seam between kura's portable query layer and a specific database client library. Each impl wraps one client (pgo, esqlite, mysql_otp, ...) behind a uniform query/transaction surface.

The pool layer (kura_pool) hands out a connection. The driver layer runs SQL on it. Splitting them lets a single pool impl (e.g. an in-memory test pool) be paired with multiple drivers, and lets a driver be swapped without touching pool semantics.

Three call shapes

query/5 runs SQL on a pool. The driver picks (or already has) a connection. Used by the common case where the caller does not own a checkout.

query_on/4 runs SQL on a specific connection the caller already holds. Used by the sandbox path: the test process owns a checked-out conn and wants every query routed to it.

transaction/3 wraps a fun in a transaction. The driver chooses how to thread connection context into queries inside the fun (process dict, explicit arg, etc.); kura code inside the fun calls kura_db:query/3 as usual and the driver's query/5 impl observes the transaction context.

Today

The canonical impl is kura_driver_pgo. It uses pgo's process-dict based transaction context (pgo_transaction_connection) so existing code that does kura_db:transaction(Repo, fun() -> kura_repo:insert(...) end) continues to work transparently.

Summary

Types

Driver-specific options. The pgo driver honors decode_opts. Other drivers may ignore unknown keys or define their own.

Parameter list in the order placeholders appear in the SQL.

Driver-specific result shape. Today this is whatever the underlying client returns (#{rows := [...], num_rows := N, ...} for pgo). A future kura layer may normalize this; the driver behaviour does not prescribe a shape.

Query SQL string. Driver impls accept iodata.

Callbacks

Optional. Create the database if missing. Called by kura_migrator.

Optional. Round-trip a trivial query against Pool (e.g. SELECT 1).

Run SQL on a pool. The driver leases a connection (via PoolMod) or threads through an active transaction context, runs the query, and returns the result.

Run SQL on a specific connection the caller already owns. Used by the sandbox path where a test process holds a checked-out conn for its lifetime.

Wrap Fun in a database transaction over a pool. Queries inside Fun route to the transaction's connection by whatever convention the driver uses (pgo: process dict).

Types

opts()

-type opts() :: map().

Driver-specific options. The pgo driver honors decode_opts. Other drivers may ignore unknown keys or define their own.

params()

-type params() :: [term()].

Parameter list in the order placeholders appear in the SQL.

query_result()

-type query_result() :: dynamic().

Driver-specific result shape. Today this is whatever the underlying client returns (#{rows := [...], num_rows := N, ...} for pgo). A future kura layer may normalize this; the driver behaviour does not prescribe a shape.

sql()

-type sql() :: iodata().

Query SQL string. Driver impls accept iodata.

Callbacks

ensure_database(Config)

(optional)
-callback ensure_database(Config :: map()) -> ok | {error, term()}.

Optional. Create the database if missing. Called by kura_migrator.

probe_pool(Pool)

(optional)
-callback probe_pool(Pool :: kura_pool:name()) -> ok | {error, term()}.

Optional. Round-trip a trivial query against Pool (e.g. SELECT 1).

query(PoolMod, Pool, SQL, Params, Opts)

-callback query(PoolMod, Pool, SQL, Params, Opts) -> query_result()
                   when
                       PoolMod :: module(),
                       Pool :: kura_pool:name(),
                       SQL :: sql(),
                       Params :: params(),
                       Opts :: opts().

Run SQL on a pool. The driver leases a connection (via PoolMod) or threads through an active transaction context, runs the query, and returns the result.

query_on(Conn, SQL, Params, Opts)

-callback query_on(Conn, SQL, Params, Opts) -> query_result()
                      when Conn :: kura_pool:conn(), SQL :: sql(), Params :: params(), Opts :: opts().

Run SQL on a specific connection the caller already owns. Used by the sandbox path where a test process holds a checked-out conn for its lifetime.

transaction(PoolMod, Pool, Fun, Opts)

-callback transaction(PoolMod, Pool, Fun, Opts) -> term()
                         when
                             PoolMod :: module(),
                             Pool :: kura_pool:name(),
                             Fun :: fun(() -> term()),
                             Opts :: opts().

Wrap Fun in a database transaction over a pool. Queries inside Fun route to the transaction's connection by whatever convention the driver uses (pgo: process dict).

Opts carries driver-specific options. The pgo driver honors pool_options => [{timeout, infinity | non_neg_integer()}] for long-running streams. Other drivers may ignore unknown keys.