[CalendarServer-changes] [6382] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Tue Sep 28 13:31:07 PDT 2010
Revision: 6382
http://trac.macosforge.org/projects/calendarserver/changeset/6382
Author: cdaboo at apple.com
Date: 2010-09-28 13:31:05 -0700 (Tue, 28 Sep 2010)
Log Message:
-----------
Depth:infinity sync support (missing notification collection right now).
Modified Paths:
--------------
CalendarServer/trunk/twext/web2/dav/resource.py
CalendarServer/trunk/twistedcaldav/index.py
CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/storebridge.py
CalendarServer/trunk/twistedcaldav/test/test_index.py
CalendarServer/trunk/twistedcaldav/test/test_vcardindex.py
CalendarServer/trunk/twistedcaldav/vcardindex.py
CalendarServer/trunk/txdav/caldav/datastore/sql.py
CalendarServer/trunk/txdav/carddav/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql
CalendarServer/trunk/txdav/common/datastore/sql_tables.py
CalendarServer/trunk/txdav/common/datastore/test/util.py
Modified: CalendarServer/trunk/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/resource.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twext/web2/dav/resource.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -717,6 +717,12 @@
returnValue(None)
# First find all depth 1 children
+ names1= []
+ namesDeep = []
+ if names:
+ for name in names:
+ (names1 if name.rstrip("/").find("/") == -1 else namesDeep).append(name.rstrip("/"))
+
#children = []
#yield self.findChildren("1", request, lambda x, y: children.append((x, y)), privileges=None, inherited_aces=None)
@@ -724,7 +730,7 @@
basepath = request.urlForResource(self)
childnames = list(self.listChildren())
for childname in childnames:
- if names and childname not in names:
+ if names1 and childname not in names1:
continue
childpath = joinURL(basepath, urllib.quote(childname))
child = (yield request.locateChildResource(self, childname))
@@ -766,17 +772,24 @@
for resource, url in items[2]:
badcallback(resource, url)
- # TODO: Depth: infinity support
if depth == "infinity":
+ # Split names into child collection groups
+ child_collections = {}
+ for name in namesDeep:
+ collection, name = name.split("/", 1)
+ child_collections.setdefault(collection, []).append(name)
+
for collection, url in allowed_collections:
- collection_inherited_aces = (
- yield collection.inheritedACEsforChildren(request)
- )
- yield collection.findChildrenFaster(
- depth, request, okcallback, badcallback,
- names, privileges,
- inherited_aces=collection_inherited_aces
- )
+ collection_name = collection.name()
+ if collection_name in child_collections:
+ collection_inherited_aces = (
+ yield collection.inheritedACEsforChildren(request)
+ )
+ yield collection.findChildrenFaster(
+ depth, request, okcallback, badcallback,
+ child_collections[collection_name], privileges,
+ inherited_aces=collection_inherited_aces
+ )
returnValue(None)
Modified: CalendarServer/trunk/twistedcaldav/index.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/index.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/index.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -277,7 +277,7 @@
self.log_info("Search falls outside range of index for %s %s" % (name, minDate))
self.reExpandResource(name, minDate)
- def whatchanged(self, revision):
+ def whatchanged(self, revision, depth):
results = [(name.encode("utf-8"), deleted) for name, deleted in self._db_execute("select NAME, DELETED from REVISIONS where REVISION > :1", revision)]
results.sort(key=lambda x:x[1])
Modified: CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -29,11 +29,12 @@
from twext.web2 import responsecode
from twext.web2.dav import davxml
from twext.web2.dav.element.base import WebDAVElement
+from twext.web2.dav.element.extensions import SyncCollection
from twext.web2.dav.http import MultiStatusResponse, statusForFailure
from twext.web2.dav.method.prop_common import responseForHref
from twext.web2.dav.method.propfind import propertyName
from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError
+from twext.web2.http import HTTPError, StatusResponse
from twistedcaldav.config import config
@@ -46,16 +47,19 @@
"""
Generate a sync-collection REPORT.
"""
- if not config.EnableSyncReport or (
- not self.isPseudoCalendarCollection() and
- not self.isAddressBookCollection() and
- not self.isNotificationCollection()
- ):
+
+ # These resource support the report
+ if not config.EnableSyncReport or davxml.Report(SyncCollection(),) not in self.supportedReports():
log.err("sync-collection report is only allowed on calendar/inbox/addressbook/notification collection resources %s" % (self,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, davxml.SupportedReport()))
responses = []
+ depth = request.headers.getHeader("depth", None)
+ if depth not in ("1", "infinity"):
+ log.err("sync-collection report with invalid depth header: %s" % (depth,))
+ raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Invalid Depth header value"))
+
propertyreq = sync_collection.property.children if sync_collection.property else None
@inlineCallbacks
@@ -102,14 +106,14 @@
# the child resource loop and supply those to the checkPrivileges on each child.
filteredaces = (yield self.inheritedACEsforChildren(request))
- changed, removed, newtoken = self.whatchanged(sync_collection.sync_token)
+ changed, removed, newtoken = self.whatchanged(sync_collection.sync_token, depth)
# Now determine which valid resources are readable and which are not
ok_resources = []
forbidden_resources = []
if changed:
yield self.findChildrenFaster(
- "1",
+ depth,
request,
lambda x, y: ok_resources.append((x, y)),
lambda x, y: forbidden_resources.append((x, y)),
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -371,7 +371,7 @@
customxml.PubSubXMPPPushKeyProperty.qname(),
)
- if config.EnableSyncReport and (self.isPseudoCalendarCollection() or self.isAddressBookCollection()):
+ if config.EnableSyncReport and (davxml.Report(SyncCollection(),) in self.supportedReports()):
baseProperties += (davxml.SyncToken.qname(),)
if config.EnableAddMember and (self.isCalendarCollection() or self.isAddressBookCollection()):
@@ -540,7 +540,7 @@
returnValue(customxml.GETCTag.fromString(self.getSyncToken()))
elif qname == davxml.SyncToken.qname() and config.EnableSyncReport and (
- self.isPseudoCalendarCollection() or self.isAddressBookCollection()
+ davxml.Report(SyncCollection(),) in self.supportedReports()
):
returnValue(davxml.SyncToken.fromString(self.getSyncToken()))
@@ -1320,7 +1320,7 @@
# Collection sync stuff
- def whatchanged(self, client_token):
+ def whatchanged(self, client_token, depth):
current_token = self.getSyncToken()
current_uuid, current_revision = current_token.split("#", 1)
@@ -1342,14 +1342,15 @@
revision = 0
try:
- changed, removed = self._indexWhatChanged(revision)
+ changed, removed = self._indexWhatChanged(revision, depth)
except SyncTokenValidException:
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (dav_namespace, "valid-sync-token")))
return changed, removed, current_token
- def _indexWhatChanged(self, revision):
- return self.index().whatchanged(revision)
+ def _indexWhatChanged(self, revision, depth):
+ # Now handled directly by newstore
+ raise NotImplementedError
def getSyncToken(self):
"""
@@ -2181,6 +2182,21 @@
"""
return config.UserQuota if config.UserQuota != 0 else None
+ def supportedReports(self):
+ result = super(CommonHomeResource, self).supportedReports()
+ if config.EnableSyncReport:
+ # Allowed on any home
+ result.append(davxml.Report(SyncCollection(),))
+ return result
+
+ def _indexWhatChanged(self, revision, depth):
+ # The newstore implementation supports this directly
+ return self._newStoreHome.resourceNamesSinceToken(revision, depth)
+
+ def getSyncToken(self):
+ # The newstore implementation supports this directly
+ return self._newStoreHome.syncToken()
+
def canShare(self):
raise NotImplementedError
@@ -2633,6 +2649,9 @@
# Utilities
##
+def isCalendarHomeCollectionResource(resource):
+ return isinstance(resource, CalendarHomeResource)
+
def isCalendarCollectionResource(resource):
try:
resource = ICalDAVResource(resource)
@@ -2649,6 +2668,9 @@
else:
return resource.isPseudoCalendarCollection()
+def isAddressBookHomeCollectionResource(resource):
+ return isinstance(resource, AddressBookHomeResource)
+
def isAddressBookCollectionResource(resource):
try:
resource = ICalDAVResource(resource)
Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -241,6 +241,10 @@
return True
+ def _indexWhatChanged(self, revision, depth):
+ # The newstore implementation supports this directly
+ return self._newStoreCalendar.resourceNamesSinceToken(revision)
+
@classmethod
def transform(cls, self, calendar, home):
"""
@@ -1257,6 +1261,10 @@
return True
+ def _indexWhatChanged(self, revision, depth):
+ # The newstore implementation supports this directly
+ return self._newStoreAddressBook.resourceNamesSinceToken(revision)
+
@classmethod
def transform(cls, self, addressbook, home):
"""
@@ -1840,7 +1848,7 @@
def getSyncToken(self):
return self._newStoreNotifications.syncToken()
- def _indexWhatChanged(self, revision):
+ def _indexWhatChanged(self, revision, depth):
return self._newStoreNotifications.resourceNamesSinceToken(revision)
def addNotification(self, request, uid, xmltype, xmldata):
Modified: CalendarServer/trunk/twistedcaldav/test/test_index.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_index.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/test/test_index.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -920,7 +920,8 @@
)
for revision, results in tests:
- self.assertEquals(self.db.whatchanged(revision), results, "Mismatched results for whatchanged with revision %d" % (revision,))
+ for depth in ("1", "infinity"):
+ self.assertEquals(self.db.whatchanged(revision, depth), results, "Mismatched results for whatchanged with revision %d" % (revision,))
class MemcacheTests(SQLIndexTests):
def setUp(self):
Modified: CalendarServer/trunk/twistedcaldav/test/test_vcardindex.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_vcardindex.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/test/test_vcardindex.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -194,7 +194,8 @@
)
for revision, results in tests:
- self.assertEquals(self.db.whatchanged(revision), results, "Mismatched results for whatchanged with revision %d" % (revision,))
+ for depth in ("1", "infinity"):
+ self.assertEquals(self.db.whatchanged(revision, depth), results, "Mismatched results for whatchanged with revision %d" % (revision,))
class MemcacheTests(SQLIndexTests):
def setUp(self):
Modified: CalendarServer/trunk/twistedcaldav/vcardindex.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/vcardindex.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/twistedcaldav/vcardindex.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -385,7 +385,7 @@
results = self._db_values_for_sql(statement, *names)
return results
- def whatchanged(self, revision):
+ def whatchanged(self, revision, depth):
results = [(name.encode("utf-8"), deleted) for name, deleted in self._db_execute("select NAME, DELETED from REVISIONS where REVISION > :1", revision)]
results.sort(key=lambda x:x[1])
Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -62,13 +62,15 @@
implements(ICalendarHome)
def __init__(self, transaction, ownerUID, resourceID, notifier):
- super(CalendarHome, self).__init__(transaction, ownerUID, resourceID, notifier)
- self._shares = SQLLegacyCalendarShares(self)
self._childClass = Calendar
self._childTable = CALENDAR_TABLE
self._bindTable = CALENDAR_BIND_TABLE
+ self._revisionsTable = CALENDAR_OBJECT_REVISIONS_TABLE
+ super(CalendarHome, self).__init__(transaction, ownerUID, resourceID, notifier)
+ self._shares = SQLLegacyCalendarShares(self)
+
createCalendarWithName = CommonHome.createChildWithName
removeCalendarWithName = CommonHome.removeChildWithName
calendarWithName = CommonHome.childWithName
Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -49,13 +49,15 @@
implements(IAddressBookHome)
def __init__(self, transaction, ownerUID, resourceID, notifier):
- super(AddressBookHome, self).__init__(transaction, ownerUID, resourceID, notifier)
- self._shares = SQLLegacyAddressBookShares(self)
self._childClass = AddressBook
self._childTable = ADDRESSBOOK_TABLE
self._bindTable = ADDRESSBOOK_BIND_TABLE
+ self._revisionsTable = ADDRESSBOOK_OBJECT_REVISIONS_TABLE
+ super(AddressBookHome, self).__init__(transaction, ownerUID, resourceID, notifier)
+ self._shares = SQLLegacyAddressBookShares(self)
+
addressbooks = CommonHome.children
listAddressbooks = CommonHome.listChildren
addressbookWithName = CommonHome.childWithName
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -290,6 +290,8 @@
_childClass = None
_childTable = None
_bindTable = None
+ _revisionsTable = None
+ _notificationRevisionsTable = NOTIFICATION_OBJECT_REVISIONS_TABLE
def __init__(self, transaction, ownerUID, resourceID, notifier):
self._txn = transaction
@@ -299,6 +301,12 @@
self._children = {}
self._notifier = notifier
+ # Needed for REVISION/BIND table join
+ self._revisionBindJoinTable = {}
+ for key, value in self._revisionsTable.iteritems():
+ self._revisionBindJoinTable["REV:%s" % (key,)] = value
+ for key, value in self._bindTable.iteritems():
+ self._revisionBindJoinTable["BIND:%s" % (key,)] = value
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
@@ -432,6 +440,7 @@
child = self.childWithName(name)
if not child:
raise NoSuchHomeChildError()
+ child._deletedSyncToken()
self._txn.execSQL(
"delete from %(name)s where %(column_RESOURCE_ID)s = %%s" % self._childTable,
@@ -444,6 +453,52 @@
child.notifyChanged()
+ def syncToken(self):
+ revision = self._txn.execSQL(
+ """
+ select max(%(column_REVISION)s) from %(name)s
+ where %(column_HOME_RESOURCE_ID)s = %%s
+ """ % self._revisionsTable,
+ [self._resourceID,]
+ )[0][0]
+ return "%s#%s" % (self._resourceID, revision)
+
+ def resourceNamesSinceToken(self, token, depth):
+ results = [
+ (
+ path.encode("utf-8") if path else (collection.encode("utf-8") if collection else ""),
+ name.encode("utf-8") if name else "",
+ deleted
+ )
+ for path, collection, name, deleted in
+ self._txn.execSQL("""
+ select %(BIND:column_RESOURCE_NAME)s, %(REV:column_COLLECTION_NAME)s, %(REV:column_RESOURCE_NAME)s, %(REV:column_DELETED)s
+ from %(REV:name)s
+ left outer join %(BIND:name)s on (%(REV:name)s.%(REV:column_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s)
+ where %(REV:column_REVISION)s > %%s and %(REV:name)s.%(REV:column_HOME_RESOURCE_ID)s = %%s
+ """ % self._revisionBindJoinTable,
+ [token, self._resourceID],
+ )
+ ]
+
+ deleted = []
+ deleted_collections = set()
+ for path, name, wasdeleted in results:
+ if wasdeleted:
+ if token:
+ deleted.append("%s/%s" % (path, name,))
+ if not name:
+ deleted_collections.add(path)
+
+ changed = []
+ for path, name, wasdeleted in results:
+ if path not in deleted_collections:
+ changed.append("%s/%s" % (path, name,))
+
+ changed.sort()
+ deleted.sort()
+ return changed, deleted,
+
@cached
def properties(self):
return PropertyStore(
@@ -550,7 +605,7 @@
# update memos
del self._home._children[oldName]
self._home._children[name] = self
- self._updateSyncToken()
+ self._renameSyncToken()
self.notifyChanged()
@@ -654,22 +709,13 @@
self.notifyChanged()
- def _initSyncToken(self):
- self._txn.execSQL("""
- insert into %(name)s
- (%(column_HOME_RESOURCE_ID)s, %(column_RESOURCE_ID)s, %(column_RESOURCE_NAME)s, %(column_REVISION)s, %(column_DELETED)s)
- values (%%s, %%s, %%s, nextval('%(sequence)s'), FALSE)
- """ % self._revisionsTable,
- [self._home._resourceID, self._resourceID, ""]
- )
-
def syncToken(self):
revision = self._txn.execSQL(
"""
select %(column_REVISION)s from %(name)s
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [self._resourceID, ""]
+ [self._resourceID,]
)[0][0]
return "%s#%s" % (self._resourceID, revision,)
@@ -678,11 +724,11 @@
def resourceNamesSinceToken(self, token):
results = [
- (name.encode("utf-8"), deleted)
+ (name.encode("utf-8") if name else "", deleted)
for name, deleted in
self._txn.execSQL("""
select %(column_RESOURCE_NAME)s, %(column_DELETED)s from %(name)s
- where %(column_REVISION)s > %s and %(column_RESOURCE_ID)s = %s
+ where %(column_REVISION)s > %%s and %(column_RESOURCE_ID)s = %%s
""" % self._revisionsTable,
[token, self._resourceID],
)
@@ -701,16 +747,65 @@
return changed, deleted,
+ def _initSyncToken(self):
+
+ # Remove any deleted revision entry that uses the same name
+ self._txn.execSQL("""
+ delete from %(name)s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_COLLECTION_NAME)s = %%s
+ """ % self._revisionsTable,
+ [self._home._resourceID, self._name]
+ )
+
+ # Insert new entry
+ self._txn.execSQL("""
+ insert into %(name)s
+ (%(column_HOME_RESOURCE_ID)s, %(column_RESOURCE_ID)s, %(column_COLLECTION_NAME)s, %(column_RESOURCE_NAME)s, %(column_REVISION)s, %(column_DELETED)s)
+ values (%%s, %%s, %%s, null, nextval('%(sequence)s'), FALSE)
+ """ % self._revisionsTable,
+ [self._home._resourceID, self._resourceID, self._name]
+ )
+
def _updateSyncToken(self):
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (nextval('%(sequence)s'))
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [self._resourceID, ""]
+ [self._resourceID,]
)
+ def _renameSyncToken(self):
+
+ self._txn.execSQL("""
+ update %(name)s
+ set (%(column_REVISION)s, %(column_COLLECTION_NAME)s) = (nextval('%(sequence)s'), %%s)
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ """ % self._revisionsTable,
+ [self._name, self._resourceID,]
+ )
+
+ def _deletedSyncToken(self):
+
+ # Remove all child entries
+ self._txn.execSQL("""
+ delete from %(name)s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_ID)s = %%s and %(column_COLLECTION_NAME)s is null
+ """ % self._revisionsTable,
+ [self._home._resourceID, self._resourceID,]
+ )
+
+ # Then adjust collection entry to deleted state
+ self._txn.execSQL("""
+ update %(name)s
+ set (%(column_RESOURCE_ID)s, %(column_REVISION)s, %(column_DELETED)s)
+ = (null, nextval('%(sequence)s'), TRUE)
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ """ % self._revisionsTable,
+ [self._resourceID,]
+ )
+
def _insertRevision(self, name):
self._changeRevision("insert", name)
@@ -738,9 +833,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (%%s)
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [nextrevision, self._resourceID, ""]
+ [nextrevision, self._resourceID,]
)
elif action == "update":
self._txn.execSQL("""
@@ -753,9 +848,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (%%s)
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [nextrevision, self._resourceID, ""]
+ [nextrevision, self._resourceID,]
)
elif action == "insert":
# Note that an "insert" may happen for a resource that previously existed and then
@@ -788,9 +883,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (%%s)
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [nextrevision, self._resourceID, ""]
+ [nextrevision, self._resourceID,]
)
@cached
@@ -1050,18 +1145,18 @@
self._txn.execSQL("""
insert into %(name)s
(%(column_HOME_RESOURCE_ID)s, %(column_RESOURCE_NAME)s, %(column_REVISION)s, %(column_DELETED)s)
- values (%%s, %%s, nextval('%(sequence)s'), FALSE)
+ values (%%s, null, nextval('%(sequence)s'), FALSE)
""" % self._revisionsTable,
- [self._resourceID, ""]
+ [self._resourceID,]
)
def syncToken(self):
revision = self._txn.execSQL(
"""
select %(column_REVISION)s from %(name)s
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [self._resourceID, ""]
+ [self._resourceID,]
)[0][0]
return "%s#%s" % (self._resourceID, revision,)
@@ -1078,7 +1173,7 @@
def resourceNamesSinceToken(self, token):
results = [
- (name.encode("utf-8"), deleted)
+ (name.encode("utf-8") if name else "", deleted)
for name, deleted in
self._txn.execSQL("""
select %(column_RESOURCE_NAME)s, %(column_DELETED)s from %(name)s
@@ -1106,9 +1201,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (nextval('%(sequence)s'))
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [self._resourceID, ""]
+ [self._resourceID,]
)
def _insertRevision(self, name):
@@ -1138,9 +1233,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (%%s)
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [nextrevision, self._resourceID, ""]
+ [nextrevision, self._resourceID]
)
elif action == "update":
self._txn.execSQL("""
@@ -1153,9 +1248,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (%%s)
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [nextrevision, self._resourceID, ""]
+ [nextrevision, self._resourceID]
)
elif action == "insert":
# Note that an "insert" may happen for a resource that previously existed and then
@@ -1188,9 +1283,9 @@
self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (%%s)
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s = %%s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
""" % self._revisionsTable,
- [nextrevision, self._resourceID, ""]
+ [nextrevision, self._resourceID]
)
@cached
Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -906,31 +906,6 @@
self.log_info("Search falls outside range of index for %s %s" % (name, minDate))
self.reExpandResource(name, minDate)
- def whatchanged(self, revision):
-
- results = [
- (name.encode("utf-8"), deleted)
- for name, deleted in
- self._txn.execSQL(
- """select RESOURCE_NAME, DELETED from CALENDAR_OBJECT_REVISIONS
- where REVISION > %s and CALENDAR_RESOURCE_ID = %s""",
- [revision, self.calendar._resourceID],
- )
- ]
- results.sort(key=lambda x:x[1])
-
- changed = []
- deleted = []
- for name, wasdeleted in results:
- if name:
- if wasdeleted:
- if revision:
- deleted.append(name)
- else:
- changed.append(name)
-
- return changed, deleted,
-
def indexedSearch(self, filter, useruid='', fbtype=False):
"""
Finds resources matching the given qualifiers.
@@ -1153,31 +1128,6 @@
return obj.name()
- def whatchanged(self, revision):
-
- results = [
- (name.encode("utf-8"), deleted)
- for name, deleted in
- self._txn.execSQL(
- """select RESOURCE_NAME, DELETED from ADDRESSBOOK_OBJECT_REVISIONS
- where REVISION > %s and ADDRESSBOOK_RESOURCE_ID = %s""",
- [revision, self.addressbook._resourceID],
- )
- ]
- results.sort(key=lambda x:x[1])
-
- changed = []
- deleted = []
- for name, wasdeleted in results:
- if name:
- if wasdeleted:
- if revision:
- deleted.append(name)
- else:
- changed.append(name)
-
- return changed, deleted,
-
def searchValid(self, filter):
if isinstance(filter, carddavxml.Filter):
qualifiers = addressbookquery.sqladdressbookquery(filter)
Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql 2010-09-28 20:31:05 UTC (rev 6382)
@@ -312,8 +312,9 @@
create table CALENDAR_OBJECT_REVISIONS (
CALENDAR_HOME_RESOURCE_ID integer not null references CALENDAR_HOME,
- CALENDAR_RESOURCE_ID integer not null references CALENDAR on delete cascade,
- RESOURCE_NAME varchar(255) not null,
+ CALENDAR_RESOURCE_ID integer references CALENDAR,
+ CALENDAR_NAME varchar(255) default null,
+ RESOURCE_NAME varchar(255),
REVISION integer not null,
DELETED boolean not null,
@@ -327,8 +328,9 @@
create table ADDRESSBOOK_OBJECT_REVISIONS (
ADDRESSBOOK_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME,
- ADDRESSBOOK_RESOURCE_ID integer not null references ADDRESSBOOK on delete cascade,
- RESOURCE_NAME varchar(255) not null,
+ ADDRESSBOOK_RESOURCE_ID integer references ADDRESSBOOK,
+ ADDRESSBOOK_NAME varchar(255) default null,
+ RESOURCE_NAME varchar(255),
REVISION integer not null,
DELETED boolean not null,
@@ -342,7 +344,7 @@
create table NOTIFICATION_OBJECT_REVISIONS (
NOTIFICATION_HOME_RESOURCE_ID integer not null references NOTIFICATION_HOME on delete cascade,
- RESOURCE_NAME varchar(255) not null,
+ RESOURCE_NAME varchar(255),
REVISION integer not null,
DELETED boolean not null,
Modified: CalendarServer/trunk/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_tables.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/common/datastore/sql_tables.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -80,6 +80,7 @@
"sequence" : "REVISION_SEQ",
"column_HOME_RESOURCE_ID" : "CALENDAR_HOME_RESOURCE_ID",
"column_RESOURCE_ID" : "CALENDAR_RESOURCE_ID",
+ "column_COLLECTION_NAME" : "CALENDAR_NAME",
"column_RESOURCE_NAME" : "RESOURCE_NAME",
"column_REVISION" : "REVISION",
"column_DELETED" : "DELETED",
@@ -90,6 +91,7 @@
"sequence" : "REVISION_SEQ",
"column_HOME_RESOURCE_ID" : "ADDRESSBOOK_HOME_RESOURCE_ID",
"column_RESOURCE_ID" : "ADDRESSBOOK_RESOURCE_ID",
+ "column_COLLECTION_NAME" : "ADDRESSBOOK_NAME",
"column_RESOURCE_NAME" : "RESOURCE_NAME",
"column_REVISION" : "REVISION",
"column_DELETED" : "DELETED",
Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/util.py 2010-09-28 20:29:02 UTC (rev 6381)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py 2010-09-28 20:31:05 UTC (rev 6382)
@@ -124,6 +124,9 @@
tables = ['INVITE',
'RESOURCE_PROPERTY',
'ATTACHMENT',
+ 'NOTIFICATION_OBJECT_REVISIONS',
+ 'ADDRESSBOOK_OBJECT_REVISIONS',
+ 'CALENDAR_OBJECT_REVISIONS',
'ADDRESSBOOK_OBJECT',
'CALENDAR_OBJECT',
'CALENDAR_BIND',
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100928/e9b69c59/attachment-0001.html>
More information about the calendarserver-changes
mailing list