SQLAlchemy 2.0.36__cp313-cp313-win32.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-2.0.36.dist-info/LICENSE +19 -0
- SQLAlchemy-2.0.36.dist-info/METADATA +243 -0
- SQLAlchemy-2.0.36.dist-info/RECORD +273 -0
- SQLAlchemy-2.0.36.dist-info/WHEEL +5 -0
- SQLAlchemy-2.0.36.dist-info/top_level.txt +1 -0
- sqlalchemy/__init__.py +294 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +174 -0
- sqlalchemy/connectors/asyncio.py +213 -0
- sqlalchemy/connectors/pyodbc.py +249 -0
- sqlalchemy/cyextension/__init__.py +6 -0
- sqlalchemy/cyextension/collections.cp313-win32.pyd +0 -0
- sqlalchemy/cyextension/collections.pyx +409 -0
- sqlalchemy/cyextension/immutabledict.cp313-win32.pyd +0 -0
- sqlalchemy/cyextension/immutabledict.pxd +8 -0
- sqlalchemy/cyextension/immutabledict.pyx +133 -0
- sqlalchemy/cyextension/processors.cp313-win32.pyd +0 -0
- sqlalchemy/cyextension/processors.pyx +68 -0
- sqlalchemy/cyextension/resultproxy.cp313-win32.pyd +0 -0
- sqlalchemy/cyextension/resultproxy.pyx +102 -0
- sqlalchemy/cyextension/util.cp313-win32.pyd +0 -0
- sqlalchemy/cyextension/util.pyx +91 -0
- sqlalchemy/dialects/__init__.py +61 -0
- sqlalchemy/dialects/_typing.py +25 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +64 -0
- sqlalchemy/dialects/mssql/base.py +4010 -0
- sqlalchemy/dialects/mssql/information_schema.py +254 -0
- sqlalchemy/dialects/mssql/json.py +133 -0
- sqlalchemy/dialects/mssql/provision.py +162 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +745 -0
- sqlalchemy/dialects/mysql/__init__.py +101 -0
- sqlalchemy/dialects/mysql/aiomysql.py +333 -0
- sqlalchemy/dialects/mysql/asyncmy.py +337 -0
- sqlalchemy/dialects/mysql/base.py +3494 -0
- sqlalchemy/dialects/mysql/cymysql.py +84 -0
- sqlalchemy/dialects/mysql/dml.py +219 -0
- sqlalchemy/dialects/mysql/enumerated.py +244 -0
- sqlalchemy/dialects/mysql/expression.py +141 -0
- sqlalchemy/dialects/mysql/json.py +81 -0
- sqlalchemy/dialects/mysql/mariadb.py +32 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +277 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +180 -0
- sqlalchemy/dialects/mysql/mysqldb.py +303 -0
- sqlalchemy/dialects/mysql/provision.py +110 -0
- sqlalchemy/dialects/mysql/pymysql.py +137 -0
- sqlalchemy/dialects/mysql/pyodbc.py +138 -0
- sqlalchemy/dialects/mysql/reflection.py +677 -0
- sqlalchemy/dialects/mysql/reserved_words.py +571 -0
- sqlalchemy/dialects/mysql/types.py +774 -0
- sqlalchemy/dialects/oracle/__init__.py +67 -0
- sqlalchemy/dialects/oracle/base.py +3271 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1483 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/oracledb.py +431 -0
- sqlalchemy/dialects/oracle/provision.py +220 -0
- sqlalchemy/dialects/oracle/types.py +287 -0
- sqlalchemy/dialects/postgresql/__init__.py +167 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +187 -0
- sqlalchemy/dialects/postgresql/array.py +425 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1274 -0
- sqlalchemy/dialects/postgresql/base.py +5008 -0
- sqlalchemy/dialects/postgresql/dml.py +310 -0
- sqlalchemy/dialects/postgresql/ext.py +496 -0
- sqlalchemy/dialects/postgresql/hstore.py +397 -0
- sqlalchemy/dialects/postgresql/json.py +333 -0
- sqlalchemy/dialects/postgresql/named_types.py +509 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +662 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +300 -0
- sqlalchemy/dialects/postgresql/provision.py +175 -0
- sqlalchemy/dialects/postgresql/psycopg.py +772 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +886 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1029 -0
- sqlalchemy/dialects/postgresql/types.py +303 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +396 -0
- sqlalchemy/dialects/sqlite/base.py +2805 -0
- sqlalchemy/dialects/sqlite/dml.py +240 -0
- sqlalchemy/dialects/sqlite/json.py +92 -0
- sqlalchemy/dialects/sqlite/provision.py +198 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +155 -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 +3375 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +875 -0
- sqlalchemy/engine/cursor.py +2181 -0
- sqlalchemy/engine/default.py +2365 -0
- sqlalchemy/engine/events.py +951 -0
- sqlalchemy/engine/interfaces.py +3403 -0
- sqlalchemy/engine/mock.py +131 -0
- sqlalchemy/engine/processors.py +61 -0
- sqlalchemy/engine/reflection.py +2098 -0
- sqlalchemy/engine/result.py +2382 -0
- sqlalchemy/engine/row.py +401 -0
- sqlalchemy/engine/strategies.py +19 -0
- sqlalchemy/engine/url.py +910 -0
- sqlalchemy/engine/util.py +167 -0
- sqlalchemy/event/__init__.py +25 -0
- sqlalchemy/event/api.py +225 -0
- sqlalchemy/event/attr.py +655 -0
- sqlalchemy/event/base.py +470 -0
- sqlalchemy/event/legacy.py +246 -0
- sqlalchemy/event/registry.py +386 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +830 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2013 -0
- sqlalchemy/ext/asyncio/__init__.py +25 -0
- sqlalchemy/ext/asyncio/base.py +279 -0
- sqlalchemy/ext/asyncio/engine.py +1466 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +961 -0
- sqlalchemy/ext/asyncio/scoping.py +1614 -0
- sqlalchemy/ext/asyncio/session.py +1936 -0
- sqlalchemy/ext/automap.py +1691 -0
- sqlalchemy/ext/baked.py +574 -0
- sqlalchemy/ext/compiler.py +570 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +548 -0
- sqlalchemy/ext/horizontal_shard.py +481 -0
- sqlalchemy/ext/hybrid.py +1514 -0
- sqlalchemy/ext/indexable.py +341 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1073 -0
- sqlalchemy/ext/mypy/__init__.py +6 -0
- sqlalchemy/ext/mypy/apply.py +320 -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 +416 -0
- sqlalchemy/ext/serializer.py +181 -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 +170 -0
- sqlalchemy/orm/_orm_constructors.py +2571 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2835 -0
- sqlalchemy/orm/base.py +973 -0
- sqlalchemy/orm/bulk_persistence.py +2123 -0
- sqlalchemy/orm/clsregistry.py +571 -0
- sqlalchemy/orm/collections.py +1620 -0
- sqlalchemy/orm/context.py +3268 -0
- sqlalchemy/orm/decl_api.py +1883 -0
- sqlalchemy/orm/decl_base.py +2190 -0
- sqlalchemy/orm/dependency.py +1304 -0
- sqlalchemy/orm/descriptor_props.py +1076 -0
- sqlalchemy/orm/dynamic.py +300 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3261 -0
- sqlalchemy/orm/exc.py +228 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +754 -0
- sqlalchemy/orm/interfaces.py +1474 -0
- sqlalchemy/orm/loading.py +1682 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4432 -0
- sqlalchemy/orm/path_registry.py +811 -0
- sqlalchemy/orm/persistence.py +1782 -0
- sqlalchemy/orm/properties.py +886 -0
- sqlalchemy/orm/query.py +3396 -0
- sqlalchemy/orm/relationships.py +3500 -0
- sqlalchemy/orm/scoping.py +2165 -0
- sqlalchemy/orm/session.py +5301 -0
- sqlalchemy/orm/state.py +1143 -0
- sqlalchemy/orm/state_changes.py +198 -0
- sqlalchemy/orm/strategies.py +3473 -0
- sqlalchemy/orm/strategy_options.py +2569 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +796 -0
- sqlalchemy/orm/util.py +2424 -0
- sqlalchemy/orm/writeonly.py +678 -0
- sqlalchemy/pool/__init__.py +44 -0
- sqlalchemy/pool/base.py +1515 -0
- sqlalchemy/pool/events.py +370 -0
- sqlalchemy/pool/impl.py +581 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +70 -0
- sqlalchemy/sql/__init__.py +145 -0
- sqlalchemy/sql/_dml_constructors.py +140 -0
- sqlalchemy/sql/_elements_constructors.py +1850 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_py_util.py +75 -0
- sqlalchemy/sql/_selectable_constructors.py +635 -0
- sqlalchemy/sql/_typing.py +460 -0
- sqlalchemy/sql/annotation.py +585 -0
- sqlalchemy/sql/base.py +2185 -0
- sqlalchemy/sql/cache_key.py +1057 -0
- sqlalchemy/sql/coercions.py +1405 -0
- sqlalchemy/sql/compiler.py +7818 -0
- sqlalchemy/sql/crud.py +1669 -0
- sqlalchemy/sql/ddl.py +1378 -0
- sqlalchemy/sql/default_comparator.py +552 -0
- sqlalchemy/sql/dml.py +1817 -0
- sqlalchemy/sql/elements.py +5499 -0
- sqlalchemy/sql/events.py +455 -0
- sqlalchemy/sql/expression.py +162 -0
- sqlalchemy/sql/functions.py +2055 -0
- sqlalchemy/sql/lambdas.py +1449 -0
- sqlalchemy/sql/naming.py +212 -0
- sqlalchemy/sql/operators.py +2579 -0
- sqlalchemy/sql/roles.py +323 -0
- sqlalchemy/sql/schema.py +6158 -0
- sqlalchemy/sql/selectable.py +7004 -0
- sqlalchemy/sql/sqltypes.py +3827 -0
- sqlalchemy/sql/traversals.py +1024 -0
- sqlalchemy/sql/type_api.py +2339 -0
- sqlalchemy/sql/util.py +1486 -0
- sqlalchemy/sql/visitors.py +1165 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +989 -0
- sqlalchemy/testing/assertsql.py +516 -0
- sqlalchemy/testing/asyncio.py +135 -0
- sqlalchemy/testing/config.py +427 -0
- sqlalchemy/testing/engines.py +472 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +435 -0
- sqlalchemy/testing/fixtures/__init__.py +28 -0
- sqlalchemy/testing/fixtures/base.py +366 -0
- sqlalchemy/testing/fixtures/mypy.py +312 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +503 -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 +779 -0
- sqlalchemy/testing/plugin/pytestplugin.py +868 -0
- sqlalchemy/testing/profiling.py +324 -0
- sqlalchemy/testing/provision.py +496 -0
- sqlalchemy/testing/requirements.py +1818 -0
- sqlalchemy/testing/schema.py +224 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +211 -0
- sqlalchemy/testing/suite/test_ddl.py +389 -0
- sqlalchemy/testing/suite/test_deprecations.py +153 -0
- sqlalchemy/testing/suite/test_dialect.py +740 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3225 -0
- sqlalchemy/testing/suite/test_results.py +502 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +1999 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_types.py +2141 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +537 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +76 -0
- sqlalchemy/util/__init__.py +160 -0
- sqlalchemy/util/_collections.py +715 -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 +301 -0
- sqlalchemy/util/concurrency.py +108 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2218 -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 +629 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# dialects/oracle/types.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
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import datetime as dt
|
|
11
|
+
from typing import Optional
|
|
12
|
+
from typing import Type
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
from ... import exc
|
|
16
|
+
from ...sql import sqltypes
|
|
17
|
+
from ...types import NVARCHAR
|
|
18
|
+
from ...types import VARCHAR
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from ...engine.interfaces import Dialect
|
|
22
|
+
from ...sql.type_api import _LiteralProcessorType
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RAW(sqltypes._Binary):
|
|
26
|
+
__visit_name__ = "RAW"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
OracleRaw = RAW
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class NCLOB(sqltypes.Text):
|
|
33
|
+
__visit_name__ = "NCLOB"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class VARCHAR2(VARCHAR):
|
|
37
|
+
__visit_name__ = "VARCHAR2"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
NVARCHAR2 = NVARCHAR
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class NUMBER(sqltypes.Numeric, sqltypes.Integer):
|
|
44
|
+
__visit_name__ = "NUMBER"
|
|
45
|
+
|
|
46
|
+
def __init__(self, precision=None, scale=None, asdecimal=None):
|
|
47
|
+
if asdecimal is None:
|
|
48
|
+
asdecimal = bool(scale and scale > 0)
|
|
49
|
+
|
|
50
|
+
super().__init__(precision=precision, scale=scale, asdecimal=asdecimal)
|
|
51
|
+
|
|
52
|
+
def adapt(self, impltype):
|
|
53
|
+
ret = super().adapt(impltype)
|
|
54
|
+
# leave a hint for the DBAPI handler
|
|
55
|
+
ret._is_oracle_number = True
|
|
56
|
+
return ret
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def _type_affinity(self):
|
|
60
|
+
if bool(self.scale and self.scale > 0):
|
|
61
|
+
return sqltypes.Numeric
|
|
62
|
+
else:
|
|
63
|
+
return sqltypes.Integer
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class FLOAT(sqltypes.FLOAT):
|
|
67
|
+
"""Oracle FLOAT.
|
|
68
|
+
|
|
69
|
+
This is the same as :class:`_sqltypes.FLOAT` except that
|
|
70
|
+
an Oracle-specific :paramref:`_oracle.FLOAT.binary_precision`
|
|
71
|
+
parameter is accepted, and
|
|
72
|
+
the :paramref:`_sqltypes.Float.precision` parameter is not accepted.
|
|
73
|
+
|
|
74
|
+
Oracle FLOAT types indicate precision in terms of "binary precision", which
|
|
75
|
+
defaults to 126. For a REAL type, the value is 63. This parameter does not
|
|
76
|
+
cleanly map to a specific number of decimal places but is roughly
|
|
77
|
+
equivalent to the desired number of decimal places divided by 0.3103.
|
|
78
|
+
|
|
79
|
+
.. versionadded:: 2.0
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
__visit_name__ = "FLOAT"
|
|
84
|
+
|
|
85
|
+
def __init__(
|
|
86
|
+
self,
|
|
87
|
+
binary_precision=None,
|
|
88
|
+
asdecimal=False,
|
|
89
|
+
decimal_return_scale=None,
|
|
90
|
+
):
|
|
91
|
+
r"""
|
|
92
|
+
Construct a FLOAT
|
|
93
|
+
|
|
94
|
+
:param binary_precision: Oracle binary precision value to be rendered
|
|
95
|
+
in DDL. This may be approximated to the number of decimal characters
|
|
96
|
+
using the formula "decimal precision = 0.30103 * binary precision".
|
|
97
|
+
The default value used by Oracle for FLOAT / DOUBLE PRECISION is 126.
|
|
98
|
+
|
|
99
|
+
:param asdecimal: See :paramref:`_sqltypes.Float.asdecimal`
|
|
100
|
+
|
|
101
|
+
:param decimal_return_scale: See
|
|
102
|
+
:paramref:`_sqltypes.Float.decimal_return_scale`
|
|
103
|
+
|
|
104
|
+
"""
|
|
105
|
+
super().__init__(
|
|
106
|
+
asdecimal=asdecimal, decimal_return_scale=decimal_return_scale
|
|
107
|
+
)
|
|
108
|
+
self.binary_precision = binary_precision
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class BINARY_DOUBLE(sqltypes.Double):
|
|
112
|
+
__visit_name__ = "BINARY_DOUBLE"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class BINARY_FLOAT(sqltypes.Float):
|
|
116
|
+
__visit_name__ = "BINARY_FLOAT"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class BFILE(sqltypes.LargeBinary):
|
|
120
|
+
__visit_name__ = "BFILE"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class LONG(sqltypes.Text):
|
|
124
|
+
__visit_name__ = "LONG"
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class _OracleDateLiteralRender:
|
|
128
|
+
def _literal_processor_datetime(self, dialect):
|
|
129
|
+
def process(value):
|
|
130
|
+
if getattr(value, "microsecond", None):
|
|
131
|
+
value = (
|
|
132
|
+
f"""TO_TIMESTAMP"""
|
|
133
|
+
f"""('{value.isoformat().replace("T", " ")}', """
|
|
134
|
+
"""'YYYY-MM-DD HH24:MI:SS.FF')"""
|
|
135
|
+
)
|
|
136
|
+
else:
|
|
137
|
+
value = (
|
|
138
|
+
f"""TO_DATE"""
|
|
139
|
+
f"""('{value.isoformat().replace("T", " ")}', """
|
|
140
|
+
"""'YYYY-MM-DD HH24:MI:SS')"""
|
|
141
|
+
)
|
|
142
|
+
return value
|
|
143
|
+
|
|
144
|
+
return process
|
|
145
|
+
|
|
146
|
+
def _literal_processor_date(self, dialect):
|
|
147
|
+
def process(value):
|
|
148
|
+
if getattr(value, "microsecond", None):
|
|
149
|
+
value = (
|
|
150
|
+
f"""TO_TIMESTAMP"""
|
|
151
|
+
f"""('{value.isoformat().split("T")[0]}', """
|
|
152
|
+
"""'YYYY-MM-DD')"""
|
|
153
|
+
)
|
|
154
|
+
else:
|
|
155
|
+
value = (
|
|
156
|
+
f"""TO_DATE"""
|
|
157
|
+
f"""('{value.isoformat().split("T")[0]}', """
|
|
158
|
+
"""'YYYY-MM-DD')"""
|
|
159
|
+
)
|
|
160
|
+
return value
|
|
161
|
+
|
|
162
|
+
return process
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class DATE(_OracleDateLiteralRender, sqltypes.DateTime):
|
|
166
|
+
"""Provide the oracle DATE type.
|
|
167
|
+
|
|
168
|
+
This type has no special Python behavior, except that it subclasses
|
|
169
|
+
:class:`_types.DateTime`; this is to suit the fact that the Oracle
|
|
170
|
+
``DATE`` type supports a time value.
|
|
171
|
+
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
__visit_name__ = "DATE"
|
|
175
|
+
|
|
176
|
+
def literal_processor(self, dialect):
|
|
177
|
+
return self._literal_processor_datetime(dialect)
|
|
178
|
+
|
|
179
|
+
def _compare_type_affinity(self, other):
|
|
180
|
+
return other._type_affinity in (sqltypes.DateTime, sqltypes.Date)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class _OracleDate(_OracleDateLiteralRender, sqltypes.Date):
|
|
184
|
+
def literal_processor(self, dialect):
|
|
185
|
+
return self._literal_processor_date(dialect)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class INTERVAL(sqltypes.NativeForEmulated, sqltypes._AbstractInterval):
|
|
189
|
+
__visit_name__ = "INTERVAL"
|
|
190
|
+
|
|
191
|
+
def __init__(self, day_precision=None, second_precision=None):
|
|
192
|
+
"""Construct an INTERVAL.
|
|
193
|
+
|
|
194
|
+
Note that only DAY TO SECOND intervals are currently supported.
|
|
195
|
+
This is due to a lack of support for YEAR TO MONTH intervals
|
|
196
|
+
within available DBAPIs.
|
|
197
|
+
|
|
198
|
+
:param day_precision: the day precision value. this is the number of
|
|
199
|
+
digits to store for the day field. Defaults to "2"
|
|
200
|
+
:param second_precision: the second precision value. this is the
|
|
201
|
+
number of digits to store for the fractional seconds field.
|
|
202
|
+
Defaults to "6".
|
|
203
|
+
|
|
204
|
+
"""
|
|
205
|
+
self.day_precision = day_precision
|
|
206
|
+
self.second_precision = second_precision
|
|
207
|
+
|
|
208
|
+
@classmethod
|
|
209
|
+
def _adapt_from_generic_interval(cls, interval):
|
|
210
|
+
return INTERVAL(
|
|
211
|
+
day_precision=interval.day_precision,
|
|
212
|
+
second_precision=interval.second_precision,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@classmethod
|
|
216
|
+
def adapt_emulated_to_native(
|
|
217
|
+
cls, interval: sqltypes.Interval, **kw # type: ignore[override]
|
|
218
|
+
):
|
|
219
|
+
return INTERVAL(
|
|
220
|
+
day_precision=interval.day_precision,
|
|
221
|
+
second_precision=interval.second_precision,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def _type_affinity(self):
|
|
226
|
+
return sqltypes.Interval
|
|
227
|
+
|
|
228
|
+
def as_generic(self, allow_nulltype=False):
|
|
229
|
+
return sqltypes.Interval(
|
|
230
|
+
native=True,
|
|
231
|
+
second_precision=self.second_precision,
|
|
232
|
+
day_precision=self.day_precision,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def python_type(self) -> Type[dt.timedelta]:
|
|
237
|
+
return dt.timedelta
|
|
238
|
+
|
|
239
|
+
def literal_processor(
|
|
240
|
+
self, dialect: Dialect
|
|
241
|
+
) -> Optional[_LiteralProcessorType[dt.timedelta]]:
|
|
242
|
+
def process(value: dt.timedelta) -> str:
|
|
243
|
+
return f"NUMTODSINTERVAL({value.total_seconds()}, 'SECOND')"
|
|
244
|
+
|
|
245
|
+
return process
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class TIMESTAMP(sqltypes.TIMESTAMP):
|
|
249
|
+
"""Oracle implementation of ``TIMESTAMP``, which supports additional
|
|
250
|
+
Oracle-specific modes
|
|
251
|
+
|
|
252
|
+
.. versionadded:: 2.0
|
|
253
|
+
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
def __init__(self, timezone: bool = False, local_timezone: bool = False):
|
|
257
|
+
"""Construct a new :class:`_oracle.TIMESTAMP`.
|
|
258
|
+
|
|
259
|
+
:param timezone: boolean. Indicates that the TIMESTAMP type should
|
|
260
|
+
use Oracle's ``TIMESTAMP WITH TIME ZONE`` datatype.
|
|
261
|
+
|
|
262
|
+
:param local_timezone: boolean. Indicates that the TIMESTAMP type
|
|
263
|
+
should use Oracle's ``TIMESTAMP WITH LOCAL TIME ZONE`` datatype.
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
"""
|
|
267
|
+
if timezone and local_timezone:
|
|
268
|
+
raise exc.ArgumentError(
|
|
269
|
+
"timezone and local_timezone are mutually exclusive"
|
|
270
|
+
)
|
|
271
|
+
super().__init__(timezone=timezone)
|
|
272
|
+
self.local_timezone = local_timezone
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class ROWID(sqltypes.TypeEngine):
|
|
276
|
+
"""Oracle ROWID type.
|
|
277
|
+
|
|
278
|
+
When used in a cast() or similar, generates ROWID.
|
|
279
|
+
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
__visit_name__ = "ROWID"
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class _OracleBoolean(sqltypes.Boolean):
|
|
286
|
+
def get_dbapi_type(self, dbapi):
|
|
287
|
+
return dbapi.NUMBER
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# dialects/postgresql/__init__.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
|
+
from types import ModuleType
|
|
10
|
+
|
|
11
|
+
from . import array as arraylib # noqa # keep above base and other dialects
|
|
12
|
+
from . import asyncpg # noqa
|
|
13
|
+
from . import base
|
|
14
|
+
from . import pg8000 # noqa
|
|
15
|
+
from . import psycopg # noqa
|
|
16
|
+
from . import psycopg2 # noqa
|
|
17
|
+
from . import psycopg2cffi # noqa
|
|
18
|
+
from .array import All
|
|
19
|
+
from .array import Any
|
|
20
|
+
from .array import ARRAY
|
|
21
|
+
from .array import array
|
|
22
|
+
from .base import BIGINT
|
|
23
|
+
from .base import BOOLEAN
|
|
24
|
+
from .base import CHAR
|
|
25
|
+
from .base import DATE
|
|
26
|
+
from .base import DOMAIN
|
|
27
|
+
from .base import DOUBLE_PRECISION
|
|
28
|
+
from .base import FLOAT
|
|
29
|
+
from .base import INTEGER
|
|
30
|
+
from .base import NUMERIC
|
|
31
|
+
from .base import REAL
|
|
32
|
+
from .base import SMALLINT
|
|
33
|
+
from .base import TEXT
|
|
34
|
+
from .base import UUID
|
|
35
|
+
from .base import VARCHAR
|
|
36
|
+
from .dml import Insert
|
|
37
|
+
from .dml import insert
|
|
38
|
+
from .ext import aggregate_order_by
|
|
39
|
+
from .ext import array_agg
|
|
40
|
+
from .ext import ExcludeConstraint
|
|
41
|
+
from .ext import phraseto_tsquery
|
|
42
|
+
from .ext import plainto_tsquery
|
|
43
|
+
from .ext import to_tsquery
|
|
44
|
+
from .ext import to_tsvector
|
|
45
|
+
from .ext import ts_headline
|
|
46
|
+
from .ext import websearch_to_tsquery
|
|
47
|
+
from .hstore import HSTORE
|
|
48
|
+
from .hstore import hstore
|
|
49
|
+
from .json import JSON
|
|
50
|
+
from .json import JSONB
|
|
51
|
+
from .json import JSONPATH
|
|
52
|
+
from .named_types import CreateDomainType
|
|
53
|
+
from .named_types import CreateEnumType
|
|
54
|
+
from .named_types import DropDomainType
|
|
55
|
+
from .named_types import DropEnumType
|
|
56
|
+
from .named_types import ENUM
|
|
57
|
+
from .named_types import NamedType
|
|
58
|
+
from .ranges import AbstractMultiRange
|
|
59
|
+
from .ranges import AbstractRange
|
|
60
|
+
from .ranges import AbstractSingleRange
|
|
61
|
+
from .ranges import DATEMULTIRANGE
|
|
62
|
+
from .ranges import DATERANGE
|
|
63
|
+
from .ranges import INT4MULTIRANGE
|
|
64
|
+
from .ranges import INT4RANGE
|
|
65
|
+
from .ranges import INT8MULTIRANGE
|
|
66
|
+
from .ranges import INT8RANGE
|
|
67
|
+
from .ranges import MultiRange
|
|
68
|
+
from .ranges import NUMMULTIRANGE
|
|
69
|
+
from .ranges import NUMRANGE
|
|
70
|
+
from .ranges import Range
|
|
71
|
+
from .ranges import TSMULTIRANGE
|
|
72
|
+
from .ranges import TSRANGE
|
|
73
|
+
from .ranges import TSTZMULTIRANGE
|
|
74
|
+
from .ranges import TSTZRANGE
|
|
75
|
+
from .types import BIT
|
|
76
|
+
from .types import BYTEA
|
|
77
|
+
from .types import CIDR
|
|
78
|
+
from .types import CITEXT
|
|
79
|
+
from .types import INET
|
|
80
|
+
from .types import INTERVAL
|
|
81
|
+
from .types import MACADDR
|
|
82
|
+
from .types import MACADDR8
|
|
83
|
+
from .types import MONEY
|
|
84
|
+
from .types import OID
|
|
85
|
+
from .types import REGCLASS
|
|
86
|
+
from .types import REGCONFIG
|
|
87
|
+
from .types import TIME
|
|
88
|
+
from .types import TIMESTAMP
|
|
89
|
+
from .types import TSQUERY
|
|
90
|
+
from .types import TSVECTOR
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# Alias psycopg also as psycopg_async
|
|
94
|
+
psycopg_async = type(
|
|
95
|
+
"psycopg_async", (ModuleType,), {"dialect": psycopg.dialect_async}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
base.dialect = dialect = psycopg2.dialect
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
__all__ = (
|
|
102
|
+
"INTEGER",
|
|
103
|
+
"BIGINT",
|
|
104
|
+
"SMALLINT",
|
|
105
|
+
"VARCHAR",
|
|
106
|
+
"CHAR",
|
|
107
|
+
"TEXT",
|
|
108
|
+
"NUMERIC",
|
|
109
|
+
"FLOAT",
|
|
110
|
+
"REAL",
|
|
111
|
+
"INET",
|
|
112
|
+
"CIDR",
|
|
113
|
+
"CITEXT",
|
|
114
|
+
"UUID",
|
|
115
|
+
"BIT",
|
|
116
|
+
"MACADDR",
|
|
117
|
+
"MACADDR8",
|
|
118
|
+
"MONEY",
|
|
119
|
+
"OID",
|
|
120
|
+
"REGCLASS",
|
|
121
|
+
"REGCONFIG",
|
|
122
|
+
"TSQUERY",
|
|
123
|
+
"TSVECTOR",
|
|
124
|
+
"DOUBLE_PRECISION",
|
|
125
|
+
"TIMESTAMP",
|
|
126
|
+
"TIME",
|
|
127
|
+
"DATE",
|
|
128
|
+
"BYTEA",
|
|
129
|
+
"BOOLEAN",
|
|
130
|
+
"INTERVAL",
|
|
131
|
+
"ARRAY",
|
|
132
|
+
"ENUM",
|
|
133
|
+
"DOMAIN",
|
|
134
|
+
"dialect",
|
|
135
|
+
"array",
|
|
136
|
+
"HSTORE",
|
|
137
|
+
"hstore",
|
|
138
|
+
"INT4RANGE",
|
|
139
|
+
"INT8RANGE",
|
|
140
|
+
"NUMRANGE",
|
|
141
|
+
"DATERANGE",
|
|
142
|
+
"INT4MULTIRANGE",
|
|
143
|
+
"INT8MULTIRANGE",
|
|
144
|
+
"NUMMULTIRANGE",
|
|
145
|
+
"DATEMULTIRANGE",
|
|
146
|
+
"TSVECTOR",
|
|
147
|
+
"TSRANGE",
|
|
148
|
+
"TSTZRANGE",
|
|
149
|
+
"TSMULTIRANGE",
|
|
150
|
+
"TSTZMULTIRANGE",
|
|
151
|
+
"JSON",
|
|
152
|
+
"JSONB",
|
|
153
|
+
"JSONPATH",
|
|
154
|
+
"Any",
|
|
155
|
+
"All",
|
|
156
|
+
"DropEnumType",
|
|
157
|
+
"DropDomainType",
|
|
158
|
+
"CreateDomainType",
|
|
159
|
+
"NamedType",
|
|
160
|
+
"CreateEnumType",
|
|
161
|
+
"ExcludeConstraint",
|
|
162
|
+
"Range",
|
|
163
|
+
"aggregate_order_by",
|
|
164
|
+
"array_agg",
|
|
165
|
+
"insert",
|
|
166
|
+
"Insert",
|
|
167
|
+
)
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# dialects/postgresql/_psycopg_common.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
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import decimal
|
|
11
|
+
|
|
12
|
+
from .array import ARRAY as PGARRAY
|
|
13
|
+
from .base import _DECIMAL_TYPES
|
|
14
|
+
from .base import _FLOAT_TYPES
|
|
15
|
+
from .base import _INT_TYPES
|
|
16
|
+
from .base import PGDialect
|
|
17
|
+
from .base import PGExecutionContext
|
|
18
|
+
from .hstore import HSTORE
|
|
19
|
+
from .pg_catalog import _SpaceVector
|
|
20
|
+
from .pg_catalog import INT2VECTOR
|
|
21
|
+
from .pg_catalog import OIDVECTOR
|
|
22
|
+
from ... import exc
|
|
23
|
+
from ... import types as sqltypes
|
|
24
|
+
from ... import util
|
|
25
|
+
from ...engine import processors
|
|
26
|
+
|
|
27
|
+
_server_side_id = util.counter()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _PsycopgNumeric(sqltypes.Numeric):
|
|
31
|
+
def bind_processor(self, dialect):
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
def result_processor(self, dialect, coltype):
|
|
35
|
+
if self.asdecimal:
|
|
36
|
+
if coltype in _FLOAT_TYPES:
|
|
37
|
+
return processors.to_decimal_processor_factory(
|
|
38
|
+
decimal.Decimal, self._effective_decimal_return_scale
|
|
39
|
+
)
|
|
40
|
+
elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES:
|
|
41
|
+
# psycopg returns Decimal natively for 1700
|
|
42
|
+
return None
|
|
43
|
+
else:
|
|
44
|
+
raise exc.InvalidRequestError(
|
|
45
|
+
"Unknown PG numeric type: %d" % coltype
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
if coltype in _FLOAT_TYPES:
|
|
49
|
+
# psycopg returns float natively for 701
|
|
50
|
+
return None
|
|
51
|
+
elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES:
|
|
52
|
+
return processors.to_float
|
|
53
|
+
else:
|
|
54
|
+
raise exc.InvalidRequestError(
|
|
55
|
+
"Unknown PG numeric type: %d" % coltype
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class _PsycopgFloat(_PsycopgNumeric):
|
|
60
|
+
__visit_name__ = "float"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class _PsycopgHStore(HSTORE):
|
|
64
|
+
def bind_processor(self, dialect):
|
|
65
|
+
if dialect._has_native_hstore:
|
|
66
|
+
return None
|
|
67
|
+
else:
|
|
68
|
+
return super().bind_processor(dialect)
|
|
69
|
+
|
|
70
|
+
def result_processor(self, dialect, coltype):
|
|
71
|
+
if dialect._has_native_hstore:
|
|
72
|
+
return None
|
|
73
|
+
else:
|
|
74
|
+
return super().result_processor(dialect, coltype)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class _PsycopgARRAY(PGARRAY):
|
|
78
|
+
render_bind_cast = True
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class _PsycopgINT2VECTOR(_SpaceVector, INT2VECTOR):
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class _PsycopgOIDVECTOR(_SpaceVector, OIDVECTOR):
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class _PGExecutionContext_common_psycopg(PGExecutionContext):
|
|
90
|
+
def create_server_side_cursor(self):
|
|
91
|
+
# use server-side cursors:
|
|
92
|
+
# psycopg
|
|
93
|
+
# https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#server-side-cursors
|
|
94
|
+
# psycopg2
|
|
95
|
+
# https://www.psycopg.org/docs/usage.html#server-side-cursors
|
|
96
|
+
ident = "c_%s_%s" % (hex(id(self))[2:], hex(_server_side_id())[2:])
|
|
97
|
+
return self._dbapi_connection.cursor(ident)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class _PGDialect_common_psycopg(PGDialect):
|
|
101
|
+
supports_statement_cache = True
|
|
102
|
+
supports_server_side_cursors = True
|
|
103
|
+
|
|
104
|
+
default_paramstyle = "pyformat"
|
|
105
|
+
|
|
106
|
+
_has_native_hstore = True
|
|
107
|
+
|
|
108
|
+
colspecs = util.update_copy(
|
|
109
|
+
PGDialect.colspecs,
|
|
110
|
+
{
|
|
111
|
+
sqltypes.Numeric: _PsycopgNumeric,
|
|
112
|
+
sqltypes.Float: _PsycopgFloat,
|
|
113
|
+
HSTORE: _PsycopgHStore,
|
|
114
|
+
sqltypes.ARRAY: _PsycopgARRAY,
|
|
115
|
+
INT2VECTOR: _PsycopgINT2VECTOR,
|
|
116
|
+
OIDVECTOR: _PsycopgOIDVECTOR,
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
client_encoding=None,
|
|
123
|
+
use_native_hstore=True,
|
|
124
|
+
**kwargs,
|
|
125
|
+
):
|
|
126
|
+
PGDialect.__init__(self, **kwargs)
|
|
127
|
+
if not use_native_hstore:
|
|
128
|
+
self._has_native_hstore = False
|
|
129
|
+
self.use_native_hstore = use_native_hstore
|
|
130
|
+
self.client_encoding = client_encoding
|
|
131
|
+
|
|
132
|
+
def create_connect_args(self, url):
|
|
133
|
+
opts = url.translate_connect_args(username="user", database="dbname")
|
|
134
|
+
|
|
135
|
+
multihosts, multiports = self._split_multihost_from_url(url)
|
|
136
|
+
|
|
137
|
+
if opts or url.query:
|
|
138
|
+
if not opts:
|
|
139
|
+
opts = {}
|
|
140
|
+
if "port" in opts:
|
|
141
|
+
opts["port"] = int(opts["port"])
|
|
142
|
+
opts.update(url.query)
|
|
143
|
+
|
|
144
|
+
if multihosts:
|
|
145
|
+
opts["host"] = ",".join(multihosts)
|
|
146
|
+
comma_ports = ",".join(str(p) if p else "" for p in multiports)
|
|
147
|
+
if comma_ports:
|
|
148
|
+
opts["port"] = comma_ports
|
|
149
|
+
return ([], opts)
|
|
150
|
+
else:
|
|
151
|
+
# no connection arguments whatsoever; psycopg2.connect()
|
|
152
|
+
# requires that "dsn" be present as a blank string.
|
|
153
|
+
return ([""], opts)
|
|
154
|
+
|
|
155
|
+
def get_isolation_level_values(self, dbapi_connection):
|
|
156
|
+
return (
|
|
157
|
+
"AUTOCOMMIT",
|
|
158
|
+
"READ COMMITTED",
|
|
159
|
+
"READ UNCOMMITTED",
|
|
160
|
+
"REPEATABLE READ",
|
|
161
|
+
"SERIALIZABLE",
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
def set_deferrable(self, connection, value):
|
|
165
|
+
connection.deferrable = value
|
|
166
|
+
|
|
167
|
+
def get_deferrable(self, connection):
|
|
168
|
+
return connection.deferrable
|
|
169
|
+
|
|
170
|
+
def _do_autocommit(self, connection, value):
|
|
171
|
+
connection.autocommit = value
|
|
172
|
+
|
|
173
|
+
def do_ping(self, dbapi_connection):
|
|
174
|
+
cursor = None
|
|
175
|
+
before_autocommit = dbapi_connection.autocommit
|
|
176
|
+
|
|
177
|
+
if not before_autocommit:
|
|
178
|
+
dbapi_connection.autocommit = True
|
|
179
|
+
cursor = dbapi_connection.cursor()
|
|
180
|
+
try:
|
|
181
|
+
cursor.execute(self._dialect_specific_select_one)
|
|
182
|
+
finally:
|
|
183
|
+
cursor.close()
|
|
184
|
+
if not before_autocommit and not dbapi_connection.closed:
|
|
185
|
+
dbapi_connection.autocommit = before_autocommit
|
|
186
|
+
|
|
187
|
+
return True
|