sqlitex v1.4.0 Sqlitex.Statement
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
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 :undefinedtrue
- Converted to 1false
- Converted to 0datetime
- Converted into a string. See datetime_to_string%Decimal
- Converted into a number.
Same as bind_values/3
but raises a Sqlitex.Statement.BindValuesError on error.
Returns the statement otherwise.
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}
Same as exec/2
but raises a Sqlitex.Statement.ExecError on error.
Returns :ok otherwise.
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}
Same as fetch_all/2
but raises a Sqlitex.Statement.FetchAllError on error.
Returns the results otherwise.
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.
Same as prepare/3
but raises a Sqlitex.Statement.PrepareError on error.
Returns a new statement otherwise.