Exqlite.Sqlite3 (Exqlite v0.33.0)

View Source

The interface to the NIF implementation.

Summary

Functions

Resets a prepared statement and binds values to it.

Binds a blob value to a prepared statement.

Binds a float value to a prepared statement.

Binds an integer value to a prepared statement.

Binds a null value to a prepared statement.

Returns number of SQL parameters in a prepared statement.

Binds a text value to a prepared statement.

Get the number of changes recently.

Closes the database and releases any underlying resources.

Disconnect from database and then reopen as an in-memory database based on the serialized binary.

Allow loading native extensions.

Executes an sql script. Multiple stanzas can be passed at once.

Interrupt a long-running query.

Opens a new sqlite database at the Path provided.

Once finished with the prepared statement, call this to release the underlying resources.

Resets a prepared statement.

Serialize the contents of the database to a binary.

Send log messages to a process.

Send data change notifications to a process.

Causes the database connection to free as much memory as it can. This is useful if you are on a memory restricted system.

Types

bind_value()

@type bind_value() ::
  NaiveDateTime.t()
  | DateTime.t()
  | Date.t()
  | Time.t()
  | number()
  | iodata()
  | {:blob, iodata()}
  | atom()

db()

@type db() :: reference()

open_mode()

@type open_mode() :: :readwrite | :readonly | :nomutex

open_opt()

@type open_opt() :: {:mode, :readwrite | :readonly | [open_mode()]}

reason()

@type reason() :: atom() | String.t()

row()

@type row() :: list()

statement()

@type statement() :: reference()

Functions

bind(stmt, args)

@spec bind(
  statement(),
  [bind_value()] | %{optional(String.t()) => bind_value()} | nil
) :: :ok

Resets a prepared statement and binds values to it.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?, ?, ?, ?, ?")
iex> Sqlite3.bind(stmt, [42, 3.14, "Alice", {:blob, <<0, 0, 0>>}, nil])
iex> Sqlite3.step(conn, stmt)
{:row, [42, 3.14, "Alice", <<0, 0, 0>>, nil]}

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT :42, @pi, $name, @blob, :null")
iex> Sqlite3.bind(stmt, %{":42" => 42, "@pi" => 3.14, "$name" => "Alice", :"@blob" => {:blob, <<0, 0, 0>>}, ~c":null" => nil})
iex> Sqlite3.step(conn, stmt)
{:row, [42, 3.14, "Alice", <<0, 0, 0>>, nil]}

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind(stmt, [42, 3.14, "Alice"])
** (ArgumentError) expected 1 arguments, got 3

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?, ?")
iex> Sqlite3.bind(stmt, [42])
** (ArgumentError) expected 2 arguments, got 1

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind(stmt, [:erlang.list_to_pid(~c"<0.0.0>")])
** (ArgumentError) unsupported type: #PID<0.0.0>

bind_blob(stmt, index, blob)

@spec bind_blob(statement(), non_neg_integer(), binary()) :: :ok

Binds a blob value to a prepared statement.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind_blob(stmt, 1, <<0, 0, 0>>)
:ok

bind_float(stmt, index, float)

@spec bind_float(statement(), non_neg_integer(), float()) :: :ok

Binds a float value to a prepared statement.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind_float(stmt, 1, 3.14)
:ok

bind_integer(stmt, index, integer)

@spec bind_integer(statement(), non_neg_integer(), integer()) :: :ok

Binds an integer value to a prepared statement.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind_integer(stmt, 1, 42)
:ok

bind_null(stmt, index)

@spec bind_null(statement(), non_neg_integer()) :: :ok

Binds a null value to a prepared statement.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind_null(stmt, 1)
:ok

bind_parameter_count(stmt)

@spec bind_parameter_count(statement()) :: integer()

Returns number of SQL parameters in a prepared statement.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?, ?")
iex> Sqlite3.bind_parameter_count(stmt)
2

bind_text(stmt, index, text)

@spec bind_text(statement(), non_neg_integer(), String.t()) :: :ok

Binds a text value to a prepared statement.

iex> {:ok, conn} = Sqlite3.open(":memory:", [:readonly])
iex> {:ok, stmt} = Sqlite3.prepare(conn, "SELECT ?")
iex> Sqlite3.bind_text(stmt, 1, "Alice")
:ok

changes(conn)

@spec changes(db()) :: {:ok, integer()} | {:error, reason()}

Get the number of changes recently.

Note: If triggers are used, the count may be larger than expected.

See: https://sqlite.org/c3ref/changes.html

close(conn)

@spec close(db() | nil) :: :ok | {:error, reason()}

Closes the database and releases any underlying resources.

columns(conn, statement)

@spec columns(db(), statement()) :: {:ok, [binary()]} | {:error, reason()}

deserialize(conn, database \\ "main", serialized)

