Skip to content

Commit 64a385e

Browse files
[3.11] pythongh-90016: Reword sqlite3 adapter/converter docs (pythonGH-93095)
Also add adapters and converter recipes. Co-authored-by: CAM Gerlach <[email protected]> Co-authored-by: Alex Waygood <[email protected]. (cherry picked from commit bd3c1c1) Co-authored-by: Erlend Egeberg Aasland <[email protected]>
1 parent 1251467 commit 64a385e

File tree

5 files changed

+156
-122
lines changed

5 files changed

+156
-122
lines changed

Doc/includes/sqlite3/adapter_datetime.py

-17
This file was deleted.

Doc/includes/sqlite3/converter_point.py

+7-14
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,33 @@ def __init__(self, x, y):
55
self.x, self.y = x, y
66

77
def __repr__(self):
8-
return "(%f;%f)" % (self.x, self.y)
8+
return f"Point({self.x}, {self.y})"
99

1010
def adapt_point(point):
11-
return ("%f;%f" % (point.x, point.y)).encode('ascii')
11+
return f"{point.x};{point.y}".encode("utf-8")
1212

1313
def convert_point(s):
1414
x, y = list(map(float, s.split(b";")))
1515
return Point(x, y)
1616

17-
# Register the adapter
17+
# Register the adapter and converter
1818
sqlite3.register_adapter(Point, adapt_point)
19-
20-
# Register the converter
2119
sqlite3.register_converter("point", convert_point)
2220

21+
# 1) Parse using declared types
2322
p = Point(4.0, -3.2)
24-
25-
#########################
26-
# 1) Using declared types
2723
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
28-
cur = con.cursor()
29-
cur.execute("create table test(p point)")
24+
cur = con.execute("create table test(p point)")
3025

3126
cur.execute("insert into test(p) values (?)", (p,))
3227
cur.execute("select p from test")
3328
print("with declared types:", cur.fetchone()[0])
3429
cur.close()
3530
con.close()
3631

37-
#######################
38-
# 1) Using column names
32+
# 2) Parse using column names
3933
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
40-
cur = con.cursor()
41-
cur.execute("create table test(p)")
34+
cur = con.execute("create table test(p)")
4235

4336
cur.execute("insert into test(p) values (?)", (p,))
4437
cur.execute('select p as "p [point]" from test')

Doc/library/sqlite3.rst

+138-80
Original file line numberDiff line numberDiff line change
@@ -199,31 +199,41 @@ Module functions and constants
199199

200200
.. data:: PARSE_DECLTYPES
201201

202-
This constant is meant to be used with the *detect_types* parameter of the
203-
:func:`connect` function.
202+
Pass this flag value to the *detect_types* parameter of
203+
:func:`connect` to look up a converter function using
204+
the declared types for each column.
205+
The types are declared when the database table is created.
206+
``sqlite3`` will look up a converter function using the first word of the
207+
declared type as the converter dictionary key.
208+
For example:
204209

205-
Setting it makes the :mod:`sqlite3` module parse the declared type for each
206-
column it returns. It will parse out the first word of the declared type,
207-
i. e. for "integer primary key", it will parse out "integer", or for
208-
"number(10)" it will parse out "number". Then for that column, it will look
209-
into the converters dictionary and use the converter function registered for
210-
that type there.
210+
211+
.. code-block:: sql
212+
213+
CREATE TABLE test(
214+
i integer primary key, ! will look up a converter named "integer"
215+
p point, ! will look up a converter named "point"
216+
n number(10) ! will look up a converter named "number"
217+
)
218+
219+
This flag may be combined with :const:`PARSE_COLNAMES` using the ``|``
220+
(bitwise or) operator.
211221

212222

213223
.. data:: PARSE_COLNAMES
214224

