diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2020-06-19 15:21:39 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2020-06-19 15:21:39 +0000 |
| commit | 15dd104d5bd1c0819628dec6d9466be38dc5130f (patch) | |
| tree | c27cc01c959170895d8389408b12de8921e4b532 /lib | |
| parent | 332b8b78f6ba728b0994457420cb66e1c9bd5846 (diff) | |
| parent | 699da7ecb96e9e1af8df8072d53199a560311260 (diff) | |
| download | sqlalchemy-15dd104d5bd1c0819628dec6d9466be38dc5130f.tar.gz | |
Merge "perf tweaks"
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/engine/util.py | 9 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/context.py | 86 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/base.py | 10 |
4 files changed, 59 insertions, 49 deletions
diff --git a/lib/sqlalchemy/engine/util.py b/lib/sqlalchemy/engine/util.py index 8fb04646f..fc0260ae2 100644 --- a/lib/sqlalchemy/engine/util.py +++ b/lib/sqlalchemy/engine/util.py @@ -8,6 +8,7 @@ from .. import exc from .. import util from ..util import collections_abc +from ..util import immutabledict def connection_memoize(key): @@ -85,9 +86,11 @@ _no_kw = util.immutabledict() def _distill_params_20(params): + # TODO: this has to be in C if params is None: return _no_tuple, _no_kw, [] - elif isinstance(params, collections_abc.MutableSequence): # list + elif isinstance(params, list): + # collections_abc.MutableSequence): # avoid abc.__instancecheck__ if params and not isinstance( params[0], (collections_abc.Mapping, tuple) ): @@ -99,7 +102,9 @@ def _distill_params_20(params): return tuple(params), _no_kw, params elif isinstance( params, - (collections_abc.Sequence, collections_abc.Mapping), # tuple or dict + (tuple, dict, immutabledict), + # avoid abc.__instancecheck__ + # (collections_abc.Sequence, collections_abc.Mapping), ): return _no_tuple, params, [params] else: diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py index 588b83571..f380229e1 100644 --- a/lib/sqlalchemy/orm/context.py +++ b/lib/sqlalchemy/orm/context.py @@ -2245,7 +2245,7 @@ class _BundleEntity(_QueryEntity): class _ColumnEntity(_QueryEntity): - __slots__ = () + __slots__ = ("_fetch_column", "_row_processor") @classmethod def _for_columns(cls, compile_state, columns, parent_bundle=None): @@ -2275,6 +2275,44 @@ class _ColumnEntity(_QueryEntity): def use_id_for_hash(self): return not self.column.type.hashable + def row_processor(self, context, result): + compile_state = context.compile_state + + # the resulting callable is entirely cacheable so just return + # it if we already made one + if self._row_processor is not None: + return self._row_processor + + # retrieve the column that would have been set up in + # setup_compile_state, to avoid doing redundant work + if self._fetch_column is not None: + column = self._fetch_column + else: + # fetch_column will be None when we are doing a from_statement + # and setup_compile_state may not have been called. + column = self.column + + # previously, the RawColumnEntity didn't look for from_obj_alias + # however I can't think of a case where we would be here and + # we'd want to ignore it if this is the from_statement use case. + # it's not really a use case to have raw columns + from_statement + if compile_state._from_obj_alias: + column = compile_state._from_obj_alias.columns[column] + + if column._annotations: + # annotated columns perform more slowly in compiler and + # result due to the __eq__() method, so use deannotated + column = column._deannotate() + + if compile_state.compound_eager_adapter: + column = compile_state.compound_eager_adapter.columns[column] + + getter = result._getter(column) + + ret = getter, self._label_name, self._extra_entities + self._row_processor = ret + return ret + class _RawColumnEntity(_ColumnEntity): entity_zero = None @@ -2303,28 +2341,11 @@ class _RawColumnEntity(_ColumnEntity): self.column._from_objects[0] if self.column._from_objects else None ) self._extra_entities = (self.expr, self.column) + self._fetch_column = self._row_processor = None def corresponds_to(self, entity): return False - def row_processor(self, context, result): - if ("fetch_column", self) in context.attributes: - column = context.attributes[("fetch_column", self)] - else: - column = self.column - - if column._annotations: - # annotated columns perform more slowly in compiler and - # result due to the __eq__() method, so use deannotated - column = column._deannotate() - - compile_state = context.compile_state - if compile_state.compound_eager_adapter: - column = compile_state.compound_eager_adapter.columns[column] - - getter = result._getter(column) - return getter, self._label_name, self._extra_entities - def setup_compile_state(self, compile_state): current_adapter = compile_state._get_current_adapter() if current_adapter: @@ -2338,7 +2359,7 @@ class _RawColumnEntity(_ColumnEntity): column = column._deannotate() compile_state.primary_columns.append(column) - compile_state.attributes[("fetch_column", self)] = column + self._fetch_column = column class _ORMColumnEntity(_ColumnEntity): @@ -2386,6 +2407,7 @@ class _ORMColumnEntity(_ColumnEntity): compile_state._has_orm_entities = True self.column = column + self._fetch_column = self._row_processor = None self._extra_entities = (self.expr, self.column) @@ -2407,27 +2429,6 @@ class _ORMColumnEntity(_ColumnEntity): self.entity_zero ) and entity.common_parent(self.entity_zero) - def row_processor(self, context, result): - compile_state = context.compile_state - - if ("fetch_column", self) in context.attributes: - column = context.attributes[("fetch_column", self)] - else: - column = self.column - if compile_state._from_obj_alias: - column = compile_state._from_obj_alias.columns[column] - - if column._annotations: - # annotated columns perform more slowly in compiler and - # result due to the __eq__() method, so use deannotated - column = column._deannotate() - - if compile_state.compound_eager_adapter: - column = compile_state.compound_eager_adapter.columns[column] - - getter = result._getter(column) - return getter, self._label_name, self._extra_entities - def setup_compile_state(self, compile_state): current_adapter = compile_state._get_current_adapter() if current_adapter: @@ -2460,5 +2461,4 @@ class _ORMColumnEntity(_ColumnEntity): compile_state._fallback_from_clauses.append(ezero.selectable) compile_state.primary_columns.append(column) - - compile_state.attributes[("fetch_column", self)] = column + self._fetch_column = column diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index abbba4172..458217e22 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1637,8 +1637,7 @@ class Query( "params() takes zero or one positional argument, " "which is a dictionary." ) - params = dict(self.load_options._params) - params.update(kwargs) + params = self.load_options._params.union(kwargs) self.load_options += {"_params": params} @_generative diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py index 5f2ce8f14..4c603b6dd 100644 --- a/lib/sqlalchemy/sql/base.py +++ b/lib/sqlalchemy/sql/base.py @@ -495,8 +495,14 @@ class Generative(HasMemoized): def _generate(self): skip = self._memoized_keys - s = self.__class__.__new__(self.__class__) - s.__dict__ = {k: v for k, v in self.__dict__.items() if k not in skip} + cls = self.__class__ + s = cls.__new__(cls) + if skip: + s.__dict__ = { + k: v for k, v in self.__dict__.items() if k not in skip + } + else: + s.__dict__ = self.__dict__.copy() return s |
