[CalendarServer-changes] [9992] CalendarServer/branches/users/gaya/sharedgroups/txdav

source_changes at macosforge.org source_changes at macosforge.org
Fri Oct 26 18:55:12 PDT 2012


Revision: 9992
          http://trac.calendarserver.org//changeset/9992
Author:   gaya at apple.com
Date:     2012-10-26 18:55:12 -0700 (Fri, 26 Oct 2012)
Log Message:
-----------
add 'not null' constraints back to ADDRESSBOOK_OBJECT; initialize all rows, e.g.: VCARD_TEXT, when creating new address books (using ADDRESSBOOK_OBJECT)

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/test_sql.py

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py	2012-10-26 21:24:44 UTC (rev 9991)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/caldav/datastore/sql.py	2012-10-27 01:55:12 UTC (rev 9992)
@@ -674,6 +674,39 @@
         return super(Calendar, self).unshare(ECALENDARTYPE)
 
 
+    @classproperty
+    def _insertHomeChild(cls): #@NoSelf
+        """
+        DAL statement to create a home child with all default values.
+        """
+        child = cls._homeChildSchema
+        return Insert({child.RESOURCE_ID: schema.RESOURCE_ID_SEQ},
+                      Return=(child.RESOURCE_ID))
+
+
+    @classproperty
+    def _insertHomeChildMetaData(cls): #@NoSelf
+        """
+        DAL statement to create a home child with all default values.
+        """
+        child = cls._homeChildMetaDataSchema
+        return Insert({child.RESOURCE_ID: Parameter("resourceID")},
+                      Return=(child.CREATED, child.MODIFIED))
+
+
+    @classmethod
+    @inlineCallbacks
+    def _createChild(cls, home, name):
+        # Create this object
+        resourceID = (
+            yield cls._insertHomeChild.on(home._txn))[0][0]
+
+        created, modified = (
+            yield cls._insertHomeChildMetaData.on(home._txn,
+                                                  resourceID=resourceID))[0]
+        returnValue((resourceID, created, modified))
+
+
 icalfbtype_to_indexfbtype = {
     "UNKNOWN"         : 0,
     "FREE"            : 1,

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2012-10-26 21:24:44 UTC (rev 9991)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2012-10-27 01:55:12 UTC (rev 9992)
@@ -27,7 +27,7 @@
 ]
 
 from twext.enterprise.dal.syntax import \
-    Delete, Insert, Len, Update, Select, utcNowSQL
+    Delete, Insert, Len, Parameter, Update, Select, utcNowSQL
 
 from twext.python.clsprop import classproperty
 from twext.web2.http_headers import MimeType
@@ -54,6 +54,8 @@
     _ABO_KIND_PERSON, _ABO_KIND_GROUP, _ABO_KIND_RESOURCE, _ABO_KIND_LOCATION, schema
 from txdav.xml.rfc2518 import ResourceType
 
+from uuid import uuid4
+
 from zope.interface.declarations import implements
 
 
