diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-03-09 14:36:23 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-03-09 14:36:23 -0400 |
| commit | 9afe585f4599d8114abe8d11f924c206a8962cda (patch) | |
| tree | dd734140049a3f0e744f43791bdf18971f33bbe6 /lib/sqlalchemy | |
| parent | fcfa62bd76ee0cdb125f0eb46ec4c1f625cbd6e7 (diff) | |
| download | sqlalchemy-9afe585f4599d8114abe8d11f924c206a8962cda.tar.gz | |
- pick around gaining modest dings in callcounts here and there
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 32 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/selectable.py | 5 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/visitors.py | 14 | ||||
| -rw-r--r-- | lib/sqlalchemy/util/_collections.py | 18 |
4 files changed, 46 insertions, 23 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index fdee986d3..630be4a1a 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -100,7 +100,8 @@ class Query(object): _with_options = () _with_hints = () _enable_single_crit = True - + _orm_only_adapt = True + _orm_only_from_obj_alias = True _current_path = _path_registry def __init__(self, entities, session=None): @@ -231,7 +232,8 @@ class Query(object): adapters = [] # do we adapt all expression elements or only those # tagged as 'ORM' constructs ? - orm_only = getattr(self, '_orm_only_adapt', orm_only) + if not self._orm_only_adapt: + orm_only = False if as_filter and self._filter_aliases: for fa in self._filter_aliases._visitor_iterator: @@ -248,7 +250,7 @@ class Query(object): # to all SQL constructs. adapters.append( ( - getattr(self, '_orm_only_from_obj_alias', orm_only), + orm_only if self._orm_only_from_obj_alias else False, self._from_obj_alias.replace ) ) @@ -305,7 +307,7 @@ class Query(object): ezero = self._mapper_zero() if ezero is not None: insp = inspect(ezero) - if hasattr(insp, 'mapper'): + if not insp.is_clause_element: return insp.mapper return None @@ -3580,18 +3582,18 @@ class _ColumnEntity(_QueryEntity): if 'parententity' in elem._annotations ] - self.entities = util.unique_list( + self.entities = util.unique_list([ elem._annotations['parententity'] for elem in all_elements if 'parententity' in elem._annotations - ) + ]) - self._from_entities = set( + self._from_entities = set([ elem._annotations['parententity'] for elem in all_elements if 'parententity' in elem._annotations and actual_froms.intersection(elem._from_objects) - ) + ]) if self.entities: self.entity_zero = self.entities[0] @@ -3636,12 +3638,11 @@ class _ColumnEntity(_QueryEntity): return not _is_aliased_class(self.entity_zero) and \ entity.common_parent(self.entity_zero) - def _resolve_expr_against_query_aliases(self, query, expr, context): - return query._adapt_clause(expr, False, True) - def row_processor(self, query, context, result): - column = self._resolve_expr_against_query_aliases( - query, self.column, context) + if ('fetch_column', self) in context.attributes: + column = context.attributes[('fetch_column', self)] + else: + column = query._adapt_clause(self.column, False, True) if context.adapter: column = context.adapter.columns[column] @@ -3650,11 +3651,12 @@ class _ColumnEntity(_QueryEntity): return getter, self._label_name def setup_context(self, query, context): - column = self._resolve_expr_against_query_aliases( - query, self.column, context) + column = query._adapt_clause(self.column, False, True) context.froms += tuple(self.froms) context.primary_columns.append(column) + context.attributes[('fetch_column', self)] = column + def __str__(self): return str(self.column) diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 3384939b0..42d2e4e12 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -43,9 +43,10 @@ def _interpret_as_from(element): {"expr": util.ellipses_string(element)}) return TextClause(util.text_type(element)) - elif hasattr(insp, "selectable"): + try: return insp.selectable - raise exc.ArgumentError("FROM expression expected") + except AttributeError: + raise exc.ArgumentError("FROM expression expected") def _interpret_as_select(element): diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py index d09b82148..b53b44eec 100644 --- a/lib/sqlalchemy/sql/visitors.py +++ b/lib/sqlalchemy/sql/visitors.py @@ -213,12 +213,19 @@ def iterate(obj, opts): traversal is configured to be breadth-first. """ + # fasttrack for atomic elements like columns + children = obj.get_children(**opts) + if not children: + return [obj] + + traversal = deque() stack = deque([obj]) while stack: t = stack.popleft() - yield t + traversal.append(t) for c in t.get_children(**opts): stack.append(c) + return iter(traversal) def iterate_depthfirst(obj, opts): @@ -227,6 +234,11 @@ def iterate_depthfirst(obj, opts): traversal is configured to be depth-first. """ + # fasttrack for atomic elements like columns + children = obj.get_children(**opts) + if not children: + return [obj] + stack = deque([obj]) traversal = deque() while stack: diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py index a49848d08..84895182a 100644 --- a/lib/sqlalchemy/util/_collections.py +++ b/lib/sqlalchemy/util/_collections.py @@ -129,11 +129,13 @@ class _LW(AbstractKeyedTuple): def lightweight_named_tuple(name, fields): - tp_cls = type(name, (_LW,), {}) - for idx, field in enumerate(fields): - if field is None: - continue - setattr(tp_cls, field, property(operator.itemgetter(idx))) + tp_cls = type( + name, (_LW,), + dict([ + (field, _property_getters[idx]) + for idx, field in enumerate(fields) if field is not None + ]) + ) tp_cls._real_fields = fields tp_cls._fields = tuple([f for f in fields if f is not None]) @@ -747,6 +749,12 @@ ordered_column_set = OrderedSet populate_column_dict = PopulateDict +_getters = PopulateDict(operator.itemgetter) + +_property_getters = PopulateDict( + lambda idx: property(operator.itemgetter(idx))) + + def unique_list(seq, hashfunc=None): seen = {} if not hashfunc: |