@spec deserialize(db(), String.t(), binary()) :: :ok | {:error, reason()}

Disconnect from database and then reopen as an in-memory database based on the serialized binary.

enable_load_extension(conn, flag)

@spec enable_load_extension(db(), boolean()) :: :ok | {:error, reason()}

Allow loading native extensions.

execute(conn, sql)

@spec execute(db(), String.t()) :: :ok | {:error, reason()}

Executes an sql script. Multiple stanzas can be passed at once.

fetch_all(conn, statement)

@spec fetch_all(db(), statement()) :: {:ok, [row()]} | {:error, reason()}

fetch_all(conn, statement, chunk_size)

@spec fetch_all(db(), statement(), integer()) :: {:ok, [row()]} | {:error, reason()}

interrupt(conn)

@spec interrupt(db() | nil) :: :ok | {:error, reason()}

Interrupt a long-running query.

Warning

If you are going to interrupt a long running process, it is unsafe to call close/1 immediately after. You run the risk of undefined behavior. This is a limitation of the sqlite library itself. Please see the documentation https://www.sqlite.org/c3ref/interrupt.html for more information.

If close must be called after, it is best to put a short sleep in order to let sqlite finish doing its book keeping.

last_insert_rowid(conn)

@spec last_insert_rowid(db()) :: {:ok, integer()}

multi_step(conn, statement)

@spec multi_step(db(), statement()) ::
  :busy | {:rows, [row()]} | {:done, [row()]} | {:error, reason()}

multi_step(conn, statement, chunk_size)

@spec multi_step(db(), statement(), integer()) ::
  :busy | {:rows, [row()]} | {:done, [row()]} | {:error, reason()}

open(path, opts \\ [])

@spec open(String.t(), [open_opt()]) :: {:ok, db()} | {:error, reason()}

Opens a new sqlite database at the Path provided.

path can be ":memory" to keep the sqlite database in memory.

Options

  • :mode - use :readwrite to open the database for reading and writing , :readonly to open it in read-only mode or [:readonly | :readwrite, :nomutex] to open it with no mutex mode. :readwrite will also create the database if it doesn't already exist. Defaults to :readwrite. Note: [:readwrite, :nomutex] is not recommended.

prepare(conn, sql)

@spec prepare(db(), String.t()) :: {:ok, statement()} | {:error, reason()}

release(conn, statement)

@spec release(db(), statement()) :: :ok | {:error, reason()}

Once finished with the prepared statement, call this to release the underlying resources.

This should be called whenever you are done operating with the prepared statement. If the system has a high load the garbage collector may not clean up the prepared statements in a timely manner and causing higher than normal levels of memory pressure.

If you are operating on limited memory capacity systems, definitely call this.

reset(stmt)

@spec reset(statement()) :: :ok

Resets a prepared statement.

See: https://sqlite.org/c3ref/reset.html

serialize(conn, database \\ "main")

@spec serialize(db(), String.t()) :: {:ok, binary()} | {:error, reason()}

Serialize the contents of the database to a binary.

set_log_hook(pid)

@spec set_log_hook(pid()) :: :ok | {:error, reason()}

Send log messages to a process.

Each time a message is logged in SQLite a message will be sent to the pid provided as the argument.

The message is of the form: {:log, rc, message}, where:

See SQLITE_CONFIG_LOG and "The Error And Warning Log" for more details.

Restrictions

  • Only one pid can listen to the log messages at a time. If this function is called multiple times, only the last pid will receive the notifications

set_update_hook(conn, pid)

@spec set_update_hook(db(), pid()) :: :ok | {:error, reason()}

Send data change notifications to a process.

Each time an insert, update, or delete is performed on the connection provided as the first argument, a message will be sent to the pid provided as the second argument.

The message is of the form: {action, db_name, table, row_id}, where:

  • action is one of :insert, :update or :delete
  • db_name is a string representing the database name where the change took place
  • table is a string representing the table name where the change took place
  • row_id is an integer representing the unique row id assigned by SQLite

Restrictions

  • There are some conditions where the update hook will not be invoked by SQLite. See the documentation for more details
  • Only one pid can listen to the changes on a given database connection at a time. If this function is called multiple times for the same connection, only the last pid will receive the notifications
  • Updates only happen for the connection that is opened. For example, there are two connections A and B. When an update happens on connection B, the hook set for connection A will not receive the update, but the hook for connection B will receive the update.

shrink_memory(conn)

@spec shrink_memory(db()) :: :ok | {:error, reason()}

Causes the database connection to free as much memory as it can. This is useful if you are on a memory restricted system.

step(conn, statement)

@spec step(db(), statement()) :: :done | :busy | {:row, row()} | {:error, reason()}

transaction_status(conn)

@spec transaction_status(db()) :: {:ok, :idle | :transaction}