215-
This constant is meant to be used with the *detect_types* parameter of the
216-
:func:`connect` function.
225+
Pass this flag value to the *detect_types* parameter of
226+
:func:`connect` to look up a converter function by
227+
using the type name, parsed from the query column name,
228+
as the converter dictionary key.
229+
The type name must be wrapped in square brackets (``[]``).
230+
231+
.. code-block:: sql
217232
218-
Setting this makes the SQLite interface parse the column name for each column it
219-
returns. It will look for a string formed [mytype] in there, and then decide
220-
that 'mytype' is the type of the column. It will try to find an entry of
221-
'mytype' in the converters dictionary and then use the converter function found
222-
there to return the value. The column name found in :attr:`Cursor.description`
223-
does not include the type, i. e. if you use something like
224-
``'as "Expiration date [datetime]"'`` in your SQL, then we will parse out
225-
everything until the first ``'['`` for the column name and strip
226-
the preceding space: the column name would simply be "Expiration date".
233+
SELECT p as "p [point]" FROM test; ! will look up converter "point"
234+
235+
This flag may be combined with :const:`PARSE_DECLTYPES` using the ``|``
236+
(bitwise or) operator.
227237

228238

229239
.. function:: connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])
@@ -247,14 +257,17 @@ Module functions and constants
247257

248258
SQLite natively supports only the types TEXT, INTEGER, REAL, BLOB and NULL. If
249259
you want to use other types you must add support for them yourself. The
250-
*detect_types* parameter and the using custom **converters** registered with the
260+
*detect_types* parameter and using custom **converters** registered with the
251261
module-level :func:`register_converter` function allow you to easily do that.
252262

253-
*detect_types* defaults to 0 (i. e. off, no type detection), you can set it to
254-
any combination of :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES` to turn
255-
type detection on. Due to SQLite behaviour, types can't be detected for generated
256-
fields (for example ``max(data)``), even when *detect_types* parameter is set. In
257-
such case, the returned type is :class:`str`.
263+
*detect_types* defaults to 0 (type detection disabled).
264+
Set it to any combination (using ``|``, bitwise or) of
265+
:const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES`
266+
to enable type detection.
267+
Column names takes precedence over declared types if both flags are set.
268+
Types cannot be detected for generated fields (for example ``max(data)``),
269+
even when the *detect_types* parameter is set.
270+
In such cases, the returned type is :class:`str`.
258271

259272
By default, *check_same_thread* is :const:`True` and only the creating thread may
260273
use the connection. If set :const:`False`, the returned connection may be shared
@@ -309,21 +322,27 @@ Module functions and constants
309322
Added the ``sqlite3.connect/handle`` auditing event.
310323

311324

312-
.. function:: register_converter(typename, callable)
325+
.. function:: register_converter(typename, converter)
326+
327+
Register the *converter* callable to convert SQLite objects of type
328+
*typename* into a Python object of a specific type.
329+
The converter is invoked for all SQLite values of type *typename*;
330+
it is passed a :class:`bytes` object and should return an object of the
331+
desired Python type.
332+
Consult the parameter *detect_types* of
333+
:func:`connect` for information regarding how type detection works.
313334

314-
Registers a callable to convert a bytestring from the database into a custom
315-
Python type. The callable will be invoked for all database values that are of
316-
the type *typename*. Confer the parameter *detect_types* of the :func:`connect`
317-
function for how the type detection works. Note that *typename* and the name of
318-
the type in your query are matched in case-insensitive manner.
335+
Note: *typename* and the name of the type in your query are matched
336+
case-insensitively.
319337

320338

321-
.. function:: register_adapter(type, callable)
339+
.. function:: register_adapter(type, adapter)
322340

323-
Registers a callable to convert the custom Python type *type* into one of
324-
SQLite's supported types. The callable *callable* accepts as single parameter
325-
the Python value, and must return a value of the following types: int,
326-
float, str or bytes.
341+
Register an *adapter* callable to adapt the Python type *type* into an
342+
SQLite type.
343+
The adapter is called with a Python object of type *type* as its sole
344+
argument, and must return a value of a
345+
:ref:`type that SQLite natively understands<sqlite3-types>`.
327346

