[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