summaryrefslogtreecommitdiff
path: root/test/sql/test_operators.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-08-20 17:04:25 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-08-20 17:04:25 -0400
commitaef0c7a903464f4e05496c69ff4e78d41239c220 (patch)
tree716afd20faf81a90ca734b946be619549f8d4384 /test/sql/test_operators.py
parentce1b80ad08f58ea18914a93805754a5e19a85abb (diff)
downloadsqlalchemy-aef0c7a903464f4e05496c69ff4e78d41239c220.tar.gz
- [feature] The Core oeprator system now includes
the `getitem` operator, i.e. the bracket operator in Python. This is used at first to provide index and slice behavior to the Postgresql ARRAY type, and also provides a hook for end-user definition of custom __getitem__ schemes which can be applied at the type level as well as within ORM-level custom operator schemes. Note that this change has the effect that descriptor-based __getitem__ schemes used by the ORM in conjunction with synonym() or other "descriptor-wrapped" schemes will need to start using a custom comparator in order to maintain this behavior. - [feature] postgresql.ARRAY now supports indexing and slicing. The Python [] operator is available on all SQL expressions that are of type ARRAY; integer or simple slices can be passed. The slices can also be used on the assignment side in the SET clause of an UPDATE statement by passing them into Update.values(); see the docs for examples. - [feature] Added new "array literal" construct postgresql.array(). Basically a "tuple" that renders as ARRAY[1,2,3].
Diffstat (limited to 'test/sql/test_operators.py')
-rw-r--r--test/sql/test_operators.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py
index 05de8c9ef..26a36fd34 100644
--- a/test/sql/test_operators.py
+++ b/test/sql/test_operators.py
@@ -34,6 +34,18 @@ class DefaultColumnComparatorTest(fixtures.TestBase):
def test_plus(self):
self._do_operate_test(operators.add)
+ def test_no_getitem(self):
+ assert_raises_message(
+ NotImplementedError,
+ "Operator 'getitem' is not supported on this expression",
+ self._do_operate_test, operators.getitem
+ )
+ assert_raises_message(
+ NotImplementedError,
+ "Operator 'getitem' is not supported on this expression",
+ lambda: column('left')[3]
+ )
+
def test_in(self):
left = column('left')
assert left.comparator.operate(operators.in_op, [1, 2, 3]).compare(
@@ -224,3 +236,87 @@ class NewOperatorTest(_CustomComparatorTests, fixtures.TestBase):
def _assert_not_add_override(self, expr):
assert not hasattr(expr, "foob")
+from sqlalchemy import and_, not_, between
+
+class OperatorPrecedenceTest(fixtures.TestBase, testing.AssertsCompiledSQL):
+ __dialect__ = 'default'
+
+ def test_operator_precedence(self):
+ # TODO: clean up /break up
+ metadata = MetaData()
+ table = Table('op', metadata,
+ Column('field', Integer))
+ self.assert_compile(table.select((table.c.field == 5) == None),
+ "SELECT op.field FROM op WHERE (op.field = :field_1) IS NULL")
+ self.assert_compile(table.select((table.c.field + 5) == table.c.field),
+ "SELECT op.field FROM op WHERE op.field + :field_1 = op.field")
+ self.assert_compile(table.select((table.c.field + 5) * 6),
+ "SELECT op.field FROM op WHERE (op.field + :field_1) * :param_1")
+ self.assert_compile(table.select((table.c.field * 5) + 6),
+ "SELECT op.field FROM op WHERE op.field * :field_1 + :param_1")
+ self.assert_compile(table.select(5 + table.c.field.in_([5, 6])),
+ "SELECT op.field FROM op WHERE :param_1 + "
+ "(op.field IN (:field_1, :field_2))")
+ self.assert_compile(table.select((5 + table.c.field).in_([5, 6])),
+ "SELECT op.field FROM op WHERE :field_1 + op.field "
+ "IN (:param_1, :param_2)")
+ self.assert_compile(table.select(not_(and_(table.c.field == 5,
+ table.c.field == 7))),
+ "SELECT op.field FROM op WHERE NOT "
+ "(op.field = :field_1 AND op.field = :field_2)")
+ self.assert_compile(table.select(not_(table.c.field == 5)),
+ "SELECT op.field FROM op WHERE op.field != :field_1")
+ self.assert_compile(table.select(not_(table.c.field.between(5, 6))),
+ "SELECT op.field FROM op WHERE NOT "
+ "(op.field BETWEEN :field_1 AND :field_2)")
+ self.assert_compile(table.select(not_(table.c.field) == 5),
+ "SELECT op.field FROM op WHERE (NOT op.field) = :param_1")
+ self.assert_compile(table.select((table.c.field == table.c.field).\
+ between(False, True)),
+ "SELECT op.field FROM op WHERE (op.field = op.field) "
+ "BETWEEN :param_1 AND :param_2")
+ self.assert_compile(table.select(
+ between((table.c.field == table.c.field), False, True)),
+ "SELECT op.field FROM op WHERE (op.field = op.field) "
+ "BETWEEN :param_1 AND :param_2")
+
+class OperatorAssociativityTest(fixtures.TestBase, testing.AssertsCompiledSQL):
+ __dialect__ = 'default'
+
+ def test_associativity(self):
+ # TODO: clean up /break up
+ f = column('f')
+ self.assert_compile(f - f, "f - f")
+ self.assert_compile(f - f - f, "(f - f) - f")
+
+ self.assert_compile((f - f) - f, "(f - f) - f")
+ self.assert_compile((f - f).label('foo') - f, "(f - f) - f")
+
+ self.assert_compile(f - (f - f), "f - (f - f)")
+ self.assert_compile(f - (f - f).label('foo'), "f - (f - f)")
+
+ # because - less precedent than /
+ self.assert_compile(f / (f - f), "f / (f - f)")
+ self.assert_compile(f / (f - f).label('foo'), "f / (f - f)")
+
+ self.assert_compile(f / f - f, "f / f - f")
+ self.assert_compile((f / f) - f, "f / f - f")
+ self.assert_compile((f / f).label('foo') - f, "f / f - f")
+
+ # because / more precedent than -
+ self.assert_compile(f - (f / f), "f - f / f")
+ self.assert_compile(f - (f / f).label('foo'), "f - f / f")
+ self.assert_compile(f - f / f, "f - f / f")
+ self.assert_compile((f - f) / f, "(f - f) / f")
+
+ self.assert_compile(((f - f) / f) - f, "(f - f) / f - f")
+ self.assert_compile((f - f) / (f - f), "(f - f) / (f - f)")
+
+ # higher precedence
+ self.assert_compile((f / f) - (f / f), "f / f - f / f")
+
+ self.assert_compile((f / f) - (f - f), "f / f - (f - f)")
+ self.assert_compile((f / f) / (f - f), "(f / f) / (f - f)")
+ self.assert_compile(f / (f / (f - f)), "f / (f / (f - f))")
+
+