[CalendarServer-changes] [6789] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Jan 19 13:12:56 PST 2011


Revision: 6789
          http://trac.macosforge.org/projects/calendarserver/changeset/6789
Author:   cdaboo at apple.com
Date:     2011-01-19 13:12:56 -0800 (Wed, 19 Jan 2011)
Log Message:
-----------
Optimize SQL usage for implicit scheduling operations that lookup resource over an entire home by UID.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
    CalendarServer/trunk/twistedcaldav/scheduling/utils.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/carddav/datastore/file.py
    CalendarServer/trunk/txdav/carddav/datastore/sql.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	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -2408,6 +2408,22 @@
         returnValue(similar)
 
 
+    def hasCalendarResourceUIDSomewhereElse(self, uid, ok_object, type):
+        """
+        Test if there are other child object resources with the specified UID.
+        
+        Pass through direct to store.
+        """
+        return self._newStoreHome.hasCalendarResourceUIDSomewhereElse(uid, ok_object._newStoreObject, type)
+
+    def getCalendarResourcesForUID(self, uid, allow_shared=False):
+        """
+        Return all child object resources with the specified UID.
+        
+        Pass through direct to store.
+        """
+        return self._newStoreHome.getCalendarResourcesForUID(uid, allow_shared)
+
     def defaultAccessControlList(self):
         myPrincipal = self.principalForRecord()
 

Modified: CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/implicit.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/twistedcaldav/scheduling/implicit.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -19,15 +19,12 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
-from twext.web2.dav.util import joinURL
-from twext.web2.dav.util import parentForURL
 from twext.web2.http import HTTPError
 
 from twistedcaldav import caldavxml
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.directory.principal import DirectoryCalendarPrincipalResource
 from twistedcaldav.ical import Property
-from twistedcaldav.method import report_common
 from twistedcaldav.scheduling import addressmapping
 from twistedcaldav.scheduling.cuaddress import InvalidCalendarUser,\
     LocalCalendarUser, PartitionedCalendarUser
@@ -353,39 +350,12 @@
         calendar_owner_principal = (yield self.resource.resourceOwnerPrincipal(self.request))
         calendar_home = yield calendar_owner_principal.calendarHome(self.request)
 
-        check_parent_uri = parentForURL(check_uri)[:-1] if check_uri else None
+        # Check for matching resource somewhere else in the home
+        foundElsewhere = (yield calendar_home.hasCalendarResourceUIDSomewhereElse(self.uid, check_resource, type))
+        if foundElsewhere:
+            log.debug("Implicit - found component with same UID in a different collection: %s" % (check_uri,))
+            raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "unique-scheduling-object-resource")))
 
-        # FIXME: because of the URL->resource request mapping thing, we have to force the request
-        # to recognize this resource
-        self.request._rememberResource(calendar_home, calendar_home.url())
-
-        # Run a UID query against the UID
-
-        @inlineCallbacks
-        def queryCalendarCollection(collection, collection_uri):
-            rname = yield collection.index().resourceNameForUID(self.uid)
-            if rname:
-                child = (yield self.request.locateResource(joinURL(collection_uri, rname)))
-                if child == check_resource:
-                    returnValue(True)
-                is_scheduling_object = self.checkSchedulingObjectResource(child)
-                matched_type = "schedule" if is_scheduling_object else "calendar"
-                if (
-                    collection_uri != check_parent_uri and
-                    (type == "schedule" or matched_type == "schedule")
-                ):
-                    log.debug("Implicit - found component with same UID in a different collection: %s" % (check_uri,))
-                    raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "unique-scheduling-object-resource")))
-
-                # Here we can always return true as the unique UID in a calendar collection
-                # requirement will already have been tested.
-
-            returnValue(True)
-
-        # NB We are by-passing privilege checking here. That should be OK as the data found is not
-        # exposed to the user.
-        yield report_common.applyToCalendarCollections(calendar_home, self.request, calendar_home.url(), "infinity", queryCalendarCollection, None)
-
     @inlineCallbacks
     def isOrganizerScheduling(self):
         """

Modified: CalendarServer/trunk/twistedcaldav/scheduling/utils.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/utils.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/twistedcaldav/scheduling/utils.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -15,9 +15,11 @@
 ##
 
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twistedcaldav.method import report_common
 from twext.web2.dav.util import joinURL
+from twext.python.log import Logger
 
+log = Logger()
+
 @inlineCallbacks
 def getCalendarObjectForPrincipals(request, principal, uid, allow_shared=False):
     """
