Cleaned up the directories
This commit is contained in:
parent
f708506d68
commit
a683fcffea
1340 changed files with 554582 additions and 6840 deletions
|
@ -0,0 +1,128 @@
|
|||
import sqlalchemy as sa
|
||||
import sqlalchemy.orm
|
||||
from sqlalchemy.sql.util import ClauseAdapter
|
||||
|
||||
from ..compat import _select_args
|
||||
from .chained_join import chained_join # noqa
|
||||
|
||||
|
||||
def path_to_relationships(path, cls):
|
||||
relationships = []
|
||||
for path_name in path.split('.'):
|
||||
rel = getattr(cls, path_name)
|
||||
relationships.append(rel)
|
||||
cls = rel.mapper.class_
|
||||
return relationships
|
||||
|
||||
|
||||
def adapt_expr(expr, *selectables):
|
||||
for selectable in selectables:
|
||||
expr = ClauseAdapter(selectable).traverse(expr)
|
||||
return expr
|
||||
|
||||
|
||||
def inverse_join(selectable, left_alias, right_alias, relationship):
|
||||
if relationship.property.secondary is not None:
|
||||
secondary_alias = sa.alias(relationship.property.secondary)
|
||||
return selectable.join(
|
||||
secondary_alias,
|
||||
adapt_expr(
|
||||
relationship.property.secondaryjoin,
|
||||
sa.inspect(left_alias).selectable,
|
||||
secondary_alias
|
||||
)
|
||||
).join(
|
||||
right_alias,
|
||||
adapt_expr(
|
||||
relationship.property.primaryjoin,
|
||||
sa.inspect(right_alias).selectable,
|
||||
secondary_alias
|
||||
)
|
||||
)
|
||||
else:
|
||||
join = sa.orm.join(right_alias, left_alias, relationship)
|
||||
onclause = join.onclause
|
||||
return selectable.join(right_alias, onclause)
|
||||
|
||||
|
||||
def relationship_to_correlation(relationship, alias):
|
||||
if relationship.property.secondary is not None:
|
||||
return adapt_expr(
|
||||
relationship.property.primaryjoin,
|
||||
alias,
|
||||
)
|
||||
else:
|
||||
return sa.orm.join(
|
||||
relationship.parent,
|
||||
alias,
|
||||
relationship
|
||||
).onclause
|
||||
|
||||
|
||||
def chained_inverse_join(relationships, leaf_model):
|
||||
selectable = sa.inspect(leaf_model).selectable
|
||||
aliases = [leaf_model]
|
||||
for index, relationship in enumerate(relationships[1:]):
|
||||
aliases.append(sa.orm.aliased(relationship.mapper.class_))
|
||||
selectable = inverse_join(
|
||||
selectable,
|
||||
aliases[index],
|
||||
aliases[index + 1],
|
||||
relationships[index]
|
||||
)
|
||||
|
||||
if relationships[-1].property.secondary is not None:
|
||||
secondary_alias = sa.alias(relationships[-1].property.secondary)
|
||||
selectable = selectable.join(
|
||||
secondary_alias,
|
||||
adapt_expr(
|
||||
relationships[-1].property.secondaryjoin,
|
||||
secondary_alias,
|
||||
sa.inspect(aliases[-1]).selectable
|
||||
)
|
||||
)
|
||||
aliases.append(secondary_alias)
|
||||
return selectable, aliases
|
||||
|
||||
|
||||
def select_correlated_expression(
|
||||
root_model,
|
||||
expr,
|
||||
path,
|
||||
leaf_model,
|
||||
from_obj=None,
|
||||
order_by=None,
|
||||
correlate=True
|
||||
):
|
||||
relationships = list(reversed(path_to_relationships(path, root_model)))
|
||||
|
||||
query = sa.select(*_select_args(expr))
|
||||
|
||||
join_expr, aliases = chained_inverse_join(relationships, leaf_model)
|
||||
|
||||
if order_by:
|
||||
query = query.order_by(
|
||||
*[
|
||||
adapt_expr(
|
||||
o,
|
||||
*(sa.inspect(alias).selectable for alias in aliases)
|
||||
)
|
||||
for o in order_by
|
||||
]
|
||||
)
|
||||
|
||||
condition = relationship_to_correlation(
|
||||
relationships[-1],
|
||||
aliases[-1]
|
||||
)
|
||||
|
||||
if from_obj is not None:
|
||||
condition = adapt_expr(condition, from_obj)
|
||||
|
||||
query = query.select_from(join_expr.selectable)
|
||||
|
||||
if correlate:
|
||||
query = query.correlate(
|
||||
from_obj if from_obj is not None else root_model
|
||||
)
|
||||
return query.where(condition)
|
|
@ -0,0 +1,31 @@
|
|||
def chained_join(*relationships):
|
||||
"""
|
||||
Return a chained Join object for given relationships.
|
||||
"""
|
||||
property_ = relationships[0].property
|
||||
|
||||
if property_.secondary is not None:
|
||||
from_ = property_.secondary.join(
|
||||
property_.mapper.class_.__table__,
|
||||
property_.secondaryjoin
|
||||
)
|
||||
else:
|
||||
from_ = property_.mapper.class_.__table__
|
||||
for relationship in relationships[1:]:
|
||||
prop = relationship.property
|
||||
if prop.secondary is not None:
|
||||
from_ = from_.join(
|
||||
prop.secondary,
|
||||
prop.primaryjoin
|
||||
)
|
||||
|
||||
from_ = from_.join(
|
||||
prop.mapper.class_,
|
||||
prop.secondaryjoin
|
||||
)
|
||||
else:
|
||||
from_ = from_.join(
|
||||
prop.mapper.class_,
|
||||
prop.primaryjoin
|
||||
)
|
||||
return from_
|
Loading…
Add table
Add a link
Reference in a new issue