Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
gh-90016: Reword sqlite3 adapter/converter docs#93095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
598e26ae5b1b889399b5440bb59a82cf3e20b6f381c4dde4872013ef3c70d52681baadbf4cb1f2d1a0c194308ff06657f2b98e36397812bbd3dd5a2f381b6565eb45c172c7d95ac2af9433bf5af7646de6fbcff8b319b544e3b8fde821a7ebc295d89235f8d8484164b579f670e42fa68d97fcbd300b33File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Uh oh!
There was an error while loading.Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -209,31 +209,41 @@ Module functions and constants | ||
| .. data:: PARSE_DECLTYPES | ||
| Pass this flag value to the *detect_types* parameter of | ||
| :func:`connect` to look up a converter function using | ||
| the declared types for each column. | ||
| The types are declared when the database table is created. | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| ``sqlite3`` will look up a converter function using the first word of the | ||
| declared type as the converter dictionary key. | ||
| For example: | ||
| .. code-block:: sql | ||
| CREATE TABLE test( | ||
| i integer primary key, ! will look up a converter named "integer" | ||
| p point, ! will look up a converter named "point" | ||
| n number(10) ! will look up a converter named "number" | ||
| ) | ||
| This flag may be combined with :const:`PARSE_COLNAMES` using the ``|`` | ||
| (bitwise or) operator. | ||
| .. data:: PARSE_COLNAMES | ||
| Pass this flag value to the *detect_types* parameter of | ||
| :func:`connect` to look up a converter function by | ||
| using the type name, parsed from the query column name, | ||
| as the converter dictionary key. | ||
| The type name must be wrapped in square brackets (``[]``). | ||
| .. code-block:: sql | ||
| SELECT p as "p [point]" FROM test; ! will look up converter "point" | ||
| This flag may be combined with :const:`PARSE_DECLTYPES` using the ``|`` | ||
| (bitwise or) operator. | ||
| .. function:: connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri]) | ||
| @@ -257,14 +267,17 @@ Module functions and constants | ||
| SQLite natively supports only the types TEXT, INTEGER, REAL, BLOB and NULL. If | ||
| you want to use other types you must add support for them yourself. The | ||
| *detect_types* parameter and using custom **converters** registered with the | ||
| module-level :func:`register_converter` function allow you to easily do that. | ||
| *detect_types* defaults to 0 (type detection disabled). | ||
| Set it to any combination (using ``|``, bitwise or) of | ||
| :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES` | ||
| to enable type detection. | ||
| Column names takes precedence over declared types if both flags are set. | ||
| Types cannot be detected for generated fields (for example ``max(data)``), | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| even when the *detect_types* parameter is set. | ||
| In such cases, the returned type is :class:`str`. | ||
| By default, *check_same_thread* is :const:`True` and only the creating thread may | ||
| use the connection. If set :const:`False`, the returned connection may be shared | ||
| @@ -319,21 +332,27 @@ Module functions and constants | ||
| Added the ``sqlite3.connect/handle`` auditing event. | ||
| .. function:: register_converter(typename, converter) | ||
| Register the *converter* callable to convert SQLite objects of type | ||
| *typename* into a Python object of a specific type. | ||
| The converter is invoked for all SQLite values of type *typename*; | ||
| it is passed a :class:`bytes` object and should return an object of the | ||
| desired Python type. | ||
| Consult the parameter *detect_types* of | ||
| :func:`connect` for information regarding how type detection works. | ||
| Note: *typename* and the name of the type in your query are matched | ||
| case-insensitively. | ||
| .. function:: register_adapter(type,adapter) | ||
| Register an *adapter* callable to adapt the Python type *type* into an | ||
| SQLite type. | ||
| The adapter is called with a Python object of type *type* as its sole | ||
| argument, and must return a value of a | ||
| :ref:`type that SQLite natively understands<sqlite3-types>`. | ||
| .. function:: complete_statement(statement) | ||
| @@ -1246,60 +1265,53 @@ you can let the :mod:`sqlite3` module convert SQLite types to different Python | ||
| types via converters. | ||
| Using adapters to storecustom Python types in SQLite databases | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| SQLite supports only a limited set of data types natively. | ||
| To store custom Python types in SQLite databases, *adapt* them to one of the | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| :ref:`Python types SQLite natively understands<sqlite3-types>`. | ||
| There are two ways to adapt Python objects to SQLite types: | ||
| letting your object adapt itself, or using an *adapter callable*. | ||
| The latter will take precedence above the former. | ||
| For a library that exports a custom type, | ||
| it may make sense to enable that type to adapt itself. | ||
| As an application developer, it may make more sense to take direct control by | ||
| registering custom adapter functions. | ||
| Letting your object adapt itself | ||
| """""""""""""""""""""""""""""""" | ||
| Suppose we have a ``Point`` class that represents a pair of coordinates, | ||
| ``x`` and ``y``, in a Cartesian coordinate system. | ||
| The coordinate pair will be stored as a text string in the database, | ||
| using a semicolon to separate the coordinates. | ||
| This can be implemented by adding a ``__conform__(self, protocol)`` | ||
| method which returns the adapted value. | ||
| The object passed to *protocol* will be of type :class:`PrepareProtocol`. | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| .. literalinclude:: ../includes/sqlite3/adapter_point_1.py | ||
| Registering an adapter callable | ||
| """"""""""""""""""""""""""""""" | ||
| The other possibility is to create a function that converts the Python object | ||
| to an SQLite-compatible type. | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| This function can then be registered using :func:`register_adapter`. | ||
| .. literalinclude:: ../includes/sqlite3/adapter_point_2.py | ||
| Converting SQLite values to custom Python types | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| Writing an adapter lets youconvert *from*custom Python types*to* SQLite | ||
| values. | ||
| To be able to convert *from* SQLite values *to* custom Python types, | ||
| we use *converters*. | ||
| Let's go back to the :class:`Point` class. We stored the x and y coordinates | ||
| separated via semicolons as strings in SQLite. | ||
| @@ -1309,26 +1321,26 @@ and constructs a :class:`Point` object from it. | ||
| .. note:: | ||
| Converter functionsare**always**passeda :class:`bytes` object, | ||
| nomatterthe underlying SQLitedata type. | ||
| :: | ||
| def convert_point(s): | ||
| x, y = map(float, s.split(b";")) | ||
| return Point(x, y) | ||
| We now need to tell ``sqlite3`` when it should convert a given SQLite value. | ||
| This is done when connecting to a database, using the *detect_types* parameter | ||
| of :func:`connect`. There are three options: | ||
| * Implicit: set *detect_types* to :const:`PARSE_DECLTYPES` | ||
| * Explicit: set *detect_types* to :const:`PARSE_COLNAMES` | ||
| * Both: set *detect_types* to | ||
| ``sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES``. | ||
| Colum names take precedence over declared types. | ||
| The following example illustrates the implicit and explicit approaches: | ||
| .. literalinclude:: ../includes/sqlite3/converter_point.py | ||
| @@ -1362,6 +1374,52 @@ timestamp converter. | ||
| offsets in timestamps, either leave converters disabled, or register an | ||
| offset-aware converter with :func:`register_converter`. | ||
| .. _sqlite3-adapter-converter-recipes: | ||
| Adapter and Converter Recipes | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| This section shows recipes for common adapters and converters. | ||
| .. code-block:: | ||
| import datetime | ||
| import sqlite3 | ||
| def adapt_date_iso(val): | ||
| """Adapt datetime.date to ISO 8601 date.""" | ||
| return val.isoformat() | ||
| def adapt_datetime_iso(val): | ||
| """Adapt datetime.datetime to timezone-naive ISO 8601 date.""" | ||
| return val.isoformat() | ||
| def adapt_datetime_epoch(val) | ||
| """Adapt datetime.datetime to Unix timestamp.""" | ||
| return int(val.timestamp()) | ||
| sqlite3.register_adapter(datetime.date, adapt_date_iso) | ||
| sqlite3.register_adapter(datetime.datetime, adapt_datetime_iso) | ||
| sqlite3.register_adapter(datetime.datetime, adapt_datetime_epoch) | ||
| def convert_date(val): | ||
| """Convert ISO 8601 date to datetime.date object.""" | ||
| return datetime.date.fromisoformat(val) | ||
| def convert_datetime(val): | ||
| """Convert ISO 8601 datetime to datetime.datetime object.""" | ||
| return datetime.datetime.fromisoformat(val) | ||
| def convert_timestamp(val): | ||
| """Convert Unix epoch timestamp to datetime.datetime object.""" | ||
| return datetime.datetime.fromtimestamp(val) | ||
| sqlite3.register_converter("date", convert_date) | ||
| sqlite3.register_converter("datetime", convert_datetime) | ||
| sqlite3.register_converter("timestamp", convert_timestamp) | ||
| .. _sqlite3-controlling-transactions: | ||
| Controlling Transactions | ||
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.