summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/selectable.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-04-17 13:37:39 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-04-29 12:45:45 -0400
commit08da8115a6eb7eb125fa5f92f662d915b076fded (patch)
treea4eaee5acdd2ffd7f254b1426b97e176c6dda803 /lib/sqlalchemy/sql/selectable.py
parent099522075088a3e1a333a2285c10a8a33b203c19 (diff)
downloadsqlalchemy-08da8115a6eb7eb125fa5f92f662d915b076fded.tar.gz
Add _cache_key implementation.
This leverages the work started in #4336 to allow ClauseElement structures to be cachable based on structure, not just identity. Change-Id: Ia99ddeb5353496dd7d61243245685f02b98d8100
Diffstat (limited to 'lib/sqlalchemy/sql/selectable.py')
-rw-r--r--lib/sqlalchemy/sql/selectable.py98
1 files changed, 98 insertions, 0 deletions
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 796e2b272..a44e94da7 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -864,6 +864,16 @@ class Join(FromClause):
def get_children(self, **kwargs):
return self.left, self.right, self.onclause
+ def _cache_key(self, **kw):
+ return (
+ Join,
+ self.isouter,
+ self.full,
+ self.left._cache_key(**kw),
+ self.right._cache_key(**kw),
+ self.onclause._cache_key(**kw),
+ )
+
def _match_primaries(self, left, right):
if isinstance(left, Join):
left_right = left.right
@@ -1289,6 +1299,7 @@ class Alias(FromClause):
if self.supports_execution:
self._execution_options = baseselectable._execution_options
self.element = selectable
+ self._orig_name = name
if name is None:
if self.original.named_with_column:
name = getattr(self.original, "name", None)
@@ -1358,6 +1369,9 @@ class Alias(FromClause):
yield c
yield self.element
+ def _cache_key(self, **kw):
+ return (self.__class__, self.element._cache_key(**kw), self._orig_name)
+
@property
def _from_objects(self):
return [self]
@@ -1777,6 +1791,9 @@ class FromGrouping(FromClause):
def _copy_internals(self, clone=_clone, **kw):
self.element = clone(self.element, **kw)
+ def _cache_key(self, **kw):
+ return (FromGrouping, self.element._cache_key(**kw))
+
@property
def _from_objects(self):
return self.element._from_objects
@@ -1877,6 +1894,11 @@ class TableClause(Immutable, FromClause):
else:
return []
+ def _cache_key(self, **kw):
+ return (TableClause, self.name) + tuple(
+ col._cache_key(**kw) for col in self._columns
+ )
+
@util.dependencies("sqlalchemy.sql.dml")
def insert(self, dml, values=None, inline=False, **kwargs):
"""Generate an :func:`.insert` construct against this
@@ -2004,6 +2026,15 @@ class ForUpdateArg(ClauseElement):
if self.of is not None:
self.of = [clone(col, **kw) for col in self.of]
+ def _cache_key(self, **kw):
+ return (
+ ForUpdateArg,
+ self.nowait,
+ self.read,
+ self.skip_locked,
+ self.of._cache_key(**kw) if self.of is not None else None,
+ )
+
def __init__(
self,
nowait=False,
@@ -2653,6 +2684,27 @@ class CompoundSelect(GenerativeSelect):
+ list(self.selects)
)
+ def _cache_key(self, **kw):
+ return (
+ (CompoundSelect, self.keyword)
+ + tuple(stmt._cache_key(**kw) for stmt in self.selects)
+ + (
+ self._order_by_clause._cache_key(**kw)
+ if self._order_by_clause is not None
+ else None,
+ )
+ + (
+ self._group_by_clause._cache_key(**kw)
+ if self._group_by_clause is not None
+ else None,
+ )
+ + (
+ self._for_update_arg._cache_key(**kw)
+ if self._for_update_arg is not None
+ else None,
+ )
+ )
+
def bind(self):
if self._bind:
return self._bind
@@ -3277,6 +3329,47 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect):
]
)
+ def _cache_key(self, **kw):
+ return (
+ (Select,)
+ + ("raw_columns",)
+ + tuple(elem._cache_key(**kw) for elem in self._raw_columns)
+ + ("elements",)
+ + tuple(
+ elem._cache_key(**kw) if elem is not None else None
+ for elem in (
+ self._whereclause,
+ self._having,
+ self._order_by_clause,
+ self._group_by_clause,
+ )
+ )
+ + ("from_obj",)
+ + tuple(elem._cache_key(**kw) for elem in self._from_obj)
+ + ("correlate",)
+ + tuple(
+ elem._cache_key(**kw)
+ for elem in (
+ self._correlate if self._correlate is not None else ()
+ )
+ )
+ + ("correlate_except",)
+ + tuple(
+ elem._cache_key(**kw)
+ for elem in (
+ self._correlate_except
+ if self._correlate_except is not None
+ else ()
+ )
+ )
+ + ("for_update",),
+ (
+ self._for_update_arg._cache_key(**kw)
+ if self._for_update_arg is not None
+ else None,
+ ),
+ )
+
@_generative
def column(self, column):
"""return a new select() construct with the given column expression
@@ -3950,6 +4043,11 @@ class TextAsFrom(SelectBase):
yield c
yield self.element
+ def _cache_key(self, **kw):
+ return (TextAsFrom, self.element._cache_key(**kw)) + tuple(
+ col._cache_key(**kw) for col in self.column_args
+ )
+
def _scalar_type(self):
return self.column_args[0].type