Most functions can also return {error, unsupported}
if the feature isn't supported in that database. For example, transactions or pubsub functionality.
start_pool(Ref, NbWorkers, PoolOpts) -> ok
stop_pool(Ref) -> ok
Start and stop a pool of workers. These functions cannot be used from inside a worker.
restart_pool(Ref, PoolOpts) -> ok
Restarts the pool, one worker at a time. This operation returns immediately and is performed asynchronously. Workers are restarted one by one, by first removing the worker from the ets table, sending a message telling it to stop, waiting for it to finish processing its requests until it can stop safely, and then starting a new worker to replace it.
The goal of this operation is to allow safe reconnection with new options while making sure we don't get any query ignored or failed, and also making sure we don't overflow the server with new connections (which is why we do one by one). This operation should take a few minutes at most.
query(Ref, Query) -> bank:result()
query(Ref, Query, Params) -> bank:result()
query(Ref, Query, Params, Opts) -> bank:result() | {async, AsyncRef}
Execute a query.
prepare(Ref, Stmt, Query) -> ok
prepare(Ref, Stmt, Query, Opts) -> ok
unprepare(Ref, Stmt) -> ok
unprepare(Ref, Stmt, Opts) -> ok
Prepare or forget a statement. These functions can only be used from inside a worker. This also means that they cannot be ran asynchronously.
execute(Ref, Stmt, Params) -> bank:result()
execute(Ref, Stmt, Params, Opts) -> bank:result() | {async, AsyncRef}
Execute a prepared statement.
batch(Ref, Fun) -> any()
batch(Ref, Fun, Opts) -> any() | {async, AsyncRef}
Execute a batch fun from in a worker context.
transaction(Ref, Fun) -> any()
transaction(Ref, Fun, Opts) -> any() | {async, AsyncRef}
Execute a batch fun inside a transaction in a worker context.
sub(Ref, Channel) -> ok
sub(Ref, Channel, Opts) -> ok | {async, AsyncRef}
Subscribe to Channel
if the server supports notifications. This function cannot be used from inside a worker.
unsub(Ref, Channel) -> ok
unsub(Ref, Channel, Opts) -> ok | {async, AsyncRef}
Unsubscribe from Channel
. This function cannot be used from inside a worker.
pub(Ref, Channel, Message) -> ok
pub(Ref, Channel, Message, Opts) -> ok | {async, AsyncRef}
Publish to Channel
.
{driver, BankDriver, DriverOpts}
Driver to be used. Example: {driver, bank_pgsql, {tcp, Host, Port, [{username, Username}, {password, Password}]}}
.
{connect_retry, Time = 5000}
Time before reconnecting when the connection fails. Bank never gives up reconnecting.
{keepalive, Time = 10000}
Interval between pings.
{onconnect, Fun}
Fun that will be executed on connect.
These options are common to all kinds of queries.
async
Whether to return immediately. A ref AsyncRef
is returned to identify the result of the query that will be sent as a message.
{timeout, Time = infinity}
Timeout before giving up on the query.
{bank, AsyncRef, ok, AffectedRows, InsertID}
{bank, AsyncRef, rows, fin | nofin, Rows}
: there might be more than one such message sent,fin
indicates the last message{bank, AsyncRef, error, Reason, String}
{bank, AsyncRef, notify, Message}
I like the API including the pool in this case. You almost never just want a single connection but... it would be nice to see a single connection api as well. That would be easy enough to create given the drivers have the same API.
The pool part in erlang is actually a little more interesting due to the lack of true shared memory besides ets.