self.target = eagerloader.select_table
self.eagertarget = eagerloader.select_table.alias(self._aliashash("/target"))
self.extra_cols = {}
-
+
if eagerloader.secondary:
self.eagersecondary = eagerloader.secondary.alias(self._aliashash("/secondary"))
- self.aliasizer = sql_util.Aliasizer(eagerloader.target, eagerloader.secondary, aliases={
- eagerloader.target:self.eagertarget,
- eagerloader.secondary:self.eagersecondary
- })
+ if parentclauses is not None:
+ aliasizer = sql_util.ClauseAdapter(self.eagertarget).\
+ chain(sql_util.ClauseAdapter(self.eagersecondary)).\
+ chain(sql_util.ClauseAdapter(parentclauses.eagertarget))
+ else:
+ aliasizer = sql_util.ClauseAdapter(self.eagertarget).\
+ chain(sql_util.ClauseAdapter(self.eagersecondary))
self.eagersecondaryjoin = eagerloader.polymorphic_secondaryjoin.copy_container()
- self.aliasizer.traverse(self.eagersecondaryjoin)
+ aliasizer.traverse(self.eagersecondaryjoin)
self.eagerprimary = eagerloader.polymorphic_primaryjoin.copy_container()
- self.aliasizer.traverse(self.eagerprimary)
+ aliasizer.traverse(self.eagerprimary)
else:
self.eagerprimary = eagerloader.polymorphic_primaryjoin.copy_container()
- self.aliasizer = sql_util.Aliasizer(self.target, aliases={self.target:self.eagertarget})
- self.aliasizer.traverse(self.eagerprimary)
-
- if parentclauses is not None:
- parentclauses.aliasizer.traverse(self.eagerprimary)
+ if parentclauses is not None:
+ aliasizer = sql_util.ClauseAdapter(self.eagertarget)
+ aliasizer.chain(sql_util.ClauseAdapter(parentclauses.eagertarget, exclude=eagerloader.parent_property.remote_side))
+ else:
+ aliasizer = sql_util.ClauseAdapter(self.eagertarget)
+ aliasizer.traverse(self.eagerprimary)
if eagerloader.order_by:
- self.eager_order_by = self._aliasize_orderby(eagerloader.order_by)
+ self.eager_order_by = sql_util.ClauseAdapter(self.eagertarget).copy_and_process(util.to_list(eagerloader.order_by))
else:
self.eager_order_by = None
# use the first 4 digits of an MD5 hash
return "anon_" + util.hash(self.id + extra)[0:4]
- def _aliasize_orderby(self, orderby, copy=True):
- if copy:
- return self.aliasizer.copy_and_process(util.to_list(orderby))
- else:
- orderby = util.to_list(orderby)
- self.aliasizer.process_list(orderby)
- return orderby
-
def _create_decorator_row(self):
class EagerRowAdapter(object):
def __init__(self, row):
def traverse(self, obj):
for n in obj.get_children(**self.__traverse_options__):
self.traverse(n)
- obj.accept_visitor(self)
+ v = self
+ while v is not None:
+ obj.accept_visitor(v)
+ v = getattr(v, '_next', None)
+
+ def chain(self, visitor):
+ """'chain' an additional ClauseVisitor onto this ClauseVisitor.
+
+ the chained visitor will receive all visit events after this one."""
+ tail = self
+ while getattr(tail, '_next', None) is not None:
+ tail = tail._next
+ tail._next = visitor
+ return self
+
def visit_column(self, column):
pass
def visit_table(self, table):
if elem is not None:
binary.right = elem
-class Aliasizer(AbstractClauseProcessor):
- """Convert a table instance within an expression to be an alias of that table."""
-
- def __init__(self, *tables, **kwargs):
- self.tables = {}
- self.aliases = kwargs.get('aliases', {})
- for t in tables:
- self.tables[t] = t
- if not self.aliases.has_key(t):
- self.aliases[t] = sql.alias(t)
- if isinstance(t, sql.Join):
- for t2 in t.columns:
- self.tables[t2.table] = t2
- self.aliases[t2.table] = self.aliases[t]
- self.binary = None
-
- def get_alias(self, table):
- return self.aliases[table]
-
- def convert_element(self, elem):
- if isinstance(elem, sql.ColumnElement) and hasattr(elem, 'table') and self.tables.has_key(elem.table):
- return self.get_alias(elem.table).corresponding_column(elem)
- else:
- return None
-
+ # TODO: visit_select().
+
class ClauseAdapter(AbstractClauseProcessor):
"""Given a clause (like as in a WHERE criterion), locate columns
which are embedded within a given selectable, and changes those