@@ -239,6 +239,7 @@ inserted data and retrieved values from it in multiple ways.
239239 * :ref: `sqlite3-adapters `
240240 * :ref: `sqlite3-converters `
241241 * :ref: `sqlite3-connection-context-manager `
242+ * :ref: `sqlite3-howto-row-factory `
242243
243244 * :ref: `sqlite3-explanation ` for in-depth background on transaction control.
244245
@@ -1316,31 +1317,14 @@ Connection objects
13161317
13171318 .. attribute :: row_factory
13181319
1319- A callable that accepts two arguments,
1320- a :class: `Cursor ` object and the raw row results as a :class: `tuple `,
1321- and returns a custom object representing an SQLite row.
1322-
1323- Example:
1320+ The initial :attr: `~Cursor.row_factory `
1321+ for :class: `Cursor ` objects created from this connection.
1322+ Assigning to this attribute does not affect the :attr: `!row_factory `
1323+ of existing cursors belonging to this connection, only new ones.
1324+ Is ``None `` by default,
1325+ meaning each row is returned as a :class: `tuple `.
13241326
1325- .. doctest ::
1326-
1327- >>> def dict_factory (cursor , row ):
1328- ... col_names = [col[0 ] for col in cursor.description]
1329- ... return {key: value for key, value in zip (col_names, row)}
1330- >>> con = sqlite3.connect(" :memory:" )
1331- >>> con.row_factory = dict_factory
1332- >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
1333- ... print (row)
1334- {'a': 1, 'b': 2}
1335-
1336- If returning a tuple doesn't suffice and you want name-based access to
1337- columns, you should consider setting :attr: `row_factory ` to the
1338- highly optimized :class: `sqlite3.Row ` type. :class: `Row ` provides both
1339- index-based and case-insensitive name-based access to columns with almost no
1340- memory overhead. It will probably be better than your own custom
1341- dictionary-based approach or even a db_row based solution.
1342-
1343- .. XXX what's a db_row-based solution?
1327+ See :ref: `sqlite3-howto-row-factory ` for more details.
13441328
13451329 .. attribute :: text_factory
13461330
@@ -1497,7 +1481,7 @@ Cursor objects
14971481
14981482 .. method :: fetchone()
14991483
1500- If :attr: `~Connection .row_factory ` is ``None ``,
1484+ If :attr: `~Cursor .row_factory ` is ``None ``,
15011485 return the next row query result set as a :class: `tuple `.
15021486 Else, pass it to the row factory and return its result.
15031487 Return ``None `` if no more data is available.
@@ -1591,6 +1575,22 @@ Cursor objects
15911575 including :abbr: `CTE ( Common Table Expression ) ` queries.
15921576 It is only updated by the :meth: `execute ` and :meth: `executemany ` methods.
15931577
1578+ .. attribute :: row_factory
1579+
1580+ Control how a row fetched from this :class: `!Cursor ` is represented.
1581+ If ``None ``, a row is represented as a :class: `tuple `.
1582+ Can be set to the included :class: `sqlite3.Row `;
1583+ or a :term: `callable ` that accepts two arguments,
1584+ a :class: `Cursor ` object and the :class: `!tuple ` of row values,
1585+ and returns a custom object representing an SQLite row.
1586+
1587+ Defaults to what :attr: `Connection.row_factory ` was set to
1588+ when the :class: `!Cursor ` was created.
1589+ Assigning to this attribute does not affect
1590+ :attr: `Connection.row_factory ` of the parent connection.
1591+
1592+ See :ref: `sqlite3-howto-row-factory ` for more details.
1593+
15941594
15951595.. The sqlite3.Row example used to be a how-to. It has now been incorporated
15961596 into the Row reference. We keep the anchor here in order not to break
@@ -1609,7 +1609,10 @@ Row objects
16091609 It supports iteration, equality testing, :func: `len `,
16101610 and :term: `mapping ` access by column name and index.
16111611
1612- Two row objects compare equal if have equal columns and equal members.
1612+ Two :class: `!Row ` objects compare equal
1613+ if they have identical column names and values.
1614+
1615+ See :ref: `sqlite3-howto-row-factory ` for more details.
16131616
16141617 .. method :: keys
16151618
@@ -1620,21 +1623,6 @@ Row objects
16201623 .. versionchanged :: 3.5
16211624 Added support of slicing.
16221625
1623- Example:
1624-
1625- .. doctest ::
1626-
1627- >>> con = sqlite3.connect(" :memory:" )
1628- >>> con.row_factory = sqlite3.Row
1629- >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
1630- >>> row = res.fetchone()
1631- >>> row.keys()
1632- ['name', 'radius']
1633- >>> row[0 ], row[" name" ] # Access by index and name.
1634- ('Earth', 'Earth')
1635- >>> row[" RADIUS" ] # Column names are case-insensitive.
1636- 6378
1637-
16381626
16391627.. _sqlite3-blob-objects :
16401628
@@ -2358,6 +2346,96 @@ can be found in the `SQLite URI documentation`_.
23582346.. _SQLite URI documentation : https://www.sqlite.org/uri.html
23592347
23602348
2349+ .. _sqlite3-howto-row-factory :
2350+
2351+ How to create and use row factories
2352+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2353+
2354+ By default, :mod: `!sqlite3 ` represents each row as a :class: `tuple `.
2355+ If a :class: `!tuple ` does not suit your needs,
2356+ you can use the :class: `sqlite3.Row ` class
2357+ or a custom :attr: `~Cursor.row_factory `.
2358+
2359+ While :attr: `!row_factory ` exists as an attribute both on the
2360+ :class: `Cursor ` and the :class: `Connection `,
2361+ it is recommended to set :class: `Connection.row_factory `,
2362+ so all cursors created from the connection will use the same row factory.
2363+
2364+ :class: `!Row ` provides indexed and case-insensitive named access to columns,
2365+ with minimal memory overhead and performance impact over a :class: `!tuple `.
2366+ To use :class: `!Row ` as a row factory,
2367+ assign it to the :attr: `!row_factory ` attribute:
2368+
2369+ .. doctest ::
2370+
2371+ >>> con = sqlite3.connect(" :memory:" )
2372+ >>> con.row_factory = sqlite3.Row
2373+
2374+ Queries now return :class: `!Row ` objects:
2375+
2376+ .. doctest ::
2377+
2378+ >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
2379+ >>> row = res.fetchone()
2380+ >>> row.keys()
2381+ ['name', 'radius']
2382+ >>> row[0 ] # Access by index.
2383+ 'Earth'
2384+ >>> row[" name" ] # Access by name.
2385+ 'Earth'
2386+ >>> row[" RADIUS" ] # Column names are case-insensitive.
2387+ 6378
2388+
2389+ You can create a custom :attr: `~Cursor.row_factory `
2390+ that returns each row as a :class: `dict `, with column names mapped to values:
2391+
2392+ .. testcode ::
2393+
2394+ def dict_factory(cursor, row):
2395+ fields = [column[0] for column in cursor.description]
2396+ return {key: value for key, value in zip(fields, row)}
2397+
2398+ Using it, queries now return a :class: `!dict ` instead of a :class: `!tuple `:
2399+
2400+ .. doctest ::
2401+
2402+ >>> con = sqlite3.connect(" :memory:" )
2403+ >>> con.row_factory = dict_factory
2404+ >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
2405+ ... print (row)
2406+ {'a': 1, 'b': 2}
2407+
2408+ The following row factory returns a :term: `named tuple `:
2409+
2410+ .. testcode ::
2411+
2412+ from collections import namedtuple
2413+
2414+ def namedtuple_factory(cursor, row):
2415+ fields = [column[0] for column in cursor.description]
2416+ cls = namedtuple("Row", fields)
2417+ return cls._make(row)
2418+
2419+ :func: `!namedtuple_factory ` can be used as follows:
2420+
2421+ .. doctest ::
2422+
2423+ >>> con = sqlite3.connect(" :memory:" )
2424+ >>> con.row_factory = namedtuple_factory
2425+ >>> cur = con.execute(" SELECT 1 AS a, 2 AS b" )
2426+ >>> row = cur.fetchone()
2427+ >>> row
2428+ Row(a=1, b=2)
2429+ >>> row[0 ] # Indexed access.
2430+ 1
2431+ >>> row.b # Attribute access.
2432+ 2
2433+
2434+ With some adjustments, the above recipe can be adapted to use a
2435+ :class: `~dataclasses.dataclass `, or any other custom class,
2436+ instead of a :class: `~collections.namedtuple `.
2437+
2438+
23612439.. _sqlite3-explanation :
23622440
23632441Explanation
0 commit comments