sqlitex v1.6.0 Sqlitex.Statement View Source

Provides an interface for working with SQLite prepared statements.

Care should be taken when using prepared statements directly - they are not immutable objects like most things in Elixir. Sharing a statement between different processes can cause problems if the processes accidentally interleave operations on the statement. It's a good idea to create different statements per process, or to wrap the statements up in a GenServer to prevent interleaving operations.

Example

iex(2)> {:ok, db} = Sqlitex.open(":memory:")
iex(3)> Sqlitex.query(db, "CREATE TABLE data (id, name);")
{:ok, []}
iex(4)> {:ok, statement} = Sqlitex.Statement.prepare(db, "INSERT INTO data VALUES (?, ?);")
iex(5)> Sqlitex.Statement.bind_values(statement, [1, "hello"])
iex(6)> Sqlitex.Statement.exec(statement)
:ok
iex(7)> {:ok, statement} = Sqlitex.Statement.prepare(db, "SELECT * FROM data;")
iex(8)> Sqlitex.Statement.fetch_all(statement)
{:ok, [[id: 1, name: "hello"]]}
iex(9)> Sqlitex.close(db)
:ok

RETURNING Clause Support

SQLite does not support the RETURNING extension to INSERT, DELETE, and UPDATE commands. (See https://www.postgresql.org/docs/9.6/static/sql-insert.html for a description of the Postgres implementation of this clause.)

Ecto 2.0+ relies on being able to capture this information, so have invented our own implementation with the following syntax:

;--RETURNING ON [INSERT | UPDATE | DELETE] <table>,<col>,<col>,...

When the prepare/2 and prepare!/2 functions are given a query that contains the above returning clause, they separate this clause from the end of the query and store it separately in the Statement struct. Only the portion of the query preceding the returning clause is passed to SQLite's prepare function.

Later, when such a statement struct is passed to fetch_all/2 or fetch_all!/2 the returning clause is parsed and the query is performed with the following additional logic:

SAVEPOINT sp_<random>;
CREATE TEMP TABLE temp.t_<random> (<returning>);
CREATE TEMP TRIGGER tr_<random> AFTER UPDATE ON main.<table> BEGIN
    INSERT INTO t_<random> SELECT NEW.<returning>;
END;
UPDATE ...; -- whatever the original statement was
DROP TRIGGER tr_<random>;
SELECT <returning> FROM temp.t_<random>;
DROP TABLE temp.t_<random>;
RELEASE sp_<random>;

A more detailed description of the motivations for making this change is here: https://github.com/jazzyb/sqlite_ecto/wiki/Sqlite.Ecto's-Pseudo-Returning-Clause

Link to this section Summary

Functions

Binds values to a Sqlitex.Statement.

Same as bind_values/3 but raises a Sqlitex.Statement.BindValuesError on error.

Runs a statement that returns no results.

Same as exec/2 but raises a Sqlitex.Statement.ExecError on error.

Fetches all rows using a statement.

Same as fetch_all/2 but raises a Sqlitex.Statement.FetchAllError on error.

Prepare a Sqlitex.Statement

Same as prepare/3 but raises a Sqlitex.Statement.PrepareError on error.

Link to this section Functions

Link to this function

bind_values(statement, values, opts \\ []) View Source

Binds values to a Sqlitex.Statement.

Parameters

  • statement - The statement to bind values into.
  • values - A list of values to bind into the statement.

Also accepts the following keyword options:

  • db_timeout - The time in ms allowed for the statement to run. Defaults to 5000, or the :db_timeout value in Application env.

Returns

  • {:ok, statement} on success
  • See :esqlite3.prepare for errors.

Value transformations

Some values will be transformed before insertion into the database.

  • nil - Converted to :undefined
  • true - Converted to 1
  • false - Converted to 0
  • datetime - Converted into a string. See datetime_to_string
  • %Decimal - Converted into a number.
Link to this function

bind_values!(statement, values, opts \\ []) View Source

Same as bind_values/3 but raises a Sqlitex.Statement.BindValuesError on error.

Returns the statement otherwise.

Link to this function

exec(statement, opts \\ []) View Source

Runs a statement that returns no results.

Should be called after the statement has been bound.

Parameters

  • statement - The statement to run.

Also accepts the following keyword options:

  • db_timeout - The time in ms allowed for the statement to run. Defaults to 5000, or the :db_timeout value in Application env.

Returns

  • :ok
  • {:error, error}
Link to this function

exec!(statement, opts \\ []) View Source

Same as exec/2 but raises a Sqlitex.Statement.ExecError on error.

Returns :ok otherwise.

Link to this function

fetch_all(statement, into \\ []) View Source

Fetches all rows using a statement.

Should be called after the statement has been bound.

Parameters

  • statement - The statement to run.
  • into - The collection to put the results into. Defaults to an empty list.

Returns

  • {:ok, results}
  • {:error, error}
Link to this function

fetch_all!(statement, into \\ []) View Source

Same as fetch_all/2 but raises a Sqlitex.Statement.FetchAllError on error.

Returns the results otherwise.

Link to this function

prepare(db, sql, opts \\ []) View Source

Prepare a Sqlitex.Statement

Parameters

  • db - The database to prepare the statement for.
  • sql - The SQL of the statement to prepare.

Also accepts the following keyword options:

  • db_timeout - The time in ms allowed for the statement to run. Defaults to 5000, or the :db_timeout value in Application env.

Returns

  • {:ok, statement} on success
  • See :esqlite3.prepare for errors.
Link to this function

prepare!(db, sql, opts \\ []) View Source

Same as prepare/3 but raises a Sqlitex.Statement.PrepareError on error.

Returns a new statement otherwise.