summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-08-16 13:25:46 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-08-16 13:25:46 -0400
commitfd4ac5b3171dacf2efba31c520c546e2422fba36 (patch)
treee7a98eba0ec6eca12c679294a6cae52994702da9
parenta180239d8eda8c20ea39f4f5190abf51deba8b05 (diff)
downloadsqlalchemy-fd4ac5b3171dacf2efba31c520c546e2422fba36.tar.gz
- we're going to attempt to get the type/operator system to eat its own dogfood and
use the type-based comparator in all cases. will attempt to remove the _adapt_expression() method entirely as this represents an incomplete and redundant system (though it might be a lot faster)
-rw-r--r--lib/sqlalchemy/sql/expression.py52
-rw-r--r--lib/sqlalchemy/sql/util.py2
-rw-r--r--lib/sqlalchemy/types.py9
-rw-r--r--test/lib/profiles.txt19
4 files changed, 41 insertions, 41 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 613705c38..a0715a975 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -2099,6 +2099,8 @@ class _DefaultColumnComparator(object):
if isinstance(other, (SelectBase, Alias)):
other = other.as_scalar()
return other
+ elif isinstance(other, sqltypes.TypeEngine.Comparator):
+ return other.expr
elif not isinstance(other, ClauseElement):
return expr._bind_param(operator, other)
elif isinstance(other, (SelectBase, Alias)):
@@ -2152,24 +2154,24 @@ class ColumnElement(ClauseElement, ColumnOperators):
__visit_name__ = 'column'
primary_key = False
foreign_keys = []
- type = None
quote = None
_label = None
_key_label = None
_alt_names = ()
@util.memoized_property
+ def type(self):
+ return sqltypes.NULLTYPE
+
+ @util.memoized_property
def comparator(self):
- if self.type is None:
- return None
- elif self.type.comparator_factory is not None:
- return self.type.comparator_factory(self)
- else:
- return None
+ return self.type.comparator_factory(self)
+
+ #def _assert_comparator(self):
+ # assert self.comparator.expr is self
def __getattr__(self, key):
- if self.comparator is None:
- raise AttributeError(key)
+ #self._assert_comparator()
try:
return getattr(self.comparator, key)
except AttributeError:
@@ -2180,26 +2182,13 @@ class ColumnElement(ClauseElement, ColumnOperators):
key)
)
- @property
- def expression(self):
- """Return a column expression.
-
- Part of the inspection interface; returns self.
-
- """
- return self
-
def operate(self, op, *other, **kwargs):
- if self.comparator:
- return op(self.comparator, *other, **kwargs)
- else:
- return _DEFAULT_COMPARATOR.operate(self, op, *other, **kwargs)
+ #self._assert_comparator()
+ return op(self.comparator, *other, **kwargs)
def reverse_operate(self, op, other, **kwargs):
- if self.comparator:
- return op(other, self.comparator, **kwargs)
- else:
- return _DEFAULT_COMPARATOR.reverse_operate(self, op, other, **kwargs)
+ #self._assert_comparator()
+ return op(other, self.comparator, **kwargs)
def _bind_param(self, operator, obj):
return BindParameter(None, obj,
@@ -2207,6 +2196,15 @@ class ColumnElement(ClauseElement, ColumnOperators):
_compared_to_type=self.type, unique=True)
@property
+ def expression(self):
+ """Return a column expression.
+
+ Part of the inspection interface; returns self.
+
+ """
+ return self
+
+ @property
def _select_iterable(self):
return (self, )
@@ -4007,7 +4005,7 @@ class Grouping(ColumnElement):
def __init__(self, element):
self.element = element
- self.type = getattr(element, 'type', None)
+ self.type = getattr(element, 'type', sqltypes.NULLTYPE)
@property
def _label(self):
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py
index 6bfaf4b8c..35761def1 100644
--- a/lib/sqlalchemy/sql/util.py
+++ b/lib/sqlalchemy/sql/util.py
@@ -420,6 +420,7 @@ class Annotated(object):
element.c
self.__dict__ = element.__dict__.copy()
+ self.__dict__.pop('comparator', None)
self.__element = element
self._annotations = values
@@ -431,6 +432,7 @@ class Annotated(object):
def _with_annotations(self, values):
clone = self.__class__.__new__(self.__class__)
clone.__dict__ = self.__dict__.copy()
+ clone.__dict__.pop('comparator', None)
clone._annotations = values
return clone
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py
index 6c9041630..40cf2f331 100644
--- a/lib/sqlalchemy/types.py
+++ b/lib/sqlalchemy/types.py
@@ -47,9 +47,13 @@ class TypeEngine(AbstractType):
type level. See :attr:`.TypeEngine.comparator_factory`.
"""
+
def __init__(self, expr):
self.expr = expr
+ def __reduce__(self):
+ return _reconstitute_comparator, (self.expr, )
+
def operate(self, op, *other, **kwargs):
return _DEFAULT_COMPARATOR.operate(self.expr, op, *other, **kwargs)
@@ -57,7 +61,7 @@ class TypeEngine(AbstractType):
return _DEFAULT_COMPARATOR.reverse_operate(self.expr, op, other,
**kwargs)
- comparator_factory = None
+ comparator_factory = Comparator
"""A :class:`.TypeEngine.Comparator` class which will apply
to operations performed by owning :class:`.ColumnElement` objects.
@@ -406,6 +410,9 @@ class TypeEngine(AbstractType):
def __repr__(self):
return util.generic_repr(self)
+def _reconstitute_comparator(expression):
+ return expression.comparator
+
class UserDefinedType(TypeEngine):
"""Base for user defined types.
diff --git a/test/lib/profiles.txt b/test/lib/profiles.txt
index 5572a8ebc..edbee75e9 100644
--- a/test/lib/profiles.txt
+++ b/test/lib/profiles.txt
@@ -1,15 +1,15 @@
# /Users/classic/dev/sqla_comparators/./test/lib/profiles.txt
# This file is written out on a per-environment basis.
-# For each test in aaa_profiling, the corresponding function and
+# For each test in aaa_profiling, the corresponding function and
# environment is located within this file. If it doesn't exist,
# the test is skipped.
-# If a callcount does exist, it is compared to what we received.
+# If a callcount does exist, it is compared to what we received.
# assertions are raised if the counts do not match.
-#
-# To add a new callcount test, apply the function_call_count
-# decorator and re-run the tests using the --write-profiles option -
+#
+# To add a new callcount test, apply the function_call_count
+# decorator and re-run the tests using the --write-profiles option -
# this file will be rewritten including the new count.
-#
+#
# TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert
@@ -195,13 +195,6 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.2_
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.6_sqlite_pysqlite_nocextensions 12
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_cextensions 12
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_nocextensions 12
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_cextensions 12
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_nocextensions 12
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_cextensions 12
-test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_nocextensions 12
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_string