328347

329348
.. function:: complete_statement(statement)
@@ -1236,60 +1255,53 @@ you can let the :mod:`sqlite3` module convert SQLite types to different Python
12361255
types via converters.
12371256

12381257

1239-
Using adapters to store additional Python types in SQLite databases
1240-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1258+
Using adapters to store custom Python types in SQLite databases
1259+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12411260

1242-
As described before, SQLite supports only a limited set of types natively. To
1243-
use other Python types with SQLite, you must **adapt** them to one of the
1244-
sqlite3 module's supported types for SQLite: one of NoneType, int, float,
1245-
str, bytes.
1261+
SQLite supports only a limited set of data types natively.
1262+
To store custom Python types in SQLite databases, *adapt* them to one of the
1263+
:ref:`Python types SQLite natively understands<sqlite3-types>`.
12461264

1247-
There are two ways to enable the :mod:`sqlite3` module to adapt a custom Python
1248-
type to one of the supported ones.
1265+
There are two ways to adapt Python objects to SQLite types:
1266+
letting your object adapt itself, or using an *adapter callable*.
1267+
The latter will take precedence above the former.
1268+
For a library that exports a custom type,
1269+
it may make sense to enable that type to adapt itself.
1270+
As an application developer, it may make more sense to take direct control by
1271+
registering custom adapter functions.
12491272

12501273

12511274
Letting your object adapt itself
12521275
""""""""""""""""""""""""""""""""
12531276

1254-
This is a good approach if you write the class yourself. Let's suppose you have
1255-
a class like this::
1256-
1257-
class Point:
1258-
def __init__(self, x, y):
1259-
self.x, self.y = x, y
1260-
1261-
Now you want to store the point in a single SQLite column. First you'll have to
1262-
choose one of the supported types to be used for representing the point.
1263-
Let's just use str and separate the coordinates using a semicolon. Then you need
1264-
to give your class a method ``__conform__(self, protocol)`` which must return
1265-
the converted value. The parameter *protocol* will be :class:`PrepareProtocol`.
1277+
Suppose we have a ``Point`` class that represents a pair of coordinates,
1278+
``x`` and ``y``, in a Cartesian coordinate system.
1279+
The coordinate pair will be stored as a text string in the database,
1280+
using a semicolon to separate the coordinates.
1281+
This can be implemented by adding a ``__conform__(self, protocol)``
1282+
method which returns the adapted value.
1283+
The object passed to *protocol* will be of type :class:`PrepareProtocol`.
12661284

12671285
.. literalinclude:: ../includes/sqlite3/adapter_point_1.py
12681286

12691287

12701288
Registering an adapter callable
12711289
"""""""""""""""""""""""""""""""
12721290

1273-
The other possibility is to create a function that converts the type to the
1274-
string representation and register the function with :meth:`register_adapter`.
1291+
The other possibility is to create a function that converts the Python object
1292+
to an SQLite-compatible type.
1293+
This function can then be registered using :func:`register_adapter`.
12751294

12761295
.. literalinclude:: ../includes/sqlite3/adapter_point_2.py
12771296

1278-
The :mod:`sqlite3` module has two default adapters for Python's built-in
1279-
:class:`datetime.date` and :class:`datetime.datetime` types. Now let's suppose
1280-
we want to store :class:`datetime.datetime` objects not in ISO representation,
1281-
but as a Unix timestamp.
1282-
1283-
.. literalinclude:: ../includes/sqlite3/adapter_datetime.py
1284-
12851297

12861298
Converting SQLite values to custom Python types
12871299
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12881300

1289-
Writing an adapter lets you send custom Python types to SQLite. But to make it
1290-
really useful we need to make the Python to SQLite to Python roundtrip work.
1291-
1292-
Enter converters.
1301+
Writing an adapter lets you convert *from* custom Python types *to* SQLite
1302+
values.
1303+
To be able to convert *from* SQLite values *to* custom Python types,
1304+
we use *converters*.
12931305

