[tryton-debian-vcs] python-sql branch upstream updated. upstream/0.3-1-g2607225

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Tue Aug 26 16:41:08 UTC 2014


The following commit has been merged in the upstream branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/python-sql.git;a=commitdiff;h=upstream/0.3-1-g2607225

commit 2607225870456a9e362579d07a9793c756b2e289
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Tue Aug 26 14:57:41 2014 +0200

    Adding upstream version 0.4.

diff --git a/CHANGELOG b/CHANGELOG
index 06d65f3..b3144e4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,12 @@
+Version 0.4 - 2014-08-03
+* Fix Mapping in Trim function
+* Add __truediv__ alias of __div__ for Python3
+* Fix For tables setter when tables is not a list
+* Allow to add Table to existing From list
+* Fix Select with for_ clause
+* Add Null alias for None
+* Add missing format of operand in Unary operator
+
 Version 0.3 - 2014-01-31
 * Add returning to Update
 * Add missing params for returning
diff --git a/PKG-INFO b/PKG-INFO
index 1dd3522..85cba71 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-sql
-Version: 0.3
+Version: 0.4
 Summary: Library to write SQL queries
 Home-page: http://code.google.com/p/python-sql/
 Author: B2CK
diff --git a/python_sql.egg-info/PKG-INFO b/python_sql.egg-info/PKG-INFO
index 1dd3522..85cba71 100644
--- a/python_sql.egg-info/PKG-INFO
+++ b/python_sql.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-sql
-Version: 0.3
+Version: 0.4
 Summary: Library to write SQL queries
 Home-page: http://code.google.com/p/python-sql/
 Author: B2CK
diff --git a/sql/__init__.py b/sql/__init__.py
index 1238546..fb09560 100644
--- a/sql/__init__.py
+++ b/sql/__init__.py
@@ -29,7 +29,7 @@
 
 from __future__ import division
 
-__version__ = '0.3'
+__version__ = '0.4'
 __all__ = ['Flavor', 'Table', 'Literal', 'Column', 'Join', 'Asc', 'Desc']
 
 import string
@@ -321,7 +321,7 @@ class Select(Query, FromItem, _SelectQueryMixin):
         if value is not None:
             if isinstance(value, For):
                 value = [value]
-            assert isinstance(all(isinstance(f, For) for f in value))
+            assert all(isinstance(f, For) for f in value)
         self.__for_ = value
 
     @staticmethod
@@ -349,7 +349,7 @@ class Select(Query, FromItem, _SelectQueryMixin):
                 having = ' HAVING ' + str(self.having)
             for_ = ''
             if self.for_ is not None:
-                for_ = ' '.join(self.for_)
+                for_ = ' ' + ' '.join(map(str, self.for_))
             return ('SELECT %s FROM %s' % (columns, from_) + where + group_by
                 + having + self._order_by_str + self._limit_str +
                 self._offset_str + for_)
@@ -811,7 +811,8 @@ class From(list):
         return tuple(p)
 
     def __add__(self, other):
-        assert isinstance(other, (Join, Select))
+        assert isinstance(other, FromItem)
+        assert not isinstance(other, CombiningQuery)
         return From(super(From, self).__add__([other]))
 
 
@@ -853,6 +854,8 @@ class Expression(object):
         from sql.operators import Div
         return Div(self, other)
 
+    __truediv__ = __div__
+
     def __floordiv__(self, other):
         from sql.functions import Div
         return Div(self, other)
@@ -957,6 +960,8 @@ class Literal(Expression):
     def params(self):
         return (self.__value,)
 
+Null = None
+
 
 class Column(Expression):
     __slots__ = ('__from', '__name')
@@ -1074,7 +1079,7 @@ class For(object):
     @tables.setter
     def tables(self, value):
         if not isinstance(value, list):
-            value = list(value)
+            value = [value]
         all(isinstance(table, Table) for table in value)
         self.__tables = value
 
diff --git a/sql/functions.py b/sql/functions.py
index 6e86138..c987df2 100644
--- a/sql/functions.py
+++ b/sql/functions.py
@@ -332,7 +332,7 @@ class Trim(Function):
     def params(self):
         Mapping = Flavor.get().function_mapping.get(self.__class__)
         if Mapping:
-            return Mapping(*self.args).params
+            return Mapping(self.string, self.position, self.characters).params
         p = []
         for arg in (self.characters, self.string):
             if isinstance(arg, basestring):
diff --git a/sql/operators.py b/sql/operators.py
index 87587b3..25d9157 100644
--- a/sql/operators.py
+++ b/sql/operators.py
@@ -28,7 +28,7 @@
 import warnings
 from array import array
 
-from sql import Expression, Select, CombiningQuery, Flavor
+from sql import Expression, Select, CombiningQuery, Flavor, Null
 
 __all__ = ['And', 'Or', 'Not', 'Less', 'Greater', 'LessEqual', 'GreaterEqual',
     'Equal', 'NotEqual', 'Add', 'Sub', 'Mul', 'Div', 'FloorDiv', 'Mod', 'Pow',
@@ -112,7 +112,7 @@ class UnaryOperator(Operator):
         return (self.operand,)
 
     def __str__(self):
-        return '(%s %s)' % (self._operator, self.operand)
+        return '(%s %s)' % (self._operator, self._format(self.operand))
 
 
 class BinaryOperator(Operator):
@@ -198,16 +198,16 @@ class Equal(BinaryOperator):
 
     @property
     def _operands(self):
-        if self.left is None:
+        if self.left is Null:
             return (self.right,)
-        elif self.right is None:
+        elif self.right is Null:
             return (self.left,)
         return super(Equal, self)._operands
 
     def __str__(self):
-        if self.left is None:
+        if self.left is Null:
             return '(%s IS NULL)' % self.right
-        elif self.right is None:
+        elif self.right is Null:
             return '(%s IS NULL)' % self.left
         return super(Equal, self).__str__()
 
@@ -217,9 +217,9 @@ class NotEqual(Equal):
     _operator = '!='
 
     def __str__(self):
-        if self.left is None:
+        if self.left is Null:
             return '(%s IS NOT NULL)' % self.right
-        elif self.right is None:
+        elif self.right is Null:
             return '(%s IS NOT NULL)' % self.left
         return super(Equal, self).__str__()
 
diff --git a/sql/tests/test_cast.py b/sql/tests/test_cast.py
index a76b648..ee7bf3f 100644
--- a/sql/tests/test_cast.py
+++ b/sql/tests/test_cast.py
@@ -35,8 +35,9 @@ class TestCast(unittest.TestCase):
     column = Column(Table('t'), 'c')
 
     def test_cast(self):
-        self.assertEqual(str(Cast(self.column, 'int')),
-            'CAST("c" AS int)')
+        for cast in [Cast(self.column, 'int'), self.column.cast('int')]:
+            self.assertEqual(str(cast), 'CAST("c" AS int)')
+            self.assertEqual(cast.params, ())
 
     def test_cast_no_expression(self):
         cast = Cast(1.1, 'int')
diff --git a/sql/tests/test_column.py b/sql/tests/test_column.py
index 6be3168..080b59d 100644
--- a/sql/tests/test_column.py
+++ b/sql/tests/test_column.py
@@ -35,6 +35,7 @@ class TestColumn(unittest.TestCase):
     def test_column(self):
         column = Column(Table('t'), 'c')
         self.assertEqual(str(column), '"c"')
+        self.assertEqual(column.name, 'c')
 
         with AliasManager():
             self.assertEqual(str(column), '"a"."c"')
diff --git a/sql/tests/test_for.py b/sql/tests/test_for.py
index cf0b940..764baaf 100644
--- a/sql/tests/test_for.py
+++ b/sql/tests/test_for.py
@@ -35,3 +35,8 @@ class TestFor(unittest.TestCase):
     def test_for(self):
         for_ = For('UPDATE', Table('t1'), Table('t2'), nowait=True)
         self.assertEqual(str(for_), 'FOR UPDATE OF "t1", "t2" NOWAIT')
+
+    def test_for_single_table(self):
+        for_ = For('UPDATE')
+        for_.tables = Table('t1')
+        self.assertEqual(str(for_), 'FOR UPDATE OF "t1"')
diff --git a/sql/tests/test_functions.py b/sql/tests/test_functions.py
index 091e9b6..248142b 100644
--- a/sql/tests/test_functions.py
+++ b/sql/tests/test_functions.py
@@ -29,7 +29,8 @@
 import unittest
 
 from sql import Table, Flavor
-from sql.functions import Function, Abs, Overlay, Trim, AtTimeZone
+from sql.functions import (Function, FunctionKeyword, FunctionNotCallable, Abs,
+    Overlay, Trim, AtTimeZone, Div, CurrentTime)
 
 
 class TestFunctions(unittest.TestCase):
@@ -49,14 +50,40 @@ class TestFunctions(unittest.TestCase):
             _function = 'MY_ABS'
             params = ('test',)
 
+        class MyOverlay(FunctionKeyword):
+            _function = 'MY_OVERLAY'
+            _keywords = ('', 'PLACING', 'FROM', 'FOR')
+
+        class MyCurrentTime(FunctionNotCallable):
+            _function = 'MY_CURRENT_TIME'
+
+        class MyTrim(Trim):
+            _function = 'MY_TRIM'
+
         abs_ = Abs(self.table.c1)
+        overlay = Overlay(self.table.c1, 'test', 2)
+        current_time = CurrentTime()
+        trim = Trim(' test ')
         flavor = Flavor(function_mapping={
                 Abs: MyAbs,
+                Overlay: MyOverlay,
+                CurrentTime: MyCurrentTime,
+                Trim: MyTrim,
                 })
         Flavor.set(flavor)
         try:
             self.assertEqual(str(abs_), 'MY_ABS("c1")')
             self.assertEqual(abs_.params, ('test',))
+
+            self.assertEqual(str(overlay),
+                'MY_OVERLAY("c1" PLACING %s FROM %s)')
+            self.assertEqual(overlay.params, ('test', 2))
+
+            self.assertEqual(str(current_time), 'MY_CURRENT_TIME')
+            self.assertEqual(current_time.params, ())
+
+            self.assertEqual(str(trim), 'MY_TRIM(BOTH %s FROM %s)')
+            self.assertEqual(trim.params, (' ', ' test ',))
         finally:
             Flavor.set(Flavor())
 
@@ -74,6 +101,10 @@ class TestFunctions(unittest.TestCase):
         self.assertEqual(str(trim), 'TRIM(BOTH %s FROM %s)')
         self.assertEqual(trim.params, (' ', ' test ',))
 
+        trim = Trim(self.table.c1)
+        self.assertEqual(str(trim), 'TRIM(BOTH %s FROM "c1")')
+        self.assertEqual(trim.params, (' ',))
+
     def test_at_time_zone(self):
         time_zone = AtTimeZone(self.table.c1, 'UTC')
         self.assertEqual(str(time_zone), '"c1" AT TIME ZONE %s')
@@ -93,3 +124,14 @@ class TestFunctions(unittest.TestCase):
             self.assertEqual(time_zone.params, ('UTC',))
         finally:
             Flavor.set(Flavor())
+
+    def test_div(self):
+        for div in [Div(self.table.c1, self.table.c2),
+                self.table.c1 // self.table.c2]:
+            self.assertEqual(str(div), 'DIV("c1", "c2")')
+            self.assertEqual(div.params, ())
+
+    def test_current_time(self):
+        current_time = CurrentTime()
+        self.assertEqual(str(current_time), 'CURRENT_TIME')
+        self.assertEqual(current_time.params, ())
diff --git a/sql/tests/test_literal.py b/sql/tests/test_literal.py
index 7c8f3b4..c8dd5bf 100644
--- a/sql/tests/test_literal.py
+++ b/sql/tests/test_literal.py
@@ -36,3 +36,4 @@ class TestLiteral(unittest.TestCase):
         literal = Literal(1)
         self.assertEqual(str(literal), '%s')
         self.assertEqual(literal.params, (1,))
+        self.assertEqual(literal.value, 1)
diff --git a/sql/tests/test_operators.py b/sql/tests/test_operators.py
index d726655..23619e3 100644
--- a/sql/tests/test_operators.py
+++ b/sql/tests/test_operators.py
@@ -30,82 +30,250 @@ import unittest
 import warnings
 from array import array
 
-from sql import Table, Literal
-from sql.operators import And, Not, Less, Equal, NotEqual, In, FloorDiv
+from sql import Table, Literal, Null, Flavor
+from sql.operators import (And, Or, Not, Neg, Pos, Less, Greater, LessEqual,
+    GreaterEqual, Equal, NotEqual, Sub, Mul, Div, Mod, Pow, Abs, LShift,
+    RShift, Like, NotLike, ILike, NotILike, In, NotIn, FloorDiv, Exists)
 
 
 class TestOperators(unittest.TestCase):
     table = Table('t')
 
     def test_and(self):
-        and_ = And((self.table.c1, self.table.c2))
-        self.assertEqual(str(and_), '("c1" AND "c2")')
-        self.assertEqual(and_.params, ())
+        for and_ in [And((self.table.c1, self.table.c2)),
+                self.table.c1 & self.table.c2]:
+            self.assertEqual(str(and_), '("c1" AND "c2")')
+            self.assertEqual(and_.params, ())
 
         and_ = And((Literal(True), self.table.c2))
         self.assertEqual(str(and_), '(%s AND "c2")')
         self.assertEqual(and_.params, (True,))
 
+    def test_operator_operators(self):
+        and_ = And((Literal(True), self.table.c1))
+        and2 = and_ & And((Literal(True), self.table.c2))
+        self.assertEqual(str(and2), '((%s AND "c1") AND %s AND "c2")')
+        self.assertEqual(and2.params, (True, True))
+
+        and3 = and_ & Literal(True)
+        self.assertEqual(str(and3), '((%s AND "c1") AND %s)')
+        self.assertEqual(and3.params, (True, True))
+
+        or_ = Or((Literal(True), self.table.c1))
+        or2 = or_ | Or((Literal(True), self.table.c2))
+        self.assertEqual(str(or2), '((%s OR "c1") OR %s OR "c2")')
+        self.assertEqual(or2.params, (True, True))
+
+        or3 = or_ | Literal(True)
+        self.assertEqual(str(or3), '((%s OR "c1") OR %s)')
+        self.assertEqual(or3.params, (True, True))
+
+    def test_operator_compat_column(self):
+        and_ = And((self.table.c1, self.table.c2))
+        self.assertEqual(and_.table, '')
+        self.assertEqual(and_.name, '')
+
+    def test_or(self):
+        for or_ in [Or((self.table.c1, self.table.c2)),
+                self.table.c1 | self.table.c2]:
+            self.assertEqual(str(or_), '("c1" OR "c2")')
+            self.assertEqual(or_.params, ())
+
     def test_not(self):
-        not_ = Not(self.table.c)
-        self.assertEqual(str(not_), '(NOT "c")')
-        self.assertEqual(not_.params, ())
+        for not_ in [Not(self.table.c), ~self.table.c]:
+            self.assertEqual(str(not_), '(NOT "c")')
+            self.assertEqual(not_.params, ())
 
         not_ = Not(Literal(False))
         self.assertEqual(str(not_), '(NOT %s)')
         self.assertEqual(not_.params, (False,))
 
+    def test_neg(self):
+        for neg in [Neg(self.table.c1), -self.table.c1]:
+            self.assertEqual(str(neg), '(- "c1")')
+            self.assertEqual(neg.params, ())
+
+    def test_pos(self):
+        for pos in [Pos(self.table.c1), +self.table.c1]:
+            self.assertEqual(str(pos), '(+ "c1")')
+            self.assertEqual(pos.params, ())
+
     def test_less(self):
-        less = Less(self.table.c1, self.table.c2)
-        self.assertEqual(str(less), '("c1" < "c2")')
-        self.assertEqual(less.params, ())
+        for less in [Less(self.table.c1, self.table.c2),
+                self.table.c1 < self.table.c2,
+                ~GreaterEqual(self.table.c1, self.table.c2)]:
+            self.assertEqual(str(less), '("c1" < "c2")')
+            self.assertEqual(less.params, ())
 
         less = Less(Literal(0), self.table.c2)
         self.assertEqual(str(less), '(%s < "c2")')
         self.assertEqual(less.params, (0,))
 
+    def test_greater(self):
+        for greater in [Greater(self.table.c1, self.table.c2),
+                self.table.c1 > self.table.c2,
+                ~LessEqual(self.table.c1, self.table.c2)]:
+            self.assertEqual(str(greater), '("c1" > "c2")')
+            self.assertEqual(greater.params, ())
+
+    def test_less_equal(self):
+        for less in [LessEqual(self.table.c1, self.table.c2),
+                self.table.c1 <= self.table.c2,
+                ~Greater(self.table.c1, self.table.c2)]:
+            self.assertEqual(str(less), '("c1" <= "c2")')
+            self.assertEqual(less.params, ())
+
+    def test_greater_equal(self):
+        for greater in [GreaterEqual(self.table.c1, self.table.c2),
+                self.table.c1 >= self.table.c2,
+                ~Less(self.table.c1, self.table.c2)]:
+            self.assertEqual(str(greater), '("c1" >= "c2")')
+            self.assertEqual(greater.params, ())
+
     def test_equal(self):
-        equal = Equal(self.table.c1, self.table.c2)
-        self.assertEqual(str(equal), '("c1" = "c2")')
-        self.assertEqual(equal.params, ())
+        for equal in [Equal(self.table.c1, self.table.c2),
+                self.table.c1 == self.table.c2,
+                ~NotEqual(self.table.c1, self.table.c2)]:
+            self.assertEqual(str(equal), '("c1" = "c2")')
+            self.assertEqual(equal.params, ())
 
         equal = Equal(Literal('foo'), Literal('bar'))
         self.assertEqual(str(equal), '(%s = %s)')
         self.assertEqual(equal.params, ('foo', 'bar'))
 
-        equal = Equal(self.table.c1, None)
+        equal = Equal(self.table.c1, Null)
         self.assertEqual(str(equal), '("c1" IS NULL)')
         self.assertEqual(equal.params, ())
 
-        equal = Equal(Literal('test'), None)
+        equal = Equal(Literal('test'), Null)
         self.assertEqual(str(equal), '(%s IS NULL)')
         self.assertEqual(equal.params, ('test',))
 
-        equal = Equal(None, self.table.c1)
+        equal = Equal(Null, self.table.c1)
         self.assertEqual(str(equal), '("c1" IS NULL)')
         self.assertEqual(equal.params, ())
 
-        equal = Equal(None, Literal('test'))
+        equal = Equal(Null, Literal('test'))
         self.assertEqual(str(equal), '(%s IS NULL)')
         self.assertEqual(equal.params, ('test',))
 
     def test_not_equal(self):
-        equal = NotEqual(self.table.c1, self.table.c2)
-        self.assertEqual(str(equal), '("c1" != "c2")')
-        self.assertEqual(equal.params, ())
+        for equal in [NotEqual(self.table.c1, self.table.c2),
+                self.table.c1 != self.table.c2,
+                ~Equal(self.table.c1, self.table.c2)]:
+            self.assertEqual(str(equal), '("c1" != "c2")')
+            self.assertEqual(equal.params, ())
 
-        equal = NotEqual(self.table.c1, None)
+        equal = NotEqual(self.table.c1, Null)
         self.assertEqual(str(equal), '("c1" IS NOT NULL)')
         self.assertEqual(equal.params, ())
 
-        equal = NotEqual(None, self.table.c1)
+        equal = NotEqual(Null, self.table.c1)
         self.assertEqual(str(equal), '("c1" IS NOT NULL)')
         self.assertEqual(equal.params, ())
 
+    def test_sub(self):
+        for sub in [Sub(self.table.c1, self.table.c2),
+                self.table.c1 - self.table.c2]:
+            self.assertEqual(str(sub), '("c1" - "c2")')
+            self.assertEqual(sub.params, ())
+
+    def test_mul(self):
+        for mul in [Mul(self.table.c1, self.table.c2),
+                self.table.c1 * self.table.c2]:
+            self.assertEqual(str(mul), '("c1" * "c2")')
+            self.assertEqual(mul.params, ())
+
+    def test_div(self):
+        for div in [Div(self.table.c1, self.table.c2),
+                self.table.c1 / self.table.c2]:
+            self.assertEqual(str(div), '("c1" / "c2")')
+            self.assertEqual(div.params, ())
+
+    def test_mod(self):
+        for mod in [Mod(self.table.c1, self.table.c2),
+                self.table.c1 % self.table.c2]:
+            self.assertEqual(str(mod), '("c1" % "c2")')
+            self.assertEqual(mod.params, ())
+
+    def test_pow(self):
+        for pow_ in [Pow(self.table.c1, self.table.c2),
+                self.table.c1 ** self.table.c2]:
+            self.assertEqual(str(pow_), '("c1" ^ "c2")')
+            self.assertEqual(pow_.params, ())
+
+    def test_abs(self):
+        for abs_ in [Abs(self.table.c1), abs(self.table.c1)]:
+            self.assertEqual(str(abs_), '(@ "c1")')
+            self.assertEqual(abs_.params, ())
+
+    def test_lshift(self):
+        for lshift in [LShift(self.table.c1, 2),
+                self.table.c1 << 2]:
+            self.assertEqual(str(lshift), '("c1" << %s)')
+            self.assertEqual(lshift.params, (2,))
+
+    def test_rshift(self):
+        for rshift in [RShift(self.table.c1, 2),
+                self.table.c1 >> 2]:
+            self.assertEqual(str(rshift), '("c1" >> %s)')
+            self.assertEqual(rshift.params, (2,))
+
+    def test_like(self):
+        for like in [Like(self.table.c1, 'foo'),
+                self.table.c1.like('foo'),
+                ~NotLike(self.table.c1, 'foo'),
+                ~~Like(self.table.c1, 'foo')]:
+            self.assertEqual(str(like), '("c1" LIKE %s)')
+            self.assertEqual(like.params, ('foo',))
+
+    def test_ilike(self):
+        flavor = Flavor(ilike=True)
+        Flavor.set(flavor)
+        try:
+            for like in [ILike(self.table.c1, 'foo'),
+                    self.table.c1.ilike('foo'),
+                    ~NotILike(self.table.c1, 'foo')]:
+                self.assertEqual(str(like), '("c1" ILIKE %s)')
+                self.assertEqual(like.params, ('foo',))
+        finally:
+            Flavor.set(Flavor())
+
+        flavor = Flavor(ilike=False)
+        Flavor.set(flavor)
+        try:
+            like = ILike(self.table.c1, 'foo')
+            self.assertEqual(str(like), '("c1" LIKE %s)')
+            self.assertEqual(like.params, ('foo',))
+        finally:
+            Flavor.set(Flavor())
+
+    def test_not_ilike(self):
+        flavor = Flavor(ilike=True)
+        Flavor.set(flavor)
+        try:
+            for like in [NotILike(self.table.c1, 'foo'),
+                    ~self.table.c1.ilike('foo')]:
+                self.assertEqual(str(like), '("c1" NOT ILIKE %s)')
+                self.assertEqual(like.params, ('foo',))
+        finally:
+            Flavor.set(Flavor())
+
+        flavor = Flavor(ilike=False)
+        Flavor.set(flavor)
+        try:
+            like = NotILike(self.table.c1, 'foo')
+            self.assertEqual(str(like), '("c1" NOT LIKE %s)')
+            self.assertEqual(like.params, ('foo',))
+        finally:
+            Flavor.set(Flavor())
+
     def test_in(self):
-        in_ = In(self.table.c1, [self.table.c2, 1, None])
-        self.assertEqual(str(in_), '("c1" IN ("c2", %s, %s))')
-        self.assertEqual(in_.params, (1, None))
+        for in_ in [In(self.table.c1, [self.table.c2, 1, Null]),
+                ~NotIn(self.table.c1, [self.table.c2, 1, Null]),
+                ~~In(self.table.c1, [self.table.c2, 1, Null])]:
+            self.assertEqual(str(in_), '("c1" IN ("c2", %s, %s))')
+            self.assertEqual(in_.params, (1, None))
 
         t2 = Table('t2')
         in_ = In(self.table.c1, t2.select(t2.c2))
@@ -124,6 +292,14 @@ class TestOperators(unittest.TestCase):
             '("c1" IN (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s))')
         self.assertEqual(in_.params, tuple(range(10)))
 
+    def test_exists(self):
+        exists = Exists(self.table.select(self.table.c1,
+                where=self.table.c1 == 1))
+        self.assertEqual(str(exists),
+            '(EXISTS (SELECT "a"."c1" FROM "t" AS "a" '
+            'WHERE ("a"."c1" = %s)))')
+        self.assertEqual(exists.params, (1,))
+
     def test_floordiv(self):
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter("always")
diff --git a/sql/tests/test_select.py b/sql/tests/test_select.py
index 0adadd7..bf8cd26 100644
--- a/sql/tests/test_select.py
+++ b/sql/tests/test_select.py
@@ -29,7 +29,7 @@
 
 import unittest
 
-from sql import Table, Join, Union, Literal, Flavor
+from sql import Table, Join, Union, Literal, Flavor, For
 from sql.functions import Now, Function
 from sql.aggregate import Min
 
@@ -57,6 +57,14 @@ class TestSelect(unittest.TestCase):
             'SELECT * FROM "t" AS "a" WHERE ("a"."c" = %s)')
         self.assertEqual(query.params, ('foo',))
 
+    def test_select_from_list(self):
+        t2 = Table('t2')
+        t3 = Table('t3')
+        query = (self.table + t2 + t3).select(self.table.c, getattr(t2, '*'))
+        self.assertEqual(str(query),
+            'SELECT "a"."c", "b".* FROM "t" AS "a", "t2" AS "b", "t3" AS "c"')
+        self.assertEqual(query.params, ())
+
     def test_select_union(self):
         query1 = self.table.select()
         query2 = Table('t2').select()
@@ -92,6 +100,20 @@ class TestSelect(unittest.TestCase):
             'ORDER BY %s')
         self.assertEqual(union.params, (1,))
 
+    def test_select_intersect(self):
+        query1 = self.table.select()
+        query2 = Table('t2').select()
+        intersect = query1 & query2
+        self.assertEqual(str(intersect),
+            'SELECT * FROM "t" AS "a" INTERSECT SELECT * FROM "t2" AS "b"')
+
+    def test_select_except(self):
+        query1 = self.table.select()
+        query2 = Table('t2').select()
+        except_ = query1 - query2
+        self.assertEqual(str(except_),
+            'SELECT * FROM "t" AS "a" EXCEPT SELECT * FROM "t2" AS "b"')
+
     def test_select_join(self):
         t1 = Table('t1')
         t2 = Table('t2')
