# `Exqlite.Sqlite3`
[🔗](https://github.com/elixir-sqlite/exqlite/blob/v0.36.0/lib/exqlite/sqlite3.ex#L1)

The interface to the NIF implementation.

# `bind_value`

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

# `db`

```elixir
@type db() :: reference()
```

# `open_mode`

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

# `open_opt`

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

# `reason`

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

# `row`

```elixir
@type row() :: list()
```

# `statement`

```elixir
@type statement() :: reference()
```

# `bind`

```elixir
@spec bind(
  statement(),
  [bind_value()] | %{optional(String.t()) =&gt; 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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@spec bind_parameter_count(statement()) :: non_neg_integer() | {:error, atom()}
```

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`

```elixir
@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`

```elixir
@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`

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

Closes the database and releases any underlying resources.

# `columns`

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

# `deserialize`

```elixir
@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`

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

Allow loading native extensions.

# `execute`

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

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

# `fetch_all`

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

# `fetch_all`

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

# `interrupt`

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

Interrupt a long-running query.

> #### Warning {: .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`

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

# `multi_step`

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

# `multi_step`

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

# `open`

```elixir
@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`

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

# `release`

```elixir
@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`

```elixir
@spec reset(statement()) :: :ok | {:error, atom()}
```

Resets a prepared statement.

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

# `serialize`

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

Serialize the contents of the database to a binary.

# `set_authorizer`

```elixir
@spec set_authorizer(db(), [atom()]) :: :ok | {:error, reason()}
```

Set an authorizer that denies specific SQL operations.

Accepts a list of action atoms to deny. Any SQL statement that triggers a
denied action will fail with a "not authorized" error during preparation.

Pass an empty list to clear the authorizer.

## Action atoms

`:attach`, `:detach`, `:pragma`, `:insert`, `:update`, `:delete`,
`:create_table`, `:drop_table`, `:create_index`, `:drop_index`,
`:create_trigger`, `:drop_trigger`, `:create_view`, `:drop_view`,
`:alter_table`, `:reindex`, `:analyze`, `:function`, `:savepoint`,
`:transaction`, `:read`, `:select`, `:recursive`,
`:create_temp_table`, `:create_temp_index`, `:create_temp_trigger`,
`:create_temp_view`, `:drop_temp_table`, `:drop_temp_index`,
`:drop_temp_trigger`, `:drop_temp_view`, `:create_vtable`, `:drop_vtable`

## Examples

    # Block ATTACH and DETACH (prevent cross-database reads)
    :ok = Sqlite3.set_authorizer(conn, [:attach, :detach])

    # Clear the authorizer
    :ok = Sqlite3.set_authorizer(conn, [])

# `set_log_hook`

```elixir
@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:

  * `rc` is an integer [result code](https://www.sqlite.org/rescode.html) or an [extended result code](https://www.sqlite.org/rescode.html#extrc)
  * `message` is a string representing the log message

See [`SQLITE_CONFIG_LOG`](https://www.sqlite.org/c3ref/c_config_covering_index_scan.html) and
["The Error And Warning Log"](https://www.sqlite.org/errlog.html) 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`

```elixir
@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](https://www.sqlite.org/c3ref/update_hook.html)
  * 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`

```elixir
@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`

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

# `transaction_status`

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