@@ -207,9 +209,67 @@
         """
         return super(AddressBook, self).unshare(EADDRESSBOOKTYPE)
 
+    @classproperty
+    def _insertHomeChild(cls): #@NoSelf
+        """
+        DAL statement to create a home child with all default values.
+        """
+        child = cls._homeChildSchema
+        return Insert({child.RESOURCE_ID: schema.RESOURCE_ID_SEQ,
+                       child.RESOURCE_NAME: Parameter("name"),
+                       child.VCARD_TEXT: Parameter("text"),
+                       child.VCARD_UID: Parameter("uid"),
+                       child.KIND: _ABO_KIND_GROUP,
+                       child.MD5: Parameter("md5"),
+                       },
+                      Return=(child.RESOURCE_ID))
 
+    @classproperty
+    def _insertHomeChildMetaData(cls): #@NoSelf
+        """
+        DAL statement to create a home child with all default values.
+        """
+        child = cls._homeChildMetaDataSchema
+        return Insert({child.RESOURCE_ID: Parameter("resourceID")},
+                      Return=(child.CREATED, child.MODIFIED))
 
 
+    @classmethod
+    @inlineCallbacks
+    def _createChild(cls, home, name):
+        # Create this object
+        component = VCard.fromString(
+            """BEGIN:VCARD
+VERSION:3.0
+PRODID:-//Apple Inc.//AddressBook 6.1//EN
+UID:%s
+FN:%s
+N:%s;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+END:VCARD
+""".replace("\n", "\r\n") % (uuid4(), name, name)
+            )
+
+        componentText = str(component)
+        md5 = hashlib.md5(componentText).hexdigest()
+
+        resourceID = (
+            yield cls._insertHomeChild.on(home._txn,
+                                          name=name,
+                                          text=componentText,
+                                          uid=component.resourceUID(),
+                                          md5=md5,
+                                          ))[0][0]
+
+        created, modified = (
+            yield cls._insertHomeChildMetaData.on(home._txn,
+                                                  resourceID=resourceID))[0]
+
+        returnValue((resourceID, created, modified))
+
+
+
+
 class AddressBookObject(CommonObjectResource):
 
     implements(IAddressBookObject)
@@ -339,7 +399,7 @@
         # ADDRESSBOOK_OBJECT table update
         uid = component.resourceUID()
         assert inserting or self._uid == uid # can't change UID. Should be checked in upper layers
-        self._uid = component.resourceUID()
+        self._uid = uid
         self._md5 = hashlib.md5(componentText).hexdigest()
         self._size = len(componentText)
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2012-10-26 21:24:44 UTC (rev 9991)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2012-10-27 01:55:12 UTC (rev 9992)
@@ -2776,26 +2776,6 @@
 
 
     @classproperty
-    def _insertHomeChild(cls): #@NoSelf
-        """
-        DAL statement to create a home child with all default values.
-        """
-        child = cls._homeChildSchema
-        return Insert({child.RESOURCE_ID: schema.RESOURCE_ID_SEQ},
-                      Return=(child.RESOURCE_ID))
-
-
-    @classproperty
-    def _insertHomeChildMetaData(cls): #@NoSelf
-        """
-        DAL statement to create a home child with all default values.
-        """
-        child = cls._homeChildMetaDataSchema
-        return Insert({child.RESOURCE_ID: Parameter("resourceID")},
-                      Return=(child.CREATED, child.MODIFIED))
-
-
-    @classproperty
     def _bindInsertQuery(cls, **kw): #@NoSelf
         """
         DAL statement to create a bind entry that connects a collection to its
@@ -2811,7 +2791,6 @@
             bind.MESSAGE: Parameter("message"),
         })
 
-
     @classmethod
     @inlineCallbacks
     def create(cls, home, name):
@@ -2825,15 +2804,8 @@
         if name.startswith("."):
             raise HomeChildNameNotAllowedError(name)
 
-        # Create this object
-        resourceID = (
-            yield cls._insertHomeChild.on(home._txn))[0][0]
+        resourceID, created, modified = yield cls._createChild(home, name)
 
