[CalendarServer-changes] [6628] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Nov 12 13:22:32 PST 2010
Revision: 6628
http://trac.macosforge.org/projects/calendarserver/changeset/6628
Author: cdaboo at apple.com
Date: 2010-11-12 13:22:30 -0800 (Fri, 12 Nov 2010)
Log Message:
-----------
Make depth:1 on a home collection be more efficient wrt SQL use via a load of all child data in one go.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/txdav/base/propertystore/sql.py
CalendarServer/trunk/txdav/caldav/datastore/file.py
CalendarServer/trunk/txdav/caldav/datastore/scheduling.py
CalendarServer/trunk/txdav/caldav/datastore/sql.py
CalendarServer/trunk/txdav/caldav/datastore/test/common.py
CalendarServer/trunk/txdav/caldav/icalendarstore.py
CalendarServer/trunk/txdav/carddav/datastore/file.py
CalendarServer/trunk/txdav/carddav/datastore/sql.py
CalendarServer/trunk/txdav/carddav/datastore/test/common.py
CalendarServer/trunk/txdav/carddav/iaddressbookstore.py
CalendarServer/trunk/txdav/common/datastore/file.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql_tables.py
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -2063,6 +2063,24 @@
@inlineCallbacks
+ def findChildrenFaster(
+ self, depth, request, okcallback, badcallback,
+ names, privileges, inherited_aces
+ ):
+ """
+ Override to pre-load children in certain collection types for better performance.
+ """
+
+ if depth == "1":
+ yield self._newStoreHome.loadChildren()
+
+ result = (yield super(CommonHomeResource, self).findChildrenFaster(
+ depth, request, okcallback, badcallback, names, privileges, inherited_aces
+ ))
+
+ returnValue(result)
+
+ @inlineCallbacks
def makeChild(self, name):
# Try built-in children first
if name in self._provisionedChildren:
@@ -2117,8 +2135,8 @@
"""
children = set(self._provisionedChildren.keys())
children.update(self._provisionedLinks.keys())
- children.update((yield self.allShareNames()))
children.update((yield self._newStoreHome.listChildren()))
+ children.update((yield self._newStoreHome.listSharedChildren()))
returnValue(children)
Modified: CalendarServer/trunk/txdav/base/propertystore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/base/propertystore/sql.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/base/propertystore/sql.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -56,7 +56,35 @@
self._cached[(name, uid)] = value
returnValue(self)
+ @classmethod
+ @inlineCallbacks
+ def loadAll(cls, defaultuser, txn, joinTable, joinColumn, parentIDColumn, parentID):
+ """
+ Return a list of property stores for all objects in a parent collection
+ """
+ rows = yield txn.execSQL(
+ """
+ select RESOURCE_ID, NAME, VIEWER_UID, VALUE from RESOURCE_PROPERTY
+ left join %s on (RESOURCE_ID = %s)
+ where %s = %%s
+ """ % (joinTable, joinColumn, parentIDColumn),
+ [parentID]
+ )
+
+ createdStores = {}
+ for resource_id, name, view_uid, value in rows:
+ if resource_id not in createdStores:
+ store = cls.__new__(cls)
+ super(PropertyStore, store).__init__(defaultuser)
+ store._txn = txn
+ store._resourceID = resource_id
+ store._cached = {}
+ createdStores[resource_id] = store
+ createdStores[resource_id]._cached[(name, view_uid)] = value
+ returnValue(createdStores)
+
+
def _getitem_uid(self, key, uid):
validKey(key)
Modified: CalendarServer/trunk/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/file.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/caldav/datastore/file.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -124,6 +124,7 @@
yield name
listCalendars = listChildren
+ loadCalendars = CommonHome.loadChildren
@inlineCallbacks
Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -82,6 +82,15 @@
returnValue(wrapped)
+ @inlineCallbacks
+ def loadCalendars(self):
+ superCalendars = (yield super(ImplicitCalendarHome, self).loadCalendars())
+ wrapped = []
+ for calendar in superCalendars:
+ wrapped.append(ImplicitCalendar(self, calendar))
+ returnValue(wrapped)
+
+
def createCalendarWithName(self, name):
self._calendarHome.createCalendarWithName(name)
Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -53,7 +53,8 @@
SQLLegacyCalendarShares, PostgresLegacyInboxIndexEmulator
from txdav.common.datastore.sql_tables import CALENDAR_TABLE,\
CALENDAR_BIND_TABLE, CALENDAR_OBJECT_REVISIONS_TABLE, CALENDAR_OBJECT_TABLE,\
- _ATTACHMENTS_MODE_WRITE, CALENDAR_HOME_TABLE, CALENDAR_HOME_METADATA_TABLE
+ _ATTACHMENTS_MODE_WRITE, CALENDAR_HOME_TABLE, CALENDAR_HOME_METADATA_TABLE,\
+ CALENDAR_AND_CALENDAR_BIND, CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE
from txdav.common.icommondatastore import IndexedSearchException
from vobject.icalendar import utc
@@ -84,6 +85,7 @@
calendarWithName = CommonHome.childWithName
calendars = CommonHome.children
listCalendars = CommonHome.listChildren
+ loadCalendars = CommonHome.loadChildren
@inlineCallbacks
@@ -116,7 +118,9 @@
_bindTable = CALENDAR_BIND_TABLE
_homeChildTable = CALENDAR_TABLE
+ _homeChildBindTable = CALENDAR_AND_CALENDAR_BIND
_revisionsTable = CALENDAR_OBJECT_REVISIONS_TABLE
+ _revisionsBindTable = CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE
_objectTable = CALENDAR_OBJECT_TABLE
def __init__(self, home, name, resourceID):
Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -774,7 +774,32 @@
set(home1_calendarNames)
)
+ @inlineCallbacks
+ def test_loadAllCalendars(self):
+ """
+ L{ICalendarHome.loadCalendars} returns an iterable of L{ICalendar}
+ providers, which are consistent with the results from
+ L{ICalendar.calendarWithName}.
+ """
+ # Add a dot directory to make sure we don't find it
+ # self.home1._path.child(".foo").createDirectory()
+ home = yield self.homeUnderTest()
+ calendars = (yield home.loadCalendars())
+ for calendar in calendars:
+ self.assertProvides(ICalendar, calendar)
+ self.assertEquals(calendar,
+ (yield home.calendarWithName(calendar.name())))
+
+ self.assertEquals(
+ set(c.name() for c in calendars),
+ set(home1_calendarNames)
+ )
+
+ for c in calendars:
+ self.assertTrue(c.properties() is not None)
+
+
@inlineCallbacks
def test_calendarsAfterAddCalendar(self):
"""
Modified: CalendarServer/trunk/txdav/caldav/icalendarstore.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/icalendarstore.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/caldav/icalendarstore.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -105,6 +105,13 @@
@return: an iterable of L{ICalendar}s.
"""
+ def loadCalendars():
+ """
+ Pre-load all calendars Depth:1.
+
+ @return: an iterable of L{ICalendar}s.
+ """
+
def calendarWithName(name):
"""
Retrieve the calendar with the given C{name} contained in this
Modified: CalendarServer/trunk/txdav/carddav/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/file.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/carddav/datastore/file.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -74,6 +74,7 @@
addressbooks = CommonHome.children
listAddressbooks = CommonHome.listChildren
+ loadAddressbooks = CommonHome.loadChildren
addressbookWithName = CommonHome.childWithName
createAddressBookWithName = CommonHome.createChildWithName
removeAddressBookWithName = CommonHome.removeChildWithName
Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -49,7 +49,8 @@
from txdav.common.datastore.sql_tables import ADDRESSBOOK_TABLE,\
ADDRESSBOOK_BIND_TABLE, ADDRESSBOOK_OBJECT_REVISIONS_TABLE,\
ADDRESSBOOK_OBJECT_TABLE, ADDRESSBOOK_HOME_TABLE,\
- ADDRESSBOOK_HOME_METADATA_TABLE
+ ADDRESSBOOK_HOME_METADATA_TABLE, ADDRESSBOOK_AND_ADDRESSBOOK_BIND,\
+ ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE
from txdav.base.propertystore.base import PropertyName
@@ -74,6 +75,7 @@
addressbooks = CommonHome.children
listAddressbooks = CommonHome.listChildren
+ loadAddressbooks = CommonHome.loadChildren
addressbookWithName = CommonHome.childWithName
createAddressBookWithName = CommonHome.createChildWithName
removeAddressBookWithName = CommonHome.removeChildWithName
@@ -92,7 +94,9 @@
_bindTable = ADDRESSBOOK_BIND_TABLE
_homeChildTable = ADDRESSBOOK_TABLE
+ _homeChildBindTable = ADDRESSBOOK_AND_ADDRESSBOOK_BIND
_revisionsTable = ADDRESSBOOK_OBJECT_REVISIONS_TABLE
+ _revisionsBindTable = ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE
_objectTable = ADDRESSBOOK_OBJECT_TABLE
def __init__(self, home, name, resourceID):
Modified: CalendarServer/trunk/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/test/common.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/carddav/datastore/test/common.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -630,6 +630,32 @@
@inlineCallbacks
+ def test_loadAllAddressBooks(self):
+ """
+ L{IAddressBookHome.loadAddressBooks} returns an iterable of L{IAddressBook}
+ providers, which are consistent with the results from
+ L{IAddressBook.addressbookWithName}.
+ """
+ # Add a dot directory to make sure we don't find it
+ # self.home1._path.child(".foo").createDirectory()
+ home = yield self.homeUnderTest()
+ addressbooks = (yield home.loadAddressbooks())
+
+ for addressbook in addressbooks:
+ self.assertProvides(IAddressBook, addressbook)
+ self.assertEquals(addressbook,
+ (yield home.addressbookWithName(addressbook.name())))
+
+ self.assertEquals(
+ set(c.name() for c in addressbooks),
+ set(home1_addressbookNames)
+ )
+
+ for c in addressbooks:
+ self.assertTrue(c.properties() is not None)
+
+
+ @inlineCallbacks
def test_addressbooksAfterAddAddressBook(self):
"""
L{IAddressBookHome.addressbooks} includes addressbooks recently added with
Modified: CalendarServer/trunk/txdav/carddav/iaddressbookstore.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/iaddressbookstore.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/carddav/iaddressbookstore.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -79,6 +79,13 @@
@return: an iterable of L{IAddressBook}s.
"""
+ def loadAddressbooks():
+ """
+ Pre-load all addressbooks Depth:1.
+
+ @return: an iterable of L{IAddressBook}s.
+ """
+
def addressbookWithName(name):
"""
Retrieve the addressbook with the given C{name} contained in this
Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/common/datastore/file.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -338,7 +338,11 @@
if not name.startswith(".")
)
+ # For file store there is no efficient "bulk" load of all children so just
+ # use the "iterate over each child" method.
+ loadChildren = children
+
def listChildren(self):
"""
Return a set of the names of the child resources.
@@ -352,6 +356,20 @@
))
+ def listSharedChildren(self):
+ """
+ Retrieve the names of the children in this home.
+
+ @return: an iterable of C{str}s.
+ """
+ return [share.localname for share in self._shares.allRecords()]
+
+ if self._childrenLoaded:
+ return succeed(self._sharedChildren.keys())
+ else:
+ return self._childClass.listObjects(self, owned=False)
+
+
def childWithName(self, name):
child = self._newChildren.get(name)
if child is not None:
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -37,7 +37,7 @@
from twisted.python.modules import getModule
from twisted.python.util import FancyEqMixin
-from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twisted.application.service import Service
@@ -244,9 +244,11 @@
self._ownerUID = ownerUID
self._resourceID = None
self._shares = None
+ self._childrenLoaded = False
self._children = {}
self._sharedChildren = {}
self._notifier = notifier
+ self._quotaUsedBytes = None
# Needed for REVISION/BIND table join
self._revisionBindJoinTable = {}
@@ -360,13 +362,32 @@
returnValue(x)
+ @inlineCallbacks
+ def loadChildren(self):
+ """
+ Load and cache all children - Depth:1 optimization
+ """
+ results1 = (yield self._childClass.loadAllChildren(self, owned=True))
+ for result in results1:
+ self._children[result.name()] = result
+ results2 = (yield self._childClass.loadAllChildren(self, owned=False))
+ for result in results2:
+ self._sharedChildren[result.name()] = result
+ self._childrenLoaded = True
+ returnValue(results1 + results2)
+
+
def listChildren(self):
"""
Retrieve the names of the children in this home.
@return: an iterable of C{str}s.
"""
- return self._childClass.listObjects(self, owned=True)
+
+ if self._childrenLoaded:
+ return succeed(self._children.keys())
+ else:
+ return self._childClass.listObjects(self, owned=True)
def listSharedChildren(self):
@@ -375,7 +396,10 @@
@return: an iterable of C{str}s.
"""
- return self._childClass.listObjects(self, owned=False)
+ if self._childrenLoaded:
+ return succeed(self._sharedChildren.keys())
+ else:
+ return self._childClass.listObjects(self, owned=False)
@memoizedKey("name", "_children")
@@ -581,11 +605,15 @@
@inlineCallbacks
def quotaUsedBytes(self):
- returnValue((yield self._txn.execSQL(
- "select %(column_QUOTA_USED_BYTES)s from %(name)s"
- " where %(column_RESOURCE_ID)s = %%s" % self._homeMetaDataTable,
- [self._resourceID]
- ))[0][0])
+
+ if self._quotaUsedBytes is None:
+ self._quotaUsedBytes = (yield self._txn.execSQL(
+ "select %(column_QUOTA_USED_BYTES)s from %(name)s"
+ " where %(column_RESOURCE_ID)s = %%s" % self._homeMetaDataTable,
+ [self._resourceID]
+ ))[0][0]
+
+ returnValue(self._quotaUsedBytes)
@inlineCallbacks
@@ -603,7 +631,7 @@
[self._resourceID]
)
- quotaUsedBytes = (yield self._txn.execSQL("""
+ self._quotaUsedBytes = (yield self._txn.execSQL("""
update %(name)s
set %(column_QUOTA_USED_BYTES)s = %(column_QUOTA_USED_BYTES)s + %%s
where %(column_RESOURCE_ID)s = %%s
@@ -611,9 +639,10 @@
""" % self._homeMetaDataTable,
[delta, self._resourceID]
))[0][0]
+
# Double check integrity
- if quotaUsedBytes < 0:
- log.error("Fixing quota adjusted below zero to %s by change amount %s" % (quotaUsedBytes, delta,))
+ if self._quotaUsedBytes < 0:
+ log.error("Fixing quota adjusted below zero to %s by change amount %s" % (self._quotaUsedBytes, delta,))
yield self._txn.execSQL("""
update %(name)s
set %(column_QUOTA_USED_BYTES)s = 0
@@ -621,6 +650,7 @@
""" % self._homeMetaDataTable,
[self._resourceID]
)
+ self._quotaUsedBytes = 0
def notifierID(self, label="default"):
@@ -647,7 +677,9 @@
_objectResourceClass = None
_bindTable = None
_homeChildTable = None
+ _homeChildBindTable = None
_revisionsTable = None
+ _revisionsBindTable = None
_objectTable = None
def __init__(self, home, name, resourceID):
@@ -657,6 +689,7 @@
self._created = None
self._modified = None
self._objects = {}
+ self._syncTokenRevision = None
if home._notifier:
childID = "%s/%s" % (home.uid(), name)
@@ -703,6 +736,70 @@
@classmethod
@inlineCallbacks
+ def loadAllChildren(cls, home, owned):
+ """
+ Load all child objects and return a list of them. This must create the child classes
+ and initialize them using "batched" SQL operations to keep this contacts wrt the number of
+ children. This is an optimization for Depth:1 operations on the home.
+ """
+
+ results = []
+
+ # Load from the main table first
+ dataRows = (yield home._txn.execSQL(("""
+ select %(CHILD:column_RESOURCE_ID)s, %(BIND:column_RESOURCE_NAME)s, %(CHILD:column_CREATED)s, %(CHILD:column_MODIFIED)s
+ from %(CHILD:name)s
+ left outer join %(BIND:name)s on (%(CHILD:column_RESOURCE_ID)s = %(BIND:column_RESOURCE_ID)s)
+ where
+ %(BIND:column_HOME_RESOURCE_ID)s = %%s and
+ %(BIND:column_BIND_MODE)s """ + ("=" if owned else "!=") + """ %%s
+ """) % cls._homeChildBindTable,
+ [
+ home._resourceID,
+ _BIND_MODE_OWN,
+ ]
+ ))
+
+ if dataRows:
+ # Get property stores for all these child resources (if any found)
+ propertyStores =(yield PropertyStore.loadAll(
+ home.uid(),
+ home._txn,
+ cls._bindTable["name"],
+ cls._bindTable["column_RESOURCE_ID"],
+ cls._bindTable["column_HOME_RESOURCE_ID"],
+ home._resourceID,
+ ))
+
+ revisions = (yield home._txn.execSQL(("""
+ select %(REV:name)s.%(REV:column_RESOURCE_ID)s, max(%(REV:column_REVISION)s) from %(REV:name)s
+ left join %(BIND:name)s on (%(REV:name)s.%(REV:column_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s)
+ where
+ %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = %%s and
+ %(BIND:column_BIND_MODE)s """ + ("=" if owned else "!=") + """ %%s and
+ %(REV:column_DELETED)s = FALSE
+ group by %(REV:name)s.%(REV:column_RESOURCE_ID)s
+ """) % cls._revisionsBindTable,
+ [
+ home._resourceID,
+ _BIND_MODE_OWN,
+ ]
+ ))
+ revisions = dict(revisions)
+
+ # Create the actual objects merging in properties
+ for resource_id, resource_name, created, modified in dataRows:
+ child = cls(home, resource_name, resource_id)
+ child._created = created
+ child._modified = modified
+ child._syncTokenRevision = revisions[resource_id]
+ child._loadPropertyStore(propertyStores.get(resource_id, None))
+ results.append(child)
+
+ returnValue(results)
+
+ @classmethod
+ @inlineCallbacks
def objectWithName(cls, home, name, owned):
"""
Retrieve the child with the given C{name} contained in this
@@ -1036,22 +1133,15 @@
@inlineCallbacks
def syncToken(self):
- revision = (yield self._txn.execSQL(
- """
- select max(%(column_REVISION)s) from %(name)s
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is not null
- """ % self._revisionsTable,
- [self._resourceID,]
- ))[0][0]
- if revision is None:
- revision = (yield self._txn.execSQL(
+ if self._syncTokenRevision is None:
+ self._syncTokenRevision = (yield self._txn.execSQL(
"""
- select %(column_REVISION)s from %(name)s
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ select max(%(column_REVISION)s) from %(name)s
+ where %(column_RESOURCE_ID)s = %%s
""" % self._revisionsTable,
[self._resourceID,]
))[0][0]
- returnValue(("%s#%s" % (self._resourceID, revision,)))
+ returnValue(("%s#%s" % (self._resourceID, self._syncTokenRevision,)))
def objectResourcesSinceToken(self, token):
@@ -1097,37 +1187,40 @@
)
# Insert new entry
- yield self._txn.execSQL("""
+ self._syncTokenRevision = (yield 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)
+ returning %(column_REVISION)s
""" % self._revisionsTable,
[self._home._resourceID, self._resourceID, self._name]
- )
+ ))[0][0]
@inlineCallbacks
def _updateSyncToken(self):
- yield self._txn.execSQL("""
+ self._syncTokenRevision = (yield self._txn.execSQL("""
update %(name)s
set (%(column_REVISION)s) = (nextval('%(sequence)s'))
where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ returning %(column_REVISION)s
""" % self._revisionsTable,
[self._resourceID,]
- )
+ ))[0][0]
@inlineCallbacks
def _renameSyncToken(self):
- yield self._txn.execSQL("""
+ self._syncTokenRevision = (yield 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
+ returning %(column_REVISION)s
""" % self._revisionsTable,
[self._name, self._resourceID,]
- )
+ ))[0][0]
@inlineCallbacks
@@ -1142,15 +1235,17 @@
)
# Then adjust collection entry to deleted state (do this for all entries with this collection's
- # resource-id so that we deal with direct shares which are not normally removed thorugh an unshare
+ # resource-id so that we deal with direct shares which are not normally removed through an unshare
yield 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
+ returning %(column_REVISION)s
""" % self._revisionsTable,
[self._resourceID,]
)
+ self._syncTokenRevision = None
def _insertRevision(self, name):
@@ -1214,15 +1309,18 @@
""" % self._revisionsTable,
[self._home._resourceID, self._resourceID, name, nextrevision]
)
+
+ self._syncTokenRevision = nextrevision
@inlineCallbacks
- def _loadPropertyStore(self):
- props = yield PropertyStore.load(
- self.ownerHome().uid(),
- self._txn,
- self._resourceID
- )
+ def _loadPropertyStore(self, props=None):
+ if props is None:
+ props = yield PropertyStore.load(
+ self.ownerHome().uid(),
+ self._txn,
+ self._resourceID
+ )
self.initPropertyStore(props)
self._properties = props
Modified: CalendarServer/trunk/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_tables.py 2010-11-12 19:03:22 UTC (rev 6627)
+++ CalendarServer/trunk/txdav/common/datastore/sql_tables.py 2010-11-12 21:22:30 UTC (rev 6628)
@@ -161,3 +161,20 @@
_BIND_MODE_READ = 1
_BIND_MODE_WRITE = 2
_BIND_MODE_DIRECT = 3
+
+# Some combined tables used in joins
+CALENDAR_AND_CALENDAR_BIND = {}
+CALENDAR_AND_CALENDAR_BIND.update([("CHILD:%s" % (k,), v) for k,v in CALENDAR_TABLE.items()])
+CALENDAR_AND_CALENDAR_BIND.update([("BIND:%s" % (k,), v) for k,v in CALENDAR_BIND_TABLE.items()])
+
+CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE = {}
+CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE.update([("REV:%s" % (k,), v) for k,v in CALENDAR_OBJECT_REVISIONS_TABLE.items()])
+CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE.update([("BIND:%s" % (k,), v) for k,v in CALENDAR_BIND_TABLE.items()])
+
+ADDRESSBOOK_AND_ADDRESSBOOK_BIND = {}
+ADDRESSBOOK_AND_ADDRESSBOOK_BIND.update([("CHILD:%s" % (k,), v) for k,v in ADDRESSBOOK_TABLE.items()])
+ADDRESSBOOK_AND_ADDRESSBOOK_BIND.update([("BIND:%s" % (k,), v) for k,v in ADDRESSBOOK_BIND_TABLE.items()])
+
+ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE = {}
+ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE.update([("REV:%s" % (k,), v) for k,v in ADDRESSBOOK_OBJECT_REVISIONS_TABLE.items()])
+ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE.update([("BIND:%s" % (k,), v) for k,v in ADDRESSBOOK_BIND_TABLE.items()])
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101112/636e2571/attachment-0001.html>
More information about the calendarserver-changes
mailing list