@@ -39,32 +41,17 @@
         # force the request to recognize this resource.
         request._rememberResource(calendar_home, calendar_home.url())
 
-        # Run a UID query against the UID.
-        @inlineCallbacks
-        def queryCalendarCollection(collection, uri):
-            if not allow_shared:
-                if collection.isVirtualShare():
-                    returnValue(True)
+        # Get matching newstore objects
+        objectResources = (yield calendar_home.getCalendarResourcesForUID(uid, allow_shared))
+        
+        # We really want only one or zero of these
+        if len(objectResources) == 1:
+            result["calendar_collection_uri"] = joinURL(calendar_home.url(), objectResources[0]._parentCollection.name())
+            result["calendar_collection"] = (yield request.locateResource(result["calendar_collection_uri"]))
+            result["resource_name"] = objectResources[0].name()
+            result["resource"] = (yield request.locateResource(joinURL(result["calendar_collection_uri"], result["resource_name"])))
+        elif len(objectResources):
+            log.debug("Should only have zero or one scheduling object resource with UID '%s' in calendar home: %s" % (uid, calendar_home,))
 
-            rname = yield collection.index().resourceNameForUID(uid)
-            if rname:
-                resource = yield collection.getChild(rname)
-                request._rememberResource(resource, joinURL(uri, rname))
-
-                result["resource"] = resource
-                result["resource_name"] = rname
-                result["calendar_collection"] = collection
-                result["calendar_collection_uri"] = uri
-                returnValue(False)
-            else:
-                returnValue(True)
-
-        # NB We are by-passing privilege checking here. That should be OK as
-        # the data found is not exposed to the user.
-        yield report_common.applyToCalendarCollections(
-            calendar_home, request, calendar_home.url(),
-            "infinity", queryCalendarCollection, None
-        )
-
     returnValue((result["resource"], result["resource_name"], result["calendar_collection"], result["calendar_collection_uri"],))
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/file.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/caldav/datastore/file.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -128,6 +128,30 @@
 
 
     @inlineCallbacks
+    def hasCalendarResourceUIDSomewhereElse(self, uid, ok_object, type):
+        
+        objectResources = (yield self.objectResourcesWithUID(uid, ("inbox",)))
+        for objectResource in objectResources:
+            if ok_object and objectResource._path == ok_object._path:
+                continue
+            matched_type = "schedule" if objectResource.isScheduleObject else "calendar"
+            if type == "schedule" or matched_type == "schedule":
+                returnValue(True)
+            
+        returnValue(False)
+
+    @inlineCallbacks
+    def getCalendarResourcesForUID(self, uid, allow_shared=False):
+        
+        results = []
+        objectResources = (yield self.objectResourcesWithUID(uid, ("inbox",)))
+        for objectResource in objectResources:
+            if allow_shared or objectResource._parentCollection._owned:
+                results.append(objectResource)
+            
+        returnValue(results)
+
+    @inlineCallbacks
     def calendarObjectWithDropboxID(self, dropboxID):
         """
         Implement lookup with brute-force scanning.
@@ -169,7 +193,7 @@
     """
     implements(ICalendar)
 
-    def __init__(self, name, calendarHome, realName=None):
+    def __init__(self, name, calendarHome, owned, realName=None):
         """
         Initialize a calendar pointing at a path on disk.
 
@@ -184,7 +208,7 @@
         will eventually have on disk.
         @type realName: C{str}
         """
-        super(Calendar, self).__init__(name, calendarHome, realName=realName)
+        super(Calendar, self).__init__(name, calendarHome, owned, realName=realName)
 
         self._index = Index(self)
         self._invites = Invites(self)

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -107,8 +107,14 @@
         else:
             returnValue(None)
 
+    def hasCalendarResourceUIDSomewhereElse(self, uid, ok_object, type):
+        return self._calendarHome.hasCalendarResourceUIDSomewhereElse(uid, ok_object, type)
 
+    def getCalendarResourcesForUID(self, uid, allow_shared=False):
+        return self._calendarHome.getCalendarResourcesForUID(uid, allow_shared)
 
