.. _cysqlite_ext:
cysqlite Extension
==================
SQLite database implementation using `cysqlite `_
as the driver. The ``cysqlite`` extension also works with the following SQLite
extensions, which can be imported from ``playhouse.cysqlite_ext``:
* :py:class:`RowIDField`
* :py:class:`DocIDField`
* :py:class:`AutoIncrementField`
* :py:class:`ISODateTimeField`
* :py:class:`JSONField` and :py:class:`JSONPath`
* :py:class:`JSONBField` and :py:class:`JSONBPath`
* :py:class:`SearchField`
* :py:class:`VirtualModel`
* :py:class:`FTSModel`, providing full-text search.
* :py:class:`FTS5Model`, providing full-text search using FTS5.
.. py:class:: CySqliteDatabase(database, pragmas=None, timeout=5, rank_functions=True, regexp_function=True, **kwargs)
:param list pragmas: A list of 2-tuples containing pragma key and value to
set every time a connection is opened.
:param timeout: Set the busy-timeout on the SQLite driver (in seconds).
:param bool rank_functions: Make search result ranking functions available.
:param bool regexp_function: Make the REGEXP function available.
.. seealso::
CySqliteDatabase extends :py:class:`SqliteDatabase` and inherits all
methods for declaring user-defined functions, aggregates, window
functions, collations, pragmas, etc.
Example:
.. code-block:: python
db = CySqliteDatabase('app.db', pragmas={'journal_mode': 'wal'})
.. py:method:: table_function(name=None)
Class-decorator for registering a ``cysqlite.TableFunction``. Table
functions are user-defined functions that, rather than returning a
single, scalar value, can return any number of rows of tabular data.
See `cysqlite docs `_ for details on
``TableFunction`` API.
Example:
.. code-block:: python
from cysqlite import TableFunction
@db.table_function('series')
class Series(TableFunction):
columns = ['value']
params = ['start', 'stop', 'step']
def initialize(self, start=0, stop=None, step=1):
"""
Table-functions declare an initialize() method, which is
called with whatever arguments the user has called the
function with.
"""
self.start = self.current = start
self.stop = stop or float('Inf')
self.step = step
def iterate(self, idx):
"""
Iterate is called repeatedly by the SQLite database engine
until the required number of rows has been read **or** the
function raises a `StopIteration` signalling no more rows
are available.
"""
if self.current > self.stop:
raise StopIteration
ret, self.current = self.current, self.current + self.step
return (ret,)
# Usage:
cursor = db.execute_sql('SELECT * FROM series(?, ?, ?)', (0, 5, 2))
for value, in cursor:
print(value)
# Prints:
# 0
# 2
# 4
.. py:method:: unregister_table_function(name)
:param name: Name of the user-defined table function.
:returns: True or False, depending on whether the function was removed.
Unregister the user-defined scalar function.
.. py:method:: on_commit(fn)
:param fn: callable or ``None`` to clear the current hook.
Register a callback to be executed whenever a transaction is committed
on the current connection. The callback accepts no parameters and the
return value is ignored.
However, if the callback raises a :py:class:`ValueError`, the
transaction will be aborted and rolled-back.
Example:
.. code-block:: python
db = CySqliteDatabase(':memory:')
@db.on_commit
def on_commit():
logger.info('COMMITing changes')
.. py:method:: on_rollback(fn)
:param fn: callable or ``None`` to clear the current hook.
Register a callback to be executed whenever a transaction is rolled
back on the current connection. The callback accepts no parameters and
the return value is ignored.
Example:
.. code-block:: python
@db.on_rollback
def on_rollback():
logger.info('Rolling back changes')
.. py:method:: on_update(fn)
:param fn: callable or ``None`` to clear the current hook.
Register a callback to be executed whenever the database is written to
(via an *UPDATE*, *INSERT* or *DELETE* query). The callback should
accept the following parameters:
* ``query`` - the type of query, either *INSERT*, *UPDATE* or *DELETE*.
* database name - the default database is named *main*.
* table name - name of table being modified.
* rowid - the rowid of the row being modified.
The callback's return value is ignored.
Example:
.. code-block:: python
db = CySqliteDatabase(':memory:')
@db.on_update
def on_update(query_type, db, table, rowid):
# e.g. INSERT row 3 into table users.
logger.info('%s row %s into table %s', query_type, rowid, table)
.. py:method:: authorizer(fn)
:param fn: callable or ``None`` to clear the current authorizer.
Register an authorizer callback. Authorizer callbacks must accept 5
parameters, which vary depending on the operation being checked.
* op: operation code, e.g. ``cysqlite.SQLITE_INSERT``.
* p1: operation-specific value, e.g. table name for ``SQLITE_INSERT``.
* p2: operation-specific value.
* p3: database name, e.g. ``"main"``.
* p4: inner-most trigger or view responsible for the access attempt if
applicable, else ``None``.
See `sqlite authorizer documentation `_
for description of authorizer codes and values for parameters p1 and p2.
The authorizer callback must return one of:
* ``cysqlite.SQLITE_OK``: allow operation.
* ``cysqlite.SQLITE_IGNORE``: allow statement compilation but prevent
the operation from occuring.
* ``cysqlite.SQLITE_DENY``: prevent statement compilation.
More details can be found in the `cysqlite docs `_.
.. py:method:: trace(fn, mask=2):
:param fn: callable or ``None`` to clear the current trace hook.
:param int mask: mask of what types of events to trace. Default value
corresponds to ``SQLITE_TRACE_PROFILE``.
Register a trace hook (``sqlite3_trace_v2``). Trace callback must
accept 4 parameters, which vary depending on the operation being
traced.
* event: type of event, e.g. ``SQLITE_TRACE_PROFILE``.
* sid: memory address of statement (only ``SQLITE_TRACE_CLOSE``), else -1.
* sql: SQL string (only ``SQLITE_TRACE_STMT``), else None.
* ns: estimated number of nanoseconds the statement took to run (only
``SQLITE_TRACE_PROFILE``), else -1.
Any return value from callback is ignored.
More details can be found in the `cysqlite docs `_.
.. py:method:: progress(fn, n=1)
:param fn: callable or ``None`` to clear the current progress handler.
:param int n: approximate number of VM instructions to execute between
calls to the progress handler.
Register a progress handler (``sqlite3_progress_handler``). Callback
takes no arguments and returns 0 to allow progress to continue or any
non-zero value to interrupt progress.
More details can be found in the `cysqlite docs `_.
.. py:attribute:: autocommit
Property which returns a boolean indicating if autocommit is enabled.
By default, this value will be ``True`` except when inside a
transaction (or :py:meth:`~Database.atomic` block).
Example:
.. code-block:: pycon
>>> db = CySqliteDatabase(':memory:')
>>> db.autocommit
True
>>> with db.atomic():
... print(db.autocommit)
...
False
>>> db.autocommit
True
.. py:method:: backup(destination, pages=None, name=None, progress=None)
:param CySqliteDatabase destination: Database object to serve as
destination for the backup.
:param int pages: Number of pages per iteration. Default value of -1
indicates all pages should be backed-up in a single step.
:param str name: Name of source database (may differ if you used ATTACH
DATABASE to load multiple databases). Defaults to "main".
:param progress: Progress callback, called with three parameters: the
number of pages remaining, the total page count, and whether the
backup is complete.
Example:
.. code-block:: python
master = CySqliteDatabase('master.db')
replica = CySqliteDatabase('replica.db')
# Backup the contents of master to replica.
master.backup(replica)
.. py:method:: backup_to_file(filename, pages, name, progress)
:param filename: Filename to store the database backup.
:param int pages: Number of pages per iteration. Default value of -1
indicates all pages should be backed-up in a single step.
:param str name: Name of source database (may differ if you used ATTACH
DATABASE to load multiple databases). Defaults to "main".
:param progress: Progress callback, called with three parameters: the
number of pages remaining, the total page count, and whether the
backup is complete.
Backup the current database to a file. The backed-up data is not a
database dump, but an actual SQLite database file.
Example:
.. code-block:: python
db = CySqliteDatabase('app.db')
def nightly_backup():
filename = 'backup-%s.db' % (datetime.date.today())
db.backup_to_file(filename)
.. py:method:: blob_open(table, column, rowid, read_only=False)
:param str table: Name of table containing data.
:param str column: Name of column containing data.
:param int rowid: ID of row to retrieve.
:param bool read_only: Open the blob for reading only.
:param str dbname: Database name (e.g. if multiple databases attached).
:returns: ``cysqlite.Blob`` instance which provides efficient access to
the underlying binary data.
:rtype: cysqlite.Blob
See `cysqlite documentation `_ for
more details.
Example:
.. code-block:: python
class Image(Model):
filename = TextField()
data = BlobField()
buf_size = 1024 * 1024 * 8 # Allocate 8MB for storing file.
rowid = Image.insert({Image.filename: 'thefile.jpg',
Image.data: ZeroBlob(buf_size)}).execute()
# Open the blob, returning a file-like object.
blob = db.blob_open('image', 'data', rowid)
# Write some data to the blob.
blob.write(image_data)
img_size = blob.tell()
# Read the data back out of the blob.
blob.seek(0)
image_data = blob.read(img_size)
.. include:: sqlite-method-defs.rst