SQLAlchemy 2.0.47__cp313-cp313t-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqlalchemy/__init__.py +283 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +184 -0
- sqlalchemy/connectors/asyncio.py +429 -0
- sqlalchemy/connectors/pyodbc.py +250 -0
- sqlalchemy/cyextension/__init__.py +6 -0
- sqlalchemy/cyextension/collections.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/collections.pyx +409 -0
- sqlalchemy/cyextension/immutabledict.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/immutabledict.pxd +8 -0
- sqlalchemy/cyextension/immutabledict.pyx +133 -0
- sqlalchemy/cyextension/processors.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/processors.pyx +68 -0
- sqlalchemy/cyextension/resultproxy.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/resultproxy.pyx +102 -0
- sqlalchemy/cyextension/util.cp313t-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/util.pyx +90 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +30 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4093 -0
- sqlalchemy/dialects/mssql/information_schema.py +285 -0
- sqlalchemy/dialects/mssql/json.py +129 -0
- sqlalchemy/dialects/mssql/provision.py +185 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +760 -0
- sqlalchemy/dialects/mysql/__init__.py +104 -0
- sqlalchemy/dialects/mysql/aiomysql.py +250 -0
- sqlalchemy/dialects/mysql/asyncmy.py +231 -0
- sqlalchemy/dialects/mysql/base.py +3949 -0
- sqlalchemy/dialects/mysql/cymysql.py +106 -0
- sqlalchemy/dialects/mysql/dml.py +225 -0
- sqlalchemy/dialects/mysql/enumerated.py +282 -0
- sqlalchemy/dialects/mysql/expression.py +146 -0
- sqlalchemy/dialects/mysql/json.py +91 -0
- sqlalchemy/dialects/mysql/mariadb.py +72 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
- sqlalchemy/dialects/mysql/mysqldb.py +314 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +158 -0
- sqlalchemy/dialects/mysql/pyodbc.py +157 -0
- sqlalchemy/dialects/mysql/reflection.py +727 -0
- sqlalchemy/dialects/mysql/reserved_words.py +570 -0
- sqlalchemy/dialects/mysql/types.py +835 -0
- sqlalchemy/dialects/oracle/__init__.py +81 -0
- sqlalchemy/dialects/oracle/base.py +3802 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/oracledb.py +941 -0
- sqlalchemy/dialects/oracle/provision.py +297 -0
- sqlalchemy/dialects/oracle/types.py +316 -0
- sqlalchemy/dialects/oracle/vector.py +365 -0
- sqlalchemy/dialects/postgresql/__init__.py +167 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
- sqlalchemy/dialects/postgresql/array.py +519 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
- sqlalchemy/dialects/postgresql/base.py +5378 -0
- sqlalchemy/dialects/postgresql/dml.py +339 -0
- sqlalchemy/dialects/postgresql/ext.py +540 -0
- sqlalchemy/dialects/postgresql/hstore.py +406 -0
- sqlalchemy/dialects/postgresql/json.py +404 -0
- sqlalchemy/dialects/postgresql/named_types.py +524 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +669 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
- sqlalchemy/dialects/postgresql/provision.py +183 -0
- sqlalchemy/dialects/postgresql/psycopg.py +862 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1031 -0
- sqlalchemy/dialects/postgresql/types.py +313 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
- sqlalchemy/dialects/sqlite/base.py +3056 -0
- sqlalchemy/dialects/sqlite/dml.py +263 -0
- sqlalchemy/dialects/sqlite/json.py +92 -0
- sqlalchemy/dialects/sqlite/provision.py +229 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_py_processors.py +136 -0
- sqlalchemy/engine/_py_row.py +128 -0
- sqlalchemy/engine/_py_util.py +74 -0
- sqlalchemy/engine/base.py +3390 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +893 -0
- sqlalchemy/engine/cursor.py +2298 -0
- sqlalchemy/engine/default.py +2394 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3471 -0
- sqlalchemy/engine/mock.py +134 -0
- sqlalchemy/engine/processors.py +61 -0
- sqlalchemy/engine/reflection.py +2102 -0
- sqlalchemy/engine/result.py +2399 -0
- sqlalchemy/engine/row.py +400 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +924 -0
- sqlalchemy/engine/util.py +167 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +676 -0
- sqlalchemy/event/base.py +472 -0
- sqlalchemy/event/legacy.py +258 -0
- sqlalchemy/event/registry.py +390 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +832 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2027 -0
- sqlalchemy/ext/asyncio/__init__.py +25 -0
- sqlalchemy/ext/asyncio/base.py +281 -0
- sqlalchemy/ext/asyncio/engine.py +1471 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +965 -0
- sqlalchemy/ext/asyncio/scoping.py +1599 -0
- sqlalchemy/ext/asyncio/session.py +1947 -0
- sqlalchemy/ext/automap.py +1701 -0
- sqlalchemy/ext/baked.py +570 -0
- sqlalchemy/ext/compiler.py +600 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +564 -0
- sqlalchemy/ext/horizontal_shard.py +478 -0
- sqlalchemy/ext/hybrid.py +1535 -0
- sqlalchemy/ext/indexable.py +364 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1085 -0
- sqlalchemy/ext/mypy/__init__.py +6 -0
- sqlalchemy/ext/mypy/apply.py +324 -0
- sqlalchemy/ext/mypy/decl_class.py +515 -0
- sqlalchemy/ext/mypy/infer.py +590 -0
- sqlalchemy/ext/mypy/names.py +335 -0
- sqlalchemy/ext/mypy/plugin.py +303 -0
- sqlalchemy/ext/mypy/util.py +357 -0
- sqlalchemy/ext/orderinglist.py +439 -0
- sqlalchemy/ext/serializer.py +185 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +288 -0
- sqlalchemy/orm/__init__.py +171 -0
- sqlalchemy/orm/_orm_constructors.py +2661 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2845 -0
- sqlalchemy/orm/base.py +971 -0
- sqlalchemy/orm/bulk_persistence.py +2135 -0
- sqlalchemy/orm/clsregistry.py +571 -0
- sqlalchemy/orm/collections.py +1627 -0
- sqlalchemy/orm/context.py +3334 -0
- sqlalchemy/orm/decl_api.py +2004 -0
- sqlalchemy/orm/decl_base.py +2192 -0
- sqlalchemy/orm/dependency.py +1302 -0
- sqlalchemy/orm/descriptor_props.py +1092 -0
- sqlalchemy/orm/dynamic.py +300 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3252 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +754 -0
- sqlalchemy/orm/interfaces.py +1496 -0
- sqlalchemy/orm/loading.py +1686 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4444 -0
- sqlalchemy/orm/path_registry.py +809 -0
- sqlalchemy/orm/persistence.py +1788 -0
- sqlalchemy/orm/properties.py +935 -0
- sqlalchemy/orm/query.py +3459 -0
- sqlalchemy/orm/relationships.py +3508 -0
- sqlalchemy/orm/scoping.py +2148 -0
- sqlalchemy/orm/session.py +5280 -0
- sqlalchemy/orm/state.py +1168 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3470 -0
- sqlalchemy/orm/strategy_options.py +2568 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +796 -0
- sqlalchemy/orm/util.py +2403 -0
- sqlalchemy/orm/writeonly.py +674 -0
- sqlalchemy/pool/__init__.py +44 -0
- sqlalchemy/pool/base.py +1524 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +588 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +69 -0
- sqlalchemy/sql/__init__.py +145 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +1872 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_py_util.py +75 -0
- sqlalchemy/sql/_selectable_constructors.py +763 -0
- sqlalchemy/sql/_typing.py +482 -0
- sqlalchemy/sql/annotation.py +587 -0
- sqlalchemy/sql/base.py +2293 -0
- sqlalchemy/sql/cache_key.py +1057 -0
- sqlalchemy/sql/coercions.py +1404 -0
- sqlalchemy/sql/compiler.py +8081 -0
- sqlalchemy/sql/crud.py +1752 -0
- sqlalchemy/sql/ddl.py +1444 -0
- sqlalchemy/sql/default_comparator.py +551 -0
- sqlalchemy/sql/dml.py +1850 -0
- sqlalchemy/sql/elements.py +5589 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +159 -0
- sqlalchemy/sql/functions.py +2158 -0
- sqlalchemy/sql/lambdas.py +1442 -0
- sqlalchemy/sql/naming.py +209 -0
- sqlalchemy/sql/operators.py +2623 -0
- sqlalchemy/sql/roles.py +323 -0
- sqlalchemy/sql/schema.py +6222 -0
- sqlalchemy/sql/selectable.py +7265 -0
- sqlalchemy/sql/sqltypes.py +3930 -0
- sqlalchemy/sql/traversals.py +1024 -0
- sqlalchemy/sql/type_api.py +2368 -0
- sqlalchemy/sql/util.py +1485 -0
- sqlalchemy/sql/visitors.py +1164 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +994 -0
- sqlalchemy/testing/assertsql.py +520 -0
- sqlalchemy/testing/asyncio.py +135 -0
- sqlalchemy/testing/config.py +434 -0
- sqlalchemy/testing/engines.py +483 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +476 -0
- sqlalchemy/testing/fixtures/__init__.py +28 -0
- sqlalchemy/testing/fixtures/base.py +384 -0
- sqlalchemy/testing/fixtures/mypy.py +332 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +482 -0
- sqlalchemy/testing/pickleable.py +155 -0
- sqlalchemy/testing/plugin/__init__.py +6 -0
- sqlalchemy/testing/plugin/bootstrap.py +51 -0
- sqlalchemy/testing/plugin/plugin_base.py +828 -0
- sqlalchemy/testing/plugin/pytestplugin.py +892 -0
- sqlalchemy/testing/profiling.py +329 -0
- sqlalchemy/testing/provision.py +603 -0
- sqlalchemy/testing/requirements.py +1945 -0
- sqlalchemy/testing/schema.py +198 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +237 -0
- sqlalchemy/testing/suite/test_ddl.py +389 -0
- sqlalchemy/testing/suite/test_deprecations.py +153 -0
- sqlalchemy/testing/suite/test_dialect.py +776 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3557 -0
- sqlalchemy/testing/suite/test_results.py +504 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +2010 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_types.py +2147 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +535 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +74 -0
- sqlalchemy/util/__init__.py +162 -0
- sqlalchemy/util/_collections.py +712 -0
- sqlalchemy/util/_concurrency_py3k.py +288 -0
- sqlalchemy/util/_has_cy.py +40 -0
- sqlalchemy/util/_py_collections.py +541 -0
- sqlalchemy/util/compat.py +421 -0
- sqlalchemy/util/concurrency.py +110 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2203 -0
- sqlalchemy/util/preloaded.py +150 -0
- sqlalchemy/util/queue.py +322 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +734 -0
- sqlalchemy-2.0.47.dist-info/METADATA +243 -0
- sqlalchemy-2.0.47.dist-info/RECORD +274 -0
- sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
- sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.0.47.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
# dialects/postgresql/ext.py
|
|
2
|
+
# Copyright (C) 2005-2026 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
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
from typing import Iterable
|
|
12
|
+
from typing import List
|
|
13
|
+
from typing import Optional
|
|
14
|
+
from typing import overload
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
from typing import TypeVar
|
|
18
|
+
|
|
19
|
+
from . import types
|
|
20
|
+
from .array import ARRAY
|
|
21
|
+
from ...sql import coercions
|
|
22
|
+
from ...sql import elements
|
|
23
|
+
from ...sql import expression
|
|
24
|
+
from ...sql import functions
|
|
25
|
+
from ...sql import roles
|
|
26
|
+
from ...sql import schema
|
|
27
|
+
from ...sql.schema import ColumnCollectionConstraint
|
|
28
|
+
from ...sql.sqltypes import TEXT
|
|
29
|
+
from ...sql.visitors import InternalTraversal
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from ...sql._typing import _ColumnExpressionArgument
|
|
33
|
+
from ...sql._typing import _DDLColumnArgument
|
|
34
|
+
from ...sql.elements import ClauseElement
|
|
35
|
+
from ...sql.elements import ColumnElement
|
|
36
|
+
from ...sql.operators import OperatorType
|
|
37
|
+
from ...sql.selectable import FromClause
|
|
38
|
+
from ...sql.visitors import _CloneCallableType
|
|
39
|
+
from ...sql.visitors import _TraverseInternalsType
|
|
40
|
+
|
|
41
|
+
_T = TypeVar("_T", bound=Any)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class aggregate_order_by(expression.ColumnElement[_T]):
|
|
45
|
+
"""Represent a PostgreSQL aggregate order by expression.
|
|
46
|
+
|
|
47
|
+
E.g.::
|
|
48
|
+
|
|
49
|
+
from sqlalchemy.dialects.postgresql import aggregate_order_by
|
|
50
|
+
|
|
51
|
+
expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc()))
|
|
52
|
+
stmt = select(expr)
|
|
53
|
+
|
|
54
|
+
would represent the expression:
|
|
55
|
+
|
|
56
|
+
.. sourcecode:: sql
|
|
57
|
+
|
|
58
|
+
SELECT array_agg(a ORDER BY b DESC) FROM table;
|
|
59
|
+
|
|
60
|
+
Similarly::
|
|
61
|
+
|
|
62
|
+
expr = func.string_agg(
|
|
63
|
+
table.c.a, aggregate_order_by(literal_column("','"), table.c.a)
|
|
64
|
+
)
|
|
65
|
+
stmt = select(expr)
|
|
66
|
+
|
|
67
|
+
Would represent:
|
|
68
|
+
|
|
69
|
+
.. sourcecode:: sql
|
|
70
|
+
|
|
71
|
+
SELECT string_agg(a, ',' ORDER BY a) FROM table;
|
|
72
|
+
|
|
73
|
+
.. versionchanged:: 1.2.13 - the ORDER BY argument may be multiple terms
|
|
74
|
+
|
|
75
|
+
.. seealso::
|
|
76
|
+
|
|
77
|
+
:class:`_functions.array_agg`
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
__visit_name__ = "aggregate_order_by"
|
|
82
|
+
|
|
83
|
+
stringify_dialect = "postgresql"
|
|
84
|
+
_traverse_internals: _TraverseInternalsType = [
|
|
85
|
+
("target", InternalTraversal.dp_clauseelement),
|
|
86
|
+
("type", InternalTraversal.dp_type),
|
|
87
|
+
("order_by", InternalTraversal.dp_clauseelement),
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
@overload
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
target: ColumnElement[_T],
|
|
94
|
+
*order_by: _ColumnExpressionArgument[Any],
|
|
95
|
+
): ...
|
|
96
|
+
|
|
97
|
+
@overload
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
target: _ColumnExpressionArgument[_T],
|
|
101
|
+
*order_by: _ColumnExpressionArgument[Any],
|
|
102
|
+
): ...
|
|
103
|
+
|
|
104
|
+
def __init__(
|
|
105
|
+
self,
|
|
106
|
+
target: _ColumnExpressionArgument[_T],
|
|
107
|
+
*order_by: _ColumnExpressionArgument[Any],
|
|
108
|
+
):
|
|
109
|
+
self.target: ClauseElement = coercions.expect(
|
|
110
|
+
roles.ExpressionElementRole, target
|
|
111
|
+
)
|
|
112
|
+
self.type = self.target.type
|
|
113
|
+
|
|
114
|
+
_lob = len(order_by)
|
|
115
|
+
self.order_by: ClauseElement
|
|
116
|
+
if _lob == 0:
|
|
117
|
+
raise TypeError("at least one ORDER BY element is required")
|
|
118
|
+
elif _lob == 1:
|
|
119
|
+
self.order_by = coercions.expect(
|
|
120
|
+
roles.ExpressionElementRole, order_by[0]
|
|
121
|
+
)
|
|
122
|
+
else:
|
|
123
|
+
self.order_by = elements.ClauseList(
|
|
124
|
+
*order_by, _literal_as_text_role=roles.ExpressionElementRole
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def self_group(
|
|
128
|
+
self, against: Optional[OperatorType] = None
|
|
129
|
+
) -> ClauseElement:
|
|
130
|
+
return self
|
|
131
|
+
|
|
132
|
+
def get_children(self, **kwargs: Any) -> Iterable[ClauseElement]:
|
|
133
|
+
return self.target, self.order_by
|
|
134
|
+
|
|
135
|
+
def _copy_internals(
|
|
136
|
+
self, clone: _CloneCallableType = elements._clone, **kw: Any
|
|
137
|
+
) -> None:
|
|
138
|
+
self.target = clone(self.target, **kw)
|
|
139
|
+
self.order_by = clone(self.order_by, **kw)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def _from_objects(self) -> List[FromClause]:
|
|
143
|
+
return self.target._from_objects + self.order_by._from_objects
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ExcludeConstraint(ColumnCollectionConstraint):
|
|
147
|
+
"""A table-level EXCLUDE constraint.
|
|
148
|
+
|
|
149
|
+
Defines an EXCLUDE constraint as described in the `PostgreSQL
|
|
150
|
+
documentation`__.
|
|
151
|
+
|
|
152
|
+
__ https://www.postgresql.org/docs/current/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
|
|
153
|
+
|
|
154
|
+
""" # noqa
|
|
155
|
+
|
|
156
|
+
__visit_name__ = "exclude_constraint"
|
|
157
|
+
|
|
158
|
+
where = None
|
|
159
|
+
inherit_cache = False
|
|
160
|
+
|
|
161
|
+
create_drop_stringify_dialect = "postgresql"
|
|
162
|
+
|
|
163
|
+
@elements._document_text_coercion(
|
|
164
|
+
"where",
|
|
165
|
+
":class:`.ExcludeConstraint`",
|
|
166
|
+
":paramref:`.ExcludeConstraint.where`",
|
|
167
|
+
)
|
|
168
|
+
def __init__(
|
|
169
|
+
self, *elements: Tuple[_DDLColumnArgument, str], **kw: Any
|
|
170
|
+
) -> None:
|
|
171
|
+
r"""
|
|
172
|
+
Create an :class:`.ExcludeConstraint` object.
|
|
173
|
+
|
|
174
|
+
E.g.::
|
|
175
|
+
|
|
176
|
+
const = ExcludeConstraint(
|
|
177
|
+
(Column("period"), "&&"),
|
|
178
|
+
(Column("group"), "="),
|
|
179
|
+
where=(Column("group") != "some group"),
|
|
180
|
+
ops={"group": "my_operator_class"},
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
The constraint is normally embedded into the :class:`_schema.Table`
|
|
184
|
+
construct
|
|
185
|
+
directly, or added later using :meth:`.append_constraint`::
|
|
186
|
+
|
|
187
|
+
some_table = Table(
|
|
188
|
+
"some_table",
|
|
189
|
+
metadata,
|
|
190
|
+
Column("id", Integer, primary_key=True),
|
|
191
|
+
Column("period", TSRANGE()),
|
|
192
|
+
Column("group", String),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
some_table.append_constraint(
|
|
196
|
+
ExcludeConstraint(
|
|
197
|
+
(some_table.c.period, "&&"),
|
|
198
|
+
(some_table.c.group, "="),
|
|
199
|
+
where=some_table.c.group != "some group",
|
|
200
|
+
name="some_table_excl_const",
|
|
201
|
+
ops={"group": "my_operator_class"},
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
The exclude constraint defined in this example requires the
|
|
206
|
+
``btree_gist`` extension, that can be created using the
|
|
207
|
+
command ``CREATE EXTENSION btree_gist;``.
|
|
208
|
+
|
|
209
|
+
:param \*elements:
|
|
210
|
+
|
|
211
|
+
A sequence of two tuples of the form ``(column, operator)`` where
|
|
212
|
+
"column" is either a :class:`_schema.Column` object, or a SQL
|
|
213
|
+
expression element (e.g. ``func.int8range(table.from, table.to)``)
|
|
214
|
+
or the name of a column as string, and "operator" is a string
|
|
215
|
+
containing the operator to use (e.g. `"&&"` or `"="`).
|
|
216
|
+
|
|
217
|
+
In order to specify a column name when a :class:`_schema.Column`
|
|
218
|
+
object is not available, while ensuring
|
|
219
|
+
that any necessary quoting rules take effect, an ad-hoc
|
|
220
|
+
:class:`_schema.Column` or :func:`_expression.column`
|
|
221
|
+
object should be used.
|
|
222
|
+
The ``column`` may also be a string SQL expression when
|
|
223
|
+
passed as :func:`_expression.literal_column` or
|
|
224
|
+
:func:`_expression.text`
|
|
225
|
+
|
|
226
|
+
:param name:
|
|
227
|
+
Optional, the in-database name of this constraint.
|
|
228
|
+
|
|
229
|
+
:param deferrable:
|
|
230
|
+
Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when
|
|
231
|
+
issuing DDL for this constraint.
|
|
232
|
+
|
|
233
|
+
:param initially:
|
|
234
|
+
Optional string. If set, emit INITIALLY <value> when issuing DDL
|
|
235
|
+
for this constraint.
|
|
236
|
+
|
|
237
|
+
:param using:
|
|
238
|
+
Optional string. If set, emit USING <index_method> when issuing DDL
|
|
239
|
+
for this constraint. Defaults to 'gist'.
|
|
240
|
+
|
|
241
|
+
:param where:
|
|
242
|
+
Optional SQL expression construct or literal SQL string.
|
|
243
|
+
If set, emit WHERE <predicate> when issuing DDL
|
|
244
|
+
for this constraint.
|
|
245
|
+
|
|
246
|
+
:param ops:
|
|
247
|
+
Optional dictionary. Used to define operator classes for the
|
|
248
|
+
elements; works the same way as that of the
|
|
249
|
+
:ref:`postgresql_ops <postgresql_operator_classes>`
|
|
250
|
+
parameter specified to the :class:`_schema.Index` construct.
|
|
251
|
+
|
|
252
|
+
.. versionadded:: 1.3.21
|
|
253
|
+
|
|
254
|
+
.. seealso::
|
|
255
|
+
|
|
256
|
+
:ref:`postgresql_operator_classes` - general description of how
|
|
257
|
+
PostgreSQL operator classes are specified.
|
|
258
|
+
|
|
259
|
+
"""
|
|
260
|
+
columns = []
|
|
261
|
+
render_exprs = []
|
|
262
|
+
self.operators = {}
|
|
263
|
+
|
|
264
|
+
expressions, operators = zip(*elements)
|
|
265
|
+
|
|
266
|
+
for (expr, column, strname, add_element), operator in zip(
|
|
267
|
+
coercions.expect_col_expression_collection(
|
|
268
|
+
roles.DDLConstraintColumnRole, expressions
|
|
269
|
+
),
|
|
270
|
+
operators,
|
|
271
|
+
):
|
|
272
|
+
if add_element is not None:
|
|
273
|
+
columns.append(add_element)
|
|
274
|
+
|
|
275
|
+
name = column.name if column is not None else strname
|
|
276
|
+
|
|
277
|
+
if name is not None:
|
|
278
|
+
# backwards compat
|
|
279
|
+
self.operators[name] = operator
|
|
280
|
+
|
|
281
|
+
render_exprs.append((expr, name, operator))
|
|
282
|
+
|
|
283
|
+
self._render_exprs = render_exprs
|
|
284
|
+
|
|
285
|
+
ColumnCollectionConstraint.__init__(
|
|
286
|
+
self,
|
|
287
|
+
*columns,
|
|
288
|
+
name=kw.get("name"),
|
|
289
|
+
deferrable=kw.get("deferrable"),
|
|
290
|
+
initially=kw.get("initially"),
|
|
291
|
+
)
|
|
292
|
+
self.using = kw.get("using", "gist")
|
|
293
|
+
where = kw.get("where")
|
|
294
|
+
if where is not None:
|
|
295
|
+
self.where = coercions.expect(roles.StatementOptionRole, where)
|
|
296
|
+
|
|
297
|
+
self.ops = kw.get("ops", {})
|
|
298
|
+
|
|
299
|
+
def _set_parent(self, table, **kw):
|
|
300
|
+
super()._set_parent(table)
|
|
301
|
+
|
|
302
|
+
self._render_exprs = [
|
|
303
|
+
(
|
|
304
|
+
expr if not isinstance(expr, str) else table.c[expr],
|
|
305
|
+
name,
|
|
306
|
+
operator,
|
|
307
|
+
)
|
|
308
|
+
for expr, name, operator in (self._render_exprs)
|
|
309
|
+
]
|
|
310
|
+
|
|
311
|
+
def _copy(self, target_table=None, **kw):
|
|
312
|
+
elements = [
|
|
313
|
+
(
|
|
314
|
+
schema._copy_expression(expr, self.parent, target_table),
|
|
315
|
+
operator,
|
|
316
|
+
)
|
|
317
|
+
for expr, _, operator in self._render_exprs
|
|
318
|
+
]
|
|
319
|
+
c = self.__class__(
|
|
320
|
+
*elements,
|
|
321
|
+
name=self.name,
|
|
322
|
+
deferrable=self.deferrable,
|
|
323
|
+
initially=self.initially,
|
|
324
|
+
where=self.where,
|
|
325
|
+
using=self.using,
|
|
326
|
+
)
|
|
327
|
+
c.dispatch._update(self.dispatch)
|
|
328
|
+
return c
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def array_agg(*arg, **kw):
|
|
332
|
+
"""PostgreSQL-specific form of :class:`_functions.array_agg`, ensures
|
|
333
|
+
return type is :class:`_postgresql.ARRAY` and not
|
|
334
|
+
the plain :class:`_types.ARRAY`, unless an explicit ``type_``
|
|
335
|
+
is passed.
|
|
336
|
+
|
|
337
|
+
"""
|
|
338
|
+
kw["_default_array_type"] = ARRAY
|
|
339
|
+
return functions.func.array_agg(*arg, **kw)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class _regconfig_fn(functions.GenericFunction[_T]):
|
|
343
|
+
inherit_cache = True
|
|
344
|
+
|
|
345
|
+
def __init__(self, *args, **kwargs):
|
|
346
|
+
args = list(args)
|
|
347
|
+
if len(args) > 1:
|
|
348
|
+
initial_arg = coercions.expect(
|
|
349
|
+
roles.ExpressionElementRole,
|
|
350
|
+
args.pop(0),
|
|
351
|
+
name=getattr(self, "name", None),
|
|
352
|
+
apply_propagate_attrs=self,
|
|
353
|
+
type_=types.REGCONFIG,
|
|
354
|
+
)
|
|
355
|
+
initial_arg = [initial_arg]
|
|
356
|
+
else:
|
|
357
|
+
initial_arg = []
|
|
358
|
+
|
|
359
|
+
addtl_args = [
|
|
360
|
+
coercions.expect(
|
|
361
|
+
roles.ExpressionElementRole,
|
|
362
|
+
c,
|
|
363
|
+
name=getattr(self, "name", None),
|
|
364
|
+
apply_propagate_attrs=self,
|
|
365
|
+
)
|
|
366
|
+
for c in args
|
|
367
|
+
]
|
|
368
|
+
super().__init__(*(initial_arg + addtl_args), **kwargs)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class to_tsvector(_regconfig_fn):
|
|
372
|
+
"""The PostgreSQL ``to_tsvector`` SQL function.
|
|
373
|
+
|
|
374
|
+
This function applies automatic casting of the REGCONFIG argument
|
|
375
|
+
to use the :class:`_postgresql.REGCONFIG` datatype automatically,
|
|
376
|
+
and applies a return type of :class:`_postgresql.TSVECTOR`.
|
|
377
|
+
|
|
378
|
+
Assuming the PostgreSQL dialect has been imported, either by invoking
|
|
379
|
+
``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
|
|
380
|
+
engine using ``create_engine("postgresql...")``,
|
|
381
|
+
:class:`_postgresql.to_tsvector` will be used automatically when invoking
|
|
382
|
+
``sqlalchemy.func.to_tsvector()``, ensuring the correct argument and return
|
|
383
|
+
type handlers are used at compile and execution time.
|
|
384
|
+
|
|
385
|
+
.. versionadded:: 2.0.0rc1
|
|
386
|
+
|
|
387
|
+
"""
|
|
388
|
+
|
|
389
|
+
inherit_cache = True
|
|
390
|
+
type = types.TSVECTOR
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class to_tsquery(_regconfig_fn):
|
|
394
|
+
"""The PostgreSQL ``to_tsquery`` SQL function.
|
|
395
|
+
|
|
396
|
+
This function applies automatic casting of the REGCONFIG argument
|
|
397
|
+
to use the :class:`_postgresql.REGCONFIG` datatype automatically,
|
|
398
|
+
and applies a return type of :class:`_postgresql.TSQUERY`.
|
|
399
|
+
|
|
400
|
+
Assuming the PostgreSQL dialect has been imported, either by invoking
|
|
401
|
+
``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
|
|
402
|
+
engine using ``create_engine("postgresql...")``,
|
|
403
|
+
:class:`_postgresql.to_tsquery` will be used automatically when invoking
|
|
404
|
+
``sqlalchemy.func.to_tsquery()``, ensuring the correct argument and return
|
|
405
|
+
type handlers are used at compile and execution time.
|
|
406
|
+
|
|
407
|
+
.. versionadded:: 2.0.0rc1
|
|
408
|
+
|
|
409
|
+
"""
|
|
410
|
+
|
|
411
|
+
inherit_cache = True
|
|
412
|
+
type = types.TSQUERY
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
class plainto_tsquery(_regconfig_fn):
|
|
416
|
+
"""The PostgreSQL ``plainto_tsquery`` SQL function.
|
|
417
|
+
|
|
418
|
+
This function applies automatic casting of the REGCONFIG argument
|
|
419
|
+
to use the :class:`_postgresql.REGCONFIG` datatype automatically,
|
|
420
|
+
and applies a return type of :class:`_postgresql.TSQUERY`.
|
|
421
|
+
|
|
422
|
+
Assuming the PostgreSQL dialect has been imported, either by invoking
|
|
423
|
+
``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
|
|
424
|
+
engine using ``create_engine("postgresql...")``,
|
|
425
|
+
:class:`_postgresql.plainto_tsquery` will be used automatically when
|
|
426
|
+
invoking ``sqlalchemy.func.plainto_tsquery()``, ensuring the correct
|
|
427
|
+
argument and return type handlers are used at compile and execution time.
|
|
428
|
+
|
|
429
|
+
.. versionadded:: 2.0.0rc1
|
|
430
|
+
|
|
431
|
+
"""
|
|
432
|
+
|
|
433
|
+
inherit_cache = True
|
|
434
|
+
type = types.TSQUERY
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class phraseto_tsquery(_regconfig_fn):
|
|
438
|
+
"""The PostgreSQL ``phraseto_tsquery`` SQL function.
|
|
439
|
+
|
|
440
|
+
This function applies automatic casting of the REGCONFIG argument
|
|
441
|
+
to use the :class:`_postgresql.REGCONFIG` datatype automatically,
|
|
442
|
+
and applies a return type of :class:`_postgresql.TSQUERY`.
|
|
443
|
+
|
|
444
|
+
Assuming the PostgreSQL dialect has been imported, either by invoking
|
|
445
|
+
``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
|
|
446
|
+
engine using ``create_engine("postgresql...")``,
|
|
447
|
+
:class:`_postgresql.phraseto_tsquery` will be used automatically when
|
|
448
|
+
invoking ``sqlalchemy.func.phraseto_tsquery()``, ensuring the correct
|
|
449
|
+
argument and return type handlers are used at compile and execution time.
|
|
450
|
+
|
|
451
|
+
.. versionadded:: 2.0.0rc1
|
|
452
|
+
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
inherit_cache = True
|
|
456
|
+
type = types.TSQUERY
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
class websearch_to_tsquery(_regconfig_fn):
|
|
460
|
+
"""The PostgreSQL ``websearch_to_tsquery`` SQL function.
|
|
461
|
+
|
|
462
|
+
This function applies automatic casting of the REGCONFIG argument
|
|
463
|
+
to use the :class:`_postgresql.REGCONFIG` datatype automatically,
|
|
464
|
+
and applies a return type of :class:`_postgresql.TSQUERY`.
|
|
465
|
+
|
|
466
|
+
Assuming the PostgreSQL dialect has been imported, either by invoking
|
|
467
|
+
``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
|
|
468
|
+
engine using ``create_engine("postgresql...")``,
|
|
469
|
+
:class:`_postgresql.websearch_to_tsquery` will be used automatically when
|
|
470
|
+
invoking ``sqlalchemy.func.websearch_to_tsquery()``, ensuring the correct
|
|
471
|
+
argument and return type handlers are used at compile and execution time.
|
|
472
|
+
|
|
473
|
+
.. versionadded:: 2.0.0rc1
|
|
474
|
+
|
|
475
|
+
"""
|
|
476
|
+
|
|
477
|
+
inherit_cache = True
|
|
478
|
+
type = types.TSQUERY
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class ts_headline(_regconfig_fn):
|
|
482
|
+
"""The PostgreSQL ``ts_headline`` SQL function.
|
|
483
|
+
|
|
484
|
+
This function applies automatic casting of the REGCONFIG argument
|
|
485
|
+
to use the :class:`_postgresql.REGCONFIG` datatype automatically,
|
|
486
|
+
and applies a return type of :class:`_types.TEXT`.
|
|
487
|
+
|
|
488
|
+
Assuming the PostgreSQL dialect has been imported, either by invoking
|
|
489
|
+
``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
|
|
490
|
+
engine using ``create_engine("postgresql...")``,
|
|
491
|
+
:class:`_postgresql.ts_headline` will be used automatically when invoking
|
|
492
|
+
``sqlalchemy.func.ts_headline()``, ensuring the correct argument and return
|
|
493
|
+
type handlers are used at compile and execution time.
|
|
494
|
+
|
|
495
|
+
.. versionadded:: 2.0.0rc1
|
|
496
|
+
|
|
497
|
+
"""
|
|
498
|
+
|
|
499
|
+
inherit_cache = True
|
|
500
|
+
type = TEXT
|
|
501
|
+
|
|
502
|
+
def __init__(self, *args, **kwargs):
|
|
503
|
+
args = list(args)
|
|
504
|
+
|
|
505
|
+
# parse types according to
|
|
506
|
+
# https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE
|
|
507
|
+
if len(args) < 2:
|
|
508
|
+
# invalid args; don't do anything
|
|
509
|
+
has_regconfig = False
|
|
510
|
+
elif (
|
|
511
|
+
isinstance(args[1], elements.ColumnElement)
|
|
512
|
+
and args[1].type._type_affinity is types.TSQUERY
|
|
513
|
+
):
|
|
514
|
+
# tsquery is second argument, no regconfig argument
|
|
515
|
+
has_regconfig = False
|
|
516
|
+
else:
|
|
517
|
+
has_regconfig = True
|
|
518
|
+
|
|
519
|
+
if has_regconfig:
|
|
520
|
+
initial_arg = coercions.expect(
|
|
521
|
+
roles.ExpressionElementRole,
|
|
522
|
+
args.pop(0),
|
|
523
|
+
apply_propagate_attrs=self,
|
|
524
|
+
name=getattr(self, "name", None),
|
|
525
|
+
type_=types.REGCONFIG,
|
|
526
|
+
)
|
|
527
|
+
initial_arg = [initial_arg]
|
|
528
|
+
else:
|
|
529
|
+
initial_arg = []
|
|
530
|
+
|
|
531
|
+
addtl_args = [
|
|
532
|
+
coercions.expect(
|
|
533
|
+
roles.ExpressionElementRole,
|
|
534
|
+
c,
|
|
535
|
+
name=getattr(self, "name", None),
|
|
536
|
+
apply_propagate_attrs=self,
|
|
537
|
+
)
|
|
538
|
+
for c in args
|
|
539
|
+
]
|
|
540
|
+
super().__init__(*(initial_arg + addtl_args), **kwargs)
|