+
+
 class ImplicitCalendarObject(object):
     implements(ICalendarObject)
     def setComponent(self, component): ""

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -73,6 +73,7 @@
     _homeMetaDataTable = CALENDAR_HOME_METADATA_TABLE
     _childTable = CALENDAR_TABLE
     _bindTable = CALENDAR_BIND_TABLE
+    _objectBindTable = CALENDAR_OBJECT_AND_BIND_TABLE
     _notifierPrefix = "CalDAV"
     _revisionsTable = CALENDAR_OBJECT_REVISIONS_TABLE
 
@@ -91,6 +92,30 @@
 
 
     @inlineCallbacks
+    def hasCalendarResourceUIDSomewhereElse(self, uid, ok_object, type):
+        
+        objectResources = (yield self.objectResourcesWithUID(uid, ("inbox",)))
+        for objectResource in objectResources:
+            if ok_object and objectResource._resourceID == ok_object._resourceID:
+                continue
+            matched_type = "schedule" if objectResource.isScheduleObject else "calendar"
+            if type == "schedule" or matched_type == "schedule":
+                returnValue(True)
+            
+        returnValue(False)
+
+    @inlineCallbacks
+    def getCalendarResourcesForUID(self, uid, allow_shared=False):
+        
+        results = []
+        objectResources = (yield self.objectResourcesWithUID(uid, ("inbox",)))
+        for objectResource in objectResources:
+            if allow_shared or objectResource._parentCollection._owned:
+                results.append(objectResource)
+            
+        returnValue(results)
+
+    @inlineCallbacks
     def calendarObjectWithDropboxID(self, dropboxID):
         """
         Implement lookup via queries.
@@ -157,7 +182,7 @@
     _revisionsBindTable = CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE
     _objectTable = CALENDAR_OBJECT_TABLE
 
-    def __init__(self, home, name, resourceID):
+    def __init__(self, home, name, resourceID, owned):
         """
         Initialize a calendar pointing at a record in a database.
 
@@ -167,7 +192,7 @@
         @param home: the home containing this calendar.
         @type home: L{CalendarHome}
         """
-        super(Calendar, self).__init__(home, name, resourceID)
+        super(Calendar, self).__init__(home, name, resourceID, owned)
 
         if name == 'inbox':
             self._index = PostgresLegacyInboxIndexEmulator(self)

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -718,6 +718,38 @@
 
 
     @inlineCallbacks
+    def test_hasCalendarResourceUIDSomewhereElse(self):
+        """
+        L{ICalendar.calendarObjects} will enumerate the calendar objects present
+        in the filesystem, in name order, but skip those with hidden names.
+        """
+        home = yield self.homeUnderTest()
+        object = yield self.calendarObjectUnderTest()
+        result = (yield home.hasCalendarResourceUIDSomewhereElse("123", object, "schedule"))
+        self.assertFalse(result)
+
+        result = (yield home.hasCalendarResourceUIDSomewhereElse("uid1", object, "schedule"))
+        self.assertFalse(result)
+
+        result = (yield home.hasCalendarResourceUIDSomewhereElse("uid2", object, "schedule"))
+        self.assertTrue(result)
+
+
+    @inlineCallbacks
+    def test_getCalendarResourcesForUID(self):
+        """
+        L{ICalendar.calendarObjects} will enumerate the calendar objects present
+        in the filesystem, in name order, but skip those with hidden names.
+        """
+        home = yield self.homeUnderTest()
+        calendarObjects = (yield home.getCalendarResourcesForUID("123"))
+        self.assertEquals(len(calendarObjects), 0)
+
+        calendarObjects = (yield home.getCalendarResourcesForUID("uid1"))
+        self.assertEquals(len(calendarObjects), 1)
+
+
+    @inlineCallbacks
     def test_calendarObjectName(self):
         """
         L{ICalendarObject.name} reflects the name of the calendar object.

Modified: CalendarServer/trunk/txdav/carddav/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/file.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/carddav/datastore/file.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -92,7 +92,7 @@
     """
     implements(IAddressBook)
 
-    def __init__(self, name, addressbookHome, realName=None):
+    def __init__(self, name, addressbookHome, owned, realName=None):
         """
         Initialize an addressbook pointing at a path on disk.
 
