1# dialects/sqlite/base.py
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7# mypy: ignore-errors
8
9
10r"""
11.. dialect:: sqlite
12 :name: SQLite
13 :full_support: 3.36.0
14 :normal_support: 3.12+
15 :best_effort: 3.7.16+
16
17.. _sqlite_datetime:
18
19Date and Time Types
20-------------------
21
22SQLite does not have built-in DATE, TIME, or DATETIME types, and pysqlite does
23not provide out of the box functionality for translating values between Python
24`datetime` objects and a SQLite-supported format. SQLAlchemy's own
25:class:`~sqlalchemy.types.DateTime` and related types provide date formatting
26and parsing functionality when SQLite is used. The implementation classes are
27:class:`_sqlite.DATETIME`, :class:`_sqlite.DATE` and :class:`_sqlite.TIME`.
28These types represent dates and times as ISO formatted strings, which also
29nicely support ordering. There's no reliance on typical "libc" internals for
30these functions so historical dates are fully supported.
31
32Ensuring Text affinity
33^^^^^^^^^^^^^^^^^^^^^^
34
35The DDL rendered for these types is the standard ``DATE``, ``TIME``
36and ``DATETIME`` indicators. However, custom storage formats can also be
37applied to these types. When the
38storage format is detected as containing no alpha characters, the DDL for
39these types is rendered as ``DATE_CHAR``, ``TIME_CHAR``, and ``DATETIME_CHAR``,
40so that the column continues to have textual affinity.
41
42.. seealso::
43
44 `Type Affinity <https://www.sqlite.org/datatype3.html#affinity>`_ -
45 in the SQLite documentation
46
47.. _sqlite_autoincrement:
48
49SQLite Auto Incrementing Behavior
50----------------------------------
51
52Background on SQLite's autoincrement is at: https://sqlite.org/autoinc.html
53
54Key concepts:
55
56* SQLite has an implicit "auto increment" feature that takes place for any
57 non-composite primary-key column that is specifically created using
58 "INTEGER PRIMARY KEY" for the type + primary key.
59
60* SQLite also has an explicit "AUTOINCREMENT" keyword, that is **not**
61 equivalent to the implicit autoincrement feature; this keyword is not
62 recommended for general use. SQLAlchemy does not render this keyword
63 unless a special SQLite-specific directive is used (see below). However,
64 it still requires that the column's type is named "INTEGER".
65
66Using the AUTOINCREMENT Keyword
67^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68
69To specifically render the AUTOINCREMENT keyword on the primary key column
70when rendering DDL, add the flag ``sqlite_autoincrement=True`` to the Table
71construct::
72
73 Table('sometable', metadata,
74 Column('id', Integer, primary_key=True),
75 sqlite_autoincrement=True)
76
77Allowing autoincrement behavior SQLAlchemy types other than Integer/INTEGER
78^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
79
80SQLite's typing model is based on naming conventions. Among other things, this
81means that any type name which contains the substring ``"INT"`` will be
82determined to be of "integer affinity". A type named ``"BIGINT"``,
83``"SPECIAL_INT"`` or even ``"XYZINTQPR"``, will be considered by SQLite to be
84of "integer" affinity. However, **the SQLite autoincrement feature, whether
85implicitly or explicitly enabled, requires that the name of the column's type
86is exactly the string "INTEGER"**. Therefore, if an application uses a type
87like :class:`.BigInteger` for a primary key, on SQLite this type will need to
88be rendered as the name ``"INTEGER"`` when emitting the initial ``CREATE
89TABLE`` statement in order for the autoincrement behavior to be available.
90
91One approach to achieve this is to use :class:`.Integer` on SQLite
92only using :meth:`.TypeEngine.with_variant`::
93
94 table = Table(
95 "my_table", metadata,
96 Column("id", BigInteger().with_variant(Integer, "sqlite"), primary_key=True)
97 )
98
99Another is to use a subclass of :class:`.BigInteger` that overrides its DDL
100name to be ``INTEGER`` when compiled against SQLite::
101
102 from sqlalchemy import BigInteger
103 from sqlalchemy.ext.compiler import compiles
104
105 class SLBigInteger(BigInteger):
106 pass
107
108 @compiles(SLBigInteger, 'sqlite')
109 def bi_c(element, compiler, **kw):
110 return "INTEGER"
111
112 @compiles(SLBigInteger)
113 def bi_c(element, compiler, **kw):
114 return compiler.visit_BIGINT(element, **kw)
115
116
117 table = Table(
118 "my_table", metadata,
119 Column("id", SLBigInteger(), primary_key=True)
120 )
121
122.. seealso::
123
124 :meth:`.TypeEngine.with_variant`
125
126 :ref:`sqlalchemy.ext.compiler_toplevel`
127
128 `Datatypes In SQLite Version 3 <https://sqlite.org/datatype3.html>`_
129
130.. _sqlite_concurrency:
131
132Database Locking Behavior / Concurrency
133---------------------------------------
134
135SQLite is not designed for a high level of write concurrency. The database
136itself, being a file, is locked completely during write operations within
137transactions, meaning exactly one "connection" (in reality a file handle)
138has exclusive access to the database during this period - all other
139"connections" will be blocked during this time.
140
141The Python DBAPI specification also calls for a connection model that is
142always in a transaction; there is no ``connection.begin()`` method,
143only ``connection.commit()`` and ``connection.rollback()``, upon which a
144new transaction is to be begun immediately. This may seem to imply
145that the SQLite driver would in theory allow only a single filehandle on a
146particular database file at any time; however, there are several
147factors both within SQLite itself as well as within the pysqlite driver
148which loosen this restriction significantly.
149
150However, no matter what locking modes are used, SQLite will still always
151lock the database file once a transaction is started and DML (e.g. INSERT,
152UPDATE, DELETE) has at least been emitted, and this will block
153other transactions at least at the point that they also attempt to emit DML.
154By default, the length of time on this block is very short before it times out
155with an error.
156
157This behavior becomes more critical when used in conjunction with the
158SQLAlchemy ORM. SQLAlchemy's :class:`.Session` object by default runs
159within a transaction, and with its autoflush model, may emit DML preceding
160any SELECT statement. This may lead to a SQLite database that locks
161more quickly than is expected. The locking mode of SQLite and the pysqlite
162driver can be manipulated to some degree, however it should be noted that
163achieving a high degree of write-concurrency with SQLite is a losing battle.
164
165For more information on SQLite's lack of write concurrency by design, please
166see
167`Situations Where Another RDBMS May Work Better - High Concurrency
168<https://www.sqlite.org/whentouse.html>`_ near the bottom of the page.
169
170The following subsections introduce areas that are impacted by SQLite's
171file-based architecture and additionally will usually require workarounds to
172work when using the pysqlite driver.
173
174.. _sqlite_isolation_level:
175
176Transaction Isolation Level / Autocommit
177----------------------------------------
178
179SQLite supports "transaction isolation" in a non-standard way, along two
180axes. One is that of the
181`PRAGMA read_uncommitted <https://www.sqlite.org/pragma.html#pragma_read_uncommitted>`_
182instruction. This setting can essentially switch SQLite between its
183default mode of ``SERIALIZABLE`` isolation, and a "dirty read" isolation
184mode normally referred to as ``READ UNCOMMITTED``.
185
186SQLAlchemy ties into this PRAGMA statement using the
187:paramref:`_sa.create_engine.isolation_level` parameter of
188:func:`_sa.create_engine`.
189Valid values for this parameter when used with SQLite are ``"SERIALIZABLE"``
190and ``"READ UNCOMMITTED"`` corresponding to a value of 0 and 1, respectively.
191SQLite defaults to ``SERIALIZABLE``, however its behavior is impacted by
192the pysqlite driver's default behavior.
193
194When using the pysqlite driver, the ``"AUTOCOMMIT"`` isolation level is also
195available, which will alter the pysqlite connection using the ``.isolation_level``
196attribute on the DBAPI connection and set it to None for the duration
197of the setting.
198
199.. versionadded:: 1.3.16 added support for SQLite AUTOCOMMIT isolation level
200 when using the pysqlite / sqlite3 SQLite driver.
201
202
203The other axis along which SQLite's transactional locking is impacted is
204via the nature of the ``BEGIN`` statement used. The three varieties
205are "deferred", "immediate", and "exclusive", as described at
206`BEGIN TRANSACTION <https://sqlite.org/lang_transaction.html>`_. A straight
207``BEGIN`` statement uses the "deferred" mode, where the database file is
208not locked until the first read or write operation, and read access remains
209open to other transactions until the first write operation. But again,
210it is critical to note that the pysqlite driver interferes with this behavior
211by *not even emitting BEGIN* until the first write operation.
212
213.. warning::
214
215 SQLite's transactional scope is impacted by unresolved
216 issues in the pysqlite driver, which defers BEGIN statements to a greater
217 degree than is often feasible. See the section :ref:`pysqlite_serializable`
218 or :ref:`aiosqlite_serializable` for techniques to work around this behavior.
219
220.. seealso::
221
222 :ref:`dbapi_autocommit`
223
224INSERT/UPDATE/DELETE...RETURNING
225---------------------------------
226
227The SQLite dialect supports SQLite 3.35's ``INSERT|UPDATE|DELETE..RETURNING``
228syntax. ``INSERT..RETURNING`` may be used
229automatically in some cases in order to fetch newly generated identifiers in
230place of the traditional approach of using ``cursor.lastrowid``, however
231``cursor.lastrowid`` is currently still preferred for simple single-statement
232cases for its better performance.
233
234To specify an explicit ``RETURNING`` clause, use the
235:meth:`._UpdateBase.returning` method on a per-statement basis::
236
237 # INSERT..RETURNING
238 result = connection.execute(
239 table.insert().
240 values(name='foo').
241 returning(table.c.col1, table.c.col2)
242 )
243 print(result.all())
244
245 # UPDATE..RETURNING
246 result = connection.execute(
247 table.update().
248 where(table.c.name=='foo').
249 values(name='bar').
250 returning(table.c.col1, table.c.col2)
251 )
252 print(result.all())
253
254 # DELETE..RETURNING
255 result = connection.execute(
256 table.delete().
257 where(table.c.name=='foo').
258 returning(table.c.col1, table.c.col2)
259 )
260 print(result.all())
261
262.. versionadded:: 2.0 Added support for SQLite RETURNING
263
264SAVEPOINT Support
265----------------------------
266
267SQLite supports SAVEPOINTs, which only function once a transaction is
268begun. SQLAlchemy's SAVEPOINT support is available using the
269:meth:`_engine.Connection.begin_nested` method at the Core level, and
270:meth:`.Session.begin_nested` at the ORM level. However, SAVEPOINTs
271won't work at all with pysqlite unless workarounds are taken.
272
273.. warning::
274
275 SQLite's SAVEPOINT feature is impacted by unresolved
276 issues in the pysqlite and aiosqlite drivers, which defer BEGIN statements
277 to a greater degree than is often feasible. See the sections
278 :ref:`pysqlite_serializable` and :ref:`aiosqlite_serializable`
279 for techniques to work around this behavior.
280
281Transactional DDL
282----------------------------
283
284The SQLite database supports transactional :term:`DDL` as well.
285In this case, the pysqlite driver is not only failing to start transactions,
286it also is ending any existing transaction when DDL is detected, so again,
287workarounds are required.
288
289.. warning::
290
291 SQLite's transactional DDL is impacted by unresolved issues
292 in the pysqlite driver, which fails to emit BEGIN and additionally
293 forces a COMMIT to cancel any transaction when DDL is encountered.
294 See the section :ref:`pysqlite_serializable`
295 for techniques to work around this behavior.
296
297.. _sqlite_foreign_keys:
298
299Foreign Key Support
300-------------------
301
302SQLite supports FOREIGN KEY syntax when emitting CREATE statements for tables,
303however by default these constraints have no effect on the operation of the
304table.
305
306Constraint checking on SQLite has three prerequisites:
307
308* At least version 3.6.19 of SQLite must be in use
309* The SQLite library must be compiled *without* the SQLITE_OMIT_FOREIGN_KEY
310 or SQLITE_OMIT_TRIGGER symbols enabled.
311* The ``PRAGMA foreign_keys = ON`` statement must be emitted on all
312 connections before use -- including the initial call to
313 :meth:`sqlalchemy.schema.MetaData.create_all`.
314
315SQLAlchemy allows for the ``PRAGMA`` statement to be emitted automatically for
316new connections through the usage of events::
317
318 from sqlalchemy.engine import Engine
319 from sqlalchemy import event
320
321 @event.listens_for(Engine, "connect")
322 def set_sqlite_pragma(dbapi_connection, connection_record):
323 cursor = dbapi_connection.cursor()
324 cursor.execute("PRAGMA foreign_keys=ON")
325 cursor.close()
326
327.. warning::
328
329 When SQLite foreign keys are enabled, it is **not possible**
330 to emit CREATE or DROP statements for tables that contain
331 mutually-dependent foreign key constraints;
332 to emit the DDL for these tables requires that ALTER TABLE be used to
333 create or drop these constraints separately, for which SQLite has
334 no support.
335
336.. seealso::
337
338 `SQLite Foreign Key Support <https://www.sqlite.org/foreignkeys.html>`_
339 - on the SQLite web site.
340
341 :ref:`event_toplevel` - SQLAlchemy event API.
342
343 :ref:`use_alter` - more information on SQLAlchemy's facilities for handling
344 mutually-dependent foreign key constraints.
345
346.. _sqlite_on_conflict_ddl:
347
348ON CONFLICT support for constraints
349-----------------------------------
350
351.. seealso:: This section describes the :term:`DDL` version of "ON CONFLICT" for
352 SQLite, which occurs within a CREATE TABLE statement. For "ON CONFLICT" as
353 applied to an INSERT statement, see :ref:`sqlite_on_conflict_insert`.
354
355SQLite supports a non-standard DDL clause known as ON CONFLICT which can be applied
356to primary key, unique, check, and not null constraints. In DDL, it is
357rendered either within the "CONSTRAINT" clause or within the column definition
358itself depending on the location of the target constraint. To render this
359clause within DDL, the extension parameter ``sqlite_on_conflict`` can be
360specified with a string conflict resolution algorithm within the
361:class:`.PrimaryKeyConstraint`, :class:`.UniqueConstraint`,
362:class:`.CheckConstraint` objects. Within the :class:`_schema.Column` object,
363there
364are individual parameters ``sqlite_on_conflict_not_null``,
365``sqlite_on_conflict_primary_key``, ``sqlite_on_conflict_unique`` which each
366correspond to the three types of relevant constraint types that can be
367indicated from a :class:`_schema.Column` object.
368
369.. seealso::
370
371 `ON CONFLICT <https://www.sqlite.org/lang_conflict.html>`_ - in the SQLite
372 documentation
373
374.. versionadded:: 1.3
375
376
377The ``sqlite_on_conflict`` parameters accept a string argument which is just
378the resolution name to be chosen, which on SQLite can be one of ROLLBACK,
379ABORT, FAIL, IGNORE, and REPLACE. For example, to add a UNIQUE constraint
380that specifies the IGNORE algorithm::
381
382 some_table = Table(
383 'some_table', metadata,
384 Column('id', Integer, primary_key=True),
385 Column('data', Integer),
386 UniqueConstraint('id', 'data', sqlite_on_conflict='IGNORE')
387 )
388
389The above renders CREATE TABLE DDL as::
390
391 CREATE TABLE some_table (
392 id INTEGER NOT NULL,
393 data INTEGER,
394 PRIMARY KEY (id),
395 UNIQUE (id, data) ON CONFLICT IGNORE
396 )
397
398
399When using the :paramref:`_schema.Column.unique`
400flag to add a UNIQUE constraint
401to a single column, the ``sqlite_on_conflict_unique`` parameter can
402be added to the :class:`_schema.Column` as well, which will be added to the
403UNIQUE constraint in the DDL::
404
405 some_table = Table(
406 'some_table', metadata,
407 Column('id', Integer, primary_key=True),
408 Column('data', Integer, unique=True,
409 sqlite_on_conflict_unique='IGNORE')
410 )
411
412rendering::
413
414 CREATE TABLE some_table (
415 id INTEGER NOT NULL,
416 data INTEGER,
417 PRIMARY KEY (id),
418 UNIQUE (data) ON CONFLICT IGNORE
419 )
420
421To apply the FAIL algorithm for a NOT NULL constraint,
422``sqlite_on_conflict_not_null`` is used::
423
424 some_table = Table(
425 'some_table', metadata,
426 Column('id', Integer, primary_key=True),
427 Column('data', Integer, nullable=False,
428 sqlite_on_conflict_not_null='FAIL')
429 )
430
431this renders the column inline ON CONFLICT phrase::
432
433 CREATE TABLE some_table (
434 id INTEGER NOT NULL,
435 data INTEGER NOT NULL ON CONFLICT FAIL,
436 PRIMARY KEY (id)
437 )
438
439
440Similarly, for an inline primary key, use ``sqlite_on_conflict_primary_key``::
441
442 some_table = Table(
443 'some_table', metadata,
444 Column('id', Integer, primary_key=True,
445 sqlite_on_conflict_primary_key='FAIL')
446 )
447
448SQLAlchemy renders the PRIMARY KEY constraint separately, so the conflict
449resolution algorithm is applied to the constraint itself::
450
451 CREATE TABLE some_table (
452 id INTEGER NOT NULL,
453 PRIMARY KEY (id) ON CONFLICT FAIL
454 )
455
456.. _sqlite_on_conflict_insert:
457
458INSERT...ON CONFLICT (Upsert)
459-----------------------------------
460
461.. seealso:: This section describes the :term:`DML` version of "ON CONFLICT" for
462 SQLite, which occurs within an INSERT statement. For "ON CONFLICT" as
463 applied to a CREATE TABLE statement, see :ref:`sqlite_on_conflict_ddl`.
464
465From version 3.24.0 onwards, SQLite supports "upserts" (update or insert)
466of rows into a table via the ``ON CONFLICT`` clause of the ``INSERT``
467statement. A candidate row will only be inserted if that row does not violate
468any unique or primary key constraints. In the case of a unique constraint violation, a
469secondary action can occur which can be either "DO UPDATE", indicating that
470the data in the target row should be updated, or "DO NOTHING", which indicates
471to silently skip this row.
472
473Conflicts are determined using columns that are part of existing unique
474constraints and indexes. These constraints are identified by stating the
475columns and conditions that comprise the indexes.
476
477SQLAlchemy provides ``ON CONFLICT`` support via the SQLite-specific
478:func:`_sqlite.insert()` function, which provides
479the generative methods :meth:`_sqlite.Insert.on_conflict_do_update`
480and :meth:`_sqlite.Insert.on_conflict_do_nothing`:
481
482.. sourcecode:: pycon+sql
483
484 >>> from sqlalchemy.dialects.sqlite import insert
485
486 >>> insert_stmt = insert(my_table).values(
487 ... id='some_existing_id',
488 ... data='inserted value')
489
490 >>> do_update_stmt = insert_stmt.on_conflict_do_update(
491 ... index_elements=['id'],
492 ... set_=dict(data='updated value')
493 ... )
494
495 >>> print(do_update_stmt)
496 {printsql}INSERT INTO my_table (id, data) VALUES (?, ?)
497 ON CONFLICT (id) DO UPDATE SET data = ?{stop}
498
499 >>> do_nothing_stmt = insert_stmt.on_conflict_do_nothing(
500 ... index_elements=['id']
501 ... )
502
503 >>> print(do_nothing_stmt)
504 {printsql}INSERT INTO my_table (id, data) VALUES (?, ?)
505 ON CONFLICT (id) DO NOTHING
506
507.. versionadded:: 1.4
508
509.. seealso::
510
511 `Upsert
512 <https://sqlite.org/lang_UPSERT.html>`_
513 - in the SQLite documentation.
514
515
516Specifying the Target
517^^^^^^^^^^^^^^^^^^^^^
518
519Both methods supply the "target" of the conflict using column inference:
520
521* The :paramref:`_sqlite.Insert.on_conflict_do_update.index_elements` argument
522 specifies a sequence containing string column names, :class:`_schema.Column`
523 objects, and/or SQL expression elements, which would identify a unique index
524 or unique constraint.
525
526* When using :paramref:`_sqlite.Insert.on_conflict_do_update.index_elements`
527 to infer an index, a partial index can be inferred by also specifying the
528 :paramref:`_sqlite.Insert.on_conflict_do_update.index_where` parameter:
529
530 .. sourcecode:: pycon+sql
531
532 >>> stmt = insert(my_table).values(user_email='a@b.com', data='inserted data')
533
534 >>> do_update_stmt = stmt.on_conflict_do_update(
535 ... index_elements=[my_table.c.user_email],
536 ... index_where=my_table.c.user_email.like('%@gmail.com'),
537 ... set_=dict(data=stmt.excluded.data)
538 ... )
539
540 >>> print(do_update_stmt)
541 {printsql}INSERT INTO my_table (data, user_email) VALUES (?, ?)
542 ON CONFLICT (user_email)
543 WHERE user_email LIKE '%@gmail.com'
544 DO UPDATE SET data = excluded.data
545
546The SET Clause
547^^^^^^^^^^^^^^^
548
549``ON CONFLICT...DO UPDATE`` is used to perform an update of the already
550existing row, using any combination of new values as well as values
551from the proposed insertion. These values are specified using the
552:paramref:`_sqlite.Insert.on_conflict_do_update.set_` parameter. This
553parameter accepts a dictionary which consists of direct values
554for UPDATE:
555
556.. sourcecode:: pycon+sql
557
558 >>> stmt = insert(my_table).values(id='some_id', data='inserted value')
559
560 >>> do_update_stmt = stmt.on_conflict_do_update(
561 ... index_elements=['id'],
562 ... set_=dict(data='updated value')
563 ... )
564
565 >>> print(do_update_stmt)
566 {printsql}INSERT INTO my_table (id, data) VALUES (?, ?)
567 ON CONFLICT (id) DO UPDATE SET data = ?
568
569.. warning::
570
571 The :meth:`_sqlite.Insert.on_conflict_do_update` method does **not** take
572 into account Python-side default UPDATE values or generation functions,
573 e.g. those specified using :paramref:`_schema.Column.onupdate`. These
574 values will not be exercised for an ON CONFLICT style of UPDATE, unless
575 they are manually specified in the
576 :paramref:`_sqlite.Insert.on_conflict_do_update.set_` dictionary.
577
578Updating using the Excluded INSERT Values
579^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
580
581In order to refer to the proposed insertion row, the special alias
582:attr:`~.sqlite.Insert.excluded` is available as an attribute on
583the :class:`_sqlite.Insert` object; this object creates an "excluded." prefix
584on a column, that informs the DO UPDATE to update the row with the value that
585would have been inserted had the constraint not failed:
586
587.. sourcecode:: pycon+sql
588
589 >>> stmt = insert(my_table).values(
590 ... id='some_id',
591 ... data='inserted value',
592 ... author='jlh'
593 ... )
594
595 >>> do_update_stmt = stmt.on_conflict_do_update(
596 ... index_elements=['id'],
597 ... set_=dict(data='updated value', author=stmt.excluded.author)
598 ... )
599
600 >>> print(do_update_stmt)
601 {printsql}INSERT INTO my_table (id, data, author) VALUES (?, ?, ?)
602 ON CONFLICT (id) DO UPDATE SET data = ?, author = excluded.author
603
604Additional WHERE Criteria
605^^^^^^^^^^^^^^^^^^^^^^^^^
606
607The :meth:`_sqlite.Insert.on_conflict_do_update` method also accepts
608a WHERE clause using the :paramref:`_sqlite.Insert.on_conflict_do_update.where`
609parameter, which will limit those rows which receive an UPDATE:
610
611.. sourcecode:: pycon+sql
612
613 >>> stmt = insert(my_table).values(
614 ... id='some_id',
615 ... data='inserted value',
616 ... author='jlh'
617 ... )
618
619 >>> on_update_stmt = stmt.on_conflict_do_update(
620 ... index_elements=['id'],
621 ... set_=dict(data='updated value', author=stmt.excluded.author),
622 ... where=(my_table.c.status == 2)
623 ... )
624 >>> print(on_update_stmt)
625 {printsql}INSERT INTO my_table (id, data, author) VALUES (?, ?, ?)
626 ON CONFLICT (id) DO UPDATE SET data = ?, author = excluded.author
627 WHERE my_table.status = ?
628
629
630Skipping Rows with DO NOTHING
631^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
632
633``ON CONFLICT`` may be used to skip inserting a row entirely
634if any conflict with a unique constraint occurs; below this is illustrated
635using the :meth:`_sqlite.Insert.on_conflict_do_nothing` method:
636
637.. sourcecode:: pycon+sql
638
639 >>> stmt = insert(my_table).values(id='some_id', data='inserted value')
640 >>> stmt = stmt.on_conflict_do_nothing(index_elements=['id'])
641 >>> print(stmt)
642 {printsql}INSERT INTO my_table (id, data) VALUES (?, ?) ON CONFLICT (id) DO NOTHING
643
644
645If ``DO NOTHING`` is used without specifying any columns or constraint,
646it has the effect of skipping the INSERT for any unique violation which
647occurs:
648
649.. sourcecode:: pycon+sql
650
651 >>> stmt = insert(my_table).values(id='some_id', data='inserted value')
652 >>> stmt = stmt.on_conflict_do_nothing()
653 >>> print(stmt)
654 {printsql}INSERT INTO my_table (id, data) VALUES (?, ?) ON CONFLICT DO NOTHING
655
656.. _sqlite_type_reflection:
657
658Type Reflection
659---------------
660
661SQLite types are unlike those of most other database backends, in that
662the string name of the type usually does not correspond to a "type" in a
663one-to-one fashion. Instead, SQLite links per-column typing behavior
664to one of five so-called "type affinities" based on a string matching
665pattern for the type.
666
667SQLAlchemy's reflection process, when inspecting types, uses a simple
668lookup table to link the keywords returned to provided SQLAlchemy types.
669This lookup table is present within the SQLite dialect as it is for all
670other dialects. However, the SQLite dialect has a different "fallback"
671routine for when a particular type name is not located in the lookup map;
672it instead implements the SQLite "type affinity" scheme located at
673https://www.sqlite.org/datatype3.html section 2.1.
674
675The provided typemap will make direct associations from an exact string
676name match for the following types:
677
678:class:`_types.BIGINT`, :class:`_types.BLOB`,
679:class:`_types.BOOLEAN`, :class:`_types.BOOLEAN`,
680:class:`_types.CHAR`, :class:`_types.DATE`,
681:class:`_types.DATETIME`, :class:`_types.FLOAT`,
682:class:`_types.DECIMAL`, :class:`_types.FLOAT`,
683:class:`_types.INTEGER`, :class:`_types.INTEGER`,
684:class:`_types.NUMERIC`, :class:`_types.REAL`,
685:class:`_types.SMALLINT`, :class:`_types.TEXT`,
686:class:`_types.TIME`, :class:`_types.TIMESTAMP`,
687:class:`_types.VARCHAR`, :class:`_types.NVARCHAR`,
688:class:`_types.NCHAR`
689
690When a type name does not match one of the above types, the "type affinity"
691lookup is used instead:
692
693* :class:`_types.INTEGER` is returned if the type name includes the
694 string ``INT``
695* :class:`_types.TEXT` is returned if the type name includes the
696 string ``CHAR``, ``CLOB`` or ``TEXT``
697* :class:`_types.NullType` is returned if the type name includes the
698 string ``BLOB``
699* :class:`_types.REAL` is returned if the type name includes the string
700 ``REAL``, ``FLOA`` or ``DOUB``.
701* Otherwise, the :class:`_types.NUMERIC` type is used.
702
703.. _sqlite_partial_index:
704
705Partial Indexes
706---------------
707
708A partial index, e.g. one which uses a WHERE clause, can be specified
709with the DDL system using the argument ``sqlite_where``::
710
711 tbl = Table('testtbl', m, Column('data', Integer))
712 idx = Index('test_idx1', tbl.c.data,
713 sqlite_where=and_(tbl.c.data > 5, tbl.c.data < 10))
714
715The index will be rendered at create time as::
716
717 CREATE INDEX test_idx1 ON testtbl (data)
718 WHERE data > 5 AND data < 10
719
720.. _sqlite_dotted_column_names:
721
722Dotted Column Names
723-------------------
724
725Using table or column names that explicitly have periods in them is
726**not recommended**. While this is generally a bad idea for relational
727databases in general, as the dot is a syntactically significant character,
728the SQLite driver up until version **3.10.0** of SQLite has a bug which
729requires that SQLAlchemy filter out these dots in result sets.
730
731The bug, entirely outside of SQLAlchemy, can be illustrated thusly::
732
733 import sqlite3
734
735 assert sqlite3.sqlite_version_info < (3, 10, 0), "bug is fixed in this version"
736
737 conn = sqlite3.connect(":memory:")
738 cursor = conn.cursor()
739
740 cursor.execute("create table x (a integer, b integer)")
741 cursor.execute("insert into x (a, b) values (1, 1)")
742 cursor.execute("insert into x (a, b) values (2, 2)")
743
744 cursor.execute("select x.a, x.b from x")
745 assert [c[0] for c in cursor.description] == ['a', 'b']
746
747 cursor.execute('''
748 select x.a, x.b from x where a=1
749 union
750 select x.a, x.b from x where a=2
751 ''')
752 assert [c[0] for c in cursor.description] == ['a', 'b'], \
753 [c[0] for c in cursor.description]
754
755The second assertion fails::
756
757 Traceback (most recent call last):
758 File "test.py", line 19, in <module>
759 [c[0] for c in cursor.description]
760 AssertionError: ['x.a', 'x.b']
761
762Where above, the driver incorrectly reports the names of the columns
763including the name of the table, which is entirely inconsistent vs.
764when the UNION is not present.
765
766SQLAlchemy relies upon column names being predictable in how they match
767to the original statement, so the SQLAlchemy dialect has no choice but
768to filter these out::
769
770
771 from sqlalchemy import create_engine
772
773 eng = create_engine("sqlite://")
774 conn = eng.connect()
775
776 conn.exec_driver_sql("create table x (a integer, b integer)")
777 conn.exec_driver_sql("insert into x (a, b) values (1, 1)")
778 conn.exec_driver_sql("insert into x (a, b) values (2, 2)")
779
780 result = conn.exec_driver_sql("select x.a, x.b from x")
781 assert result.keys() == ["a", "b"]
782
783 result = conn.exec_driver_sql('''
784 select x.a, x.b from x where a=1
785 union
786 select x.a, x.b from x where a=2
787 ''')
788 assert result.keys() == ["a", "b"]
789
790Note that above, even though SQLAlchemy filters out the dots, *both
791names are still addressable*::
792
793 >>> row = result.first()
794 >>> row["a"]
795 1
796 >>> row["x.a"]
797 1
798 >>> row["b"]
799 1
800 >>> row["x.b"]
801 1
802
803Therefore, the workaround applied by SQLAlchemy only impacts
804:meth:`_engine.CursorResult.keys` and :meth:`.Row.keys()` in the public API. In
805the very specific case where an application is forced to use column names that
806contain dots, and the functionality of :meth:`_engine.CursorResult.keys` and
807:meth:`.Row.keys()` is required to return these dotted names unmodified,
808the ``sqlite_raw_colnames`` execution option may be provided, either on a
809per-:class:`_engine.Connection` basis::
810
811 result = conn.execution_options(sqlite_raw_colnames=True).exec_driver_sql('''
812 select x.a, x.b from x where a=1
813 union
814 select x.a, x.b from x where a=2
815 ''')
816 assert result.keys() == ["x.a", "x.b"]
817
818or on a per-:class:`_engine.Engine` basis::
819
820 engine = create_engine("sqlite://", execution_options={"sqlite_raw_colnames": True})
821
822When using the per-:class:`_engine.Engine` execution option, note that
823**Core and ORM queries that use UNION may not function properly**.
824
825SQLite-specific table options
826-----------------------------
827
828One option for CREATE TABLE is supported directly by the SQLite
829dialect in conjunction with the :class:`_schema.Table` construct:
830
831* ``WITHOUT ROWID``::
832
833 Table("some_table", metadata, ..., sqlite_with_rowid=False)
834
835.. seealso::
836
837 `SQLite CREATE TABLE options
838 <https://www.sqlite.org/lang_createtable.html>`_
839
840
841.. _sqlite_include_internal:
842
843Reflecting internal schema tables
844----------------------------------
845
846Reflection methods that return lists of tables will omit so-called
847"SQLite internal schema object" names, which are considered by SQLite
848as any object name that is prefixed with ``sqlite_``. An example of
849such an object is the ``sqlite_sequence`` table that's generated when
850the ``AUTOINCREMENT`` column parameter is used. In order to return
851these objects, the parameter ``sqlite_include_internal=True`` may be
852passed to methods such as :meth:`_schema.MetaData.reflect` or
853:meth:`.Inspector.get_table_names`.
854
855.. versionadded:: 2.0 Added the ``sqlite_include_internal=True`` parameter.
856 Previously, these tables were not ignored by SQLAlchemy reflection
857 methods.
858
859.. note::
860
861 The ``sqlite_include_internal`` parameter does not refer to the
862 "system" tables that are present in schemas such as ``sqlite_master``.
863
864.. seealso::
865
866 `SQLite Internal Schema Objects <https://www.sqlite.org/fileformat2.html#intschema>`_ - in the SQLite
867 documentation.
868
869""" # noqa
870from __future__ import annotations
871
872import datetime
873import numbers
874import re
875from typing import Optional
876
877from .json import JSON
878from .json import JSONIndexType
879from .json import JSONPathType
880from ... import exc
881from ... import schema as sa_schema
882from ... import sql
883from ... import text
884from ... import types as sqltypes
885from ... import util
886from ...engine import default
887from ...engine import processors
888from ...engine import reflection
889from ...engine.reflection import ReflectionDefaults
890from ...sql import coercions
891from ...sql import ColumnElement
892from ...sql import compiler
893from ...sql import elements
894from ...sql import roles
895from ...sql import schema
896from ...types import BLOB # noqa
897from ...types import BOOLEAN # noqa
898from ...types import CHAR # noqa
899from ...types import DECIMAL # noqa
900from ...types import FLOAT # noqa
901from ...types import INTEGER # noqa
902from ...types import NUMERIC # noqa
903from ...types import REAL # noqa
904from ...types import SMALLINT # noqa
905from ...types import TEXT # noqa
906from ...types import TIMESTAMP # noqa
907from ...types import VARCHAR # noqa
908
909
910class _SQliteJson(JSON):
911 def result_processor(self, dialect, coltype):
912 default_processor = super().result_processor(dialect, coltype)
913
914 def process(value):
915 try:
916 return default_processor(value)
917 except TypeError:
918 if isinstance(value, numbers.Number):
919 return value
920 else:
921 raise
922
923 return process
924
925
926class _DateTimeMixin:
927 _reg = None
928 _storage_format = None
929
930 def __init__(self, storage_format=None, regexp=None, **kw):
931 super().__init__(**kw)
932 if regexp is not None:
933 self._reg = re.compile(regexp)
934 if storage_format is not None:
935 self._storage_format = storage_format
936
937 @property
938 def format_is_text_affinity(self):
939 """return True if the storage format will automatically imply
940 a TEXT affinity.
941
942 If the storage format contains no non-numeric characters,
943 it will imply a NUMERIC storage format on SQLite; in this case,
944 the type will generate its DDL as DATE_CHAR, DATETIME_CHAR,
945 TIME_CHAR.
946
947 """
948 spec = self._storage_format % {
949 "year": 0,
950 "month": 0,
951 "day": 0,
952 "hour": 0,
953 "minute": 0,
954 "second": 0,
955 "microsecond": 0,
956 }
957 return bool(re.search(r"[^0-9]", spec))
958
959 def adapt(self, cls, **kw):
960 if issubclass(cls, _DateTimeMixin):
961 if self._storage_format:
962 kw["storage_format"] = self._storage_format
963 if self._reg:
964 kw["regexp"] = self._reg
965 return super().adapt(cls, **kw)
966
967 def literal_processor(self, dialect):
968 bp = self.bind_processor(dialect)
969
970 def process(value):
971 return "'%s'" % bp(value)
972
973 return process
974
975
976class DATETIME(_DateTimeMixin, sqltypes.DateTime):
977 r"""Represent a Python datetime object in SQLite using a string.
978
979 The default string storage format is::
980
981 "%(year)04d-%(month)02d-%(day)02d %(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
982
983 e.g.::
984
985 2021-03-15 12:05:57.105542
986
987 The incoming storage format is by default parsed using the
988 Python ``datetime.fromisoformat()`` function.
989
990 .. versionchanged:: 2.0 ``datetime.fromisoformat()`` is used for default
991 datetime string parsing.
992
993 The storage format can be customized to some degree using the
994 ``storage_format`` and ``regexp`` parameters, such as::
995
996 import re
997 from sqlalchemy.dialects.sqlite import DATETIME
998
999 dt = DATETIME(storage_format="%(year)04d/%(month)02d/%(day)02d "
1000 "%(hour)02d:%(minute)02d:%(second)02d",
1001 regexp=r"(\d+)/(\d+)/(\d+) (\d+)-(\d+)-(\d+)"
1002 )
1003
1004 :param storage_format: format string which will be applied to the dict
1005 with keys year, month, day, hour, minute, second, and microsecond.
1006
1007 :param regexp: regular expression which will be applied to incoming result
1008 rows, replacing the use of ``datetime.fromisoformat()`` to parse incoming
1009 strings. If the regexp contains named groups, the resulting match dict is
1010 applied to the Python datetime() constructor as keyword arguments.
1011 Otherwise, if positional groups are used, the datetime() constructor
1012 is called with positional arguments via
1013 ``*map(int, match_obj.groups(0))``.
1014
1015 """ # noqa
1016
1017 _storage_format = (
1018 "%(year)04d-%(month)02d-%(day)02d "
1019 "%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
1020 )
1021
1022 def __init__(self, *args, **kwargs):
1023 truncate_microseconds = kwargs.pop("truncate_microseconds", False)
1024 super().__init__(*args, **kwargs)
1025 if truncate_microseconds:
1026 assert "storage_format" not in kwargs, (
1027 "You can specify only "
1028 "one of truncate_microseconds or storage_format."
1029 )
1030 assert "regexp" not in kwargs, (
1031 "You can specify only one of "
1032 "truncate_microseconds or regexp."
1033 )
1034 self._storage_format = (
1035 "%(year)04d-%(month)02d-%(day)02d "
1036 "%(hour)02d:%(minute)02d:%(second)02d"
1037 )
1038
1039 def bind_processor(self, dialect):
1040 datetime_datetime = datetime.datetime
1041 datetime_date = datetime.date
1042 format_ = self._storage_format
1043
1044 def process(value):
1045 if value is None:
1046 return None
1047 elif isinstance(value, datetime_datetime):
1048 return format_ % {
1049 "year": value.year,
1050 "month": value.month,
1051 "day": value.day,
1052 "hour": value.hour,
1053 "minute": value.minute,
1054 "second": value.second,
1055 "microsecond": value.microsecond,
1056 }
1057 elif isinstance(value, datetime_date):
1058 return format_ % {
1059 "year": value.year,
1060 "month": value.month,
1061 "day": value.day,
1062 "hour": 0,
1063 "minute": 0,
1064 "second": 0,
1065 "microsecond": 0,
1066 }
1067 else:
1068 raise TypeError(
1069 "SQLite DateTime type only accepts Python "
1070 "datetime and date objects as input."
1071 )
1072
1073 return process
1074
1075 def result_processor(self, dialect, coltype):
1076 if self._reg:
1077 return processors.str_to_datetime_processor_factory(
1078 self._reg, datetime.datetime
1079 )
1080 else:
1081 return processors.str_to_datetime
1082
1083
1084class DATE(_DateTimeMixin, sqltypes.Date):
1085 r"""Represent a Python date object in SQLite using a string.
1086
1087 The default string storage format is::
1088
1089 "%(year)04d-%(month)02d-%(day)02d"
1090
1091 e.g.::
1092
1093 2011-03-15
1094
1095 The incoming storage format is by default parsed using the
1096 Python ``date.fromisoformat()`` function.
1097
1098 .. versionchanged:: 2.0 ``date.fromisoformat()`` is used for default
1099 date string parsing.
1100
1101
1102 The storage format can be customized to some degree using the
1103 ``storage_format`` and ``regexp`` parameters, such as::
1104
1105 import re
1106 from sqlalchemy.dialects.sqlite import DATE
1107
1108 d = DATE(
1109 storage_format="%(month)02d/%(day)02d/%(year)04d",
1110 regexp=re.compile("(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)")
1111 )
1112
1113 :param storage_format: format string which will be applied to the
1114 dict with keys year, month, and day.
1115
1116 :param regexp: regular expression which will be applied to
1117 incoming result rows, replacing the use of ``date.fromisoformat()`` to
1118 parse incoming strings. If the regexp contains named groups, the resulting
1119 match dict is applied to the Python date() constructor as keyword
1120 arguments. Otherwise, if positional groups are used, the date()
1121 constructor is called with positional arguments via
1122 ``*map(int, match_obj.groups(0))``.
1123
1124 """
1125
1126 _storage_format = "%(year)04d-%(month)02d-%(day)02d"
1127
1128 def bind_processor(self, dialect):
1129 datetime_date = datetime.date
1130 format_ = self._storage_format
1131
1132 def process(value):
1133 if value is None:
1134 return None
1135 elif isinstance(value, datetime_date):
1136 return format_ % {
1137 "year": value.year,
1138 "month": value.month,
1139 "day": value.day,
1140 }
1141 else:
1142 raise TypeError(
1143 "SQLite Date type only accepts Python "
1144 "date objects as input."
1145 )
1146
1147 return process
1148
1149 def result_processor(self, dialect, coltype):
1150 if self._reg:
1151 return processors.str_to_datetime_processor_factory(
1152 self._reg, datetime.date
1153 )
1154 else:
1155 return processors.str_to_date
1156
1157
1158class TIME(_DateTimeMixin, sqltypes.Time):
1159 r"""Represent a Python time object in SQLite using a string.
1160
1161 The default string storage format is::
1162
1163 "%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
1164
1165 e.g.::
1166
1167 12:05:57.10558
1168
1169 The incoming storage format is by default parsed using the
1170 Python ``time.fromisoformat()`` function.
1171
1172 .. versionchanged:: 2.0 ``time.fromisoformat()`` is used for default
1173 time string parsing.
1174
1175 The storage format can be customized to some degree using the
1176 ``storage_format`` and ``regexp`` parameters, such as::
1177
1178 import re
1179 from sqlalchemy.dialects.sqlite import TIME
1180
1181 t = TIME(storage_format="%(hour)02d-%(minute)02d-"
1182 "%(second)02d-%(microsecond)06d",
1183 regexp=re.compile("(\d+)-(\d+)-(\d+)-(?:-(\d+))?")
1184 )
1185
1186 :param storage_format: format string which will be applied to the dict
1187 with keys hour, minute, second, and microsecond.
1188
1189 :param regexp: regular expression which will be applied to incoming result
1190 rows, replacing the use of ``datetime.fromisoformat()`` to parse incoming
1191 strings. If the regexp contains named groups, the resulting match dict is
1192 applied to the Python time() constructor as keyword arguments. Otherwise,
1193 if positional groups are used, the time() constructor is called with
1194 positional arguments via ``*map(int, match_obj.groups(0))``.
1195
1196 """
1197
1198 _storage_format = "%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
1199
1200 def __init__(self, *args, **kwargs):
1201 truncate_microseconds = kwargs.pop("truncate_microseconds", False)
1202 super().__init__(*args, **kwargs)
1203 if truncate_microseconds:
1204 assert "storage_format" not in kwargs, (
1205 "You can specify only "
1206 "one of truncate_microseconds or storage_format."
1207 )
1208 assert "regexp" not in kwargs, (
1209 "You can specify only one of "
1210 "truncate_microseconds or regexp."
1211 )
1212 self._storage_format = "%(hour)02d:%(minute)02d:%(second)02d"
1213
1214 def bind_processor(self, dialect):
1215 datetime_time = datetime.time
1216 format_ = self._storage_format
1217
1218 def process(value):
1219 if value is None:
1220 return None
1221 elif isinstance(value, datetime_time):
1222 return format_ % {
1223 "hour": value.hour,
1224 "minute": value.minute,
1225 "second": value.second,
1226 "microsecond": value.microsecond,
1227 }
1228 else:
1229 raise TypeError(
1230 "SQLite Time type only accepts Python "
1231 "time objects as input."
1232 )
1233
1234 return process
1235
1236 def result_processor(self, dialect, coltype):
1237 if self._reg:
1238 return processors.str_to_datetime_processor_factory(
1239 self._reg, datetime.time
1240 )
1241 else:
1242 return processors.str_to_time
1243
1244
1245colspecs = {
1246 sqltypes.Date: DATE,
1247 sqltypes.DateTime: DATETIME,
1248 sqltypes.JSON: _SQliteJson,
1249 sqltypes.JSON.JSONIndexType: JSONIndexType,
1250 sqltypes.JSON.JSONPathType: JSONPathType,
1251 sqltypes.Time: TIME,
1252}
1253
1254ischema_names = {
1255 "BIGINT": sqltypes.BIGINT,
1256 "BLOB": sqltypes.BLOB,
1257 "BOOL": sqltypes.BOOLEAN,
1258 "BOOLEAN": sqltypes.BOOLEAN,
1259 "CHAR": sqltypes.CHAR,
1260 "DATE": sqltypes.DATE,
1261 "DATE_CHAR": sqltypes.DATE,
1262 "DATETIME": sqltypes.DATETIME,
1263 "DATETIME_CHAR": sqltypes.DATETIME,
1264 "DOUBLE": sqltypes.DOUBLE,
1265 "DECIMAL": sqltypes.DECIMAL,
1266 "FLOAT": sqltypes.FLOAT,
1267 "INT": sqltypes.INTEGER,
1268 "INTEGER": sqltypes.INTEGER,
1269 "JSON": JSON,
1270 "NUMERIC": sqltypes.NUMERIC,
1271 "REAL": sqltypes.REAL,
1272 "SMALLINT": sqltypes.SMALLINT,
1273 "TEXT": sqltypes.TEXT,
1274 "TIME": sqltypes.TIME,
1275 "TIME_CHAR": sqltypes.TIME,
1276 "TIMESTAMP": sqltypes.TIMESTAMP,
1277 "VARCHAR": sqltypes.VARCHAR,
1278 "NVARCHAR": sqltypes.NVARCHAR,
1279 "NCHAR": sqltypes.NCHAR,
1280}
1281
1282
1283class SQLiteCompiler(compiler.SQLCompiler):
1284 extract_map = util.update_copy(
1285 compiler.SQLCompiler.extract_map,
1286 {
1287 "month": "%m",
1288 "day": "%d",
1289 "year": "%Y",
1290 "second": "%S",
1291 "hour": "%H",
1292 "doy": "%j",
1293 "minute": "%M",
1294 "epoch": "%s",
1295 "dow": "%w",
1296 "week": "%W",
1297 },
1298 )
1299
1300 def visit_truediv_binary(self, binary, operator, **kw):
1301 return (
1302 self.process(binary.left, **kw)
1303 + " / "
1304 + "(%s + 0.0)" % self.process(binary.right, **kw)
1305 )
1306
1307 def visit_now_func(self, fn, **kw):
1308 return "CURRENT_TIMESTAMP"
1309
1310 def visit_localtimestamp_func(self, func, **kw):
1311 return 'DATETIME(CURRENT_TIMESTAMP, "localtime")'
1312
1313 def visit_true(self, expr, **kw):
1314 return "1"
1315
1316 def visit_false(self, expr, **kw):
1317 return "0"
1318
1319 def visit_char_length_func(self, fn, **kw):
1320 return "length%s" % self.function_argspec(fn)
1321
1322 def visit_aggregate_strings_func(self, fn, **kw):
1323 return "group_concat%s" % self.function_argspec(fn)
1324
1325 def visit_cast(self, cast, **kwargs):
1326 if self.dialect.supports_cast:
1327 return super().visit_cast(cast, **kwargs)
1328 else:
1329 return self.process(cast.clause, **kwargs)
1330
1331 def visit_extract(self, extract, **kw):
1332 try:
1333 return "CAST(STRFTIME('%s', %s) AS INTEGER)" % (
1334 self.extract_map[extract.field],
1335 self.process(extract.expr, **kw),
1336 )
1337 except KeyError as err:
1338 raise exc.CompileError(
1339 "%s is not a valid extract argument." % extract.field
1340 ) from err
1341
1342 def returning_clause(
1343 self,
1344 stmt,
1345 returning_cols,
1346 *,
1347 populate_result_map,
1348 **kw,
1349 ):
1350 kw["include_table"] = False
1351 return super().returning_clause(
1352 stmt, returning_cols, populate_result_map=populate_result_map, **kw
1353 )
1354
1355 def limit_clause(self, select, **kw):
1356 text = ""
1357 if select._limit_clause is not None:
1358 text += "\n LIMIT " + self.process(select._limit_clause, **kw)
1359 if select._offset_clause is not None:
1360 if select._limit_clause is None:
1361 text += "\n LIMIT " + self.process(sql.literal(-1))
1362 text += " OFFSET " + self.process(select._offset_clause, **kw)
1363 else:
1364 text += " OFFSET " + self.process(sql.literal(0), **kw)
1365 return text
1366
1367 def for_update_clause(self, select, **kw):
1368 # sqlite has no "FOR UPDATE" AFAICT
1369 return ""
1370
1371 def update_from_clause(
1372 self, update_stmt, from_table, extra_froms, from_hints, **kw
1373 ):
1374 kw["asfrom"] = True
1375 return "FROM " + ", ".join(
1376 t._compiler_dispatch(self, fromhints=from_hints, **kw)
1377 for t in extra_froms
1378 )
1379
1380 def visit_is_distinct_from_binary(self, binary, operator, **kw):
1381 return "%s IS NOT %s" % (
1382 self.process(binary.left),
1383 self.process(binary.right),
1384 )
1385
1386 def visit_is_not_distinct_from_binary(self, binary, operator, **kw):
1387 return "%s IS %s" % (
1388 self.process(binary.left),
1389 self.process(binary.right),
1390 )
1391
1392 def visit_json_getitem_op_binary(self, binary, operator, **kw):
1393 if binary.type._type_affinity is sqltypes.JSON:
1394 expr = "JSON_QUOTE(JSON_EXTRACT(%s, %s))"
1395 else:
1396 expr = "JSON_EXTRACT(%s, %s)"
1397
1398 return expr % (
1399 self.process(binary.left, **kw),
1400 self.process(binary.right, **kw),
1401 )
1402
1403 def visit_json_path_getitem_op_binary(self, binary, operator, **kw):
1404 if binary.type._type_affinity is sqltypes.JSON:
1405 expr = "JSON_QUOTE(JSON_EXTRACT(%s, %s))"
1406 else:
1407 expr = "JSON_EXTRACT(%s, %s)"
1408
1409 return expr % (
1410 self.process(binary.left, **kw),
1411 self.process(binary.right, **kw),
1412 )
1413
1414 def visit_empty_set_op_expr(self, type_, expand_op, **kw):
1415 # slightly old SQLite versions don't seem to be able to handle
1416 # the empty set impl
1417 return self.visit_empty_set_expr(type_)
1418
1419 def visit_empty_set_expr(self, element_types, **kw):
1420 return "SELECT %s FROM (SELECT %s) WHERE 1!=1" % (
1421 ", ".join("1" for type_ in element_types or [INTEGER()]),
1422 ", ".join("1" for type_ in element_types or [INTEGER()]),
1423 )
1424
1425 def visit_regexp_match_op_binary(self, binary, operator, **kw):
1426 return self._generate_generic_binary(binary, " REGEXP ", **kw)
1427
1428 def visit_not_regexp_match_op_binary(self, binary, operator, **kw):
1429 return self._generate_generic_binary(binary, " NOT REGEXP ", **kw)
1430
1431 def _on_conflict_target(self, clause, **kw):
1432 if clause.constraint_target is not None:
1433 target_text = "(%s)" % clause.constraint_target
1434 elif clause.inferred_target_elements is not None:
1435 target_text = "(%s)" % ", ".join(
1436 (
1437 self.preparer.quote(c)
1438 if isinstance(c, str)
1439 else self.process(c, include_table=False, use_schema=False)
1440 )
1441 for c in clause.inferred_target_elements
1442 )
1443 if clause.inferred_target_whereclause is not None:
1444 target_text += " WHERE %s" % self.process(
1445 clause.inferred_target_whereclause,
1446 include_table=False,
1447 use_schema=False,
1448 literal_binds=True,
1449 )
1450
1451 else:
1452 target_text = ""
1453
1454 return target_text
1455
1456 def visit_on_conflict_do_nothing(self, on_conflict, **kw):
1457 target_text = self._on_conflict_target(on_conflict, **kw)
1458
1459 if target_text:
1460 return "ON CONFLICT %s DO NOTHING" % target_text
1461 else:
1462 return "ON CONFLICT DO NOTHING"
1463
1464 def visit_on_conflict_do_update(self, on_conflict, **kw):
1465 clause = on_conflict
1466
1467 target_text = self._on_conflict_target(on_conflict, **kw)
1468
1469 action_set_ops = []
1470
1471 set_parameters = dict(clause.update_values_to_set)
1472 # create a list of column assignment clauses as tuples
1473
1474 insert_statement = self.stack[-1]["selectable"]
1475 cols = insert_statement.table.c
1476 for c in cols:
1477 col_key = c.key
1478
1479 if col_key in set_parameters:
1480 value = set_parameters.pop(col_key)
1481 elif c in set_parameters:
1482 value = set_parameters.pop(c)
1483 else:
1484 continue
1485
1486 if coercions._is_literal(value):
1487 value = elements.BindParameter(None, value, type_=c.type)
1488
1489 else:
1490 if (
1491 isinstance(value, elements.BindParameter)
1492 and value.type._isnull
1493 ):
1494 value = value._clone()
1495 value.type = c.type
1496 value_text = self.process(value.self_group(), use_schema=False)
1497
1498 key_text = self.preparer.quote(c.name)
1499 action_set_ops.append("%s = %s" % (key_text, value_text))
1500
1501 # check for names that don't match columns
1502 if set_parameters:
1503 util.warn(
1504 "Additional column names not matching "
1505 "any column keys in table '%s': %s"
1506 % (
1507 self.current_executable.table.name,
1508 (", ".join("'%s'" % c for c in set_parameters)),
1509 )
1510 )
1511 for k, v in set_parameters.items():
1512 key_text = (
1513 self.preparer.quote(k)
1514 if isinstance(k, str)
1515 else self.process(k, use_schema=False)
1516 )
1517 value_text = self.process(
1518 coercions.expect(roles.ExpressionElementRole, v),
1519 use_schema=False,
1520 )
1521 action_set_ops.append("%s = %s" % (key_text, value_text))
1522
1523 action_text = ", ".join(action_set_ops)
1524 if clause.update_whereclause is not None:
1525 action_text += " WHERE %s" % self.process(
1526 clause.update_whereclause, include_table=True, use_schema=False
1527 )
1528
1529 return "ON CONFLICT %s DO UPDATE SET %s" % (target_text, action_text)
1530
1531
1532class SQLiteDDLCompiler(compiler.DDLCompiler):
1533 def get_column_specification(self, column, **kwargs):
1534 coltype = self.dialect.type_compiler_instance.process(
1535 column.type, type_expression=column
1536 )
1537 colspec = self.preparer.format_column(column) + " " + coltype
1538 default = self.get_column_default_string(column)
1539 if default is not None:
1540 if isinstance(column.server_default.arg, ColumnElement):
1541 default = "(" + default + ")"
1542 colspec += " DEFAULT " + default
1543
1544 if not column.nullable:
1545 colspec += " NOT NULL"
1546
1547 on_conflict_clause = column.dialect_options["sqlite"][
1548 "on_conflict_not_null"
1549 ]
1550 if on_conflict_clause is not None:
1551 colspec += " ON CONFLICT " + on_conflict_clause
1552
1553 if column.primary_key:
1554 if (
1555 column.autoincrement is True
1556 and len(column.table.primary_key.columns) != 1
1557 ):
1558 raise exc.CompileError(
1559 "SQLite does not support autoincrement for "
1560 "composite primary keys"
1561 )
1562
1563 if (
1564 column.table.dialect_options["sqlite"]["autoincrement"]
1565 and len(column.table.primary_key.columns) == 1
1566 and issubclass(column.type._type_affinity, sqltypes.Integer)
1567 and not column.foreign_keys
1568 ):
1569 colspec += " PRIMARY KEY"
1570
1571 on_conflict_clause = column.dialect_options["sqlite"][
1572 "on_conflict_primary_key"
1573 ]
1574 if on_conflict_clause is not None:
1575 colspec += " ON CONFLICT " + on_conflict_clause
1576
1577 colspec += " AUTOINCREMENT"
1578
1579 if column.computed is not None:
1580 colspec += " " + self.process(column.computed)
1581
1582 return colspec
1583
1584 def visit_primary_key_constraint(self, constraint, **kw):
1585 # for columns with sqlite_autoincrement=True,
1586 # the PRIMARY KEY constraint can only be inline
1587 # with the column itself.
1588 if len(constraint.columns) == 1:
1589 c = list(constraint)[0]
1590 if (
1591 c.primary_key
1592 and c.table.dialect_options["sqlite"]["autoincrement"]
1593 and issubclass(c.type._type_affinity, sqltypes.Integer)
1594 and not c.foreign_keys
1595 ):
1596 return None
1597
1598 text = super().visit_primary_key_constraint(constraint)
1599
1600 on_conflict_clause = constraint.dialect_options["sqlite"][
1601 "on_conflict"
1602 ]
1603 if on_conflict_clause is None and len(constraint.columns) == 1:
1604 on_conflict_clause = list(constraint)[0].dialect_options["sqlite"][
1605 "on_conflict_primary_key"
1606 ]
1607
1608 if on_conflict_clause is not None:
1609 text += " ON CONFLICT " + on_conflict_clause
1610
1611 return text
1612
1613 def visit_unique_constraint(self, constraint, **kw):
1614 text = super().visit_unique_constraint(constraint)
1615
1616 on_conflict_clause = constraint.dialect_options["sqlite"][
1617 "on_conflict"
1618 ]
1619 if on_conflict_clause is None and len(constraint.columns) == 1:
1620 col1 = list(constraint)[0]
1621 if isinstance(col1, schema.SchemaItem):
1622 on_conflict_clause = list(constraint)[0].dialect_options[
1623 "sqlite"
1624 ]["on_conflict_unique"]
1625
1626 if on_conflict_clause is not None:
1627 text += " ON CONFLICT " + on_conflict_clause
1628
1629 return text
1630
1631 def visit_check_constraint(self, constraint, **kw):
1632 text = super().visit_check_constraint(constraint)
1633
1634 on_conflict_clause = constraint.dialect_options["sqlite"][
1635 "on_conflict"
1636 ]
1637
1638 if on_conflict_clause is not None:
1639 text += " ON CONFLICT " + on_conflict_clause
1640
1641 return text
1642
1643 def visit_column_check_constraint(self, constraint, **kw):
1644 text = super().visit_column_check_constraint(constraint)
1645
1646 if constraint.dialect_options["sqlite"]["on_conflict"] is not None:
1647 raise exc.CompileError(
1648 "SQLite does not support on conflict clause for "
1649 "column check constraint"
1650 )
1651
1652 return text
1653
1654 def visit_foreign_key_constraint(self, constraint, **kw):
1655 local_table = constraint.elements[0].parent.table
1656 remote_table = constraint.elements[0].column.table
1657
1658 if local_table.schema != remote_table.schema:
1659 return None
1660 else:
1661 return super().visit_foreign_key_constraint(constraint)
1662
1663 def define_constraint_remote_table(self, constraint, table, preparer):
1664 """Format the remote table clause of a CREATE CONSTRAINT clause."""
1665
1666 return preparer.format_table(table, use_schema=False)
1667
1668 def visit_create_index(
1669 self, create, include_schema=False, include_table_schema=True, **kw
1670 ):
1671 index = create.element
1672 self._verify_index_table(index)
1673 preparer = self.preparer
1674 text = "CREATE "
1675 if index.unique:
1676 text += "UNIQUE "
1677
1678 text += "INDEX "
1679
1680 if create.if_not_exists:
1681 text += "IF NOT EXISTS "
1682
1683 text += "%s ON %s (%s)" % (
1684 self._prepared_index_name(index, include_schema=True),
1685 preparer.format_table(index.table, use_schema=False),
1686 ", ".join(
1687 self.sql_compiler.process(
1688 expr, include_table=False, literal_binds=True
1689 )
1690 for expr in index.expressions
1691 ),
1692 )
1693
1694 whereclause = index.dialect_options["sqlite"]["where"]
1695 if whereclause is not None:
1696 where_compiled = self.sql_compiler.process(
1697 whereclause, include_table=False, literal_binds=True
1698 )
1699 text += " WHERE " + where_compiled
1700
1701 return text
1702
1703 def post_create_table(self, table):
1704 if table.dialect_options["sqlite"]["with_rowid"] is False:
1705 return "\n WITHOUT ROWID"
1706 return ""
1707
1708
1709class SQLiteTypeCompiler(compiler.GenericTypeCompiler):
1710 def visit_large_binary(self, type_, **kw):
1711 return self.visit_BLOB(type_)
1712
1713 def visit_DATETIME(self, type_, **kw):
1714 if (
1715 not isinstance(type_, _DateTimeMixin)
1716 or type_.format_is_text_affinity
1717 ):
1718 return super().visit_DATETIME(type_)
1719 else:
1720 return "DATETIME_CHAR"
1721
1722 def visit_DATE(self, type_, **kw):
1723 if (
1724 not isinstance(type_, _DateTimeMixin)
1725 or type_.format_is_text_affinity
1726 ):
1727 return super().visit_DATE(type_)
1728 else:
1729 return "DATE_CHAR"
1730
1731 def visit_TIME(self, type_, **kw):
1732 if (
1733 not isinstance(type_, _DateTimeMixin)
1734 or type_.format_is_text_affinity
1735 ):
1736 return super().visit_TIME(type_)
1737 else:
1738 return "TIME_CHAR"
1739
1740 def visit_JSON(self, type_, **kw):
1741 # note this name provides NUMERIC affinity, not TEXT.
1742 # should not be an issue unless the JSON value consists of a single
1743 # numeric value. JSONTEXT can be used if this case is required.
1744 return "JSON"
1745
1746
1747class SQLiteIdentifierPreparer(compiler.IdentifierPreparer):
1748 reserved_words = {
1749 "add",
1750 "after",
1751 "all",
1752 "alter",
1753 "analyze",
1754 "and",
1755 "as",
1756 "asc",
1757 "attach",
1758 "autoincrement",
1759 "before",
1760 "begin",
1761 "between",
1762 "by",
1763 "cascade",
1764 "case",
1765 "cast",
1766 "check",
1767 "collate",
1768 "column",
1769 "commit",
1770 "conflict",
1771 "constraint",
1772 "create",
1773 "cross",
1774 "current_date",
1775 "current_time",
1776 "current_timestamp",
1777 "database",
1778 "default",
1779 "deferrable",
1780 "deferred",
1781 "delete",
1782 "desc",
1783 "detach",
1784 "distinct",
1785 "drop",
1786 "each",
1787 "else",
1788 "end",
1789 "escape",
1790 "except",
1791 "exclusive",
1792 "exists",
1793 "explain",
1794 "false",
1795 "fail",
1796 "for",
1797 "foreign",
1798 "from",
1799 "full",
1800 "glob",
1801 "group",
1802 "having",
1803 "if",
1804 "ignore",
1805 "immediate",
1806 "in",
1807 "index",
1808 "indexed",
1809 "initially",
1810 "inner",
1811 "insert",
1812 "instead",
1813 "intersect",
1814 "into",
1815 "is",
1816 "isnull",
1817 "join",
1818 "key",
1819 "left",
1820 "like",
1821 "limit",
1822 "match",
1823 "natural",
1824 "not",
1825 "notnull",
1826 "null",
1827 "of",
1828 "offset",
1829 "on",
1830 "or",
1831 "order",
1832 "outer",
1833 "plan",
1834 "pragma",
1835 "primary",
1836 "query",
1837 "raise",
1838 "references",
1839 "reindex",
1840 "rename",
1841 "replace",
1842 "restrict",
1843 "right",
1844 "rollback",
1845 "row",
1846 "select",
1847 "set",
1848 "table",
1849 "temp",
1850 "temporary",
1851 "then",
1852 "to",
1853 "transaction",
1854 "trigger",
1855 "true",
1856 "union",
1857 "unique",
1858 "update",
1859 "using",
1860 "vacuum",
1861 "values",
1862 "view",
1863 "virtual",
1864 "when",
1865 "where",
1866 }
1867
1868
1869class SQLiteExecutionContext(default.DefaultExecutionContext):
1870 @util.memoized_property
1871 def _preserve_raw_colnames(self):
1872 return (
1873 not self.dialect._broken_dotted_colnames
1874 or self.execution_options.get("sqlite_raw_colnames", False)
1875 )
1876
1877 def _translate_colname(self, colname):
1878 # TODO: detect SQLite version 3.10.0 or greater;
1879 # see [ticket:3633]
1880
1881 # adjust for dotted column names. SQLite
1882 # in the case of UNION may store col names as
1883 # "tablename.colname", or if using an attached database,
1884 # "database.tablename.colname", in cursor.description
1885 if not self._preserve_raw_colnames and "." in colname:
1886 return colname.split(".")[-1], colname
1887 else:
1888 return colname, None
1889
1890
1891class SQLiteDialect(default.DefaultDialect):
1892 name = "sqlite"
1893 supports_alter = False
1894
1895 # SQlite supports "DEFAULT VALUES" but *does not* support
1896 # "VALUES (DEFAULT)"
1897 supports_default_values = True
1898 supports_default_metavalue = False
1899
1900 # sqlite issue:
1901 # https://github.com/python/cpython/issues/93421
1902 # note this parameter is no longer used by the ORM or default dialect
1903 # see #9414
1904 supports_sane_rowcount_returning = False
1905
1906 supports_empty_insert = False
1907 supports_cast = True
1908 supports_multivalues_insert = True
1909 use_insertmanyvalues = True
1910 tuple_in_values = True
1911 supports_statement_cache = True
1912 insert_null_pk_still_autoincrements = True
1913 insert_returning = True
1914 update_returning = True
1915 update_returning_multifrom = True
1916 delete_returning = True
1917 update_returning_multifrom = True
1918
1919 supports_default_metavalue = True
1920 """dialect supports INSERT... VALUES (DEFAULT) syntax"""
1921
1922 default_metavalue_token = "NULL"
1923 """for INSERT... VALUES (DEFAULT) syntax, the token to put in the
1924 parenthesis."""
1925
1926 default_paramstyle = "qmark"
1927 execution_ctx_cls = SQLiteExecutionContext
1928 statement_compiler = SQLiteCompiler
1929 ddl_compiler = SQLiteDDLCompiler
1930 type_compiler_cls = SQLiteTypeCompiler
1931 preparer = SQLiteIdentifierPreparer
1932 ischema_names = ischema_names
1933 colspecs = colspecs
1934
1935 construct_arguments = [
1936 (
1937 sa_schema.Table,
1938 {
1939 "autoincrement": False,
1940 "with_rowid": True,
1941 },
1942 ),
1943 (sa_schema.Index, {"where": None}),
1944 (
1945 sa_schema.Column,
1946 {
1947 "on_conflict_primary_key": None,
1948 "on_conflict_not_null": None,
1949 "on_conflict_unique": None,
1950 },
1951 ),
1952 (sa_schema.Constraint, {"on_conflict": None}),
1953 ]
1954
1955 _broken_fk_pragma_quotes = False
1956 _broken_dotted_colnames = False
1957
1958 @util.deprecated_params(
1959 _json_serializer=(
1960 "1.3.7",
1961 "The _json_serializer argument to the SQLite dialect has "
1962 "been renamed to the correct name of json_serializer. The old "
1963 "argument name will be removed in a future release.",
1964 ),
1965 _json_deserializer=(
1966 "1.3.7",
1967 "The _json_deserializer argument to the SQLite dialect has "
1968 "been renamed to the correct name of json_deserializer. The old "
1969 "argument name will be removed in a future release.",
1970 ),
1971 )
1972 def __init__(
1973 self,
1974 native_datetime=False,
1975 json_serializer=None,
1976 json_deserializer=None,
1977 _json_serializer=None,
1978 _json_deserializer=None,
1979 **kwargs,
1980 ):
1981 default.DefaultDialect.__init__(self, **kwargs)
1982
1983 if _json_serializer:
1984 json_serializer = _json_serializer
1985 if _json_deserializer:
1986 json_deserializer = _json_deserializer
1987 self._json_serializer = json_serializer
1988 self._json_deserializer = json_deserializer
1989
1990 # this flag used by pysqlite dialect, and perhaps others in the
1991 # future, to indicate the driver is handling date/timestamp
1992 # conversions (and perhaps datetime/time as well on some hypothetical
1993 # driver ?)
1994 self.native_datetime = native_datetime
1995
1996 if self.dbapi is not None:
1997 if self.dbapi.sqlite_version_info < (3, 7, 16):
1998 util.warn(
1999 "SQLite version %s is older than 3.7.16, and will not "
2000 "support right nested joins, as are sometimes used in "
2001 "more complex ORM scenarios. SQLAlchemy 1.4 and above "
2002 "no longer tries to rewrite these joins."
2003 % (self.dbapi.sqlite_version_info,)
2004 )
2005
2006 # NOTE: python 3.7 on fedora for me has SQLite 3.34.1. These
2007 # version checks are getting very stale.
2008 self._broken_dotted_colnames = self.dbapi.sqlite_version_info < (
2009 3,
2010 10,
2011 0,
2012 )
2013 self.supports_default_values = self.dbapi.sqlite_version_info >= (
2014 3,
2015 3,
2016 8,
2017 )
2018 self.supports_cast = self.dbapi.sqlite_version_info >= (3, 2, 3)
2019 self.supports_multivalues_insert = (
2020 # https://www.sqlite.org/releaselog/3_7_11.html
2021 self.dbapi.sqlite_version_info
2022 >= (3, 7, 11)
2023 )
2024 # see https://www.sqlalchemy.org/trac/ticket/2568
2025 # as well as https://www.sqlite.org/src/info/600482d161
2026 self._broken_fk_pragma_quotes = self.dbapi.sqlite_version_info < (
2027 3,
2028 6,
2029 14,
2030 )
2031
2032 if self.dbapi.sqlite_version_info < (3, 35) or util.pypy:
2033 self.update_returning = self.delete_returning = (
2034 self.insert_returning
2035 ) = False
2036
2037 if self.dbapi.sqlite_version_info < (3, 32, 0):
2038 # https://www.sqlite.org/limits.html
2039 self.insertmanyvalues_max_parameters = 999
2040
2041 _isolation_lookup = util.immutabledict(
2042 {"READ UNCOMMITTED": 1, "SERIALIZABLE": 0}
2043 )
2044
2045 def get_isolation_level_values(self, dbapi_connection):
2046 return list(self._isolation_lookup)
2047
2048 def set_isolation_level(self, dbapi_connection, level):
2049 isolation_level = self._isolation_lookup[level]
2050
2051 cursor = dbapi_connection.cursor()
2052 cursor.execute(f"PRAGMA read_uncommitted = {isolation_level}")
2053 cursor.close()
2054
2055 def get_isolation_level(self, dbapi_connection):
2056 cursor = dbapi_connection.cursor()
2057 cursor.execute("PRAGMA read_uncommitted")
2058 res = cursor.fetchone()
2059 if res:
2060 value = res[0]
2061 else:
2062 # https://www.sqlite.org/changes.html#version_3_3_3
2063 # "Optional READ UNCOMMITTED isolation (instead of the
2064 # default isolation level of SERIALIZABLE) and
2065 # table level locking when database connections
2066 # share a common cache.""
2067 # pre-SQLite 3.3.0 default to 0
2068 value = 0
2069 cursor.close()
2070 if value == 0:
2071 return "SERIALIZABLE"
2072 elif value == 1:
2073 return "READ UNCOMMITTED"
2074 else:
2075 assert False, "Unknown isolation level %s" % value
2076
2077 @reflection.cache
2078 def get_schema_names(self, connection, **kw):
2079 s = "PRAGMA database_list"
2080 dl = connection.exec_driver_sql(s)
2081
2082 return [db[1] for db in dl if db[1] != "temp"]
2083
2084 def _format_schema(self, schema, table_name):
2085 if schema is not None:
2086 qschema = self.identifier_preparer.quote_identifier(schema)
2087 name = f"{qschema}.{table_name}"
2088 else:
2089 name = table_name
2090 return name
2091
2092 def _sqlite_main_query(
2093 self,
2094 table: str,
2095 type_: str,
2096 schema: Optional[str],
2097 sqlite_include_internal: bool,
2098 ):
2099 main = self._format_schema(schema, table)
2100 if not sqlite_include_internal:
2101 filter_table = " AND name NOT LIKE 'sqlite~_%' ESCAPE '~'"
2102 else:
2103 filter_table = ""
2104 query = (
2105 f"SELECT name FROM {main} "
2106 f"WHERE type='{type_}'{filter_table} "
2107 "ORDER BY name"
2108 )
2109 return query
2110
2111 @reflection.cache
2112 def get_table_names(
2113 self, connection, schema=None, sqlite_include_internal=False, **kw
2114 ):
2115 query = self._sqlite_main_query(
2116 "sqlite_master", "table", schema, sqlite_include_internal
2117 )
2118 names = connection.exec_driver_sql(query).scalars().all()
2119 return names
2120
2121 @reflection.cache
2122 def get_temp_table_names(
2123 self, connection, sqlite_include_internal=False, **kw
2124 ):
2125 query = self._sqlite_main_query(
2126 "sqlite_temp_master", "table", None, sqlite_include_internal
2127 )
2128 names = connection.exec_driver_sql(query).scalars().all()
2129 return names
2130
2131 @reflection.cache
2132 def get_temp_view_names(
2133 self, connection, sqlite_include_internal=False, **kw
2134 ):
2135 query = self._sqlite_main_query(
2136 "sqlite_temp_master", "view", None, sqlite_include_internal
2137 )
2138 names = connection.exec_driver_sql(query).scalars().all()
2139 return names
2140
2141 @reflection.cache
2142 def has_table(self, connection, table_name, schema=None, **kw):
2143 self._ensure_has_table_connection(connection)
2144
2145 if schema is not None and schema not in self.get_schema_names(
2146 connection, **kw
2147 ):
2148 return False
2149
2150 info = self._get_table_pragma(
2151 connection, "table_info", table_name, schema=schema
2152 )
2153 return bool(info)
2154
2155 def _get_default_schema_name(self, connection):
2156 return "main"
2157
2158 @reflection.cache
2159 def get_view_names(
2160 self, connection, schema=None, sqlite_include_internal=False, **kw
2161 ):
2162 query = self._sqlite_main_query(
2163 "sqlite_master", "view", schema, sqlite_include_internal
2164 )
2165 names = connection.exec_driver_sql(query).scalars().all()
2166 return names
2167
2168 @reflection.cache
2169 def get_view_definition(self, connection, view_name, schema=None, **kw):
2170 if schema is not None:
2171 qschema = self.identifier_preparer.quote_identifier(schema)
2172 master = f"{qschema}.sqlite_master"
2173 s = ("SELECT sql FROM %s WHERE name = ? AND type='view'") % (
2174 master,
2175 )
2176 rs = connection.exec_driver_sql(s, (view_name,))
2177 else:
2178 try:
2179 s = (
2180 "SELECT sql FROM "
2181 " (SELECT * FROM sqlite_master UNION ALL "
2182 " SELECT * FROM sqlite_temp_master) "
2183 "WHERE name = ? "
2184 "AND type='view'"
2185 )
2186 rs = connection.exec_driver_sql(s, (view_name,))
2187 except exc.DBAPIError:
2188 s = (
2189 "SELECT sql FROM sqlite_master WHERE name = ? "
2190 "AND type='view'"
2191 )
2192 rs = connection.exec_driver_sql(s, (view_name,))
2193
2194 result = rs.fetchall()
2195 if result:
2196 return result[0].sql
2197 else:
2198 raise exc.NoSuchTableError(
2199 f"{schema}.{view_name}" if schema else view_name
2200 )
2201
2202 @reflection.cache
2203 def get_columns(self, connection, table_name, schema=None, **kw):
2204 pragma = "table_info"
2205 # computed columns are threaded as hidden, they require table_xinfo
2206 if self.server_version_info >= (3, 31):
2207 pragma = "table_xinfo"
2208 info = self._get_table_pragma(
2209 connection, pragma, table_name, schema=schema
2210 )
2211 columns = []
2212 tablesql = None
2213 for row in info:
2214 name = row[1]
2215 type_ = row[2].upper()
2216 nullable = not row[3]
2217 default = row[4]
2218 primary_key = row[5]
2219 hidden = row[6] if pragma == "table_xinfo" else 0
2220
2221 # hidden has value 0 for normal columns, 1 for hidden columns,
2222 # 2 for computed virtual columns and 3 for computed stored columns
2223 # https://www.sqlite.org/src/info/069351b85f9a706f60d3e98fbc8aaf40c374356b967c0464aede30ead3d9d18b
2224 if hidden == 1:
2225 continue
2226
2227 generated = bool(hidden)
2228 persisted = hidden == 3
2229
2230 if tablesql is None and generated:
2231 tablesql = self._get_table_sql(
2232 connection, table_name, schema, **kw
2233 )
2234
2235 columns.append(
2236 self._get_column_info(
2237 name,
2238 type_,
2239 nullable,
2240 default,
2241 primary_key,
2242 generated,
2243 persisted,
2244 tablesql,
2245 )
2246 )
2247 if columns:
2248 return columns
2249 elif not self.has_table(connection, table_name, schema):
2250 raise exc.NoSuchTableError(
2251 f"{schema}.{table_name}" if schema else table_name
2252 )
2253 else:
2254 return ReflectionDefaults.columns()
2255
2256 def _get_column_info(
2257 self,
2258 name,
2259 type_,
2260 nullable,
2261 default,
2262 primary_key,
2263 generated,
2264 persisted,
2265 tablesql,
2266 ):
2267 if generated:
2268 # the type of a column "cc INTEGER GENERATED ALWAYS AS (1 + 42)"
2269 # somehow is "INTEGER GENERATED ALWAYS"
2270 type_ = re.sub("generated", "", type_, flags=re.IGNORECASE)
2271 type_ = re.sub("always", "", type_, flags=re.IGNORECASE).strip()
2272
2273 coltype = self._resolve_type_affinity(type_)
2274
2275 if default is not None:
2276 default = str(default)
2277
2278 colspec = {
2279 "name": name,
2280 "type": coltype,
2281 "nullable": nullable,
2282 "default": default,
2283 "primary_key": primary_key,
2284 }
2285 if generated:
2286 sqltext = ""
2287 if tablesql:
2288 pattern = r"[^,]*\s+AS\s+\(([^,]*)\)\s*(?:virtual|stored)?"
2289 match = re.search(
2290 re.escape(name) + pattern, tablesql, re.IGNORECASE
2291 )
2292 if match:
2293 sqltext = match.group(1)
2294 colspec["computed"] = {"sqltext": sqltext, "persisted": persisted}
2295 return colspec
2296
2297 def _resolve_type_affinity(self, type_):
2298 """Return a data type from a reflected column, using affinity rules.
2299
2300 SQLite's goal for universal compatibility introduces some complexity
2301 during reflection, as a column's defined type might not actually be a
2302 type that SQLite understands - or indeed, my not be defined *at all*.
2303 Internally, SQLite handles this with a 'data type affinity' for each
2304 column definition, mapping to one of 'TEXT', 'NUMERIC', 'INTEGER',
2305 'REAL', or 'NONE' (raw bits). The algorithm that determines this is
2306 listed in https://www.sqlite.org/datatype3.html section 2.1.
2307
2308 This method allows SQLAlchemy to support that algorithm, while still
2309 providing access to smarter reflection utilities by recognizing
2310 column definitions that SQLite only supports through affinity (like
2311 DATE and DOUBLE).
2312
2313 """
2314 match = re.match(r"([\w ]+)(\(.*?\))?", type_)
2315 if match:
2316 coltype = match.group(1)
2317 args = match.group(2)
2318 else:
2319 coltype = ""
2320 args = ""
2321
2322 if coltype in self.ischema_names:
2323 coltype = self.ischema_names[coltype]
2324 elif "INT" in coltype:
2325 coltype = sqltypes.INTEGER
2326 elif "CHAR" in coltype or "CLOB" in coltype or "TEXT" in coltype:
2327 coltype = sqltypes.TEXT
2328 elif "BLOB" in coltype or not coltype:
2329 coltype = sqltypes.NullType
2330 elif "REAL" in coltype or "FLOA" in coltype or "DOUB" in coltype:
2331 coltype = sqltypes.REAL
2332 else:
2333 coltype = sqltypes.NUMERIC
2334
2335 if args is not None:
2336 args = re.findall(r"(\d+)", args)
2337 try:
2338 coltype = coltype(*[int(a) for a in args])
2339 except TypeError:
2340 util.warn(
2341 "Could not instantiate type %s with "
2342 "reflected arguments %s; using no arguments."
2343 % (coltype, args)
2344 )
2345 coltype = coltype()
2346 else:
2347 coltype = coltype()
2348
2349 return coltype
2350
2351 @reflection.cache
2352 def get_pk_constraint(self, connection, table_name, schema=None, **kw):
2353 constraint_name = None
2354 table_data = self._get_table_sql(connection, table_name, schema=schema)
2355 if table_data:
2356 PK_PATTERN = r"CONSTRAINT (\w+) PRIMARY KEY"
2357 result = re.search(PK_PATTERN, table_data, re.I)
2358 constraint_name = result.group(1) if result else None
2359
2360 cols = self.get_columns(connection, table_name, schema, **kw)
2361 # consider only pk columns. This also avoids sorting the cached
2362 # value returned by get_columns
2363 cols = [col for col in cols if col.get("primary_key", 0) > 0]
2364 cols.sort(key=lambda col: col.get("primary_key"))
2365 pkeys = [col["name"] for col in cols]
2366
2367 if pkeys:
2368 return {"constrained_columns": pkeys, "name": constraint_name}
2369 else:
2370 return ReflectionDefaults.pk_constraint()
2371
2372 @reflection.cache
2373 def get_foreign_keys(self, connection, table_name, schema=None, **kw):
2374 # sqlite makes this *extremely difficult*.
2375 # First, use the pragma to get the actual FKs.
2376 pragma_fks = self._get_table_pragma(
2377 connection, "foreign_key_list", table_name, schema=schema
2378 )
2379
2380 fks = {}
2381
2382 for row in pragma_fks:
2383 (numerical_id, rtbl, lcol, rcol) = (row[0], row[2], row[3], row[4])
2384
2385 if not rcol:
2386 # no referred column, which means it was not named in the
2387 # original DDL. The referred columns of the foreign key
2388 # constraint are therefore the primary key of the referred
2389 # table.
2390 try:
2391 referred_pk = self.get_pk_constraint(
2392 connection, rtbl, schema=schema, **kw
2393 )
2394 referred_columns = referred_pk["constrained_columns"]
2395 except exc.NoSuchTableError:
2396 # ignore not existing parents
2397 referred_columns = []
2398 else:
2399 # note we use this list only if this is the first column
2400 # in the constraint. for subsequent columns we ignore the
2401 # list and append "rcol" if present.
2402 referred_columns = []
2403
2404 if self._broken_fk_pragma_quotes:
2405 rtbl = re.sub(r"^[\"\[`\']|[\"\]`\']$", "", rtbl)
2406
2407 if numerical_id in fks:
2408 fk = fks[numerical_id]
2409 else:
2410 fk = fks[numerical_id] = {
2411 "name": None,
2412 "constrained_columns": [],
2413 "referred_schema": schema,
2414 "referred_table": rtbl,
2415 "referred_columns": referred_columns,
2416 "options": {},
2417 }
2418 fks[numerical_id] = fk
2419
2420 fk["constrained_columns"].append(lcol)
2421
2422 if rcol:
2423 fk["referred_columns"].append(rcol)
2424
2425 def fk_sig(constrained_columns, referred_table, referred_columns):
2426 return (
2427 tuple(constrained_columns)
2428 + (referred_table,)
2429 + tuple(referred_columns)
2430 )
2431
2432 # then, parse the actual SQL and attempt to find DDL that matches
2433 # the names as well. SQLite saves the DDL in whatever format
2434 # it was typed in as, so need to be liberal here.
2435
2436 keys_by_signature = {
2437 fk_sig(
2438 fk["constrained_columns"],
2439 fk["referred_table"],
2440 fk["referred_columns"],
2441 ): fk
2442 for fk in fks.values()
2443 }
2444
2445 table_data = self._get_table_sql(connection, table_name, schema=schema)
2446
2447 def parse_fks():
2448 if table_data is None:
2449 # system tables, etc.
2450 return
2451
2452 # note that we already have the FKs from PRAGMA above. This whole
2453 # regexp thing is trying to locate additional detail about the
2454 # FKs, namely the name of the constraint and other options.
2455 # so parsing the columns is really about matching it up to what
2456 # we already have.
2457 FK_PATTERN = (
2458 r"(?:CONSTRAINT (\w+) +)?"
2459 r"FOREIGN KEY *\( *(.+?) *\) +"
2460 r'REFERENCES +(?:(?:"(.+?)")|([a-z0-9_]+)) *\( *((?:(?:"[^"]+"|[a-z0-9_]+) *(?:, *)?)+)\) *' # noqa: E501
2461 r"((?:ON (?:DELETE|UPDATE) "
2462 r"(?:SET NULL|SET DEFAULT|CASCADE|RESTRICT|NO ACTION) *)*)"
2463 r"((?:NOT +)?DEFERRABLE)?"
2464 r"(?: +INITIALLY +(DEFERRED|IMMEDIATE))?"
2465 )
2466 for match in re.finditer(FK_PATTERN, table_data, re.I):
2467 (
2468 constraint_name,
2469 constrained_columns,
2470 referred_quoted_name,
2471 referred_name,
2472 referred_columns,
2473 onupdatedelete,
2474 deferrable,
2475 initially,
2476 ) = match.group(1, 2, 3, 4, 5, 6, 7, 8)
2477 constrained_columns = list(
2478 self._find_cols_in_sig(constrained_columns)
2479 )
2480 if not referred_columns:
2481 referred_columns = constrained_columns
2482 else:
2483 referred_columns = list(
2484 self._find_cols_in_sig(referred_columns)
2485 )
2486 referred_name = referred_quoted_name or referred_name
2487 options = {}
2488
2489 for token in re.split(r" *\bON\b *", onupdatedelete.upper()):
2490 if token.startswith("DELETE"):
2491 ondelete = token[6:].strip()
2492 if ondelete and ondelete != "NO ACTION":
2493 options["ondelete"] = ondelete
2494 elif token.startswith("UPDATE"):
2495 onupdate = token[6:].strip()
2496 if onupdate and onupdate != "NO ACTION":
2497 options["onupdate"] = onupdate
2498
2499 if deferrable:
2500 options["deferrable"] = "NOT" not in deferrable.upper()
2501 if initially:
2502 options["initially"] = initially.upper()
2503
2504 yield (
2505 constraint_name,
2506 constrained_columns,
2507 referred_name,
2508 referred_columns,
2509 options,
2510 )
2511
2512 fkeys = []
2513
2514 for (
2515 constraint_name,
2516 constrained_columns,
2517 referred_name,
2518 referred_columns,
2519 options,
2520 ) in parse_fks():
2521 sig = fk_sig(constrained_columns, referred_name, referred_columns)
2522 if sig not in keys_by_signature:
2523 util.warn(
2524 "WARNING: SQL-parsed foreign key constraint "
2525 "'%s' could not be located in PRAGMA "
2526 "foreign_keys for table %s" % (sig, table_name)
2527 )
2528 continue
2529 key = keys_by_signature.pop(sig)
2530 key["name"] = constraint_name
2531 key["options"] = options
2532 fkeys.append(key)
2533 # assume the remainders are the unnamed, inline constraints, just
2534 # use them as is as it's extremely difficult to parse inline
2535 # constraints
2536 fkeys.extend(keys_by_signature.values())
2537 if fkeys:
2538 return fkeys
2539 else:
2540 return ReflectionDefaults.foreign_keys()
2541
2542 def _find_cols_in_sig(self, sig):
2543 for match in re.finditer(r'(?:"(.+?)")|([a-z0-9_]+)', sig, re.I):
2544 yield match.group(1) or match.group(2)
2545
2546 @reflection.cache
2547 def get_unique_constraints(
2548 self, connection, table_name, schema=None, **kw
2549 ):
2550 auto_index_by_sig = {}
2551 for idx in self.get_indexes(
2552 connection,
2553 table_name,
2554 schema=schema,
2555 include_auto_indexes=True,
2556 **kw,
2557 ):
2558 if not idx["name"].startswith("sqlite_autoindex"):
2559 continue
2560 sig = tuple(idx["column_names"])
2561 auto_index_by_sig[sig] = idx
2562
2563 table_data = self._get_table_sql(
2564 connection, table_name, schema=schema, **kw
2565 )
2566 unique_constraints = []
2567
2568 def parse_uqs():
2569 if table_data is None:
2570 return
2571 UNIQUE_PATTERN = r'(?:CONSTRAINT "?(.+?)"? +)?UNIQUE *\((.+?)\)'
2572 INLINE_UNIQUE_PATTERN = (
2573 r'(?:(".+?")|(?:[\[`])?([a-z0-9_]+)(?:[\]`])?) '
2574 r"+[a-z0-9_ ]+? +UNIQUE"
2575 )
2576
2577 for match in re.finditer(UNIQUE_PATTERN, table_data, re.I):
2578 name, cols = match.group(1, 2)
2579 yield name, list(self._find_cols_in_sig(cols))
2580
2581 # we need to match inlines as well, as we seek to differentiate
2582 # a UNIQUE constraint from a UNIQUE INDEX, even though these
2583 # are kind of the same thing :)
2584 for match in re.finditer(INLINE_UNIQUE_PATTERN, table_data, re.I):
2585 cols = list(
2586 self._find_cols_in_sig(match.group(1) or match.group(2))
2587 )
2588 yield None, cols
2589
2590 for name, cols in parse_uqs():
2591 sig = tuple(cols)
2592 if sig in auto_index_by_sig:
2593 auto_index_by_sig.pop(sig)
2594 parsed_constraint = {"name": name, "column_names": cols}
2595 unique_constraints.append(parsed_constraint)
2596 # NOTE: auto_index_by_sig might not be empty here,
2597 # the PRIMARY KEY may have an entry.
2598 if unique_constraints:
2599 return unique_constraints
2600 else:
2601 return ReflectionDefaults.unique_constraints()
2602
2603 @reflection.cache
2604 def get_check_constraints(self, connection, table_name, schema=None, **kw):
2605 table_data = self._get_table_sql(
2606 connection, table_name, schema=schema, **kw
2607 )
2608
2609 CHECK_PATTERN = r"(?:CONSTRAINT (.+) +)?" r"CHECK *\( *(.+) *\),? *"
2610 cks = []
2611 # NOTE: we aren't using re.S here because we actually are
2612 # taking advantage of each CHECK constraint being all on one
2613 # line in the table definition in order to delineate. This
2614 # necessarily makes assumptions as to how the CREATE TABLE
2615 # was emitted.
2616
2617 for match in re.finditer(CHECK_PATTERN, table_data or "", re.I):
2618 name = match.group(1)
2619
2620 if name:
2621 name = re.sub(r'^"|"$', "", name)
2622
2623 cks.append({"sqltext": match.group(2), "name": name})
2624 cks.sort(key=lambda d: d["name"] or "~") # sort None as last
2625 if cks:
2626 return cks
2627 else:
2628 return ReflectionDefaults.check_constraints()
2629
2630 @reflection.cache
2631 def get_indexes(self, connection, table_name, schema=None, **kw):
2632 pragma_indexes = self._get_table_pragma(
2633 connection, "index_list", table_name, schema=schema
2634 )
2635 indexes = []
2636
2637 # regular expression to extract the filter predicate of a partial
2638 # index. this could fail to extract the predicate correctly on
2639 # indexes created like
2640 # CREATE INDEX i ON t (col || ') where') WHERE col <> ''
2641 # but as this function does not support expression-based indexes
2642 # this case does not occur.
2643 partial_pred_re = re.compile(r"\)\s+where\s+(.+)", re.IGNORECASE)
2644
2645 if schema:
2646 schema_expr = "%s." % self.identifier_preparer.quote_identifier(
2647 schema
2648 )
2649 else:
2650 schema_expr = ""
2651
2652 include_auto_indexes = kw.pop("include_auto_indexes", False)
2653 for row in pragma_indexes:
2654 # ignore implicit primary key index.
2655 # https://www.mail-archive.com/sqlite-users@sqlite.org/msg30517.html
2656 if not include_auto_indexes and row[1].startswith(
2657 "sqlite_autoindex"
2658 ):
2659 continue
2660 indexes.append(
2661 dict(
2662 name=row[1],
2663 column_names=[],
2664 unique=row[2],
2665 dialect_options={},
2666 )
2667 )
2668
2669 # check partial indexes
2670 if len(row) >= 5 and row[4]:
2671 s = (
2672 "SELECT sql FROM %(schema)ssqlite_master "
2673 "WHERE name = ? "
2674 "AND type = 'index'" % {"schema": schema_expr}
2675 )
2676 rs = connection.exec_driver_sql(s, (row[1],))
2677 index_sql = rs.scalar()
2678 predicate_match = partial_pred_re.search(index_sql)
2679 if predicate_match is None:
2680 # unless the regex is broken this case shouldn't happen
2681 # because we know this is a partial index, so the
2682 # definition sql should match the regex
2683 util.warn(
2684 "Failed to look up filter predicate of "
2685 "partial index %s" % row[1]
2686 )
2687 else:
2688 predicate = predicate_match.group(1)
2689 indexes[-1]["dialect_options"]["sqlite_where"] = text(
2690 predicate
2691 )
2692
2693 # loop thru unique indexes to get the column names.
2694 for idx in list(indexes):
2695 pragma_index = self._get_table_pragma(
2696 connection, "index_info", idx["name"], schema=schema
2697 )
2698
2699 for row in pragma_index:
2700 if row[2] is None:
2701 util.warn(
2702 "Skipped unsupported reflection of "
2703 "expression-based index %s" % idx["name"]
2704 )
2705 indexes.remove(idx)
2706 break
2707 else:
2708 idx["column_names"].append(row[2])
2709
2710 indexes.sort(key=lambda d: d["name"] or "~") # sort None as last
2711 if indexes:
2712 return indexes
2713 elif not self.has_table(connection, table_name, schema):
2714 raise exc.NoSuchTableError(
2715 f"{schema}.{table_name}" if schema else table_name
2716 )
2717 else:
2718 return ReflectionDefaults.indexes()
2719
2720 def _is_sys_table(self, table_name):
2721 return table_name in {
2722 "sqlite_schema",
2723 "sqlite_master",
2724 "sqlite_temp_schema",
2725 "sqlite_temp_master",
2726 }
2727
2728 @reflection.cache
2729 def _get_table_sql(self, connection, table_name, schema=None, **kw):
2730 if schema:
2731 schema_expr = "%s." % (
2732 self.identifier_preparer.quote_identifier(schema)
2733 )
2734 else:
2735 schema_expr = ""
2736 try:
2737 s = (
2738 "SELECT sql FROM "
2739 " (SELECT * FROM %(schema)ssqlite_master UNION ALL "
2740 " SELECT * FROM %(schema)ssqlite_temp_master) "
2741 "WHERE name = ? "
2742 "AND type in ('table', 'view')" % {"schema": schema_expr}
2743 )
2744 rs = connection.exec_driver_sql(s, (table_name,))
2745 except exc.DBAPIError:
2746 s = (
2747 "SELECT sql FROM %(schema)ssqlite_master "
2748 "WHERE name = ? "
2749 "AND type in ('table', 'view')" % {"schema": schema_expr}
2750 )
2751 rs = connection.exec_driver_sql(s, (table_name,))
2752 value = rs.scalar()
2753 if value is None and not self._is_sys_table(table_name):
2754 raise exc.NoSuchTableError(f"{schema_expr}{table_name}")
2755 return value
2756
2757 def _get_table_pragma(self, connection, pragma, table_name, schema=None):
2758 quote = self.identifier_preparer.quote_identifier
2759 if schema is not None:
2760 statements = [f"PRAGMA {quote(schema)}."]
2761 else:
2762 # because PRAGMA looks in all attached databases if no schema
2763 # given, need to specify "main" schema, however since we want
2764 # 'temp' tables in the same namespace as 'main', need to run
2765 # the PRAGMA twice
2766 statements = ["PRAGMA main.", "PRAGMA temp."]
2767
2768 qtable = quote(table_name)
2769 for statement in statements:
2770 statement = f"{statement}{pragma}({qtable})"
2771 cursor = connection.exec_driver_sql(statement)
2772 if not cursor._soft_closed:
2773 # work around SQLite issue whereby cursor.description
2774 # is blank when PRAGMA returns no rows:
2775 # https://www.sqlite.org/cvstrac/tktview?tn=1884
2776 result = cursor.fetchall()
2777 else:
2778 result = []
2779 if result:
2780 return result
2781 else:
2782 return []