-        # Initialize this object
-        _created, _modified = (
-            yield cls._insertHomeChildMetaData.on(home._txn,
-                                                  resourceID=resourceID))[0]
-
         # Bind table needs entry
         yield cls._bindInsertQuery.on(
             home._txn, homeID=home._resourceID, resourceID=resourceID,
@@ -2843,8 +2815,8 @@
 
         # Initialize other state
         child = cls(home, name, resourceID, _BIND_MODE_OWN, _BIND_STATUS_ACCEPTED)
-        child._created = _created
-        child._modified = _modified
+        child._created = created
+        child._modified = modified
         yield child._loadPropertyStore()
 
         child.properties()[

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2012-10-26 21:24:44 UTC (rev 9991)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2012-10-27 01:55:12 UTC (rev 9992)
@@ -338,19 +338,18 @@
 -- AddressBook Object --
 -----------------------------
 
--- #### TO DO: Add back the non null constraints (removed for quick removal of ADDRESS_BOOK table ####
 
   create table ADDRESSBOOK_OBJECT (
-  RESOURCE_ID             integer      primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
-  ADDRESSBOOK_RESOURCE_ID integer      default null references ADDRESSBOOK_OBJECT on delete cascade,
-  RESOURCE_NAME           varchar(255) default null,
-  VCARD_TEXT              text         default null,
-  VCARD_UID               varchar(255) default null,
-  MD5                     char(32)     default null,
+  RESOURCE_ID             integer      primary key default nextval('RESOURCE_ID_SEQ'),	-- implicit index
+  ADDRESSBOOK_RESOURCE_ID integer      references ADDRESSBOOK_OBJECT on delete cascade,	-- ### could add non-null, but ab woul reference itself
+  RESOURCE_NAME           varchar(255) not null,
+  VCARD_TEXT              text         not null,
+  VCARD_UID               varchar(255) not null,
+  MD5                     char(32)     not null,
   CREATED                 timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   MODIFIED                timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  KIND 			  		  integer      default 1 not null, -- enum OBJECT_KIND -- ### TO DO: remove default 1=group for address book code compatibility.
-
+  KIND 			  		  integer      not null, -- enum OBJECT_KIND 
+  
   unique(ADDRESSBOOK_RESOURCE_ID, RESOURCE_NAME), -- implicit index
   unique(ADDRESSBOOK_RESOURCE_ID, VCARD_UID)      -- implicit index
 );
@@ -359,15 +358,15 @@
 -- AddressBook Object kind --
 -----------------------------
 
-create table ADDRESS_BOOK_OBJECT_KIND (
+create table ADDRESSBOOK_OBJECT_KIND (
   ID          integer     primary key,
   DESCRIPTION varchar(16) not null unique
 );
 
-insert into ADDRESS_BOOK_OBJECT_KIND values (0, 'person');
-insert into ADDRESS_BOOK_OBJECT_KIND values (1, 'group' );
-insert into ADDRESS_BOOK_OBJECT_KIND values (2, 'resource');
-insert into ADDRESS_BOOK_OBJECT_KIND values (3, 'location');
+insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
+insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
+insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
+insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
 
 ---------------------------------
 -- Address Book Object Members --

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py	2012-10-26 21:24:44 UTC (rev 9991)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py	2012-10-27 01:55:12 UTC (rev 9992)
@@ -177,8 +177,8 @@
 
 
 _addressBookObjectKind = _schemaConstants(
-    schema.ADDRESS_BOOK_OBJECT_KIND.DESCRIPTION,
-    schema.ADDRESS_BOOK_OBJECT_KIND.ID
+    schema.ADDRESSBOOK_OBJECT_KIND.DESCRIPTION,
+    schema.ADDRESSBOOK_OBJECT_KIND.ID
 )
 
 _ABO_KIND_PERSON = _addressBookObjectKind('person')

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/test_sql.py	2012-10-26 21:24:44 UTC (rev 9991)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/test_sql.py	2012-10-27 01:55:12 UTC (rev 9992)
@@ -18,22 +18,22 @@
 Tests for L{txdav.common.datastore.sql}.
 """
 
-from twext.enterprise.dal.syntax import Select
-from txdav.xml import element as davxml
+from twext.enterprise.dal.syntax import Insert, Select
 
-from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
 from twisted.internet.task import Clock
+
 from twisted.trial.unittest import TestCase
-from twisted.internet.defer import Deferred
 
-from txdav.common.datastore.sql import log, CommonStoreTransactionMonitor,\
-    CommonHome, CommonHomeChild, ECALENDARTYPE
-from txdav.common.datastore.sql_tables import schema, CALENDAR_BIND_TABLE,\
-    CALENDAR_OBJECT_REVISIONS_TABLE
+from txdav.caldav.datastore.sql import Calendar
+from txdav.carddav.datastore.sql import AddressBook
+from txdav.common.datastore.sql import fixUUIDNormalization, log, \
+    CommonStoreTransactionMonitor, ECALENDARTYPE, EADDRESSBOOKTYPE
+from txdav.common.datastore.sql_tables import schema
+
 from txdav.common.datastore.test.util import CommonCommonTests, buildStore
+
 from txdav.common.icommondatastore import AllRetriesFailed
-from twext.enterprise.dal.syntax import Insert
-from txdav.common.datastore.sql import fixUUIDNormalization
 
 class CommonSQLStoreTests(CommonCommonTests, TestCase):
     """
@@ -61,7 +61,7 @@
         """
         txn.execSQL works with all logging options on.
         """
-        
+
         # Patch config to turn on logging then rebuild the store
         self.patch(self._sqlStore, "logLabels", True)
         self.patch(self._sqlStore, "logStats", True)
@@ -70,7 +70,7 @@
         txn = self.transactionUnderTest()
         cs = schema.CALENDARSERVER
         version = (yield Select(
-                [cs.VALUE,],
+                [cs.VALUE, ],
                 From=cs,
                 Where=cs.NAME == 'VERSION',
             ).on(txn))
@@ -82,20 +82,20 @@
         """
         CommonStoreTransactionMonitor logs waiting transactions.
         """
-        
+
         c = Clock()
         self.patch(CommonStoreTransactionMonitor, "callLater", c.callLater)
 
         # Patch config to turn on log waits then rebuild the store
         self.patch(self._sqlStore, "logTransactionWaits", 1)
-        
+
         ctr = [0]
         def counter(_ignore):
             ctr[0] += 1
         self.patch(log, "error", counter)
 
-        txn = self.transactionUnderTest()        
- 
+        txn = self.transactionUnderTest()
+
         c.advance(2)
         self.assertNotEqual(ctr[0], 0)
         txn.abort()
@@ -105,13 +105,13 @@
         """
         CommonStoreTransactionMonitor terminates long transactions.
         """
-        
+
         c = Clock()
         self.patch(CommonStoreTransactionMonitor, "callLater", c.callLater)
 
         # Patch config to turn on transaction timeouts then rebuild the store
         self.patch(self._sqlStore, "timeoutTransactions", 1)
-        
+
         ctr = [0]
         def counter(_ignore):
             ctr[0] += 1
@@ -128,14 +128,14 @@
         """
         CommonStoreTransactionMonitor logs waiting transactions and terminates long transactions.
         """
-        
+
         c = Clock()
         self.patch(CommonStoreTransactionMonitor, "callLater", c.callLater)
 
         # Patch config to turn on log waits then rebuild the store
         self.patch(self._sqlStore, "logTransactionWaits", 1)
         self.patch(self._sqlStore, "timeoutTransactions", 2)
-        
+
         ctr = [0, 0]
         def counter(logStr):
             if "wait" in logStr:
@@ -145,7 +145,7 @@
         self.patch(log, "error", counter)
 
         txn = self.transactionUnderTest()
-        
+
         c.advance(2)
         self.assertNotEqual(ctr[0], 0)
         self.assertNotEqual(ctr[1], 0)
@@ -156,7 +156,7 @@
         """
         txn.subtransaction runs loop once.
         """
-        
+
         txn = self.transactionUnderTest()
         ctr = [0]
 
@@ -164,11 +164,11 @@
             ctr[0] += 1
             cs = schema.CALENDARSERVER
             return Select(
-                [cs.VALUE,],
+                [cs.VALUE, ],
                 From=cs,
                 Where=cs.NAME == 'VERSION',
             ).on(subtxn)
-            
+
         (yield txn.subtransaction(_test, retries=0))[0][0]
         self.assertEqual(ctr[0], 1)
 
@@ -178,7 +178,7 @@
         """
         txn.subtransaction runs loop twice when one failure.
         """
-        
+
         txn = self.transactionUnderTest()
         ctr = [0]
 
@@ -188,11 +188,11 @@
                 raise ValueError
             cs = schema.CALENDARSERVER
             return Select(
-                [cs.VALUE,],
+                [cs.VALUE, ],
                 From=cs,
                 Where=cs.NAME == 'VERSION',
             ).on(subtxn)
-            
+
         (yield txn.subtransaction(_test, retries=1))[0][0]
         self.assertEqual(ctr[0], 2)
 
@@ -202,7 +202,7 @@
         """
         txn.subtransaction runs loop once when one failure and no retries.
         """
-        
+
         txn = self.transactionUnderTest()
         ctr = [0]
 
@@ -211,11 +211,11 @@
             raise ValueError
             cs = schema.CALENDARSERVER
             return Select(
-                [cs.VALUE,],
+                [cs.VALUE, ],
                 From=cs,
                 Where=cs.NAME == 'VERSION',
             ).on(subtxn)
-        
+
         try:
             (yield txn.subtransaction(_test, retries=0))[0][0]
         except AllRetriesFailed:
@@ -231,7 +231,7 @@
         txn.subtransaction runs loop three times when all fail and two retries
         requested.
         """
-        
+
         txn = self.transactionUnderTest()
         ctr = [0]
 
@@ -240,11 +240,11 @@
             raise ValueError
             cs = schema.CALENDARSERVER
             return Select(
-                [cs.VALUE,],
+                [cs.VALUE, ],
                 From=cs,
                 Where=cs.NAME == 'VERSION',
             ).on(subtxn)
-        
+
         try:
             (yield txn.subtransaction(_test, retries=2))[0][0]
         except AllRetriesFailed:
@@ -282,30 +282,15 @@
 
 
     @inlineCallbacks
-    def test_changeRevision(self):
+    def test_calendarChangeRevision(self):
         """
-        CommonHomeChild._changeRevision actions.
+        Calendar._changeRevision actions.
         """
-        
-        class TestCommonHome(CommonHome):
-            _bindTable = CALENDAR_BIND_TABLE
-            _revisionsTable = CALENDAR_OBJECT_REVISIONS_TABLE
-    
-        class TestCommonHomeChild(CommonHomeChild):
-            _homeChildSchema = schema.CALENDAR
-            _homeChildMetaDataSchema = schema.CALENDAR_METADATA
-            _bindSchema = schema.CALENDAR_BIND
-            _revisionsSchema = schema.CALENDAR_OBJECT_REVISIONS
-            _bindTable = CALENDAR_BIND_TABLE
-            _revisionsTable = CALENDAR_OBJECT_REVISIONS_TABLE
-            
-            def resourceType(self):
-                return davxml.ResourceType.calendar
-    
+
         txn = self.transactionUnderTest()
         home = yield txn.homeWithUID(ECALENDARTYPE, "uid", create=True)
-        homeChild = yield TestCommonHomeChild.create(home, "B")
-        
+        homeChild = yield Calendar.create(home, "B")
+
         # insert test
         token = yield homeChild.syncToken()
         yield homeChild._changeRevision("insert", "C")
@@ -340,6 +325,49 @@
 
 
     @inlineCallbacks
+    def test_addressbookChangeRevision(self):
+        """
+        AddressBook._changeRevision actions.
+        """
+
+        txn = self.transactionUnderTest()
+        home = yield txn.homeWithUID(EADDRESSBOOKTYPE, "uid", create=True)
+        homeChild = yield AddressBook.create(home, "B")
+
+        # insert test
+        token = yield homeChild.syncToken()
+        yield homeChild._changeRevision("insert", "C")
+        changed = yield homeChild.resourceNamesSinceToken(token)
+        self.assertEqual(changed, (["C"], [],))
+
+        # update test
+        token = yield homeChild.syncToken()
+        yield homeChild._changeRevision("update", "C")
+        changed = yield homeChild.resourceNamesSinceToken(token)
+        self.assertEqual(changed, (["C"], [],))
+
+        # delete test
+        token = yield homeChild.syncToken()
+        yield homeChild._changeRevision("delete", "C")
+        changed = yield homeChild.resourceNamesSinceToken(token)
+        self.assertEqual(changed, ([], ["C"],))
+
+        # missing update test
+        token = yield homeChild.syncToken()
+        yield homeChild._changeRevision("update", "D")
+        changed = yield homeChild.resourceNamesSinceToken(token)
+        self.assertEqual(changed, (["D"], [],))
+
+        # missing delete test
+        token = yield homeChild.syncToken()
+        yield homeChild._changeRevision("delete", "E")
+        changed = yield homeChild.resourceNamesSinceToken(token)
+        self.assertEqual(changed, ([], [],))
+
+        yield txn.abort()
+
+
+    @inlineCallbacks
     def test_normalizeColumnUUIDs(self):
         """
         L{_normalizeColumnUUIDs} upper-cases only UUIDs in a given column.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121026/c252b9f9/attachment-0001.html>


More information about the calendarserver-changes mailing list