SQLAlchemy 2.1.0b2__cp313-cp313t-win_arm64.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 +298 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +171 -0
- sqlalchemy/connectors/asyncio.py +476 -0
- sqlalchemy/connectors/pyodbc.py +250 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +30 -0
- sqlalchemy/dialects/mssql/__init__.py +89 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4166 -0
- sqlalchemy/dialects/mssql/information_schema.py +285 -0
- sqlalchemy/dialects/mssql/json.py +140 -0
- sqlalchemy/dialects/mssql/mssqlpython.py +220 -0
- sqlalchemy/dialects/mssql/provision.py +196 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +698 -0
- sqlalchemy/dialects/mysql/__init__.py +106 -0
- sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
- sqlalchemy/dialects/mysql/aiomysql.py +226 -0
- sqlalchemy/dialects/mysql/asyncmy.py +214 -0
- sqlalchemy/dialects/mysql/base.py +3877 -0
- sqlalchemy/dialects/mysql/cymysql.py +106 -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 +330 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +296 -0
- sqlalchemy/dialects/mysql/mysqldb.py +312 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +157 -0
- sqlalchemy/dialects/mysql/pyodbc.py +156 -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 +3977 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1601 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/json.py +158 -0
- sqlalchemy/dialects/oracle/oracledb.py +909 -0
- sqlalchemy/dialects/oracle/provision.py +288 -0
- sqlalchemy/dialects/oracle/types.py +367 -0
- sqlalchemy/dialects/oracle/vector.py +368 -0
- sqlalchemy/dialects/postgresql/__init__.py +171 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +229 -0
- sqlalchemy/dialects/postgresql/array.py +534 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1323 -0
- sqlalchemy/dialects/postgresql/base.py +5789 -0
- sqlalchemy/dialects/postgresql/bitstring.py +327 -0
- sqlalchemy/dialects/postgresql/dml.py +360 -0
- sqlalchemy/dialects/postgresql/ext.py +593 -0
- sqlalchemy/dialects/postgresql/hstore.py +423 -0
- sqlalchemy/dialects/postgresql/json.py +408 -0
- sqlalchemy/dialects/postgresql/named_types.py +521 -0
- sqlalchemy/dialects/postgresql/operators.py +130 -0
- sqlalchemy/dialects/postgresql/pg8000.py +670 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +344 -0
- sqlalchemy/dialects/postgresql/provision.py +184 -0
- sqlalchemy/dialects/postgresql/psycopg.py +799 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1002 -0
- sqlalchemy/dialects/postgresql/types.py +388 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +321 -0
- sqlalchemy/dialects/sqlite/base.py +3063 -0
- sqlalchemy/dialects/sqlite/dml.py +279 -0
- sqlalchemy/dialects/sqlite/json.py +100 -0
- sqlalchemy/dialects/sqlite/provision.py +229 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +161 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +754 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_processors_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_processors_cy.py +92 -0
- sqlalchemy/engine/_result_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_result_cy.py +633 -0
- sqlalchemy/engine/_row_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_row_cy.py +232 -0
- sqlalchemy/engine/_util_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_util_cy.py +136 -0
- sqlalchemy/engine/base.py +3354 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +877 -0
- sqlalchemy/engine/cursor.py +2421 -0
- sqlalchemy/engine/default.py +2402 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3495 -0
- sqlalchemy/engine/mock.py +134 -0
- sqlalchemy/engine/processors.py +82 -0
- sqlalchemy/engine/reflection.py +2100 -0
- sqlalchemy/engine/result.py +1966 -0
- sqlalchemy/engine/row.py +397 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +922 -0
- sqlalchemy/engine/util.py +156 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +674 -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 +922 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2072 -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 +2007 -0
- sqlalchemy/ext/automap.py +1701 -0
- sqlalchemy/ext/baked.py +559 -0
- sqlalchemy/ext/compiler.py +600 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +560 -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 +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 +283 -0
- sqlalchemy/orm/__init__.py +176 -0
- sqlalchemy/orm/_orm_constructors.py +2694 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2868 -0
- sqlalchemy/orm/base.py +976 -0
- sqlalchemy/orm/bulk_persistence.py +2152 -0
- sqlalchemy/orm/clsregistry.py +582 -0
- sqlalchemy/orm/collections.py +1568 -0
- sqlalchemy/orm/context.py +3471 -0
- sqlalchemy/orm/decl_api.py +2280 -0
- sqlalchemy/orm/decl_base.py +2309 -0
- sqlalchemy/orm/dependency.py +1306 -0
- sqlalchemy/orm/descriptor_props.py +1183 -0
- sqlalchemy/orm/dynamic.py +307 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3386 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +746 -0
- sqlalchemy/orm/interfaces.py +1589 -0
- sqlalchemy/orm/loading.py +1684 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4411 -0
- sqlalchemy/orm/path_registry.py +829 -0
- sqlalchemy/orm/persistence.py +1789 -0
- sqlalchemy/orm/properties.py +973 -0
- sqlalchemy/orm/query.py +3528 -0
- sqlalchemy/orm/relationships.py +3570 -0
- sqlalchemy/orm/scoping.py +2232 -0
- sqlalchemy/orm/session.py +5403 -0
- sqlalchemy/orm/state.py +1175 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3492 -0
- sqlalchemy/orm/strategy_options.py +2562 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +798 -0
- sqlalchemy/orm/util.py +2438 -0
- sqlalchemy/orm/writeonly.py +694 -0
- sqlalchemy/pool/__init__.py +41 -0
- sqlalchemy/pool/base.py +1522 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +582 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +74 -0
- sqlalchemy/sql/__init__.py +156 -0
- sqlalchemy/sql/_annotated_cols.py +397 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +2164 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_selectable_constructors.py +840 -0
- sqlalchemy/sql/_typing.py +487 -0
- sqlalchemy/sql/_util_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/sql/_util_cy.py +127 -0
- sqlalchemy/sql/annotation.py +590 -0
- sqlalchemy/sql/base.py +2699 -0
- sqlalchemy/sql/cache_key.py +1066 -0
- sqlalchemy/sql/coercions.py +1373 -0
- sqlalchemy/sql/compiler.py +8327 -0
- sqlalchemy/sql/crud.py +1815 -0
- sqlalchemy/sql/ddl.py +1928 -0
- sqlalchemy/sql/default_comparator.py +654 -0
- sqlalchemy/sql/dml.py +1977 -0
- sqlalchemy/sql/elements.py +6033 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +172 -0
- sqlalchemy/sql/functions.py +2305 -0
- sqlalchemy/sql/lambdas.py +1443 -0
- sqlalchemy/sql/naming.py +209 -0
- sqlalchemy/sql/operators.py +2897 -0
- sqlalchemy/sql/roles.py +332 -0
- sqlalchemy/sql/schema.py +6703 -0
- sqlalchemy/sql/selectable.py +7553 -0
- sqlalchemy/sql/sqltypes.py +4093 -0
- sqlalchemy/sql/traversals.py +1042 -0
- sqlalchemy/sql/type_api.py +2446 -0
- sqlalchemy/sql/util.py +1495 -0
- sqlalchemy/sql/visitors.py +1157 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +1007 -0
- sqlalchemy/testing/assertsql.py +519 -0
- sqlalchemy/testing/asyncio.py +128 -0
- sqlalchemy/testing/config.py +440 -0
- sqlalchemy/testing/engines.py +483 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +476 -0
- sqlalchemy/testing/fixtures/__init__.py +30 -0
- sqlalchemy/testing/fixtures/base.py +384 -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 +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 +613 -0
- sqlalchemy/testing/requirements.py +1978 -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 +3557 -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 +535 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +76 -0
- sqlalchemy/util/__init__.py +158 -0
- sqlalchemy/util/_collections.py +688 -0
- sqlalchemy/util/_collections_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/util/_collections_cy.pxd +8 -0
- sqlalchemy/util/_collections_cy.py +516 -0
- sqlalchemy/util/_has_cython.py +46 -0
- sqlalchemy/util/_immutabledict_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/util/_immutabledict_cy.py +240 -0
- sqlalchemy/util/compat.py +299 -0
- sqlalchemy/util/concurrency.py +322 -0
- sqlalchemy/util/cython.py +79 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2320 -0
- sqlalchemy/util/preloaded.py +152 -0
- sqlalchemy/util/queue.py +304 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +711 -0
- sqlalchemy-2.1.0b2.dist-info/METADATA +269 -0
- sqlalchemy-2.1.0b2.dist-info/RECORD +270 -0
- sqlalchemy-2.1.0b2.dist-info/WHEEL +5 -0
- sqlalchemy-2.1.0b2.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.1.0b2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
# engine/_result_cy.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: disable-error-code="misc,no-redef,type-arg,untyped-decorator"
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
from enum import Enum
|
|
14
|
+
import operator
|
|
15
|
+
from typing import Any
|
|
16
|
+
from typing import Generic
|
|
17
|
+
from typing import Literal
|
|
18
|
+
from typing import overload
|
|
19
|
+
from typing import TYPE_CHECKING
|
|
20
|
+
from typing import TypeVar
|
|
21
|
+
from typing import Union
|
|
22
|
+
|
|
23
|
+
from .row import Row
|
|
24
|
+
from .row import RowMapping
|
|
25
|
+
from .. import exc
|
|
26
|
+
from ..util import HasMemoized_ro_memoized_attribute
|
|
27
|
+
from ..util.typing import Self
|
|
28
|
+
from ..util.typing import TupleAny
|
|
29
|
+
from ..util.typing import Unpack
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from .result import _ProcessorsType
|
|
33
|
+
from .result import Result
|
|
34
|
+
from .result import ResultMetaData
|
|
35
|
+
|
|
36
|
+
# START GENERATED CYTHON IMPORT
|
|
37
|
+
# This section is automatically generated by the script tools/cython_imports.py
|
|
38
|
+
try:
|
|
39
|
+
# NOTE: the cython compiler needs this "import cython" in the file, it
|
|
40
|
+
# can't be only "from sqlalchemy.util import cython" with the fallback
|
|
41
|
+
# in that module
|
|
42
|
+
import cython
|
|
43
|
+
except ModuleNotFoundError:
|
|
44
|
+
from sqlalchemy.util import cython
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _is_compiled() -> bool:
|
|
48
|
+
"""Utility function to indicate if this module is compiled or not."""
|
|
49
|
+
return cython.compiled # type: ignore[no-any-return,unused-ignore]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# END GENERATED CYTHON IMPORT
|
|
53
|
+
|
|
54
|
+
if cython.compiled:
|
|
55
|
+
from cython.cimports.cpython import Py_INCREF
|
|
56
|
+
from cython.cimports.cpython import PyList_New
|
|
57
|
+
from cython.cimports.cpython import PyList_SET_ITEM
|
|
58
|
+
from cython.cimports.cpython import PyTuple_New
|
|
59
|
+
from cython.cimports.cpython import PyTuple_SET_ITEM
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
_RowData = Row[Unpack[TupleAny]] | RowMapping | Any
|
|
63
|
+
"""A generic form of "row" that accommodates for the different kinds of
|
|
64
|
+
"rows" that different result objects return, including row, row mapping, and
|
|
65
|
+
scalar values"""
|
|
66
|
+
_R = TypeVar("_R", bound=_RowData)
|
|
67
|
+
_T = TypeVar("_T", bound=Any)
|
|
68
|
+
|
|
69
|
+
_InterimRowType = Union[_R, TupleAny]
|
|
70
|
+
"""a catchall "anything" kind of return type that can be applied
|
|
71
|
+
across all the result types
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
_UniqueFilterType = Callable[[Any], Any]
|
|
76
|
+
_UniqueFilterStateType = tuple[set[Any], _UniqueFilterType | None]
|
|
77
|
+
|
|
78
|
+
_FLAG_SIMPLE = cython.declare(cython.char, 0)
|
|
79
|
+
_FLAG_SCALAR_TO_TUPLE = cython.declare(cython.char, 1)
|
|
80
|
+
_FLAG_TUPLE_FILTER = cython.declare(cython.char, 2)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# a symbol that indicates to internal Result methods that
|
|
84
|
+
# "no row is returned". We can't use None for those cases where a scalar
|
|
85
|
+
# filter is applied to rows.
|
|
86
|
+
class _NoRow(Enum):
|
|
87
|
+
_NO_ROW = 0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
_NO_ROW = _NoRow._NO_ROW
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class BaseResultInternal(Generic[_R]):
|
|
94
|
+
__slots__ = ()
|
|
95
|
+
|
|
96
|
+
_real_result: Result[Unpack[TupleAny]] | None = None
|
|
97
|
+
_generate_rows: bool = True
|
|
98
|
+
_row_logging_fn: Callable[[Any], Any] | None
|
|
99
|
+
|
|
100
|
+
_unique_filter_state: _UniqueFilterStateType | None = None
|
|
101
|
+
_post_creational_filter: Callable[[Any], Any] | None = None
|
|
102
|
+
|
|
103
|
+
_metadata: ResultMetaData
|
|
104
|
+
|
|
105
|
+
_source_supports_scalars: bool
|
|
106
|
+
_yield_per: int | None
|
|
107
|
+
|
|
108
|
+
def _fetchiter_impl(
|
|
109
|
+
self,
|
|
110
|
+
) -> Iterator[_InterimRowType[Row[Unpack[TupleAny]]]]:
|
|
111
|
+
raise NotImplementedError()
|
|
112
|
+
|
|
113
|
+
def _fetchone_impl(
|
|
114
|
+
self, hard_close: bool = False
|
|
115
|
+
) -> _InterimRowType[Row[Unpack[TupleAny]]] | None:
|
|
116
|
+
raise NotImplementedError()
|
|
117
|
+
|
|
118
|
+
def _fetchmany_impl(
|
|
119
|
+
self, size: int | None = None
|
|
120
|
+
) -> list[_InterimRowType[Row[Unpack[TupleAny]]]]:
|
|
121
|
+
raise NotImplementedError()
|
|
122
|
+
|
|
123
|
+
def _fetchall_impl(
|
|
124
|
+
self,
|
|
125
|
+
) -> list[_InterimRowType[Row[Unpack[TupleAny]]]]:
|
|
126
|
+
raise NotImplementedError()
|
|
127
|
+
|
|
128
|
+
def _soft_close(self, hard: bool = False) -> None:
|
|
129
|
+
raise NotImplementedError()
|
|
130
|
+
|
|
131
|
+
@HasMemoized_ro_memoized_attribute
|
|
132
|
+
def _row_getter(
|
|
133
|
+
self,
|
|
134
|
+
) -> tuple[Callable[..., _R] | None, Callable[..., Sequence[_R]] | None]:
|
|
135
|
+
real_result = self if self._real_result is None else self._real_result
|
|
136
|
+
|
|
137
|
+
metadata = self._metadata
|
|
138
|
+
tuple_filters = metadata._tuplefilter
|
|
139
|
+
flag: cython.char = _FLAG_SIMPLE
|
|
140
|
+
|
|
141
|
+
if real_result._source_supports_scalars:
|
|
142
|
+
if not self._generate_rows:
|
|
143
|
+
return None, None
|
|
144
|
+
else:
|
|
145
|
+
flag = _FLAG_SCALAR_TO_TUPLE
|
|
146
|
+
elif tuple_filters is not None:
|
|
147
|
+
flag = _FLAG_TUPLE_FILTER
|
|
148
|
+
|
|
149
|
+
processors: tuple
|
|
150
|
+
proc_valid: tuple
|
|
151
|
+
|
|
152
|
+
if metadata._effective_processors is not None:
|
|
153
|
+
ep = metadata._effective_processors
|
|
154
|
+
if flag == _FLAG_TUPLE_FILTER:
|
|
155
|
+
ep = tuple_filters(ep)
|
|
156
|
+
|
|
157
|
+
processors = tuple(ep)
|
|
158
|
+
proc_valid = tuple(
|
|
159
|
+
[i for i, p in enumerate(processors) if p is not None]
|
|
160
|
+
)
|
|
161
|
+
else:
|
|
162
|
+
processors = ()
|
|
163
|
+
proc_valid = ()
|
|
164
|
+
|
|
165
|
+
proc_size: cython.Py_ssize_t = len(processors)
|
|
166
|
+
log_row = real_result._row_logging_fn
|
|
167
|
+
has_log_row: cython.bint = log_row is not None
|
|
168
|
+
|
|
169
|
+
key_to_index = metadata._key_to_index
|
|
170
|
+
_Row = Row
|
|
171
|
+
|
|
172
|
+
if flag == _FLAG_SIMPLE and proc_size == 0 and not has_log_row:
|
|
173
|
+
# just build the rows
|
|
174
|
+
|
|
175
|
+
def single_row_simple(input_row: Sequence[Any], /) -> Row:
|
|
176
|
+
return _Row(metadata, None, key_to_index, input_row)
|
|
177
|
+
|
|
178
|
+
if cython.compiled:
|
|
179
|
+
|
|
180
|
+
def many_rows_simple(rows: Sequence[Any], /) -> list[Any]:
|
|
181
|
+
size: cython.Py_hash_t = len(rows)
|
|
182
|
+
i: cython.Py_ssize_t
|
|
183
|
+
result: list = PyList_New(size)
|
|
184
|
+
for i in range(size):
|
|
185
|
+
row: object = _Row(
|
|
186
|
+
metadata, None, key_to_index, rows[i]
|
|
187
|
+
)
|
|
188
|
+
Py_INCREF(row)
|
|
189
|
+
PyList_SET_ITEM(result, i, row)
|
|
190
|
+
return result
|
|
191
|
+
|
|
192
|
+
else:
|
|
193
|
+
|
|
194
|
+
def many_rows_simple(rows: Sequence[Any], /) -> list[Any]:
|
|
195
|
+
return [
|
|
196
|
+
_Row(metadata, None, key_to_index, row) for row in rows
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
return single_row_simple, many_rows_simple # type: ignore[return-value] # noqa: E501
|
|
200
|
+
|
|
201
|
+
first_row: cython.bint = True
|
|
202
|
+
|
|
203
|
+
def single_row(input_row: Sequence[Any], /) -> Row:
|
|
204
|
+
nonlocal first_row
|
|
205
|
+
|
|
206
|
+
if flag == _FLAG_SCALAR_TO_TUPLE:
|
|
207
|
+
input_row = (input_row,)
|
|
208
|
+
elif flag == _FLAG_TUPLE_FILTER:
|
|
209
|
+
input_row = tuple_filters(input_row)
|
|
210
|
+
|
|
211
|
+
if proc_size != 0:
|
|
212
|
+
if first_row:
|
|
213
|
+
first_row = False
|
|
214
|
+
assert len(input_row) == proc_size
|
|
215
|
+
input_row = _apply_processors(
|
|
216
|
+
processors, proc_size, proc_valid, input_row
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
row: Row = _Row(metadata, None, key_to_index, input_row)
|
|
220
|
+
if has_log_row:
|
|
221
|
+
row = log_row(row)
|
|
222
|
+
return row
|
|
223
|
+
|
|
224
|
+
if cython.compiled:
|
|
225
|
+
|
|
226
|
+
def many_rows(rows: Sequence[Any], /) -> list[Any]:
|
|
227
|
+
size: cython.Py_hash_t = len(rows)
|
|
228
|
+
i: cython.Py_ssize_t
|
|
229
|
+
result: list = PyList_New(size)
|
|
230
|
+
for i in range(size):
|
|
231
|
+
row: object = single_row(rows[i])
|
|
232
|
+
Py_INCREF(row)
|
|
233
|
+
PyList_SET_ITEM(result, i, row)
|
|
234
|
+
return result
|
|
235
|
+
|
|
236
|
+
else:
|
|
237
|
+
|
|
238
|
+
def many_rows(rows: Sequence[Any], /) -> list[Any]:
|
|
239
|
+
return [single_row(row) for row in rows]
|
|
240
|
+
|
|
241
|
+
return single_row, many_rows # type: ignore[return-value]
|
|
242
|
+
|
|
243
|
+
@HasMemoized_ro_memoized_attribute
|
|
244
|
+
def _iterator_getter(self) -> Callable[[], Iterator[_R]]:
|
|
245
|
+
make_row = self._row_getter[0]
|
|
246
|
+
|
|
247
|
+
post_creational_filter = self._post_creational_filter
|
|
248
|
+
|
|
249
|
+
if self._unique_filter_state is not None:
|
|
250
|
+
uniques: set
|
|
251
|
+
uniques, strategy = self._unique_strategy
|
|
252
|
+
|
|
253
|
+
def iterrows() -> Iterator[_R]:
|
|
254
|
+
for raw_row in self._fetchiter_impl():
|
|
255
|
+
row = (
|
|
256
|
+
make_row(raw_row) if make_row is not None else raw_row
|
|
257
|
+
)
|
|
258
|
+
hashed = strategy(row) if strategy is not None else row
|
|
259
|
+
if hashed in uniques:
|
|
260
|
+
continue
|
|
261
|
+
uniques.add(hashed)
|
|
262
|
+
if post_creational_filter is not None:
|
|
263
|
+
row = post_creational_filter(row)
|
|
264
|
+
yield row
|
|
265
|
+
|
|
266
|
+
else:
|
|
267
|
+
|
|
268
|
+
def iterrows() -> Iterator[_R]:
|
|
269
|
+
for raw_row in self._fetchiter_impl():
|
|
270
|
+
row = (
|
|
271
|
+
make_row(raw_row) if make_row is not None else raw_row
|
|
272
|
+
)
|
|
273
|
+
if post_creational_filter is not None:
|
|
274
|
+
row = post_creational_filter(row)
|
|
275
|
+
yield row
|
|
276
|
+
|
|
277
|
+
return iterrows
|
|
278
|
+
|
|
279
|
+
def _raw_all_rows(self) -> Sequence[_R]:
|
|
280
|
+
make_rows = self._row_getter[1]
|
|
281
|
+
assert make_rows is not None
|
|
282
|
+
return make_rows(self._fetchall_impl())
|
|
283
|
+
|
|
284
|
+
def _allrows(self) -> Sequence[_R]:
|
|
285
|
+
post_creational_filter = self._post_creational_filter
|
|
286
|
+
|
|
287
|
+
make_rows = self._row_getter[1]
|
|
288
|
+
|
|
289
|
+
rows = self._fetchall_impl()
|
|
290
|
+
made_rows: Sequence[_InterimRowType[_R]]
|
|
291
|
+
if make_rows is not None:
|
|
292
|
+
made_rows = make_rows(rows)
|
|
293
|
+
else:
|
|
294
|
+
made_rows = rows
|
|
295
|
+
|
|
296
|
+
interim_rows: Sequence[_R]
|
|
297
|
+
|
|
298
|
+
if self._unique_filter_state is not None:
|
|
299
|
+
uniques: set
|
|
300
|
+
uniques, strategy = self._unique_strategy
|
|
301
|
+
interim_rows = _apply_unique_strategy(
|
|
302
|
+
made_rows, [], uniques, strategy
|
|
303
|
+
)
|
|
304
|
+
else:
|
|
305
|
+
interim_rows = made_rows # type: ignore
|
|
306
|
+
|
|
307
|
+
if post_creational_filter is not None:
|
|
308
|
+
interim_rows = [
|
|
309
|
+
post_creational_filter(row) for row in interim_rows
|
|
310
|
+
]
|
|
311
|
+
return interim_rows
|
|
312
|
+
|
|
313
|
+
@HasMemoized_ro_memoized_attribute
|
|
314
|
+
def _onerow_getter(
|
|
315
|
+
self,
|
|
316
|
+
) -> Callable[[Self], Literal[_NoRow._NO_ROW] | _R]:
|
|
317
|
+
make_row = self._row_getter[0]
|
|
318
|
+
|
|
319
|
+
post_creational_filter = self._post_creational_filter
|
|
320
|
+
|
|
321
|
+
if self._unique_filter_state is not None:
|
|
322
|
+
uniques: set
|
|
323
|
+
uniques, strategy = self._unique_strategy
|
|
324
|
+
|
|
325
|
+
def onerow(self: Self) -> Literal[_NoRow._NO_ROW] | _R:
|
|
326
|
+
while True:
|
|
327
|
+
row = self._fetchone_impl()
|
|
328
|
+
if row is None:
|
|
329
|
+
return _NO_ROW
|
|
330
|
+
else:
|
|
331
|
+
obj: _InterimRowType[Any] = (
|
|
332
|
+
make_row(row) if make_row is not None else row
|
|
333
|
+
)
|
|
334
|
+
hashed = strategy(obj) if strategy is not None else obj
|
|
335
|
+
if hashed in uniques:
|
|
336
|
+
continue
|
|
337
|
+
uniques.add(hashed)
|
|
338
|
+
if post_creational_filter is not None:
|
|
339
|
+
obj = post_creational_filter(obj)
|
|
340
|
+
return obj # type: ignore
|
|
341
|
+
|
|
342
|
+
else:
|
|
343
|
+
|
|
344
|
+
def onerow(self: Self) -> Literal[_NoRow._NO_ROW] | _R:
|
|
345
|
+
row = self._fetchone_impl()
|
|
346
|
+
if row is None:
|
|
347
|
+
return _NO_ROW
|
|
348
|
+
else:
|
|
349
|
+
interim_row: _InterimRowType[Any] = (
|
|
350
|
+
make_row(row) if make_row is not None else row
|
|
351
|
+
)
|
|
352
|
+
if post_creational_filter is not None:
|
|
353
|
+
interim_row = post_creational_filter(interim_row)
|
|
354
|
+
return interim_row # type: ignore
|
|
355
|
+
|
|
356
|
+
return onerow
|
|
357
|
+
|
|
358
|
+
@HasMemoized_ro_memoized_attribute
|
|
359
|
+
def _manyrow_getter(self) -> Callable[[Self, int | None], Sequence[_R]]:
|
|
360
|
+
make_rows = self._row_getter[1]
|
|
361
|
+
real_result = self if self._real_result is None else self._real_result
|
|
362
|
+
yield_per = real_result._yield_per
|
|
363
|
+
|
|
364
|
+
post_creational_filter = self._post_creational_filter
|
|
365
|
+
|
|
366
|
+
if self._unique_filter_state:
|
|
367
|
+
uniques: set
|
|
368
|
+
uniques, strategy = self._unique_strategy
|
|
369
|
+
|
|
370
|
+
def manyrows(self: Self, num: int | None, /) -> Sequence[_R]:
|
|
371
|
+
made_rows: Sequence[Any]
|
|
372
|
+
collect: list[_R] = []
|
|
373
|
+
|
|
374
|
+
_manyrows = self._fetchmany_impl
|
|
375
|
+
|
|
376
|
+
if num is None:
|
|
377
|
+
# if None is passed, we don't know the default
|
|
378
|
+
# manyrows number, DBAPI has this as cursor.arraysize
|
|
379
|
+
# different DBAPIs / fetch strategies may be different.
|
|
380
|
+
# do a fetch to find what the number is. if there are
|
|
381
|
+
# only fewer rows left, then it doesn't matter.
|
|
382
|
+
if yield_per:
|
|
383
|
+
num_required = num = yield_per
|
|
384
|
+
else:
|
|
385
|
+
rows = _manyrows()
|
|
386
|
+
num = len(rows)
|
|
387
|
+
made_rows = (
|
|
388
|
+
rows if make_rows is None else make_rows(rows)
|
|
389
|
+
)
|
|
390
|
+
_apply_unique_strategy(
|
|
391
|
+
made_rows, collect, uniques, strategy
|
|
392
|
+
)
|
|
393
|
+
num_required = num - len(collect)
|
|
394
|
+
else:
|
|
395
|
+
num_required = num
|
|
396
|
+
|
|
397
|
+
assert num is not None
|
|
398
|
+
|
|
399
|
+
while num_required:
|
|
400
|
+
rows = _manyrows(num_required)
|
|
401
|
+
if not rows:
|
|
402
|
+
break
|
|
403
|
+
|
|
404
|
+
made_rows = rows if make_rows is None else make_rows(rows)
|
|
405
|
+
_apply_unique_strategy(
|
|
406
|
+
made_rows, collect, uniques, strategy
|
|
407
|
+
)
|
|
408
|
+
num_required = num - len(collect)
|
|
409
|
+
|
|
410
|
+
if post_creational_filter is not None:
|
|
411
|
+
collect = [post_creational_filter(row) for row in collect]
|
|
412
|
+
return collect
|
|
413
|
+
|
|
414
|
+
else:
|
|
415
|
+
|
|
416
|
+
def manyrows(self: Self, num: int | None, /) -> Sequence[_R]:
|
|
417
|
+
if num is None:
|
|
418
|
+
num = yield_per
|
|
419
|
+
|
|
420
|
+
rows: Sequence = self._fetchmany_impl(num)
|
|
421
|
+
if make_rows is not None:
|
|
422
|
+
rows = make_rows(rows)
|
|
423
|
+
if post_creational_filter is not None:
|
|
424
|
+
rows = [post_creational_filter(row) for row in rows]
|
|
425
|
+
return rows
|
|
426
|
+
|
|
427
|
+
return manyrows
|
|
428
|
+
|
|
429
|
+
@overload
|
|
430
|
+
def _only_one_row(
|
|
431
|
+
self: BaseResultInternal[Row[_T, Unpack[TupleAny]]],
|
|
432
|
+
raise_for_second_row: bool,
|
|
433
|
+
raise_for_none: bool,
|
|
434
|
+
scalar: Literal[True],
|
|
435
|
+
) -> _T: ...
|
|
436
|
+
|
|
437
|
+
@overload
|
|
438
|
+
def _only_one_row(
|
|
439
|
+
self,
|
|
440
|
+
raise_for_second_row: bool,
|
|
441
|
+
raise_for_none: Literal[True],
|
|
442
|
+
scalar: bool,
|
|
443
|
+
) -> _R: ...
|
|
444
|
+
|
|
445
|
+
@overload
|
|
446
|
+
def _only_one_row(
|
|
447
|
+
self,
|
|
448
|
+
raise_for_second_row: bool,
|
|
449
|
+
raise_for_none: bool,
|
|
450
|
+
scalar: bool,
|
|
451
|
+
) -> _R | None: ...
|
|
452
|
+
|
|
453
|
+
def _only_one_row(
|
|
454
|
+
self,
|
|
455
|
+
raise_for_second_row: bool,
|
|
456
|
+
raise_for_none: bool,
|
|
457
|
+
scalar: bool,
|
|
458
|
+
) -> _R | None:
|
|
459
|
+
onerow = self._fetchone_impl
|
|
460
|
+
|
|
461
|
+
row = onerow(hard_close=True)
|
|
462
|
+
if row is None:
|
|
463
|
+
if raise_for_none:
|
|
464
|
+
raise exc.NoResultFound(
|
|
465
|
+
"No row was found when one was required"
|
|
466
|
+
)
|
|
467
|
+
else:
|
|
468
|
+
return None
|
|
469
|
+
|
|
470
|
+
if scalar and self._source_supports_scalars:
|
|
471
|
+
self._generate_rows = False
|
|
472
|
+
make_row = None
|
|
473
|
+
else:
|
|
474
|
+
make_row = self._row_getter[0]
|
|
475
|
+
|
|
476
|
+
try:
|
|
477
|
+
row = make_row(row) if make_row is not None else row # type: ignore[assignment] # noqa: E501
|
|
478
|
+
except:
|
|
479
|
+
self._soft_close(hard=True)
|
|
480
|
+
raise
|
|
481
|
+
|
|
482
|
+
if raise_for_second_row:
|
|
483
|
+
if self._unique_filter_state:
|
|
484
|
+
# for no second row but uniqueness, need to essentially
|
|
485
|
+
# consume the entire result :(
|
|
486
|
+
strategy = self._unique_strategy[1]
|
|
487
|
+
|
|
488
|
+
existing_row_hash = (
|
|
489
|
+
strategy(row) if strategy is not None else row
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
while True:
|
|
493
|
+
next_row: Any = onerow(hard_close=True)
|
|
494
|
+
if next_row is None:
|
|
495
|
+
next_row = _NO_ROW
|
|
496
|
+
break
|
|
497
|
+
|
|
498
|
+
try:
|
|
499
|
+
next_row = (
|
|
500
|
+
make_row(next_row)
|
|
501
|
+
if make_row is not None
|
|
502
|
+
else next_row
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
if strategy is not None:
|
|
506
|
+
# assert next_row is not _NO_ROW
|
|
507
|
+
if existing_row_hash == strategy(next_row):
|
|
508
|
+
continue
|
|
509
|
+
elif row == next_row:
|
|
510
|
+
continue
|
|
511
|
+
# here, we have a row and it's different
|
|
512
|
+
break
|
|
513
|
+
except:
|
|
514
|
+
self._soft_close(hard=True)
|
|
515
|
+
raise
|
|
516
|
+
else:
|
|
517
|
+
next_row = onerow(hard_close=True)
|
|
518
|
+
if next_row is None:
|
|
519
|
+
next_row = _NO_ROW
|
|
520
|
+
|
|
521
|
+
if next_row is not _NO_ROW:
|
|
522
|
+
self._soft_close(hard=True)
|
|
523
|
+
raise exc.MultipleResultsFound(
|
|
524
|
+
"Multiple rows were found when exactly one was required"
|
|
525
|
+
if raise_for_none
|
|
526
|
+
else "Multiple rows were found when one or none "
|
|
527
|
+
"was required"
|
|
528
|
+
)
|
|
529
|
+
else:
|
|
530
|
+
next_row = _NO_ROW
|
|
531
|
+
# if we checked for second row then that would have
|
|
532
|
+
# closed us :)
|
|
533
|
+
self._soft_close(hard=True)
|
|
534
|
+
|
|
535
|
+
if not scalar:
|
|
536
|
+
post_creational_filter = self._post_creational_filter
|
|
537
|
+
if post_creational_filter is not None:
|
|
538
|
+
row = post_creational_filter(row)
|
|
539
|
+
|
|
540
|
+
if scalar and make_row is not None:
|
|
541
|
+
return row[0] # type: ignore
|
|
542
|
+
else:
|
|
543
|
+
return row # type: ignore
|
|
544
|
+
|
|
545
|
+
def _iter_impl(self) -> Iterator[_R]:
|
|
546
|
+
return self._iterator_getter()
|
|
547
|
+
|
|
548
|
+
def _next_impl(self) -> _R:
|
|
549
|
+
row = self._onerow_getter(self)
|
|
550
|
+
if row is _NO_ROW:
|
|
551
|
+
raise StopIteration()
|
|
552
|
+
else:
|
|
553
|
+
return row
|
|
554
|
+
|
|
555
|
+
@HasMemoized_ro_memoized_attribute
|
|
556
|
+
def _unique_strategy(self) -> _UniqueFilterStateType:
|
|
557
|
+
assert self._unique_filter_state is not None
|
|
558
|
+
uniques, strategy = self._unique_filter_state
|
|
559
|
+
|
|
560
|
+
if strategy is None and self._metadata._unique_filters is not None:
|
|
561
|
+
real_result = (
|
|
562
|
+
self if self._real_result is None else self._real_result
|
|
563
|
+
)
|
|
564
|
+
if (
|
|
565
|
+
real_result._source_supports_scalars
|
|
566
|
+
and not self._generate_rows
|
|
567
|
+
):
|
|
568
|
+
strategy = self._metadata._unique_filters[0]
|
|
569
|
+
else:
|
|
570
|
+
filters = self._metadata._unique_filters
|
|
571
|
+
if self._metadata._tuplefilter is not None:
|
|
572
|
+
filters = self._metadata._tuplefilter(filters)
|
|
573
|
+
|
|
574
|
+
strategy = operator.methodcaller("_filter_on_values", filters)
|
|
575
|
+
return uniques, strategy
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
if cython.compiled:
|
|
579
|
+
|
|
580
|
+
@cython.inline
|
|
581
|
+
@cython.cfunc
|
|
582
|
+
@cython.wraparound(False)
|
|
583
|
+
@cython.boundscheck(False)
|
|
584
|
+
def _apply_processors(
|
|
585
|
+
proc: tuple,
|
|
586
|
+
proc_size: cython.Py_ssize_t,
|
|
587
|
+
proc_valid: object, # used only by python impl
|
|
588
|
+
data: Sequence,
|
|
589
|
+
) -> tuple[Any, ...]:
|
|
590
|
+
res: tuple = PyTuple_New(proc_size)
|
|
591
|
+
i: cython.Py_ssize_t
|
|
592
|
+
for i in range(proc_size):
|
|
593
|
+
p = proc[i]
|
|
594
|
+
if p is not None:
|
|
595
|
+
value = p(data[i])
|
|
596
|
+
else:
|
|
597
|
+
value = data[i]
|
|
598
|
+
Py_INCREF(value)
|
|
599
|
+
PyTuple_SET_ITEM(res, i, value)
|
|
600
|
+
return res
|
|
601
|
+
|
|
602
|
+
else:
|
|
603
|
+
|
|
604
|
+
def _apply_processors(
|
|
605
|
+
proc: _ProcessorsType,
|
|
606
|
+
proc_size: int, # used only by cython impl
|
|
607
|
+
proc_valid: tuple[int, ...],
|
|
608
|
+
data: Sequence[Any],
|
|
609
|
+
) -> tuple[Any, ...]:
|
|
610
|
+
res = list(data)
|
|
611
|
+
for i in proc_valid:
|
|
612
|
+
res[i] = proc[i](res[i])
|
|
613
|
+
return tuple(res)
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
@cython.inline
|
|
617
|
+
@cython.cfunc
|
|
618
|
+
def _apply_unique_strategy(
|
|
619
|
+
rows: Sequence[Any],
|
|
620
|
+
destination: list[Any],
|
|
621
|
+
uniques: set[Any],
|
|
622
|
+
strategy: Callable[[Any], Any] | None,
|
|
623
|
+
) -> list[Any]:
|
|
624
|
+
i: cython.Py_ssize_t
|
|
625
|
+
has_strategy: cython.bint = strategy is not None
|
|
626
|
+
for i in range(len(rows)):
|
|
627
|
+
row = rows[i]
|
|
628
|
+
hashed = strategy(row) if has_strategy else row
|
|
629
|
+
if hashed in uniques:
|
|
630
|
+
continue
|
|
631
|
+
uniques.add(hashed)
|
|
632
|
+
destination.append(row)
|
|
633
|
+
return destination
|
|
Binary file
|