12941306
Let's go back to the :class:`Point` class. We stored the x and y coordinates
12951307
separated via semicolons as strings in SQLite.
@@ -1299,26 +1311,26 @@ and constructs a :class:`Point` object from it.
12991311

13001312
.. note::
13011313

1302-
Converter functions **always** get called with a :class:`bytes` object, no
1303-
matter under which data type you sent the value to SQLite.
1314+
Converter functions are **always** passed a :class:`bytes` object,
1315+
no matter the underlying SQLite data type.
13041316

13051317
::
13061318

13071319
def convert_point(s):
13081320
x, y = map(float, s.split(b";"))
13091321
return Point(x, y)
13101322

1311-
Now you need to make the :mod:`sqlite3` module know that what you select from
1312-
the database is actually a point. There are two ways of doing this:
1313-
1314-
* Implicitly via the declared type
1323+
We now need to tell ``sqlite3`` when it should convert a given SQLite value.
1324+
This is done when connecting to a database, using the *detect_types* parameter
1325+
of :func:`connect`. There are three options:
13151326

1316-
* Explicitly via the column name
1327+
* Implicit: set *detect_types* to :const:`PARSE_DECLTYPES`
1328+
* Explicit: set *detect_types* to :const:`PARSE_COLNAMES`
1329+
* Both: set *detect_types* to
1330+
``sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES``.
1331+
Colum names take precedence over declared types.
13171332

1318-
Both ways are described in section :ref:`sqlite3-module-contents`, in the entries
1319-
for the constants :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES`.
1320-
1321-
The following example illustrates both approaches.
1333+
The following example illustrates the implicit and explicit approaches:
13221334

13231335
.. literalinclude:: ../includes/sqlite3/converter_point.py
13241336

@@ -1352,6 +1364,52 @@ timestamp converter.
13521364
offsets in timestamps, either leave converters disabled, or register an
13531365
offset-aware converter with :func:`register_converter`.
13541366

1367+
1368+
.. _sqlite3-adapter-converter-recipes:
1369+
1370+
Adapter and Converter Recipes
1371+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1372+
1373+
This section shows recipes for common adapters and converters.
1374+
1375+
.. code-block::
1376+
1377+
import datetime
1378+
import sqlite3
1379+
1380+
def adapt_date_iso(val):
1381+
"""Adapt datetime.date to ISO 8601 date."""
1382+
return val.isoformat()
1383+
1384+
def adapt_datetime_iso(val):
1385+
"""Adapt datetime.datetime to timezone-naive ISO 8601 date."""
1386+
return val.isoformat()
1387+
1388+
def adapt_datetime_epoch(val)
1389+
"""Adapt datetime.datetime to Unix timestamp."""
1390+
return int(val.timestamp())
1391+
1392+
sqlite3.register_adapter(datetime.date, adapt_date_iso)
1393+
sqlite3.register_adapter(datetime.datetime, adapt_datetime_iso)
1394+
sqlite3.register_adapter(datetime.datetime, adapt_datetime_epoch)
1395+
1396+
def convert_date(val):
1397+
"""Convert ISO 8601 date to datetime.date object."""
1398+
return datetime.date.fromisoformat(val)
1399+
1400+
def convert_datetime(val):
1401+
"""Convert ISO 8601 datetime to datetime.datetime object."""
1402+
return datetime.datetime.fromisoformat(val)
1403+
1404+
def convert_timestamp(val):
1405+
"""Convert Unix epoch timestamp to datetime.datetime object."""
1406+
return datetime.datetime.fromtimestamp(val)
1407+
1408+
sqlite3.register_converter("date", convert_date)
1409+
sqlite3.register_converter("datetime", convert_datetime)
1410+
sqlite3.register_converter("timestamp", convert_timestamp)
1411+
1412+
13551413
.. _sqlite3-controlling-transactions:
13561414

13571415
Controlling Transactions

Modules/_sqlite/clinic/module.c.h

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)