1
0
mirror of https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git synced 2025-08-14 00:25:46 +02:00

Проверка 09.02.2025

This commit is contained in:
MoonTestUse1
2025-02-09 01:11:49 +06:00
parent ce52f8a23a
commit 0aa3ef8fc2
5827 changed files with 14316 additions and 1906434 deletions

View File

@@ -1,5 +1,5 @@
# dialects/sqlite/base.py
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@@ -7,10 +7,9 @@
# mypy: ignore-errors
r"""
r'''
.. dialect:: sqlite
:name: SQLite
:full_support: 3.36.0
:normal_support: 3.12+
:best_effort: 3.7.16+
@@ -70,9 +69,12 @@ To specifically render the AUTOINCREMENT keyword on the primary key column
when rendering DDL, add the flag ``sqlite_autoincrement=True`` to the Table
construct::
Table('sometable', metadata,
Column('id', Integer, primary_key=True),
sqlite_autoincrement=True)
Table(
"sometable",
metadata,
Column("id", Integer, primary_key=True),
sqlite_autoincrement=True,
)
Allowing autoincrement behavior SQLAlchemy types other than Integer/INTEGER
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,8 +94,13 @@ One approach to achieve this is to use :class:`.Integer` on SQLite
only using :meth:`.TypeEngine.with_variant`::
table = Table(
"my_table", metadata,
Column("id", BigInteger().with_variant(Integer, "sqlite"), primary_key=True)
"my_table",
metadata,
Column(
"id",
BigInteger().with_variant(Integer, "sqlite"),
primary_key=True,
),
)
Another is to use a subclass of :class:`.BigInteger` that overrides its DDL
@@ -102,21 +109,23 @@ name to be ``INTEGER`` when compiled against SQLite::
from sqlalchemy import BigInteger
from sqlalchemy.ext.compiler import compiles
class SLBigInteger(BigInteger):
pass
@compiles(SLBigInteger, 'sqlite')
@compiles(SLBigInteger, "sqlite")
def bi_c(element, compiler, **kw):
return "INTEGER"
@compiles(SLBigInteger)
def bi_c(element, compiler, **kw):
return compiler.visit_BIGINT(element, **kw)
table = Table(
"my_table", metadata,
Column("id", SLBigInteger(), primary_key=True)
"my_table", metadata, Column("id", SLBigInteger(), primary_key=True)
)
.. seealso::
@@ -236,26 +245,24 @@ To specify an explicit ``RETURNING`` clause, use the
# INSERT..RETURNING
result = connection.execute(
table.insert().
values(name='foo').
returning(table.c.col1, table.c.col2)
table.insert().values(name="foo").returning(table.c.col1, table.c.col2)
)
print(result.all())
# UPDATE..RETURNING
result = connection.execute(
table.update().
where(table.c.name=='foo').
values(name='bar').
returning(table.c.col1, table.c.col2)
table.update()
.where(table.c.name == "foo")
.values(name="bar")
.returning(table.c.col1, table.c.col2)
)
print(result.all())
# DELETE..RETURNING
result = connection.execute(
table.delete().
where(table.c.name=='foo').
returning(table.c.col1, table.c.col2)
table.delete()
.where(table.c.name == "foo")
.returning(table.c.col1, table.c.col2)
)
print(result.all())
@@ -318,6 +325,7 @@ new connections through the usage of events::
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
@@ -380,13 +388,16 @@ ABORT, FAIL, IGNORE, and REPLACE. For example, to add a UNIQUE constraint
that specifies the IGNORE algorithm::
some_table = Table(
'some_table', metadata,
Column('id', Integer, primary_key=True),
Column('data', Integer),
UniqueConstraint('id', 'data', sqlite_on_conflict='IGNORE')
"some_table",
metadata,
Column("id", Integer, primary_key=True),
Column("data", Integer),
UniqueConstraint("id", "data", sqlite_on_conflict="IGNORE"),
)
The above renders CREATE TABLE DDL as::
The above renders CREATE TABLE DDL as:
.. sourcecode:: sql
CREATE TABLE some_table (
id INTEGER NOT NULL,
@@ -403,13 +414,17 @@ be added to the :class:`_schema.Column` as well, which will be added to the
UNIQUE constraint in the DDL::
some_table = Table(
'some_table', metadata,
Column('id', Integer, primary_key=True),
Column('data', Integer, unique=True,
sqlite_on_conflict_unique='IGNORE')
"some_table",
metadata,
Column("id", Integer, primary_key=True),
Column(
"data", Integer, unique=True, sqlite_on_conflict_unique="IGNORE"
),
)
rendering::
rendering:
.. sourcecode:: sql
CREATE TABLE some_table (
id INTEGER NOT NULL,
@@ -422,13 +437,17 @@ To apply the FAIL algorithm for a NOT NULL constraint,
``sqlite_on_conflict_not_null`` is used::
some_table = Table(
'some_table', metadata,
Column('id', Integer, primary_key=True),
Column('data', Integer, nullable=False,
sqlite_on_conflict_not_null='FAIL')
"some_table",
metadata,
Column("id", Integer, primary_key=True),
Column(
"data", Integer, nullable=False, sqlite_on_conflict_not_null="FAIL"
),
)
this renders the column inline ON CONFLICT phrase::
this renders the column inline ON CONFLICT phrase:
.. sourcecode:: sql
CREATE TABLE some_table (
id INTEGER NOT NULL,
@@ -440,13 +459,20 @@ this renders the column inline ON CONFLICT phrase::
Similarly, for an inline primary key, use ``sqlite_on_conflict_primary_key``::
some_table = Table(
'some_table', metadata,
Column('id', Integer, primary_key=True,
sqlite_on_conflict_primary_key='FAIL')
"some_table",
metadata,
Column(
"id",
Integer,
primary_key=True,
sqlite_on_conflict_primary_key="FAIL",
),
)
SQLAlchemy renders the PRIMARY KEY constraint separately, so the conflict
resolution algorithm is applied to the constraint itself::
resolution algorithm is applied to the constraint itself:
.. sourcecode:: sql
CREATE TABLE some_table (
id INTEGER NOT NULL,
@@ -456,7 +482,7 @@ resolution algorithm is applied to the constraint itself::
.. _sqlite_on_conflict_insert:
INSERT...ON CONFLICT (Upsert)
-----------------------------------
-----------------------------
.. seealso:: This section describes the :term:`DML` version of "ON CONFLICT" for
SQLite, which occurs within an INSERT statement. For "ON CONFLICT" as
@@ -484,21 +510,18 @@ and :meth:`_sqlite.Insert.on_conflict_do_nothing`:
>>> from sqlalchemy.dialects.sqlite import insert
>>> insert_stmt = insert(my_table).values(
... id='some_existing_id',
... data='inserted value')
... id="some_existing_id", data="inserted value"
... )
>>> do_update_stmt = insert_stmt.on_conflict_do_update(
... index_elements=['id'],
... set_=dict(data='updated value')
... index_elements=["id"], set_=dict(data="updated value")
... )
>>> print(do_update_stmt)
{printsql}INSERT INTO my_table (id, data) VALUES (?, ?)
ON CONFLICT (id) DO UPDATE SET data = ?{stop}
>>> do_nothing_stmt = insert_stmt.on_conflict_do_nothing(
... index_elements=['id']
... )
>>> do_nothing_stmt = insert_stmt.on_conflict_do_nothing(index_elements=["id"])
>>> print(do_nothing_stmt)
{printsql}INSERT INTO my_table (id, data) VALUES (?, ?)
@@ -529,13 +552,13 @@ Both methods supply the "target" of the conflict using column inference:
.. sourcecode:: pycon+sql
>>> stmt = insert(my_table).values(user_email='a@b.com', data='inserted data')
>>> stmt = insert(my_table).values(user_email="a@b.com", data="inserted data")
>>> do_update_stmt = stmt.on_conflict_do_update(
... index_elements=[my_table.c.user_email],
... index_where=my_table.c.user_email.like('%@gmail.com'),
... set_=dict(data=stmt.excluded.data)
... )
... index_where=my_table.c.user_email.like("%@gmail.com"),
... set_=dict(data=stmt.excluded.data),
... )
>>> print(do_update_stmt)
{printsql}INSERT INTO my_table (data, user_email) VALUES (?, ?)
@@ -555,11 +578,10 @@ for UPDATE:
.. sourcecode:: pycon+sql
>>> stmt = insert(my_table).values(id='some_id', data='inserted value')
>>> stmt = insert(my_table).values(id="some_id", data="inserted value")
>>> do_update_stmt = stmt.on_conflict_do_update(
... index_elements=['id'],
... set_=dict(data='updated value')
... index_elements=["id"], set_=dict(data="updated value")
... )
>>> print(do_update_stmt)
@@ -587,14 +609,12 @@ would have been inserted had the constraint not failed:
.. sourcecode:: pycon+sql
>>> stmt = insert(my_table).values(
... id='some_id',
... data='inserted value',
... author='jlh'
... id="some_id", data="inserted value", author="jlh"
... )
>>> do_update_stmt = stmt.on_conflict_do_update(
... index_elements=['id'],
... set_=dict(data='updated value', author=stmt.excluded.author)
... index_elements=["id"],
... set_=dict(data="updated value", author=stmt.excluded.author),
... )
>>> print(do_update_stmt)
@@ -611,15 +631,13 @@ parameter, which will limit those rows which receive an UPDATE:
.. sourcecode:: pycon+sql
>>> stmt = insert(my_table).values(
... id='some_id',
... data='inserted value',
... author='jlh'
... id="some_id", data="inserted value", author="jlh"
... )
>>> on_update_stmt = stmt.on_conflict_do_update(
... index_elements=['id'],
... set_=dict(data='updated value', author=stmt.excluded.author),
... where=(my_table.c.status == 2)
... index_elements=["id"],
... set_=dict(data="updated value", author=stmt.excluded.author),
... where=(my_table.c.status == 2),
... )
>>> print(on_update_stmt)
{printsql}INSERT INTO my_table (id, data, author) VALUES (?, ?, ?)
@@ -636,8 +654,8 @@ using the :meth:`_sqlite.Insert.on_conflict_do_nothing` method:
.. sourcecode:: pycon+sql
>>> stmt = insert(my_table).values(id='some_id', data='inserted value')
>>> stmt = stmt.on_conflict_do_nothing(index_elements=['id'])
>>> stmt = insert(my_table).values(id="some_id", data="inserted value")
>>> stmt = stmt.on_conflict_do_nothing(index_elements=["id"])
>>> print(stmt)
{printsql}INSERT INTO my_table (id, data) VALUES (?, ?) ON CONFLICT (id) DO NOTHING
@@ -648,7 +666,7 @@ occurs:
.. sourcecode:: pycon+sql
>>> stmt = insert(my_table).values(id='some_id', data='inserted value')
>>> stmt = insert(my_table).values(id="some_id", data="inserted value")
>>> stmt = stmt.on_conflict_do_nothing()
>>> print(stmt)
{printsql}INSERT INTO my_table (id, data) VALUES (?, ?) ON CONFLICT DO NOTHING
@@ -708,11 +726,16 @@ Partial Indexes
A partial index, e.g. one which uses a WHERE clause, can be specified
with the DDL system using the argument ``sqlite_where``::
tbl = Table('testtbl', m, Column('data', Integer))
idx = Index('test_idx1', tbl.c.data,
sqlite_where=and_(tbl.c.data > 5, tbl.c.data < 10))
tbl = Table("testtbl", m, Column("data", Integer))
idx = Index(
"test_idx1",
tbl.c.data,
sqlite_where=and_(tbl.c.data > 5, tbl.c.data < 10),
)
The index will be rendered at create time as::
The index will be rendered at create time as:
.. sourcecode:: sql
CREATE INDEX test_idx1 ON testtbl (data)
WHERE data > 5 AND data < 10
@@ -732,7 +755,11 @@ The bug, entirely outside of SQLAlchemy, can be illustrated thusly::
import sqlite3
assert sqlite3.sqlite_version_info < (3, 10, 0), "bug is fixed in this version"
assert sqlite3.sqlite_version_info < (
3,
10,
0,
), "bug is fixed in this version"
conn = sqlite3.connect(":memory:")
cursor = conn.cursor()
@@ -742,17 +769,22 @@ The bug, entirely outside of SQLAlchemy, can be illustrated thusly::
cursor.execute("insert into x (a, b) values (2, 2)")
cursor.execute("select x.a, x.b from x")
assert [c[0] for c in cursor.description] == ['a', 'b']
assert [c[0] for c in cursor.description] == ["a", "b"]
cursor.execute('''
cursor.execute(
"""
select x.a, x.b from x where a=1
union
select x.a, x.b from x where a=2
''')
assert [c[0] for c in cursor.description] == ['a', 'b'], \
[c[0] for c in cursor.description]
"""
)
assert [c[0] for c in cursor.description] == ["a", "b"], [
c[0] for c in cursor.description
]
The second assertion fails::
The second assertion fails:
.. sourcecode:: text
Traceback (most recent call last):
File "test.py", line 19, in <module>
@@ -780,11 +812,13 @@ to filter these out::
result = conn.exec_driver_sql("select x.a, x.b from x")
assert result.keys() == ["a", "b"]
result = conn.exec_driver_sql('''
result = conn.exec_driver_sql(
"""
select x.a, x.b from x where a=1
union
select x.a, x.b from x where a=2
''')
"""
)
assert result.keys() == ["a", "b"]
Note that above, even though SQLAlchemy filters out the dots, *both
@@ -808,16 +842,20 @@ contain dots, and the functionality of :meth:`_engine.CursorResult.keys` and
the ``sqlite_raw_colnames`` execution option may be provided, either on a
per-:class:`_engine.Connection` basis::
result = conn.execution_options(sqlite_raw_colnames=True).exec_driver_sql('''
result = conn.execution_options(sqlite_raw_colnames=True).exec_driver_sql(
"""
select x.a, x.b from x where a=1
union
select x.a, x.b from x where a=2
''')
"""
)
assert result.keys() == ["x.a", "x.b"]
or on a per-:class:`_engine.Engine` basis::
engine = create_engine("sqlite://", execution_options={"sqlite_raw_colnames": True})
engine = create_engine(
"sqlite://", execution_options={"sqlite_raw_colnames": True}
)
When using the per-:class:`_engine.Engine` execution option, note that
**Core and ORM queries that use UNION may not function properly**.
@@ -832,12 +870,18 @@ dialect in conjunction with the :class:`_schema.Table` construct:
Table("some_table", metadata, ..., sqlite_with_rowid=False)
*
``STRICT``::
Table("some_table", metadata, ..., sqlite_strict=True)
.. versionadded:: 2.0.37
.. seealso::
`SQLite CREATE TABLE options
<https://www.sqlite.org/lang_createtable.html>`_
.. _sqlite_include_internal:
Reflecting internal schema tables
@@ -866,7 +910,7 @@ passed to methods such as :meth:`_schema.MetaData.reflect` or
`SQLite Internal Schema Objects <https://www.sqlite.org/fileformat2.html#intschema>`_ - in the SQLite
documentation.
""" # noqa
''' # noqa
from __future__ import annotations
import datetime
@@ -980,7 +1024,9 @@ class DATETIME(_DateTimeMixin, sqltypes.DateTime):
"%(year)04d-%(month)02d-%(day)02d %(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
e.g.::
e.g.:
.. sourcecode:: text
2021-03-15 12:05:57.105542
@@ -996,9 +1042,11 @@ class DATETIME(_DateTimeMixin, sqltypes.DateTime):
import re
from sqlalchemy.dialects.sqlite import DATETIME
dt = DATETIME(storage_format="%(year)04d/%(month)02d/%(day)02d "
"%(hour)02d:%(minute)02d:%(second)02d",
regexp=r"(\d+)/(\d+)/(\d+) (\d+)-(\d+)-(\d+)"
dt = DATETIME(
storage_format=(
"%(year)04d/%(month)02d/%(day)02d %(hour)02d:%(minute)02d:%(second)02d"
),
regexp=r"(\d+)/(\d+)/(\d+) (\d+)-(\d+)-(\d+)",
)
:param storage_format: format string which will be applied to the dict
@@ -1088,7 +1136,9 @@ class DATE(_DateTimeMixin, sqltypes.Date):
"%(year)04d-%(month)02d-%(day)02d"
e.g.::
e.g.:
.. sourcecode:: text
2011-03-15
@@ -1106,9 +1156,9 @@ class DATE(_DateTimeMixin, sqltypes.Date):
from sqlalchemy.dialects.sqlite import DATE
d = DATE(
storage_format="%(month)02d/%(day)02d/%(year)04d",
regexp=re.compile("(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)")
)
storage_format="%(month)02d/%(day)02d/%(year)04d",
regexp=re.compile("(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)"),
)
:param storage_format: format string which will be applied to the
dict with keys year, month, and day.
@@ -1162,7 +1212,9 @@ class TIME(_DateTimeMixin, sqltypes.Time):
"%(hour)02d:%(minute)02d:%(second)02d.%(microsecond)06d"
e.g.::
e.g.:
.. sourcecode:: text
12:05:57.10558
@@ -1178,9 +1230,9 @@ class TIME(_DateTimeMixin, sqltypes.Time):
import re
from sqlalchemy.dialects.sqlite import TIME
t = TIME(storage_format="%(hour)02d-%(minute)02d-"
"%(second)02d-%(microsecond)06d",
regexp=re.compile("(\d+)-(\d+)-(\d+)-(?:-(\d+))?")
t = TIME(
storage_format="%(hour)02d-%(minute)02d-%(second)02d-%(microsecond)06d",
regexp=re.compile("(\d+)-(\d+)-(\d+)-(?:-(\d+))?"),
)
:param storage_format: format string which will be applied to the dict
@@ -1429,9 +1481,7 @@ class SQLiteCompiler(compiler.SQLCompiler):
return self._generate_generic_binary(binary, " NOT REGEXP ", **kw)
def _on_conflict_target(self, clause, **kw):
if clause.constraint_target is not None:
target_text = "(%s)" % clause.constraint_target
elif clause.inferred_target_elements is not None:
if clause.inferred_target_elements is not None:
target_text = "(%s)" % ", ".join(
(
self.preparer.quote(c)
@@ -1445,7 +1495,7 @@ class SQLiteCompiler(compiler.SQLCompiler):
clause.inferred_target_whereclause,
include_table=False,
use_schema=False,
literal_binds=True,
literal_execute=True,
)
else:
@@ -1528,6 +1578,13 @@ class SQLiteCompiler(compiler.SQLCompiler):
return "ON CONFLICT %s DO UPDATE SET %s" % (target_text, action_text)
def visit_bitwise_xor_op_binary(self, binary, operator, **kw):
# sqlite has no xor. Use "a XOR b" = "(a | b) - (a & b)".
kw["eager_grouping"] = True
or_ = self._generate_generic_binary(binary, " | ", **kw)
and_ = self._generate_generic_binary(binary, " & ", **kw)
return f"({or_} - {and_})"
class SQLiteDDLCompiler(compiler.DDLCompiler):
def get_column_specification(self, column, **kwargs):
@@ -1701,9 +1758,12 @@ class SQLiteDDLCompiler(compiler.DDLCompiler):
return text
def post_create_table(self, table):
text = ""
if table.dialect_options["sqlite"]["with_rowid"] is False:
return "\n WITHOUT ROWID"
return ""
text += "\n WITHOUT ROWID"
if table.dialect_options["sqlite"]["strict"] is True:
text += "\n STRICT"
return text
class SQLiteTypeCompiler(compiler.GenericTypeCompiler):
@@ -1938,6 +1998,7 @@ class SQLiteDialect(default.DefaultDialect):
{
"autoincrement": False,
"with_rowid": True,
"strict": False,
},
),
(sa_schema.Index, {"where": None}),
@@ -2231,6 +2292,14 @@ class SQLiteDialect(default.DefaultDialect):
tablesql = self._get_table_sql(
connection, table_name, schema, **kw
)
# remove create table
match = re.match(
r"create table .*?\((.*)\)$",
tablesql.strip(),
re.DOTALL | re.IGNORECASE,
)
assert match, f"create table not found in {tablesql}"
tablesql = match.group(1).strip()
columns.append(
self._get_column_info(
@@ -2285,7 +2354,10 @@ class SQLiteDialect(default.DefaultDialect):
if generated:
sqltext = ""
if tablesql:
pattern = r"[^,]*\s+AS\s+\(([^,]*)\)\s*(?:virtual|stored)?"
pattern = (
r"[^,]*\s+GENERATED\s+ALWAYS\s+AS"
r"\s+\((.*)\)\s*(?:virtual|stored)?"
)
match = re.search(
re.escape(name) + pattern, tablesql, re.IGNORECASE
)
@@ -2570,8 +2642,8 @@ class SQLiteDialect(default.DefaultDialect):
return
UNIQUE_PATTERN = r'(?:CONSTRAINT "?(.+?)"? +)?UNIQUE *\((.+?)\)'
INLINE_UNIQUE_PATTERN = (
r'(?:(".+?")|(?:[\[`])?([a-z0-9_]+)(?:[\]`])?) '
r"+[a-z0-9_ ]+? +UNIQUE"
r'(?:(".+?")|(?:[\[`])?([a-z0-9_]+)(?:[\]`])?)[\t ]'
r"+[a-z0-9_ ]+?[\t ]+UNIQUE"
)
for match in re.finditer(UNIQUE_PATTERN, table_data, re.I):
@@ -2606,15 +2678,21 @@ class SQLiteDialect(default.DefaultDialect):
connection, table_name, schema=schema, **kw
)
CHECK_PATTERN = r"(?:CONSTRAINT (.+) +)?" r"CHECK *\( *(.+) *\),? *"
cks = []
# NOTE: we aren't using re.S here because we actually are
# taking advantage of each CHECK constraint being all on one
# line in the table definition in order to delineate. This
# NOTE NOTE NOTE
# DO NOT CHANGE THIS REGULAR EXPRESSION. There is no known way
# to parse CHECK constraints that contain newlines themselves using
# regular expressions, and the approach here relies upon each
# individual
# CHECK constraint being on a single line by itself. This
# necessarily makes assumptions as to how the CREATE TABLE
# was emitted.
# was emitted. A more comprehensive DDL parsing solution would be
# needed to improve upon the current situation. See #11840 for
# background
CHECK_PATTERN = r"(?:CONSTRAINT (.+) +)?CHECK *\( *(.+) *\),? *"
cks = []
for match in re.finditer(CHECK_PATTERN, table_data or "", re.I):
name = match.group(1)
if name: