[CalendarServer-changes] [6773] CalendarServer/branches/users/glyph/dal/txdav/base/datastore

source_changes at macosforge.org source_changes at macosforge.org
Wed Jan 19 12:58:44 PST 2011


Revision: 6773
          http://trac.macosforge.org/projects/calendarserver/changeset/6773
Author:   glyph at apple.com
Date:     2011-01-19 12:58:44 -0800 (Wed, 19 Jan 2011)
Log Message:
-----------
">" and "<", "and" and "or".

Modified Paths:
--------------
    CalendarServer/branches/users/glyph/dal/txdav/base/datastore/sqlsyntax.py
    CalendarServer/branches/users/glyph/dal/txdav/base/datastore/test/test_sqlsyntax.py

Modified: CalendarServer/branches/users/glyph/dal/txdav/base/datastore/sqlsyntax.py
===================================================================
--- CalendarServer/branches/users/glyph/dal/txdav/base/datastore/sqlsyntax.py	2011-01-19 20:58:33 UTC (rev 6772)
+++ CalendarServer/branches/users/glyph/dal/txdav/base/datastore/sqlsyntax.py	2011-01-19 20:58:44 UTC (rev 6773)
@@ -15,6 +15,10 @@
 # limitations under the License.
 ##
 
+"""
+Syntax wrappers and generators for SQL.
+"""
+
 from txdav.base.datastore.sqlmodel import Schema, Table, Column
 
 class Syntax(object):
@@ -73,7 +77,15 @@
             yield ColumnSyntax(column)
 
 
+def comparison(comparator):
+    def __(self, other):
+        if isinstance(other, ColumnSyntax):
+            return ColumnComparison(self, comparator, other)
+        else:
+            return ConstantComparison(self, comparator, other)
+    return __
 
+
 class ColumnSyntax(Syntax):
     """
     Syntactic convenience for L{Column}.
@@ -81,11 +93,14 @@
 
     modelType = Column
 
-    def __eq__(self, other):
-        if isinstance(other, ColumnSyntax):
-            return ColumnComparison(self, '=', other)
-        else:
-            return ConstantComparison(self, '=', other)
+    __eq__ = comparison('=')
+    __ne__ = comparison('!=')
+    __gt__ = comparison('>')
+    __ge__ = comparison('>=')
+    __lt__ = comparison('<')
+    __le__ = comparison('<=')
+    __add__ = comparison("+")
+    __sub__ = comparison("-")
 
 
 
@@ -102,21 +117,49 @@
             "column comparisons should not be tested for truth value")
 
 
+    def booleanOp(self, operand, other):
+        return CompoundComparison(self, operand, other)
 
 
+    def And(self, other):
+        return self.booleanOp('and', other)
+
+
+    def Or(self, other):
+        return self.booleanOp('or', other)
+
+
+
 class ConstantComparison(Comparison):
 
     def toSQL(self, placeholder, quote):
-        return (' '.join([self.a.model.name, self.op, placeholder]), [self.b])
+        return SQLStatement(
+            ' '.join([self.a.model.name, self.op, placeholder]), [self.b])
 
 
 
 class ColumnComparison(Comparison):
+
     def toSQL(self, placeholder, quote):
-        return (' '.join([self.a.model.name, self.op, self.b.model.name]), [])
+        return SQLStatement(
+            ' '.join([self.a.model.name, self.op, self.b.model.name]), [])
 
 
+class CompoundComparison(Comparison):
+    """
+    A compound comparison; two or more constraints, joined by an operation
+    (currently only AND or OR).
+    """
 
+    def toSQL(self, placeholder, quote):
+        stmt = SQLStatement()
+        stmt.append(self.a.toSQL(placeholder, quote))
+        stmt.text += ' %s ' % (self.op,)
+        stmt.append(self.b.toSQL(placeholder, quote))
+        return stmt
+
+
+
 class Select(object):
     """
     'select' statement.
@@ -131,11 +174,39 @@
         """
         @return: a 2-tuple of (sql, args).
         """
-        sql = quote("select * from ") + self.From.model.name
-        args = []
+        stmt = SQLStatement(quote("select * from ") + self.From.model.name)
         if self.Where is not None:
-            moreSQL, moreArgs = self.Where.toSQL(placeholder, quote)
-            sql += (quote(" where ") + moreSQL)
-            args.extend(moreArgs)
-        return (sql, args)
+            wherestmt = self.Where.toSQL(placeholder, quote)
+            stmt.text += quote(" where ")
+            stmt.append(wherestmt)
+        return stmt
 
+
+class SQLStatement(object):
+    """
+    Combination of SQL text and arguments; a statement which may be executed
+    against a database.
+    """
+
+    def __init__(self, text="", parameters=None):
+        self.text = text
+        if parameters is None:
+            parameters = []
+        self.parameters = parameters
+
+
+    def append(self, anotherStatement):
+        self.text += anotherStatement.text
+        self.parameters += anotherStatement.parameters
+
+
+    def __eq__(self, stmt):
+        if not isinstance(stmt, SQLStatement):
+            return NotImplemented
+        return (self.text, self.parameters) == (stmt.text, stmt.parameters)
+
+
+    def __ne__(self, stmt):
+        if not isinstance(stmt, SQLStatement):
+            return NotImplemented
+        return not self.__eq__(stmt)

Modified: CalendarServer/branches/users/glyph/dal/txdav/base/datastore/test/test_sqlsyntax.py
===================================================================
--- CalendarServer/branches/users/glyph/dal/txdav/base/datastore/test/test_sqlsyntax.py	2011-01-19 20:58:33 UTC (rev 6772)
+++ CalendarServer/branches/users/glyph/dal/txdav/base/datastore/test/test_sqlsyntax.py	2011-01-19 20:58:44 UTC (rev 6773)
@@ -17,7 +17,7 @@
 
 from txdav.base.datastore.sqlmodel import Schema
 from txdav.base.datastore.sqlparser import addSQLToSchema
-from txdav.base.datastore.sqlsyntax import SchemaSyntax, Select
+from txdav.base.datastore.sqlsyntax import SchemaSyntax, Select, SQLStatement
 
 from twisted.trial.unittest import TestCase
 
@@ -41,7 +41,7 @@
         rows in a table.
         """
         self.assertEquals(Select(From=self.schema.FOO).toSQL(),
-                          ("select * from FOO", []))
+                          SQLStatement("select * from FOO", []))
 
 
     def test_simpleWhereClause(self):
@@ -51,7 +51,7 @@
         """
         self.assertEquals(Select(From=self.schema.FOO,
                                  Where=self.schema.FOO.BAR == 1).toSQL(),
-                          ("select * from FOO where BAR = ?", [1]))
+                          SQLStatement("select * from FOO where BAR = ?", [1]))
 
 
     def test_quotingAndPlaceholder(self):
@@ -63,7 +63,7 @@
                                  Where=self.schema.FOO.BAR == 1).toSQL(
                                  placeholder="*",
                                  quote=lambda partial: partial.replace("*", "**")),
-                          ("select ** from FOO where BAR = *", [1]))
+                          SQLStatement("select ** from FOO where BAR = *", [1]))
 
 
     def test_columnComparison(self):
@@ -73,7 +73,7 @@
         self.assertEquals(Select(From=self.schema.FOO,
                                  Where=self.schema.FOO.BAR ==
                                  self.schema.FOO.BAZ).toSQL(),
-                          ("select * from FOO where BAR = BAZ", []))
+                          SQLStatement("select * from FOO where BAR = BAZ", []))
 
 
     def test_comparisonTestErrorPrevention(self):
@@ -88,3 +88,15 @@
         self.assertRaises(ValueError, sampleComparison)
 
 
+
+    def test_compoundWhere(self):
+        """
+        L{Select.And} and L{Select.Or} will return compound columns.
+        """
+        self.assertEquals(
+            Select(From=self.schema.FOO,
+                   Where=(self.schema.FOO.BAR < 2).Or(
+                          self.schema.FOO.BAR > 5)).toSQL(),
+            SQLStatement("select * from FOO where BAR < ? or BAR > ?", [2, 5]))
+
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110119/7597a77f/attachment-0001.html>


More information about the calendarserver-changes mailing list