@@ -108,7 +108,7 @@
         @type realName: C{str}
         """
         
-        super(AddressBook, self).__init__(name, addressbookHome, realName=realName)
+        super(AddressBook, self).__init__(name, addressbookHome, owned, realName=realName)
 
         self._index = Index(self)
         self._invites = Invites(self)

Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -50,7 +50,8 @@
     ADDRESSBOOK_BIND_TABLE, ADDRESSBOOK_OBJECT_REVISIONS_TABLE,\
     ADDRESSBOOK_OBJECT_TABLE, ADDRESSBOOK_HOME_TABLE,\
     ADDRESSBOOK_HOME_METADATA_TABLE, ADDRESSBOOK_AND_ADDRESSBOOK_BIND,\
-    ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE
+    ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE,\
+    ADDRESSBOOK_OBJECT_AND_BIND_TABLE
 from txdav.base.propertystore.base import PropertyName
 
 
@@ -63,6 +64,7 @@
     _homeMetaDataTable = ADDRESSBOOK_HOME_METADATA_TABLE
     _childTable = ADDRESSBOOK_TABLE
     _bindTable = ADDRESSBOOK_BIND_TABLE
+    _objectBindTable = ADDRESSBOOK_OBJECT_AND_BIND_TABLE
     _notifierPrefix = "CardDAV"
     _revisionsTable = ADDRESSBOOK_OBJECT_REVISIONS_TABLE
 
@@ -99,7 +101,7 @@
     _revisionsBindTable = ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE
     _objectTable = ADDRESSBOOK_OBJECT_TABLE
 
-    def __init__(self, home, name, resourceID):
+    def __init__(self, home, name, resourceID, owned):
         """
         Initialize an addressbook pointing at a path on disk.
 
@@ -115,7 +117,7 @@
         @type realName: C{str}
         """
 
-        super(AddressBook, self).__init__(home, name, resourceID)
+        super(AddressBook, self).__init__(home, name, resourceID, owned)
 
         self._index = PostgresLegacyABIndexEmulator(self)
         self._invites = SQLLegacyAddressBookInvites(self)

Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/common/datastore/file.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -385,7 +385,7 @@
         if name.startswith("."):
             return None
 
-        child = self._childClass.objectWithName(self, name)
+        child = self._childClass.objectWithName(self, name, True)
         if child is not None:
             self._cachedChildren[name] = child
         return child
@@ -409,7 +409,7 @@
 
         # FIXME: some way to roll this back.
 
-        c = self._newChildren[name] = self._childClass(temporary.basename(), self, realName=name)
+        c = self._newChildren[name] = self._childClass(temporary.basename(), self, True, realName=name)
         c.retrieveOldIndex().create()
         def do():
             childPath = self._path.child(name)
@@ -484,6 +484,20 @@
         self._transaction.addOperation(props.flush, "flush home properties")
         return props
 
+    def objectResourcesWithUID(self, uid, ignore_children=()):
+        """
+        Return all child object resources with the specified UID, ignoring any in the
+        named child collections. The file implementation just iterates all child collections.
+        """
+        results = []
+        for child in self.children():
+            if child.name() in ignore_children:
+                continue
+            object = child.objectResourceWithUID(uid)
+            if object:
+                results.append(object)
+        return results
+
     def quotaUsedBytes(self):
 
         try:
@@ -534,7 +548,7 @@
 
     _objectResourceClass = None
 
-    def __init__(self, name, home, realName=None):
+    def __init__(self, name, home, owned, realName=None):
         """
         Initialize an home child pointing at a path on disk.
 
