SQLAlchemy 2.1.0rc1__cp315-cp315t-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 +299 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +171 -0
- sqlalchemy/connectors/asyncio.py +476 -0
- sqlalchemy/connectors/pyodbc.py +248 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +29 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4833 -0
- sqlalchemy/dialects/mssql/information_schema.py +345 -0
- sqlalchemy/dialects/mssql/json.py +140 -0
- sqlalchemy/dialects/mssql/mssqlpython.py +242 -0
- sqlalchemy/dialects/mssql/provision.py +196 -0
- sqlalchemy/dialects/mssql/pymssql.py +130 -0
- sqlalchemy/dialects/mssql/pyodbc.py +697 -0
- sqlalchemy/dialects/mysql/__init__.py +106 -0
- sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
- sqlalchemy/dialects/mysql/aiomysql.py +260 -0
- sqlalchemy/dialects/mysql/asyncmy.py +241 -0
- sqlalchemy/dialects/mysql/base.py +3896 -0
- sqlalchemy/dialects/mysql/cymysql.py +107 -0
- sqlalchemy/dialects/mysql/dml.py +279 -0
- sqlalchemy/dialects/mysql/enumerated.py +277 -0
- sqlalchemy/dialects/mysql/expression.py +146 -0
- sqlalchemy/dialects/mysql/json.py +92 -0
- sqlalchemy/dialects/mysql/mariadb.py +67 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +314 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +291 -0
- sqlalchemy/dialects/mysql/mysqldb.py +318 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +188 -0
- sqlalchemy/dialects/mysql/pyodbc.py +157 -0
- sqlalchemy/dialects/mysql/reflection.py +724 -0
- sqlalchemy/dialects/mysql/reserved_words.py +570 -0
- sqlalchemy/dialects/mysql/types.py +845 -0
- sqlalchemy/dialects/oracle/__init__.py +85 -0
- sqlalchemy/dialects/oracle/base.py +3847 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1736 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/json.py +157 -0
- sqlalchemy/dialects/oracle/oracledb.py +898 -0
- sqlalchemy/dialects/oracle/provision.py +288 -0
- sqlalchemy/dialects/oracle/types.py +367 -0
- sqlalchemy/dialects/oracle/vector.py +366 -0
- sqlalchemy/dialects/postgresql/__init__.py +170 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +232 -0
- sqlalchemy/dialects/postgresql/array.py +534 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1318 -0
- sqlalchemy/dialects/postgresql/base.py +5935 -0
- sqlalchemy/dialects/postgresql/bitstring.py +327 -0
- sqlalchemy/dialects/postgresql/dml.py +360 -0
- sqlalchemy/dialects/postgresql/ext.py +599 -0
- sqlalchemy/dialects/postgresql/hstore.py +422 -0
- sqlalchemy/dialects/postgresql/json.py +411 -0
- sqlalchemy/dialects/postgresql/named_types.py +535 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +655 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +345 -0
- sqlalchemy/dialects/postgresql/provision.py +202 -0
- sqlalchemy/dialects/postgresql/psycopg.py +800 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +62 -0
- sqlalchemy/dialects/postgresql/ranges.py +1002 -0
- sqlalchemy/dialects/postgresql/types.py +388 -0
- sqlalchemy/dialects/sqlite/__init__.py +59 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +375 -0
- sqlalchemy/dialects/sqlite/base.py +3103 -0
- sqlalchemy/dialects/sqlite/dml.py +314 -0
- sqlalchemy/dialects/sqlite/json.py +134 -0
- sqlalchemy/dialects/sqlite/provision.py +237 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +166 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +959 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_processors_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/engine/_processors_cy.py +92 -0
- sqlalchemy/engine/_result_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/engine/_result_cy.py +711 -0
- sqlalchemy/engine/_row_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/engine/_row_cy.py +232 -0
- sqlalchemy/engine/_util_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/engine/_util_cy.py +136 -0
- sqlalchemy/engine/base.py +3357 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +877 -0
- sqlalchemy/engine/cursor.py +2425 -0
- sqlalchemy/engine/default.py +2627 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3636 -0
- sqlalchemy/engine/mock.py +133 -0
- sqlalchemy/engine/processors.py +83 -0
- sqlalchemy/engine/reflection.py +2141 -0
- sqlalchemy/engine/result.py +2012 -0
- sqlalchemy/engine/row.py +397 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +922 -0
- sqlalchemy/engine/util.py +164 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +675 -0
- sqlalchemy/event/base.py +473 -0
- sqlalchemy/event/legacy.py +259 -0
- sqlalchemy/event/registry.py +391 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +939 -0
- sqlalchemy/ext/__init__.py +10 -0
- sqlalchemy/ext/associationproxy.py +2073 -0
- sqlalchemy/ext/asyncio/__init__.py +29 -0
- sqlalchemy/ext/asyncio/base.py +281 -0
- sqlalchemy/ext/asyncio/engine.py +1487 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +994 -0
- sqlalchemy/ext/asyncio/scoping.py +1679 -0
- sqlalchemy/ext/asyncio/session.py +2006 -0
- sqlalchemy/ext/automap.py +1702 -0
- sqlalchemy/ext/baked.py +558 -0
- sqlalchemy/ext/compiler.py +601 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +561 -0
- sqlalchemy/ext/horizontal_shard.py +481 -0
- sqlalchemy/ext/hybrid.py +1877 -0
- sqlalchemy/ext/indexable.py +364 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1081 -0
- sqlalchemy/ext/orderinglist.py +440 -0
- sqlalchemy/ext/serializer.py +184 -0
- sqlalchemy/future/__init__.py +17 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +188 -0
- sqlalchemy/log.py +279 -0
- sqlalchemy/orm/__init__.py +176 -0
- sqlalchemy/orm/_orm_constructors.py +2694 -0
- sqlalchemy/orm/_typing.py +180 -0
- sqlalchemy/orm/attributes.py +2868 -0
- sqlalchemy/orm/base.py +991 -0
- sqlalchemy/orm/bulk_persistence.py +2168 -0
- sqlalchemy/orm/clsregistry.py +630 -0
- sqlalchemy/orm/collections.py +1569 -0
- sqlalchemy/orm/context.py +3475 -0
- sqlalchemy/orm/decl_api.py +2283 -0
- sqlalchemy/orm/decl_base.py +2320 -0
- sqlalchemy/orm/dependency.py +1306 -0
- sqlalchemy/orm/descriptor_props.py +1183 -0
- sqlalchemy/orm/dynamic.py +306 -0
- sqlalchemy/orm/evaluator.py +378 -0
- sqlalchemy/orm/events.py +3387 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +749 -0
- sqlalchemy/orm/interfaces.py +1595 -0
- sqlalchemy/orm/loading.py +1712 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4465 -0
- sqlalchemy/orm/path_registry.py +907 -0
- sqlalchemy/orm/persistence.py +1790 -0
- sqlalchemy/orm/properties.py +972 -0
- sqlalchemy/orm/query.py +3528 -0
- sqlalchemy/orm/relationships.py +3608 -0
- sqlalchemy/orm/scoping.py +2233 -0
- sqlalchemy/orm/session.py +5468 -0
- sqlalchemy/orm/state.py +1175 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3552 -0
- sqlalchemy/orm/strategy_options.py +2648 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +797 -0
- sqlalchemy/orm/util.py +2461 -0
- sqlalchemy/orm/writeonly.py +701 -0
- sqlalchemy/pool/__init__.py +41 -0
- sqlalchemy/pool/base.py +1540 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +583 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +75 -0
- sqlalchemy/sql/__init__.py +156 -0
- sqlalchemy/sql/_annotated_cols.py +402 -0
- sqlalchemy/sql/_cache_key_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/sql/_cache_key_cy.py +363 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +2190 -0
- sqlalchemy/sql/_orm_types.py +19 -0
- sqlalchemy/sql/_selectable_constructors.py +840 -0
- sqlalchemy/sql/_typing.py +500 -0
- sqlalchemy/sql/_util_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/sql/_util_cy.pxd +11 -0
- sqlalchemy/sql/_util_cy.py +127 -0
- sqlalchemy/sql/annotation.py +590 -0
- sqlalchemy/sql/base.py +2702 -0
- sqlalchemy/sql/cache_key.py +915 -0
- sqlalchemy/sql/coercions.py +1373 -0
- sqlalchemy/sql/compiler.py +8453 -0
- sqlalchemy/sql/crud.py +1816 -0
- sqlalchemy/sql/ddl.py +1962 -0
- sqlalchemy/sql/default_comparator.py +660 -0
- sqlalchemy/sql/dml.py +2018 -0
- sqlalchemy/sql/elements.py +6057 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +171 -0
- sqlalchemy/sql/functions.py +2380 -0
- sqlalchemy/sql/lambdas.py +1442 -0
- sqlalchemy/sql/naming.py +204 -0
- sqlalchemy/sql/operators.py +2909 -0
- sqlalchemy/sql/roles.py +332 -0
- sqlalchemy/sql/schema.py +7075 -0
- sqlalchemy/sql/selectable.py +7634 -0
- sqlalchemy/sql/sqltypes.py +4130 -0
- sqlalchemy/sql/traversals.py +1041 -0
- sqlalchemy/sql/type_api.py +2450 -0
- sqlalchemy/sql/util.py +1496 -0
- sqlalchemy/sql/visitors.py +1153 -0
- sqlalchemy/testing/__init__.py +97 -0
- sqlalchemy/testing/assertions.py +1007 -0
- sqlalchemy/testing/assertsql.py +519 -0
- sqlalchemy/testing/asyncio.py +128 -0
- sqlalchemy/testing/cancellation.py +237 -0
- sqlalchemy/testing/config.py +440 -0
- sqlalchemy/testing/engines.py +482 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +501 -0
- sqlalchemy/testing/fixtures/__init__.py +30 -0
- sqlalchemy/testing/fixtures/base.py +426 -0
- sqlalchemy/testing/fixtures/mypy.py +247 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +538 -0
- sqlalchemy/testing/pickleable.py +155 -0
- sqlalchemy/testing/plugin/__init__.py +6 -0
- sqlalchemy/testing/plugin/bootstrap.py +50 -0
- sqlalchemy/testing/plugin/plugin_base.py +828 -0
- sqlalchemy/testing/plugin/pytestplugin.py +896 -0
- sqlalchemy/testing/profiles_file.py +350 -0
- sqlalchemy/testing/profiling.py +294 -0
- sqlalchemy/testing/provision.py +633 -0
- sqlalchemy/testing/requirements.py +1971 -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 +420 -0
- sqlalchemy/testing/suite/test_dialect.py +776 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3815 -0
- sqlalchemy/testing/suite/test_results.py +660 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +2112 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_table_via_select.py +686 -0
- sqlalchemy/testing/suite/test_types.py +2271 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +575 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +75 -0
- sqlalchemy/util/__init__.py +165 -0
- sqlalchemy/util/_collections.py +688 -0
- sqlalchemy/util/_collections_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/util/_collections_cy.pxd +8 -0
- sqlalchemy/util/_collections_cy.py +516 -0
- sqlalchemy/util/_has_cython.py +48 -0
- sqlalchemy/util/_immutabledict_cy.cp315t-win_amd64.pyd +0 -0
- sqlalchemy/util/_immutabledict_cy.py +240 -0
- sqlalchemy/util/compat.py +298 -0
- sqlalchemy/util/concurrency.py +272 -0
- sqlalchemy/util/cython.py +95 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2797 -0
- sqlalchemy/util/preloaded.py +153 -0
- sqlalchemy/util/queue.py +304 -0
- sqlalchemy/util/tool_support.py +202 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +709 -0
- sqlalchemy-2.1.0rc1.dist-info/METADATA +270 -0
- sqlalchemy-2.1.0rc1.dist-info/RECORD +276 -0
- sqlalchemy-2.1.0rc1.dist-info/WHEEL +5 -0
- sqlalchemy-2.1.0rc1.dist-info/licenses/AUTHORS +30 -0
- sqlalchemy-2.1.0rc1.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.1.0rc1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# dialects/mssql/information_schema.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
|
+
|
|
9
|
+
from ... import cast
|
|
10
|
+
from ... import Column
|
|
11
|
+
from ... import MetaData
|
|
12
|
+
from ... import Table
|
|
13
|
+
from ...ext.compiler import compiles
|
|
14
|
+
from ...sql import expression
|
|
15
|
+
from ...types import Boolean
|
|
16
|
+
from ...types import Integer
|
|
17
|
+
from ...types import Numeric
|
|
18
|
+
from ...types import NVARCHAR
|
|
19
|
+
from ...types import String
|
|
20
|
+
from ...types import TypeDecorator
|
|
21
|
+
from ...types import Unicode
|
|
22
|
+
|
|
23
|
+
ischema = MetaData()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class CoerceUnicode(TypeDecorator):
|
|
27
|
+
impl = Unicode
|
|
28
|
+
cache_ok = True
|
|
29
|
+
|
|
30
|
+
def bind_expression(self, bindvalue):
|
|
31
|
+
return _cast_on_2005(bindvalue)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _cast_on_2005(expression.ColumnElement):
|
|
35
|
+
def __init__(self, bindvalue):
|
|
36
|
+
self.bindvalue = bindvalue
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@compiles(_cast_on_2005)
|
|
40
|
+
def _compile(element, compiler, **kw):
|
|
41
|
+
from . import base
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
compiler.dialect.server_version_info is None
|
|
45
|
+
or compiler.dialect.server_version_info < base.MS_2005_VERSION
|
|
46
|
+
):
|
|
47
|
+
return compiler.process(element.bindvalue, **kw)
|
|
48
|
+
else:
|
|
49
|
+
return compiler.process(cast(element.bindvalue, Unicode), **kw)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
schemata = Table(
|
|
53
|
+
"SCHEMATA",
|
|
54
|
+
ischema,
|
|
55
|
+
Column("CATALOG_NAME", CoerceUnicode, key="catalog_name"),
|
|
56
|
+
Column("SCHEMA_NAME", CoerceUnicode, key="schema_name"),
|
|
57
|
+
Column("SCHEMA_OWNER", CoerceUnicode, key="schema_owner"),
|
|
58
|
+
schema="INFORMATION_SCHEMA",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
tables = Table(
|
|
62
|
+
"TABLES",
|
|
63
|
+
ischema,
|
|
64
|
+
Column("TABLE_CATALOG", CoerceUnicode, key="table_catalog"),
|
|
65
|
+
Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
|
|
66
|
+
Column("TABLE_NAME", CoerceUnicode, key="table_name"),
|
|
67
|
+
Column("TABLE_TYPE", CoerceUnicode, key="table_type"),
|
|
68
|
+
schema="INFORMATION_SCHEMA",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
columns = Table(
|
|
72
|
+
"COLUMNS",
|
|
73
|
+
ischema,
|
|
74
|
+
Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
|
|
75
|
+
Column("TABLE_NAME", CoerceUnicode, key="table_name"),
|
|
76
|
+
Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
|
|
77
|
+
Column("IS_NULLABLE", Integer, key="is_nullable"),
|
|
78
|
+
Column("DATA_TYPE", String, key="data_type"),
|
|
79
|
+
Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
|
|
80
|
+
Column(
|
|
81
|
+
"CHARACTER_MAXIMUM_LENGTH", Integer, key="character_maximum_length"
|
|
82
|
+
),
|
|
83
|
+
Column("NUMERIC_PRECISION", Integer, key="numeric_precision"),
|
|
84
|
+
Column("NUMERIC_SCALE", Integer, key="numeric_scale"),
|
|
85
|
+
Column("COLUMN_DEFAULT", Integer, key="column_default"),
|
|
86
|
+
Column("COLLATION_NAME", String, key="collation_name"),
|
|
87
|
+
schema="INFORMATION_SCHEMA",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
sys_columns = Table(
|
|
91
|
+
"columns",
|
|
92
|
+
ischema,
|
|
93
|
+
Column("object_id", Integer),
|
|
94
|
+
Column("name", CoerceUnicode),
|
|
95
|
+
Column("column_id", Integer),
|
|
96
|
+
Column("default_object_id", Integer),
|
|
97
|
+
Column("user_type_id", Integer),
|
|
98
|
+
Column("is_nullable", Integer),
|
|
99
|
+
Column("ordinal_position", Integer),
|
|
100
|
+
Column("max_length", Integer),
|
|
101
|
+
Column("precision", Integer),
|
|
102
|
+
Column("scale", Integer),
|
|
103
|
+
Column("collation_name", String),
|
|
104
|
+
schema="sys",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
sys_types = Table(
|
|
108
|
+
"types",
|
|
109
|
+
ischema,
|
|
110
|
+
Column("name", CoerceUnicode, key="name"),
|
|
111
|
+
Column("system_type_id", Integer, key="system_type_id"),
|
|
112
|
+
Column("user_type_id", Integer, key="user_type_id"),
|
|
113
|
+
Column("schema_id", Integer, key="schema_id"),
|
|
114
|
+
Column("max_length", Integer, key="max_length"),
|
|
115
|
+
Column("precision", Integer, key="precision"),
|
|
116
|
+
Column("scale", Integer, key="scale"),
|
|
117
|
+
Column("collation_name", CoerceUnicode, key="collation_name"),
|
|
118
|
+
Column("is_nullable", Boolean, key="is_nullable"),
|
|
119
|
+
Column("is_user_defined", Boolean, key="is_user_defined"),
|
|
120
|
+
Column("is_assembly_type", Boolean, key="is_assembly_type"),
|
|
121
|
+
Column("default_object_id", Integer, key="default_object_id"),
|
|
122
|
+
Column("rule_object_id", Integer, key="rule_object_id"),
|
|
123
|
+
Column("is_table_type", Boolean, key="is_table_type"),
|
|
124
|
+
schema="sys",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
constraints = Table(
|
|
128
|
+
"TABLE_CONSTRAINTS",
|
|
129
|
+
ischema,
|
|
130
|
+
Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
|
|
131
|
+
Column("TABLE_NAME", CoerceUnicode, key="table_name"),
|
|
132
|
+
Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
|
|
133
|
+
Column("CONSTRAINT_TYPE", CoerceUnicode, key="constraint_type"),
|
|
134
|
+
schema="INFORMATION_SCHEMA",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
sys_default_constraints = Table(
|
|
138
|
+
"default_constraints",
|
|
139
|
+
ischema,
|
|
140
|
+
Column("object_id", Integer),
|
|
141
|
+
Column("name", CoerceUnicode),
|
|
142
|
+
Column("schema_id", Integer),
|
|
143
|
+
Column("parent_column_id", Integer),
|
|
144
|
+
Column("definition", CoerceUnicode),
|
|
145
|
+
schema="sys",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
column_constraints = Table(
|
|
149
|
+
"CONSTRAINT_COLUMN_USAGE",
|
|
150
|
+
ischema,
|
|
151
|
+
Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
|
|
152
|
+
Column("TABLE_NAME", CoerceUnicode, key="table_name"),
|
|
153
|
+
Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
|
|
154
|
+
Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
|
|
155
|
+
schema="INFORMATION_SCHEMA",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
key_constraints = Table(
|
|
159
|
+
"KEY_COLUMN_USAGE",
|
|
160
|
+
ischema,
|
|
161
|
+
Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
|
|
162
|
+
Column("TABLE_NAME", CoerceUnicode, key="table_name"),
|
|
163
|
+
Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
|
|
164
|
+
Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
|
|
165
|
+
Column("CONSTRAINT_SCHEMA", CoerceUnicode, key="constraint_schema"),
|
|
166
|
+
Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
|
|
167
|
+
schema="INFORMATION_SCHEMA",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
ref_constraints = Table(
|
|
171
|
+
"REFERENTIAL_CONSTRAINTS",
|
|
172
|
+
ischema,
|
|
173
|
+
Column("CONSTRAINT_CATALOG", CoerceUnicode, key="constraint_catalog"),
|
|
174
|
+
Column("CONSTRAINT_SCHEMA", CoerceUnicode, key="constraint_schema"),
|
|
175
|
+
Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
|
|
176
|
+
# TODO: is CATLOG misspelled ?
|
|
177
|
+
Column(
|
|
178
|
+
"UNIQUE_CONSTRAINT_CATLOG",
|
|
179
|
+
CoerceUnicode,
|
|
180
|
+
key="unique_constraint_catalog",
|
|
181
|
+
),
|
|
182
|
+
Column(
|
|
183
|
+
"UNIQUE_CONSTRAINT_SCHEMA",
|
|
184
|
+
CoerceUnicode,
|
|
185
|
+
key="unique_constraint_schema",
|
|
186
|
+
),
|
|
187
|
+
Column(
|
|
188
|
+
"UNIQUE_CONSTRAINT_NAME", CoerceUnicode, key="unique_constraint_name"
|
|
189
|
+
),
|
|
190
|
+
Column("MATCH_OPTION", String, key="match_option"),
|
|
191
|
+
Column("UPDATE_RULE", String, key="update_rule"),
|
|
192
|
+
Column("DELETE_RULE", String, key="delete_rule"),
|
|
193
|
+
schema="INFORMATION_SCHEMA",
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
views = Table(
|
|
197
|
+
"VIEWS",
|
|
198
|
+
ischema,
|
|
199
|
+
Column("TABLE_CATALOG", CoerceUnicode, key="table_catalog"),
|
|
200
|
+
Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
|
|
201
|
+
Column("TABLE_NAME", CoerceUnicode, key="table_name"),
|
|
202
|
+
Column("VIEW_DEFINITION", CoerceUnicode, key="view_definition"),
|
|
203
|
+
Column("CHECK_OPTION", String, key="check_option"),
|
|
204
|
+
Column("IS_UPDATABLE", String, key="is_updatable"),
|
|
205
|
+
schema="INFORMATION_SCHEMA",
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
computed_columns = Table(
|
|
209
|
+
"computed_columns",
|
|
210
|
+
ischema,
|
|
211
|
+
Column("object_id", Integer),
|
|
212
|
+
Column("name", CoerceUnicode),
|
|
213
|
+
Column("column_id", Integer),
|
|
214
|
+
Column("is_computed", Boolean),
|
|
215
|
+
Column("is_persisted", Boolean),
|
|
216
|
+
Column("definition", CoerceUnicode),
|
|
217
|
+
schema="sys",
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
sequences = Table(
|
|
221
|
+
"SEQUENCES",
|
|
222
|
+
ischema,
|
|
223
|
+
Column("SEQUENCE_CATALOG", CoerceUnicode, key="sequence_catalog"),
|
|
224
|
+
Column("SEQUENCE_SCHEMA", CoerceUnicode, key="sequence_schema"),
|
|
225
|
+
Column("SEQUENCE_NAME", CoerceUnicode, key="sequence_name"),
|
|
226
|
+
schema="INFORMATION_SCHEMA",
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class NumericSqlVariant(TypeDecorator):
|
|
231
|
+
r"""This type casts sql_variant columns in the identity_columns view
|
|
232
|
+
to numeric. This is required because:
|
|
233
|
+
|
|
234
|
+
* pyodbc does not support sql_variant
|
|
235
|
+
* pymssql under python 2 return the byte representation of the number,
|
|
236
|
+
int 1 is returned as "\x01\x00\x00\x00". On python 3 it returns the
|
|
237
|
+
correct value as string.
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
impl = Unicode
|
|
241
|
+
cache_ok = True
|
|
242
|
+
|
|
243
|
+
def column_expression(self, colexpr):
|
|
244
|
+
return cast(colexpr, Numeric(38, 0))
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
identity_columns = Table(
|
|
248
|
+
"identity_columns",
|
|
249
|
+
ischema,
|
|
250
|
+
Column("object_id", Integer),
|
|
251
|
+
Column("name", CoerceUnicode),
|
|
252
|
+
Column("column_id", Integer),
|
|
253
|
+
Column("is_identity", Boolean),
|
|
254
|
+
Column("seed_value", NumericSqlVariant),
|
|
255
|
+
Column("increment_value", NumericSqlVariant),
|
|
256
|
+
Column("last_value", NumericSqlVariant),
|
|
257
|
+
Column("is_not_for_replication", Boolean),
|
|
258
|
+
schema="sys",
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class NVarcharSqlVariant(TypeDecorator):
|
|
263
|
+
"""This type casts sql_variant columns in the extended_properties view
|
|
264
|
+
to nvarchar. This is required because pyodbc does not support sql_variant
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
impl = Unicode
|
|
268
|
+
cache_ok = True
|
|
269
|
+
|
|
270
|
+
def column_expression(self, colexpr):
|
|
271
|
+
return cast(colexpr, NVARCHAR)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
extended_properties = Table(
|
|
275
|
+
"extended_properties",
|
|
276
|
+
ischema,
|
|
277
|
+
Column("class", Integer), # TINYINT
|
|
278
|
+
Column("class_desc", CoerceUnicode),
|
|
279
|
+
Column("major_id", Integer),
|
|
280
|
+
Column("minor_id", Integer),
|
|
281
|
+
Column("name", CoerceUnicode),
|
|
282
|
+
Column("value", NVarcharSqlVariant),
|
|
283
|
+
schema="sys",
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
sys_schemas = Table(
|
|
287
|
+
"schemas",
|
|
288
|
+
ischema,
|
|
289
|
+
Column("schema_id", Integer),
|
|
290
|
+
Column("name", CoerceUnicode),
|
|
291
|
+
Column("principal_id", Integer),
|
|
292
|
+
schema="sys",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
sys_objects = Table(
|
|
296
|
+
"objects",
|
|
297
|
+
ischema,
|
|
298
|
+
Column("object_id", Integer),
|
|
299
|
+
Column("name", CoerceUnicode),
|
|
300
|
+
Column("schema_id", Integer),
|
|
301
|
+
Column("parent_object_id", Integer),
|
|
302
|
+
Column("type", String), # CHAR(2)
|
|
303
|
+
Column("type_desc", CoerceUnicode),
|
|
304
|
+
schema="sys",
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
sys_key_constraints = Table(
|
|
308
|
+
"key_constraints",
|
|
309
|
+
ischema,
|
|
310
|
+
Column("object_id", Integer),
|
|
311
|
+
Column("name", CoerceUnicode),
|
|
312
|
+
Column("schema_id", Integer),
|
|
313
|
+
Column("parent_object_id", Integer),
|
|
314
|
+
Column("type", String), # CHAR(2) ('PK', 'UQ')
|
|
315
|
+
Column("unique_index_id", Integer),
|
|
316
|
+
schema="sys",
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
sys_indexes = Table(
|
|
320
|
+
"indexes",
|
|
321
|
+
ischema,
|
|
322
|
+
Column("object_id", Integer),
|
|
323
|
+
Column("index_id", Integer),
|
|
324
|
+
Column("name", CoerceUnicode),
|
|
325
|
+
Column("type", Integer), # TINYINT: 1=clustered, 2=nonclustered
|
|
326
|
+
Column("type_desc", CoerceUnicode),
|
|
327
|
+
Column("is_unique", Boolean),
|
|
328
|
+
Column("is_primary_key", Boolean),
|
|
329
|
+
Column("is_unique_constraint", Boolean),
|
|
330
|
+
Column("filter_definition", CoerceUnicode),
|
|
331
|
+
schema="sys",
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
sys_index_columns = Table(
|
|
335
|
+
"index_columns",
|
|
336
|
+
ischema,
|
|
337
|
+
Column("object_id", Integer),
|
|
338
|
+
Column("index_id", Integer),
|
|
339
|
+
Column("index_column_id", Integer),
|
|
340
|
+
Column("column_id", Integer),
|
|
341
|
+
Column("key_ordinal", Integer),
|
|
342
|
+
Column("is_descending_key", Boolean),
|
|
343
|
+
Column("is_included_column", Boolean),
|
|
344
|
+
schema="sys",
|
|
345
|
+
)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# dialects/mssql/json.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
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
from ... import types as sqltypes
|
|
13
|
+
from ...sql.sqltypes import _T_JSON
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ...engine.interfaces import Dialect
|
|
17
|
+
from ...sql.type_api import _BindProcessorType
|
|
18
|
+
from ...sql.type_api import _LiteralProcessorType
|
|
19
|
+
|
|
20
|
+
# technically, all the dialect-specific datatypes that don't have any special
|
|
21
|
+
# behaviors would be private with names like _MSJson. However, we haven't been
|
|
22
|
+
# doing this for mysql.JSON or sqlite.JSON which both have JSON / JSONIndexType
|
|
23
|
+
# / JSONPathType in their json.py files, so keep consistent with that
|
|
24
|
+
# sub-convention for now. A future change can update them all to be
|
|
25
|
+
# package-private at once.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class JSON(sqltypes.JSON[_T_JSON]):
|
|
29
|
+
"""MSSQL JSON type.
|
|
30
|
+
|
|
31
|
+
MSSQL supports JSON-formatted data as of SQL Server 2016.
|
|
32
|
+
|
|
33
|
+
The :class:`_mssql.JSON` datatype at the DDL level will represent the
|
|
34
|
+
datatype as ``NVARCHAR(max)``, but provides for JSON-level comparison
|
|
35
|
+
functions as well as Python coercion behavior.
|
|
36
|
+
|
|
37
|
+
:class:`_mssql.JSON` is used automatically whenever the base
|
|
38
|
+
:class:`_types.JSON` datatype is used against a SQL Server backend.
|
|
39
|
+
|
|
40
|
+
.. seealso::
|
|
41
|
+
|
|
42
|
+
:class:`_types.JSON` - main documentation for the generic
|
|
43
|
+
cross-platform JSON datatype.
|
|
44
|
+
|
|
45
|
+
The :class:`_mssql.JSON` type supports persistence of JSON values
|
|
46
|
+
as well as the core index operations provided by :class:`_types.JSON`
|
|
47
|
+
datatype, by adapting the operations to render the ``JSON_VALUE``
|
|
48
|
+
or ``JSON_QUERY`` functions at the database level.
|
|
49
|
+
|
|
50
|
+
The SQL Server :class:`_mssql.JSON` type necessarily makes use of the
|
|
51
|
+
``JSON_QUERY`` and ``JSON_VALUE`` functions when querying for elements
|
|
52
|
+
of a JSON object. These two functions have a major restriction in that
|
|
53
|
+
they are **mutually exclusive** based on the type of object to be returned.
|
|
54
|
+
The ``JSON_QUERY`` function **only** returns a JSON dictionary or list,
|
|
55
|
+
but not an individual string, numeric, or boolean element; the
|
|
56
|
+
``JSON_VALUE`` function **only** returns an individual string, numeric,
|
|
57
|
+
or boolean element. **both functions either return NULL or raise
|
|
58
|
+
an error if they are not used against the correct expected value**.
|
|
59
|
+
|
|
60
|
+
To handle this awkward requirement, indexed access rules are as follows:
|
|
61
|
+
|
|
62
|
+
1. When extracting a sub element from a JSON that is itself a JSON
|
|
63
|
+
dictionary or list, the :meth:`_types.JSON.Comparator.as_json` accessor
|
|
64
|
+
should be used::
|
|
65
|
+
|
|
66
|
+
stmt = select(data_table.c.data["some key"].as_json()).where(
|
|
67
|
+
data_table.c.data["some key"].as_json() == {"sub": "structure"}
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
2. When extracting a sub element from a JSON that is a plain boolean,
|
|
71
|
+
string, integer, or float, use the appropriate method among
|
|
72
|
+
:meth:`_types.JSON.Comparator.as_boolean`,
|
|
73
|
+
:meth:`_types.JSON.Comparator.as_string`,
|
|
74
|
+
:meth:`_types.JSON.Comparator.as_integer`,
|
|
75
|
+
:meth:`_types.JSON.Comparator.as_float`::
|
|
76
|
+
|
|
77
|
+
stmt = select(data_table.c.data["some key"].as_string()).where(
|
|
78
|
+
data_table.c.data["some key"].as_string() == "some string"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
.. versionadded:: 1.4
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
# note there was a result processor here that was looking for "number",
|
|
87
|
+
# but none of the tests seem to exercise it.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# Note: these objects currently match exactly those of MySQL, however since
|
|
91
|
+
# these are not generalizable to all JSON implementations, remain separately
|
|
92
|
+
# implemented for each dialect.
|
|
93
|
+
class _FormatTypeMixin:
|
|
94
|
+
def _format_value(self, value: Any) -> str:
|
|
95
|
+
raise NotImplementedError()
|
|
96
|
+
|
|
97
|
+
def bind_processor(self, dialect: Dialect) -> _BindProcessorType[Any]:
|
|
98
|
+
super_proc = self.string_bind_processor(dialect) # type: ignore[attr-defined] # noqa: E501
|
|
99
|
+
|
|
100
|
+
def process(value: Any) -> Any:
|
|
101
|
+
value = self._format_value(value)
|
|
102
|
+
if super_proc:
|
|
103
|
+
value = super_proc(value)
|
|
104
|
+
return value
|
|
105
|
+
|
|
106
|
+
return process
|
|
107
|
+
|
|
108
|
+
def literal_processor(
|
|
109
|
+
self, dialect: Dialect
|
|
110
|
+
) -> _LiteralProcessorType[Any]:
|
|
111
|
+
super_proc = self.string_literal_processor(dialect) # type: ignore[attr-defined] # noqa: E501
|
|
112
|
+
|
|
113
|
+
def process(value: Any) -> str:
|
|
114
|
+
value = self._format_value(value)
|
|
115
|
+
if super_proc:
|
|
116
|
+
value = super_proc(value)
|
|
117
|
+
return value # type: ignore[no-any-return]
|
|
118
|
+
|
|
119
|
+
return process
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class JSONIndexType(_FormatTypeMixin, sqltypes.JSON.JSONIndexType):
|
|
123
|
+
def _format_value(self, value: Any) -> str:
|
|
124
|
+
if isinstance(value, int):
|
|
125
|
+
formatted_value = "$[%s]" % value
|
|
126
|
+
else:
|
|
127
|
+
formatted_value = '$."%s"' % value
|
|
128
|
+
return formatted_value
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class JSONPathType(_FormatTypeMixin, sqltypes.JSON.JSONPathType):
|
|
132
|
+
def _format_value(self, value: Any) -> str:
|
|
133
|
+
return "$%s" % (
|
|
134
|
+
"".join(
|
|
135
|
+
[
|
|
136
|
+
"[%s]" % elem if isinstance(elem, int) else '."%s"' % elem
|
|
137
|
+
for elem in value
|
|
138
|
+
]
|
|
139
|
+
)
|
|
140
|
+
)
|