@@ -195,3 +217,10 @@ class TestSelect(unittest.TestCase):
             self.assertEqual(query.params, ())
         finally:
             Flavor.set(Flavor())
+
+    def test_select_for(self):
+        c = self.table.c
+        query = self.table.select(c, for_=For('UPDATE'))
+        self.assertEqual(str(query),
+            'SELECT "a"."c" FROM "t" AS "a" FOR UPDATE')
+        self.assertEqual(query.params, ())
diff --git a/sql/tests/test_update.py b/sql/tests/test_update.py
index 3cf1964..63ef2a8 100644
--- a/sql/tests/test_update.py
+++ b/sql/tests/test_update.py
@@ -28,7 +28,7 @@
 
 import unittest
 
-from sql import Table
+from sql import Table, Literal
 
 
 class TestUpdate(unittest.TestCase):
@@ -39,7 +39,7 @@ class TestUpdate(unittest.TestCase):
         self.assertEqual(str(query), 'UPDATE "t" SET "c" = %s')
         self.assertEqual(query.params, ('foo',))
 
-        query.where = (self.table.b == True)
+        query.where = (self.table.b == Literal(True))
         self.assertEqual(str(query),
             'UPDATE "t" SET "c" = %s WHERE ("t"."b" = %s)')
         self.assertEqual(query.params, ('foo', True))
@@ -56,11 +56,13 @@ class TestUpdate(unittest.TestCase):
     def test_update_subselect(self):
         t1 = Table('t1')
         t2 = Table('t2')
-        query = t1.update([t1.c], [t2.select(t2.c, where=t2.i == t1.i)])
-        self.assertEqual(str(query),
-            'UPDATE "t1" SET "c" = ('
-            'SELECT "b"."c" FROM "t2" AS "b" WHERE ("b"."i" = "t1"."i"))')
-        self.assertEqual(query.params, ())
+        query_list = t1.update([t1.c], [t2.select(t2.c, where=t2.i == t1.i)])
+        query_nolist = t1.update([t1.c], t2.select(t2.c, where=t2.i == t1.i))
+        for query in [query_list, query_nolist]:
+            self.assertEqual(str(query),
+                'UPDATE "t1" SET "c" = ('
+                'SELECT "b"."c" FROM "t2" AS "b" WHERE ("b"."i" = "t1"."i"))')
+            self.assertEqual(query.params, ())
 
     def test_update_returning(self):
         query = self.table.update([self.table.c], ['foo'],
-- 
python-sql



More information about the tryton-debian-vcs mailing list