@@ -551,6 +565,7 @@
         """
         self._name = name
         self._home = home
+        self._owned = owned
         self._transaction = home._transaction
         self._newObjectResources = {}
         self._cachedObjectResources = {}
@@ -568,8 +583,8 @@
 
 
     @classmethod
-    def objectWithName(cls, home, name):
-        return cls(name, home) if home._path.child(name).isdir() else None
+    def objectWithName(cls, home, name, owned):
+        return cls(name, home, owned) if home._path.child(name).isdir() else None
 
     @property
     def _path(self):
@@ -715,16 +730,11 @@
 
 
     def objectResourceWithUID(self, uid):
-        # FIXME: This _really_ needs to be inspecting an index, not parsing
-        # every resource.
-        for objectResourcePath in self._path.children():
-            if not isValidName(objectResourcePath.basename()):
-                continue
-            obj = self._objectResourceClass(objectResourcePath.basename(), self)
-            if obj.component().resourceUID() == uid:
-                if obj.name() in self._removedObjectResources:
-                    return None
-                return obj
+        rname = self.retrieveOldIndex().resourceNameForUID(uid)
+        if rname and rname not in self._removedObjectResources:
+            return self.objectResourceWithName(rname)
+        
+        return None
 
 
     @writeOperation

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -286,6 +286,7 @@
     _childClass = None
     _childTable = None
     _bindTable = None
+    _objectBindTable = None
     _notifierPrefix = None
     _revisionsTable = None
     _notificationRevisionsTable = NOTIFICATION_OBJECT_REVISIONS_TABLE
@@ -665,6 +666,36 @@
 
 
     @inlineCallbacks
+    def objectResourcesWithUID(self, uid, ignore_children=()):
+        """
+        Return all child object resources with the specified UID, ignoring any in the
+        named child collections. The file implementation just iterates all child collections.
+        """
+        
+        results = []
+        rows = (yield self._txn.execSQL("""
+            select %(OBJECT:name)s.%(OBJECT:column_PARENT_RESOURCE_ID)s, %(OBJECT:column_RESOURCE_ID)s
+            from %(OBJECT:name)s
+            left outer join %(BIND:name)s on (
+              %(OBJECT:name)s.%(OBJECT:column_PARENT_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s
+            )
+            where
+             %(OBJECT:column_UID)s = %%s and
+             %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = %%s
+            """ % self._objectBindTable,
+            [uid, self._resourceID,]
+        ))
+
+        if rows:
+            childID, objectID = rows[0]
+            child = (yield self.childWithID(childID))
+            if child and child.name() not in ignore_children:
+                objectResource = (yield child.objectResourceWithID(objectID))
+                results.append(objectResource)
+        
+        returnValue(results)
+
+    @inlineCallbacks
     def quotaUsedBytes(self):
         
         if self._quotaUsedBytes is None:
@@ -749,10 +780,11 @@
     _revisionsBindTable = None
     _objectTable = None
 
-    def __init__(self, home, name, resourceID):
+    def __init__(self, home, name, resourceID, owned):
         self._home = home
         self._name = name
         self._resourceID = resourceID
+        self._owned = owned
         self._created = None
         self._modified = None
         self._objects = {}
@@ -860,7 +892,7 @@
         
         # Create the actual objects merging in properties
         for resource_id, resource_name, created, modified in dataRows:
-            child = cls(home, resource_name, resource_id)
+            child = cls(home, resource_name, resource_id, owned)
             child._created = created
             child._modified = modified
             child._syncTokenRevision = revisions[resource_id]
@@ -915,7 +947,7 @@
         if not data:
             returnValue(None)
         resourceID = data[0][0]
-        child = cls(home, name, resourceID)
+        child = cls(home, name, resourceID, owned)
         yield child.initFromStore()
         returnValue(child)
 
@@ -933,7 +965,7 @@
         """
 
         data = yield home._txn.execSQL("""
-            select %(column_RESOURCE_NAME)s from %(name)s
+            select %(column_RESOURCE_NAME)s, %(column_BIND_MODE)s from %(name)s
             where
               %(column_RESOURCE_ID)s = %%s and
               %(column_HOME_RESOURCE_ID)s = %%s
@@ -946,8 +978,8 @@
 
         if not data:
             returnValue(None)
-        name = data[0][0]
-        child = cls(home, name, resourceID)
+        name, mode = data[0]
+        child = cls(home, name, resourceID, mode == _BIND_MODE_OWN)
         yield child.initFromStore()
         returnValue(child)
 
@@ -986,7 +1018,7 @@
         )
 
         # Initialize other state
-        child = cls(home, name, resourceID)
+        child = cls(home, name, resourceID, True)
         child._created = _created
         child._modified = _modified
         yield child._loadPropertyStore()

Modified: CalendarServer/trunk/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_tables.py	2011-01-19 21:01:21 UTC (rev 6788)
+++ CalendarServer/trunk/txdav/common/datastore/sql_tables.py	2011-01-19 21:12:56 UTC (rev 6789)
@@ -183,6 +183,10 @@
 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_AND_BIND_TABLE = {}
+ADDRESSBOOK_OBJECT_AND_BIND_TABLE.update([("OBJECT:%s" % (k,), v) for k,v in ADDRESSBOOK_OBJECT_TABLE.items()])
+ADDRESSBOOK_OBJECT_AND_BIND_TABLE.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/20110119/b28ec5d4/attachment-0001.html>


More information about the calendarserver-changes mailing list