summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-03-09 14:36:23 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-03-09 14:36:23 -0400
commit9afe585f4599d8114abe8d11f924c206a8962cda (patch)
treedd734140049a3f0e744f43791bdf18971f33bbe6 /lib/sqlalchemy
parentfcfa62bd76ee0cdb125f0eb46ec4c1f625cbd6e7 (diff)
downloadsqlalchemy-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.py32
-rw-r--r--lib/sqlalchemy/sql/selectable.py5
-rw-r--r--lib/sqlalchemy/sql/visitors.py14
-rw-r--r--lib/sqlalchemy/util/_collections.py18
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: