[CalendarServer-changes] [6197] CalendarServer/trunk/txdav

source_changes at macosforge.org source_changes at macosforge.org
Fri Aug 27 10:31:53 PDT 2010


Revision: 6197
          http://trac.macosforge.org/projects/calendarserver/changeset/6197
Author:   cdaboo at apple.com
Date:     2010-08-27 10:31:52 -0700 (Fri, 27 Aug 2010)
Log Message:
-----------
Extract common pieces for some legacy classes.

Modified Paths:
--------------
    CalendarServer/trunk/txdav/caldav/datastore/sql.py
    CalendarServer/trunk/txdav/carddav/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/sql_legacy.py

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py	2010-08-27 02:26:49 UTC (rev 6196)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py	2010-08-27 17:31:52 UTC (rev 6197)
@@ -44,8 +44,8 @@
 from txdav.common.datastore.sql import CommonHome, CommonHomeChild,\
     CommonObjectResource
 from txdav.common.datastore.sql_legacy import \
-    PostgresLegacyIndexEmulator, PostgresLegacyInvitesEmulator,\
-    PostgresLegacySharesEmulator
+    PostgresLegacyIndexEmulator, SQLLegacyCalendarInvites,\
+    SQLLegacyCalendarShares
 from txdav.common.datastore.sql_tables import CALENDAR_TABLE,\
     CALENDAR_BIND_TABLE, CALENDAR_OBJECT_REVISIONS_TABLE, CALENDAR_OBJECT_TABLE,\
     _ATTACHMENTS_MODE_WRITE
@@ -64,7 +64,7 @@
     def __init__(self, transaction, ownerUID, resourceID, notifier):
         super(CalendarHome, self).__init__(transaction, ownerUID, resourceID, notifier)
 
-        self._shares = PostgresLegacySharesEmulator(self)
+        self._shares = SQLLegacyCalendarShares(self)
         self._childClass = Calendar
         self._childTable = CALENDAR_TABLE
         self._bindTable = CALENDAR_BIND_TABLE
@@ -117,7 +117,7 @@
         super(Calendar, self).__init__(home, name, resourceID, notifier)
 
         self._index = PostgresLegacyIndexEmulator(self)
-        self._invites = PostgresLegacyInvitesEmulator(self)
+        self._invites = SQLLegacyCalendarInvites(self)
         self._objectResourceClass = CalendarObject
         self._bindTable = CALENDAR_BIND_TABLE
         self._homeChildTable = CALENDAR_TABLE

Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py	2010-08-27 02:26:49 UTC (rev 6196)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py	2010-08-27 17:31:52 UTC (rev 6197)
@@ -28,8 +28,8 @@
 from twistedcaldav.vcard import Component as VCard
 
 from txdav.common.datastore.sql_legacy import \
-    PostgresLegacyABIndexEmulator, PostgresLegacyABInvitesEmulator,\
-    PostgresLegacyABSharesEmulator
+    PostgresLegacyABIndexEmulator, SQLLegacyAddressBookInvites,\
+    SQLLegacyAddressBookShares
 
 from txdav.carddav.datastore.util import validateAddressBookComponent
 from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook,\
@@ -51,7 +51,7 @@
     def __init__(self, transaction, ownerUID, resourceID, notifier):
         super(AddressBookHome, self).__init__(transaction, ownerUID, resourceID, notifier)
 
-        self._shares = PostgresLegacyABSharesEmulator(self)
+        self._shares = SQLLegacyAddressBookShares(self)
         self._childClass = AddressBook
         self._childTable = ADDRESSBOOK_TABLE
         self._bindTable = ADDRESSBOOK_BIND_TABLE
@@ -90,7 +90,7 @@
         super(AddressBook, self).__init__(home, name, resourceID, notifier)
 
         self._index = PostgresLegacyABIndexEmulator(self)
-        self._invites = PostgresLegacyABInvitesEmulator(self)
+        self._invites = SQLLegacyAddressBookInvites(self)
         self._objectResourceClass = AddressBookObject
         self._bindTable = ADDRESSBOOK_BIND_TABLE
         self._homeChildTable = ADDRESSBOOK_TABLE

Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py	2010-08-27 02:26:49 UTC (rev 6196)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py	2010-08-27 17:31:52 UTC (rev 6197)
@@ -44,7 +44,9 @@
 
 from txdav.common.datastore.sql_tables import \
     _BIND_MODE_OWN, _BIND_MODE_READ, _BIND_MODE_WRITE, _BIND_STATUS_INVITED,\
-    _BIND_STATUS_ACCEPTED, _BIND_STATUS_DECLINED, _BIND_STATUS_INVALID
+    _BIND_STATUS_ACCEPTED, _BIND_STATUS_DECLINED, _BIND_STATUS_INVALID,\
+    CALENDAR_BIND_TABLE, CALENDAR_HOME_TABLE, ADDRESSBOOK_HOME_TABLE,\
+    ADDRESSBOOK_BIND_TABLE
 
 log = Logger()
 
@@ -56,66 +58,117 @@
     4: 'T',
 }
 
-class PostgresLegacyInvitesEmulator(object):
+class PostgresLegacyNotificationsEmulator(object):
+    def __init__(self, notificationsCollection):
+        self._collection = notificationsCollection
+
+
+    def _recordForObject(self, notificationObject):
+        return NotificationRecord(
+            notificationObject.uid(),
+            notificationObject.name(),
+            notificationObject._fieldQuery("XML_TYPE"))
+
+
+    def recordForName(self, name):
+        return self._recordForObject(
+            self._collection.notificationObjectWithName(name)
+        )
+
+
+    def recordForUID(self, uid):
+        return self._recordForObject(
+            self._collection.notificationObjectWithUID(uid)
+        )
+
+
+    def removeRecordForUID(self, uid):
+        self._collection.removeNotificationObjectWithUID(uid)
+
+
+    def removeRecordForName(self, name):
+        self._collection.removeNotificationObjectWithName(name)
+
+
+
+
+class SQLLegacyInvites(object):
     """
     Emulator for the implicit interface specified by
     L{twistedcaldav.sharing.InvitesDatabase}.
     """
 
+    _homeTable = None
+    _bindTable = None
 
-    def __init__(self, calendar):
-        self._calendar = calendar
+    def __init__(self, collection):
+        self._collection = collection
 
+        # Since we do multi-table requests we need a dict that combines tables
+        self._combinedTable = {}
+        for key, value in self._homeTable.iteritems():
+            self._combinedTable["HOME:%s" % (key,)] = value 
+        for key, value in self._bindTable.iteritems():
+            self._combinedTable["BIND:%s" % (key,)] = value 
 
     @property
     def _txn(self):
-        return self._calendar._txn
+        return self._collection._txn
 
+    def _getHomeWithUID(self, uid):
+        raise NotImplementedError()
 
     def create(self):
         "No-op, because the index implicitly always exists in the database."
+        pass
 
-
     def remove(self):
         "No-op, because the index implicitly always exists in the database."
+        pass
 
-
     def allRecords(self):
         for row in self._txn.execSQL(
-                """
-                select
-                    INVITE.INVITE_UID, INVITE.NAME, INVITE.RECIPIENT_ADDRESS,
-                    CALENDAR_HOME.OWNER_UID, CALENDAR_BIND.BIND_MODE,
-                    CALENDAR_BIND.BIND_STATUS, CALENDAR_BIND.MESSAGE
-                from
-                    INVITE, CALENDAR_HOME, CALENDAR_BIND
-                where
-                    INVITE.RESOURCE_ID = %s and
-                    INVITE.HOME_RESOURCE_ID = 
-                        CALENDAR_HOME.RESOURCE_ID and
-                    CALENDAR_BIND.CALENDAR_RESOURCE_ID =
-                        INVITE.RESOURCE_ID and
-                    CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID =
-                        INVITE.HOME_RESOURCE_ID
-                order by
-                    INVITE.NAME asc
-                """, [self._calendar._resourceID]):
+            """
+            select
+                INVITE.INVITE_UID,
+                INVITE.NAME,
+                INVITE.RECIPIENT_ADDRESS,
+                %(HOME:name)s.%(HOME:column_OWNER_UID)s,
+                %(BIND:name)s.%(BIND:column_BIND_MODE)s,
+                %(BIND:name)s.%(BIND:column_BIND_STATUS)s,
+                %(BIND:name)s.%(BIND:column_MESSAGE)s
+            from
+                INVITE, %(HOME:name)s, %(BIND:name)s
+            where
+                INVITE.RESOURCE_ID = %%s
+                and INVITE.HOME_RESOURCE_ID = %(HOME:name)s.%(HOME:column_RESOURCE_ID)s
+                and %(BIND:name)s.%(BIND:column_RESOURCE_ID)s = INVITE.RESOURCE_ID
+                and %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = INVITE.HOME_RESOURCE_ID
+            order by
+                INVITE.NAME asc
+            """ % self._combinedTable,
+            [self._collection._resourceID]
+        ):
             yield self._makeInvite(row)
 
     def recordForUserID(self, userid):
         rows = self._txn.execSQL(
             """
             select
-                INVITE.INVITE_UID, INVITE.NAME, INVITE.RECIPIENT_ADDRESS,
-                CALENDAR_HOME.OWNER_UID, CALENDAR_BIND.BIND_MODE,
-                CALENDAR_BIND.BIND_STATUS, CALENDAR_BIND.MESSAGE
+                INVITE.INVITE_UID,
+                INVITE.NAME,
+                INVITE.RECIPIENT_ADDRESS,
+                %(HOME:name)s.%(HOME:column_OWNER_UID)s,
+                %(BIND:name)s.%(BIND:column_BIND_MODE)s,
+                %(BIND:name)s.%(BIND:column_BIND_STATUS)s,
+                %(BIND:name)s.%(BIND:column_MESSAGE)s
             from
-                INVITE, CALENDAR_HOME, CALENDAR_BIND
-            where INVITE.RECIPIENT_ADDRESS = %s
-             and INVITE.HOME_RESOURCE_ID = CALENDAR_HOME.RESOURCE_ID
-             and CALENDAR_BIND.CALENDAR_RESOURCE_ID = INVITE.RESOURCE_ID
-             and CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID
-            """,
+                INVITE, %(HOME:name)s, %(BIND:name)s
+            where INVITE.RECIPIENT_ADDRESS = %%s
+             and INVITE.HOME_RESOURCE_ID = %(HOME:name)s.%(HOME:column_RESOURCE_ID)s
+             and %(BIND:name)s.%(BIND:column_RESOURCE_ID)s = INVITE.RESOURCE_ID
+             and %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = INVITE.HOME_RESOURCE_ID
+            """ % self._combinedTable,
             [userid]
         )
         return self._makeInvite(rows[0]) if rows else None
@@ -131,16 +184,20 @@
         rows = self._txn.execSQL(
             """
             select
-                INVITE.INVITE_UID, INVITE.NAME, INVITE.RECIPIENT_ADDRESS,
-                CALENDAR_HOME.OWNER_UID, CALENDAR_BIND.BIND_MODE,
-                CALENDAR_BIND.BIND_STATUS, CALENDAR_BIND.MESSAGE
+                INVITE.INVITE_UID,
+                INVITE.NAME,
+                INVITE.RECIPIENT_ADDRESS,
+                %(HOME:name)s.%(HOME:column_OWNER_UID)s,
+                %(BIND:name)s.%(BIND:column_BIND_MODE)s,
+                %(BIND:name)s.%(BIND:column_BIND_STATUS)s,
+                %(BIND:name)s.%(BIND:column_MESSAGE)s
             from
-                INVITE, CALENDAR_HOME, CALENDAR_BIND
-            where INVITE.INVITE_UID = %s
-             and INVITE.HOME_RESOURCE_ID = CALENDAR_HOME.RESOURCE_ID
-             and CALENDAR_BIND.CALENDAR_RESOURCE_ID = INVITE.RESOURCE_ID
-             and CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID
-            """,
+                INVITE, %(HOME:name)s, %(BIND:name)s
+            where INVITE.INVITE_UID = %%s
+             and INVITE.HOME_RESOURCE_ID = %(HOME:name)s.%(HOME:column_RESOURCE_ID)s
+             and %(BIND:name)s.%(BIND:column_RESOURCE_ID)s = INVITE.RESOURCE_ID
+             and %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = INVITE.HOME_RESOURCE_ID
+            """ % self._combinedTable,
             [inviteUID]
         )
         return self._makeInvite(rows[0]) if rows else None
@@ -179,7 +236,7 @@
         # it will always contain the UID.  The form is '/principals/__uids__/x'
         # (and may contain a trailing slash).
         principalUID = record.principalURL.split("/")[3]
-        shareeHome = self._txn.calendarHomeWithUID(principalUID, create=True)
+        shareeHome = self._getHomeWithUID(principalUID)
         rows = self._txn.execSQL(
             "select RESOURCE_ID, HOME_RESOURCE_ID from INVITE where RECIPIENT_ADDRESS = %s",
             [record.userid]
@@ -187,16 +244,20 @@
         if rows:
             [[resourceID, homeResourceID]] = rows
             # Invite(inviteuid, userid, principalURL, common_name, access, state, summary)
+            self._txn.execSQL(
+                """
+                update %(BIND:name)s
+                set %(BIND:column_BIND_MODE)s = %%s,
+                    %(BIND:column_BIND_STATUS)s = %%s,
+                    %(BIND:column_MESSAGE)s = %%s
+                where %(BIND:column_RESOURCE_ID)s = %%s
+                 and %(BIND:column_HOME_RESOURCE_ID)s = %%s
+                """ % self._combinedTable,
+                [bindMode, bindStatus, record.summary, resourceID, homeResourceID]
+            )
             self._txn.execSQL("""
-                update CALENDAR_BIND set BIND_MODE = %s,
-                BIND_STATUS = %s, MESSAGE = %s
-                where
-                    CALENDAR_RESOURCE_ID = %s and
-                    CALENDAR_HOME_RESOURCE_ID = %s
-            """, [bindMode, bindStatus, record.summary,
-                resourceID, homeResourceID])
-            self._txn.execSQL("""
-                update INVITE set NAME = %s, INVITE_UID = %s
+                update INVITE
+                set NAME = %s, INVITE_UID = %s
                 where RECIPIENT_ADDRESS = %s
                 """,
                 [record.name, record.inviteuid, record.userid]
@@ -204,7 +265,8 @@
         else:
             self._txn.execSQL(
                 """
-                insert into INVITE (
+                insert into INVITE
+                (
                     INVITE_UID, NAME,
                     HOME_RESOURCE_ID, RESOURCE_ID,
                     RECIPIENT_ADDRESS
@@ -213,22 +275,27 @@
                 """,
                 [
                     record.inviteuid, record.name,
-                    shareeHome._resourceID, self._calendar._resourceID,
+                    shareeHome._resourceID, self._collection._resourceID,
                     record.userid
                 ])
             self._txn.execSQL(
                 """
-                insert into CALENDAR_BIND
+                insert into %(BIND:name)s
                 (
-                    CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID, 
-                    CALENDAR_RESOURCE_NAME, BIND_MODE, BIND_STATUS,
-                    SEEN_BY_OWNER, SEEN_BY_SHAREE, MESSAGE
+                    %(BIND:column_HOME_RESOURCE_ID)s,
+                    %(BIND:column_RESOURCE_ID)s, 
+                    %(BIND:column_RESOURCE_NAME)s,
+                    %(BIND:column_BIND_MODE)s,
+                    %(BIND:column_BIND_STATUS)s,
+                    %(BIND:column_SEEN_BY_OWNER)s,
+                    %(BIND:column_SEEN_BY_SHAREE)s,
+                    %(BIND:column_MESSAGE)s
                 )
-                values (%s, %s, %s, %s, %s, %s, %s, %s)
-                """,
+                values (%%s, %%s, %%s, %%s, %%s, %%s, %%s, %%s)
+                """ % self._combinedTable,
                 [
                     shareeHome._resourceID,
-                    self._calendar._resourceID,
+                    self._collection._resourceID,
                     None, # this is NULL because it is not bound yet, let's be
                           # explicit about that.
                     bindMode,
@@ -241,10 +308,12 @@
 
     def removeRecordForUserID(self, userid):
         self._txn.execSQL(
-            "delete from CALENDAR_BIND using INVITE "
-            "where INVITE.RECIPIENT_ADDRESS = %s "
-            " and CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID "
-            " and CALENDAR_BIND.CALENDAR_RESOURCE_ID = INVITE.RESOURCE_ID",
+            """
+            delete from %(BIND:name)s using INVITE
+            where INVITE.RECIPIENT_ADDRESS = %%s
+             and %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = INVITE.HOME_RESOURCE_ID
+             and %(BIND:name)s.%(BIND:column_RESOURCE_ID)s = INVITE.RESOURCE_ID
+            """ % self._combinedTable,
             [userid]
         )
         self._txn.execSQL(
@@ -255,10 +324,12 @@
 
     def removeRecordForInviteUID(self, inviteUID):
         self._txn.execSQL(
-            "delete from CALENDAR_BIND using INVITE "
-            "where INVITE.INVITE_UID = %s "
-            " and CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID "
-            " and CALENDAR_BIND.CALENDAR_RESOURCE_ID = INVITE.RESOURCE_ID",
+            """
+            delete from %(BIND:name)s using INVITE
+            where INVITE.INVITE_UID = %s
+             and %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = INVITE.HOME_RESOURCE_ID
+             and %(BIND:name)s.%(BIND:column_RESOURCE_ID)s = INVITE.RESOURCE_ID
+            """ % self._combinedTable,
             [inviteUID]
         )
         self._txn.execSQL(
@@ -266,18 +337,52 @@
             [inviteUID]
         )
 
+class SQLLegacyCalendarInvites(SQLLegacyInvites):
+    """
+    Emulator for the implicit interface specified by
+    L{twistedcaldav.sharing.InvitesDatabase}.
+    """
 
-class PostgresLegacySharesEmulator(object):
+    def __init__(self, calendar):
+        self._homeTable = CALENDAR_HOME_TABLE
+        self._bindTable = CALENDAR_BIND_TABLE
+        super(SQLLegacyCalendarInvites, self).__init__(calendar)
 
+    def _getHomeWithUID(self, uid):
+        return self._txn.calendarHomeWithUID(uid, create=True)
+        
+class SQLLegacyAddressBookInvites(SQLLegacyInvites):
+    """
+    Emulator for the implicit interface specified by
+    L{twistedcaldav.sharing.InvitesDatabase}.
+    """
+
+    def __init__(self, addressbook):
+        self._homeTable = ADDRESSBOOK_HOME_TABLE
+        self._bindTable = ADDRESSBOOK_BIND_TABLE
+        super(SQLLegacyAddressBookInvites, self).__init__(addressbook)
+
+    def _getHomeWithUID(self, uid):
+        return self._txn.addressbookHomeWithUID(uid, create=True)
+
+class SQLLegacyShares(object):
+
+    _homeTable = None
+    _bindTable = None
+    _urlTopSegment = None
+
     def __init__(self, home):
         self._home = home
 
-
     @property
     def _txn(self):
         return self._home._txn
 
 
+    def _getHomeWithUID(self, uid):
+        raise NotImplementedError()
+
+
     def create(self):
         pass
 
@@ -289,38 +394,47 @@
     def allRecords(self):
         # This should have been a smart join that got all these columns at
         # once, but let's not bother to fix it, since the actual query we
-        # _want_ to do (just look for calendar binds in a particular homes) is
+        # _want_ to do (just look for binds in a particular homes) is
         # much simpler anyway; we should just do that.
         shareRows = self._txn.execSQL(
             """
-            select CALENDAR_RESOURCE_ID, CALENDAR_RESOURCE_NAME, MESSAGE
-            from CALENDAR_BIND
-                where CALENDAR_HOME_RESOURCE_ID = %s and
-                BIND_MODE != %s and
-                CALENDAR_RESOURCE_NAME is not null
-            """, [self._home._resourceID, _BIND_MODE_OWN])
+            select %(column_RESOURCE_ID)s, %(column_RESOURCE_NAME)s, %(column_MESSAGE)s
+            from %(name)s
+            where %(column_HOME_RESOURCE_ID)s = %%s
+             and %(column_BIND_MODE)s != %%s
+             and %(column_RESOURCE_NAME)s is not null
+            """ % self._bindTable,
+            [self._home._resourceID, _BIND_MODE_OWN]
+        )
         for resourceID, resourceName, summary in shareRows:
             [[shareuid]] = self._txn.execSQL(
                 """
                 select INVITE_UID
                 from INVITE
                 where RESOURCE_ID = %s and HOME_RESOURCE_ID = %s
-                """, [resourceID, self._home._resourceID])
+                """,
+                [resourceID, self._home._resourceID]
+            )
             sharetype = 'I'
             [[ownerHomeID, ownerResourceName]] = self._txn.execSQL(
                 """
-                select CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME
-                from CALENDAR_BIND
-                where CALENDAR_RESOURCE_ID = %s and
-                    BIND_MODE = %s
-                """, [resourceID, _BIND_MODE_OWN]
-                )
+                select %(column_HOME_RESOURCE_ID)s, %(column_RESOURCE_NAME)s
+                from %(name)s
+                where %(column_RESOURCE_ID)s = %%s
+                 and %(column_BIND_MODE)s = %%s
+                """ % self._bindTable,
+                [resourceID, _BIND_MODE_OWN]
+            )
             [[ownerUID]] = self._txn.execSQL(
-                "select OWNER_UID from CALENDAR_HOME where RESOURCE_ID = %s",
-                [ownerHomeID])
-            hosturl = '/calendars/__uids__/%s/%s' % (
-                ownerUID, ownerResourceName
+                """
+                select %(column_OWNER_UID)s from %(name)s
+                where %(column_RESOURCE_ID)s = %%s
+                """ % self._homeTable,
+                [ownerHomeID]
             )
+            hosturl = '/%s/__uids__/%s/%s' % (
+                self._urlTopSegment, ownerUID, ownerResourceName
+            )
             localname = resourceName
             record = SharedCollectionRecord(
                 shareuid, sharetype, hosturl, localname, summary
@@ -345,126 +459,88 @@
 #        print '*** SHARING***: Adding or updating this record:'
 #        import pprint
 #        pprint.pprint(record.__dict__)
-        # record.hosturl -> /calendars/__uids__/<uid>/<calendarname>
+        # record.hosturl -> /.../__uids__/<uid>/<name>
         splithost = record.hosturl.split('/')
         ownerUID = splithost[3]
-        ownerCalendarName = splithost[4]
-        ownerHome = self._txn.calendarHomeWithUID(ownerUID)
-        ownerCalendar = ownerHome.calendarWithName(ownerCalendarName)
-        calendarResourceID = ownerCalendar._resourceID
+        ownerCollectionName = splithost[4]
+        ownerHome = self._getHomeWithUID(ownerUID)
+        ownerCollection = ownerHome.childWithName(ownerCollectionName)
+        collectionResourceID = ownerCollection._resourceID
 
         # There needs to be a bind already, one that corresponds to the
         # invitation.  The invitation's UID is the same as the share UID.  I
         # just need to update its 'localname', i.e.
-        # CALENDAR_BIND.CALENDAR_RESOURCE_NAME.
+        # XXX_BIND.XXX_RESOURCE_NAME.
 
         self._txn.execSQL(
             """
-            update CALENDAR_BIND set CALENDAR_RESOURCE_NAME = %s
-            where CALENDAR_HOME_RESOURCE_ID = %s and CALENDAR_RESOURCE_ID = %s
-            """,
-            [record.localname, self._home._resourceID, calendarResourceID]
+            update %(name)s
+            set %(column_RESOURCE_NAME)s = %%s
+            where %(column_HOME_RESOURCE_ID)s = %%s
+             and %(column_RESOURCE_ID)s = %%s
+            """ % self._bindTable,
+            [record.localname, self._home._resourceID, collectionResourceID]
         )
 
 
     def removeRecordForLocalName(self, localname):
         self._txn.execSQL(
-            "update CALENDAR_BIND set CALENDAR_RESOURCE_NAME = NULL "
-            "where CALENDAR_RESOURCE_NAME = %s and CALENDAR_HOME_RESOURCE_ID = %s",
+            """
+            update %(name)s
+            set %(column_RESOURCE_NAME)s = NULL
+            where %(column_RESOURCE_NAME)s = %%s
+             and %(column_HOME_RESOURCE_ID)s = %%s
+            """ % self._bindTable,
             [localname, self._home._resourceID]
         )
 
 
     def removeRecordForShareUID(self, shareUID):
         self._txn.execSQL(
-            "update CALENDAR_BIND set CALENDAR_RESOURCE_NAME = NULL "
-            "from INVITE "
-            "where INVITE.INVITE_UID = %s "
-            " and CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID"
-            " and CALENDAR_BIND.CALENDAR_RESOURCE_ID = INVITE.RESOURCE_ID",
+            """
+            update %(name)s
+            set %(column_RESOURCE_NAME)s = NULL
+            from INVITE
+            where INVITE.INVITE_UID = %%s
+             and %(name)s.%(column_HOME_RESOURCE_ID)s = INVITE.HOME_RESOURCE_ID
+             and %(name)s.%(column_RESOURCE_ID)s = INVITE.RESOURCE_ID
+            """ % self._bindTable,
             [shareUID,]
         )
 
-
-class postgresqlgenerator(sqlgenerator):
+class SQLLegacyCalendarShares(SQLLegacyShares):
     """
-    Query generator for postgreSQL indexed searches.  (Currently unused: work
-    in progress.)
+    Emulator for the implicit interface specified by
+    L{twistedcaldav.sharing.InvitesDatabase}.
     """
 
-    ISOP = " = "
-    CONTAINSOP = " LIKE "
-    NOTCONTAINSOP = " NOT LIKE "
-    FIELDS = {
-        "TYPE": "CALENDAR_OBJECT.ICALENDAR_TYPE",
-        "UID":  "CALENDAR_OBJECT.ICALENDAR_UID",
-    }
+    def __init__(self, home):
+        self._homeTable = CALENDAR_HOME_TABLE
+        self._bindTable = CALENDAR_BIND_TABLE
+        self._urlTopSegment = "calendars"
+    
+        super(SQLLegacyCalendarShares, self).__init__(home)
 
-    def __init__(self, expr, calendarid, userid):
-        self.RESOURCEDB = "CALENDAR_OBJECT"
-        self.TIMESPANDB = "TIME_RANGE"
-        self.TIMESPANTEST = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.START_DATE < %s AND TIME_RANGE.END_DATE > %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.START_DATE < %s AND TIME_RANGE.END_DATE > %s))"
-        self.TIMESPANTEST_NOEND = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.END_DATE > %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.END_DATE > %s))"
-        self.TIMESPANTEST_NOSTART = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.START_DATE < %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.START_DATE < %s))"
-        self.TIMESPANTEST_TAIL_PIECE = " AND TIME_RANGE.CALENDAR_OBJECT_RESOURCE_ID = CALENDAR_OBJECT.RESOURCE_ID AND CALENDAR_OBJECT.CALENDAR_RESOURCE_ID = %s"
-        self.TIMESPANTEST_JOIN_ON_PIECE = "TIME_RANGE.INSTANCE_ID = TRANSPARENCY.TIME_RANGE_INSTANCE_ID AND TRANSPARENCY.USER_ID = %s"
+    def _getHomeWithUID(self, uid):
+        return self._txn.calendarHomeWithUID(uid, create=True)
+        
+class SQLLegacyAddressBookShares(SQLLegacyShares):
+    """
+    Emulator for the implicit interface specified by
+    L{twistedcaldav.sharing.InvitesDatabase}.
+    """
 
-        super(postgresqlgenerator, self).__init__(expr, calendarid, userid)
+    def __init__(self, home):
+        self._homeTable = ADDRESSBOOK_HOME_TABLE
+        self._bindTable = ADDRESSBOOK_BIND_TABLE
+        self._urlTopSegment = "addressbooks"
 
+        super(SQLLegacyAddressBookShares, self).__init__(home)
 
-    def generate(self):
-        """
-        Generate the actual SQL 'where ...' expression from the passed in
-        expression tree.
+    def _getHomeWithUID(self, uid):
+        return self._txn.addressbookHomeWithUID(uid, create=True)
         
-        @return: a C{tuple} of (C{str}, C{list}), where the C{str} is the
-            partial SQL statement, and the C{list} is the list of argument
-            substitutions to use with the SQL API execute method.
-        """
 
-        # Init state
-        self.sout = StringIO.StringIO()
-        self.arguments = []
-        self.substitutions = []
-        self.usedtimespan = False
-
-        # Generate ' where ...' partial statement
-        self.sout.write(self.WHERE)
-        self.generateExpression(self.expression)
-
-        # Prefix with ' from ...' partial statement
-        select = self.FROM + self.RESOURCEDB
-        if self.usedtimespan:
-            self.frontArgument(self.userid)
-            select += ", %s LEFT OUTER JOIN %s ON (%s)" % (
-                self.TIMESPANDB,
-                self.TRANSPARENCYDB,
-                self.TIMESPANTEST_JOIN_ON_PIECE
-            )
-        select += self.sout.getvalue()
-
-        select = select % tuple(self.substitutions)
-
-        return select, self.arguments
-
-
-    def addArgument(self, arg):
-        self.arguments.append(arg)
-        self.substitutions.append("%s")
-        self.sout.write("%s")
-
-    def setArgument(self, arg):
-        self.arguments.append(arg)
-        self.substitutions.append("%s")
-
-    def frontArgument(self, arg):
-        self.arguments.insert(0, arg)
-        self.substitutions.insert(0, "%s")
-
-    def containsArgument(self, arg):
-        return "%%%s%%" % (arg,)
-
-
 class MemcachedUIDReserver(CachePoolUserMixIn, LoggingMixIn):
     def __init__(self, index, cachePool=None):
         self.index = index
@@ -576,6 +652,85 @@
         key = self._key(uid)
         return succeed(key in self.reservations)
 
+class postgresqlgenerator(sqlgenerator):
+    """
+    Query generator for postgreSQL indexed searches.  (Currently unused: work
+    in progress.)
+    """
+
+    ISOP = " = "
+    CONTAINSOP = " LIKE "
+    NOTCONTAINSOP = " NOT LIKE "
+    FIELDS = {
+        "TYPE": "CALENDAR_OBJECT.ICALENDAR_TYPE",
+        "UID":  "CALENDAR_OBJECT.ICALENDAR_UID",
+    }
+
+    def __init__(self, expr, calendarid, userid):
+        self.RESOURCEDB = "CALENDAR_OBJECT"
+        self.TIMESPANDB = "TIME_RANGE"
+        self.TIMESPANTEST = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.START_DATE < %s AND TIME_RANGE.END_DATE > %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.START_DATE < %s AND TIME_RANGE.END_DATE > %s))"
+        self.TIMESPANTEST_NOEND = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.END_DATE > %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.END_DATE > %s))"
+        self.TIMESPANTEST_NOSTART = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.START_DATE < %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.START_DATE < %s))"
+        self.TIMESPANTEST_TAIL_PIECE = " AND TIME_RANGE.CALENDAR_OBJECT_RESOURCE_ID = CALENDAR_OBJECT.RESOURCE_ID AND CALENDAR_OBJECT.CALENDAR_RESOURCE_ID = %s"
+        self.TIMESPANTEST_JOIN_ON_PIECE = "TIME_RANGE.INSTANCE_ID = TRANSPARENCY.TIME_RANGE_INSTANCE_ID AND TRANSPARENCY.USER_ID = %s"
+
+        super(postgresqlgenerator, self).__init__(expr, calendarid, userid)
+
+
+    def generate(self):
+        """
+        Generate the actual SQL 'where ...' expression from the passed in
+        expression tree.
+        
+        @return: a C{tuple} of (C{str}, C{list}), where the C{str} is the
+            partial SQL statement, and the C{list} is the list of argument
+            substitutions to use with the SQL API execute method.
+        """
+
+        # Init state
+        self.sout = StringIO.StringIO()
+        self.arguments = []
+        self.substitutions = []
+        self.usedtimespan = False
+
+        # Generate ' where ...' partial statement
+        self.sout.write(self.WHERE)
+        self.generateExpression(self.expression)
+
+        # Prefix with ' from ...' partial statement
+        select = self.FROM + self.RESOURCEDB
+        if self.usedtimespan:
+            self.frontArgument(self.userid)
+            select += ", %s LEFT OUTER JOIN %s ON (%s)" % (
+                self.TIMESPANDB,
+                self.TRANSPARENCYDB,
+                self.TIMESPANTEST_JOIN_ON_PIECE
+            )
+        select += self.sout.getvalue()
+
+        select = select % tuple(self.substitutions)
+
+        return select, self.arguments
+
+
+    def addArgument(self, arg):
+        self.arguments.append(arg)
+        self.substitutions.append("%s")
+        self.sout.write("%s")
+
+    def setArgument(self, arg):
+        self.arguments.append(arg)
+        self.substitutions.append("%s")
+
+    def frontArgument(self, arg):
+        self.arguments.insert(0, arg)
+        self.substitutions.insert(0, "%s")
+
+    def containsArgument(self, arg):
+        return "%%%s%%" % (arg,)
+
+
 class PostgresLegacyIndexEmulator(LoggingMixIn):
     """
     Emulator for L{twistedcaldv.index.Index} and
@@ -798,40 +953,6 @@
 
 
 
-class PostgresLegacyNotificationsEmulator(object):
-    def __init__(self, notificationsCollection):
-        self._collection = notificationsCollection
-
-
-    def _recordForObject(self, notificationObject):
-        return NotificationRecord(
-            notificationObject.uid(),
-            notificationObject.name(),
-            notificationObject._fieldQuery("XML_TYPE"))
-
-
-    def recordForName(self, name):
-        return self._recordForObject(
-            self._collection.notificationObjectWithName(name)
-        )
-
-
-    def recordForUID(self, uid):
-        return self._recordForObject(
-            self._collection.notificationObjectWithUID(uid)
-        )
-
-
-    def removeRecordForUID(self, uid):
-        self._collection.removeNotificationObjectWithUID(uid)
-
-
-    def removeRecordForName(self, name):
-        self._collection.removeNotificationObjectWithName(name)
-
-
-
-
 # CARDDAV
 
 class postgresqladbkgenerator(sqlgenerator):
@@ -1056,336 +1177,3 @@
                 [name, self.addressbook._resourceID]
             )
         )
-
-
-class PostgresLegacyABInvitesEmulator(object):
-    """
-    Emulator for the implicit interface specified by
-    L{twistedcaldav.sharing.InvitesDatabase}.
-    """
-
-
-    def __init__(self, addressbook):
-        self._addressbook = addressbook
-
-
-    @property
-    def _txn(self):
-        return self._addressbook._txn
-
-
-    def create(self):
-        "No-op, because the index implicitly always exists in the database."
-
-
-    def remove(self):
-        "No-op, because the index implicitly always exists in the database."
-
-
-    def allRecords(self):
-        for row in self._txn.execSQL(
-                """
-                select
-                    INVITE.INVITE_UID, INVITE.NAME, INVITE.RECIPIENT_ADDRESS,
-                    ADDRESSBOOK_HOME.OWNER_UID, ADDRESSBOOK_BIND.BIND_MODE,
-                    ADDRESSBOOK_BIND.BIND_STATUS, ADDRESSBOOK_BIND.MESSAGE
-                from
-                    INVITE, ADDRESSBOOK_HOME, ADDRESSBOOK_BIND
-                where
-                    INVITE.RESOURCE_ID = %s and
-                    INVITE.HOME_RESOURCE_ID = 
-                        ADDRESSBOOK_HOME.RESOURCE_ID and
-                    ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_ID =
-                        INVITE.RESOURCE_ID and
-                    ADDRESSBOOK_BIND.ADDRESSBOOK_HOME_RESOURCE_ID =
-                        INVITE.HOME_RESOURCE_ID
-                order by
-                    INVITE.NAME asc
-                """, [self._addressbook._resourceID]):
-            yield self._makeInvite(row)
-
-
-    def recordForUserID(self, userid):
-        rows = self._txn.execSQL(
-            """
-            select
-                INVITE.INVITE_UID, INVITE.NAME, INVITE.RECIPIENT_ADDRESS,
-                ADDRESSBOOK_HOME.OWNER_UID, ADDRESSBOOK_BIND.BIND_MODE,
-                ADDRESSBOOK_BIND.BIND_STATUS, ADDRESSBOOK_BIND.MESSAGE
-            from
-                INVITE, ADDRESSBOOK_HOME, ADDRESSBOOK_BIND
-            where INVITE.RECIPIENT_ADDRESS = %s
-             and INVITE.HOME_RESOURCE_ID = ADDRESSBOOK_HOME.RESOURCE_ID
-             and ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_ID = INVITE.RESOURCE_ID
-             and ADDRESSBOOK_BIND.ADDRESSBOOK_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID
-            """,
-            [userid]
-        )
-        return self._makeInvite(rows[0]) if rows else None
-
-
-    def recordForPrincipalURL(self, principalURL):
-        for record in self.allRecords():
-            if record.principalURL == principalURL:
-                return record
-
-
-    def recordForInviteUID(self, inviteUID):
-        rows = self._txn.execSQL(
-            """
-            select
-                INVITE.INVITE_UID, INVITE.NAME, INVITE.RECIPIENT_ADDRESS,
-                ADDRESSBOOK_HOME.OWNER_UID, ADDRESSBOOK_BIND.BIND_MODE,
-                ADDRESSBOOK_BIND.BIND_STATUS, ADDRESSBOOK_BIND.MESSAGE
-            from
-                INVITE, ADDRESSBOOK_HOME, ADDRESSBOOK_BIND
-            where INVITE.INVITE_UID = %s
-             and INVITE.HOME_RESOURCE_ID = ADDRESSBOOK_HOME.RESOURCE_ID
-             and ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_ID = INVITE.RESOURCE_ID
-             and ADDRESSBOOK_BIND.ADDRESSBOOK_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID
-            """,
-            [inviteUID]
-        )
-        return self._makeInvite(rows[0]) if rows else None
-
-
-    def _makeInvite(self, row):
-        [inviteuid, common_name, userid, ownerUID,
-            bindMode, bindStatus, summary] = row
-        # FIXME: this is really the responsibility of the protocol layer.
-        state = {
-            _BIND_STATUS_INVITED: "NEEDS-ACTION",
-            _BIND_STATUS_ACCEPTED: "ACCEPTED",
-            _BIND_STATUS_DECLINED: "DECLINED",
-            _BIND_STATUS_INVALID: "INVALID",
-        }[bindStatus]
-        access = {
-            _BIND_MODE_OWN: "own",
-            _BIND_MODE_READ: "read-only",
-            _BIND_MODE_WRITE: "read-write"
-        }[bindMode]
-        principalURL = "/principals/__uids__/%s/" % (ownerUID,)
-        return Invite(
-            inviteuid, userid, principalURL, common_name,
-            access, state, summary
-        )
-
-    def addOrUpdateRecord(self, record):
-        bindMode = {'read-only': _BIND_MODE_READ,
-                    'read-write': _BIND_MODE_WRITE}[record.access]
-        bindStatus = {
-            "NEEDS-ACTION": _BIND_STATUS_INVITED,
-            "ACCEPTED": _BIND_STATUS_ACCEPTED,
-            "DECLINED": _BIND_STATUS_DECLINED,
-            "INVALID": _BIND_STATUS_INVALID,
-        }[record.state]
-        # principalURL is derived from a directory record's principalURL() so
-        # it will always contain the UID.  The form is '/principals/__uids__/x'
-        # (and may contain a trailing slash).
-        principalUID = record.principalURL.split("/")[3]
-        shareeHome = self._txn.addressbookHomeWithUID(principalUID, create=True)
-        rows = self._txn.execSQL(
-            "select RESOURCE_ID, HOME_RESOURCE_ID from INVITE where RECIPIENT_ADDRESS = %s",
-            [record.userid]
-        )
-        if rows:
-            [[resourceID, homeResourceID]] = rows
-            # Invite(inviteuid, userid, principalURL, common_name, access, state, summary)
-            self._txn.execSQL("""
-                update ADDRESSBOOK_BIND set BIND_MODE = %s,
-                BIND_STATUS = %s, MESSAGE = %s
-                where
-                    ADDRESSBOOK_RESOURCE_ID = %s and
-                    ADDRESSBOOK_HOME_RESOURCE_ID = %s
-            """, [bindMode, bindStatus, record.summary,
-                resourceID, homeResourceID])
-            self._txn.execSQL("""
-                update INVITE set NAME = %s, INVITE_UID = %s
-                where RECIPIENT_ADDRESS = %s
-                """,
-                [record.name, record.inviteuid, record.userid]
-            )
-        else:
-            self._txn.execSQL(
-                """
-                insert into INVITE (
-                    INVITE_UID, NAME,
-                    HOME_RESOURCE_ID, RESOURCE_ID,
-                    RECIPIENT_ADDRESS
-                )
-                values (%s, %s, %s, %s, %s)
-                """,
-                [
-                    record.inviteuid, record.name,
-                    shareeHome._resourceID, self._addressbook._resourceID,
-                    record.userid
-                ])
-            self._txn.execSQL(
-                """
-                insert into ADDRESSBOOK_BIND
-                (
-                    ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_ID, 
-                    ADDRESSBOOK_RESOURCE_NAME, BIND_MODE, BIND_STATUS,
-                    SEEN_BY_OWNER, SEEN_BY_SHAREE, MESSAGE
-                )
-                values (%s, %s, %s, %s, %s, %s, %s, %s)
-                """,
-                [
-                    shareeHome._resourceID,
-                    self._addressbook._resourceID,
-                    None, # this is NULL because it is not bound yet, let's be
-                          # explicit about that.
-                    bindMode,
-                    bindStatus,
-                    False,
-                    False,
-                    record.summary
-                ])
-
-
-    def removeRecordForUserID(self, userid):
-        self._txn.execSQL(
-            "delete from ADDRESSBOOK_BIND using INVITE "
-            "where INVITE.RECIPIENT_ADDRESS = %s "
-            " and ADDRESSBOOK_BIND.ADDRESSBOOK_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID "
-            " and ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_ID = INVITE.RESOURCE_ID",
-            [userid]
-        )
-        self._txn.execSQL(
-            "delete from INVITE where RECIPIENT_ADDRESS = %s",
-            [userid]
-        )
-
-
-    def removeRecordForInviteUID(self, inviteUID):
-        self._txn.execSQL(
-            "delete from ADDRESSBOOK_BIND using INVITE "
-            "where INVITE.INVITE_UID = %s "
-            " and ADDRESSBOOK_BIND.ADDRESSBOOK_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID "
-            " and ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_ID = INVITE.RESOURCE_ID",
-            [inviteUID]
-        )
-        self._txn.execSQL(
-            "delete from INVITE where INVITE_UID = %s",
-            [inviteUID]
-        )
-
-
-
-class PostgresLegacyABSharesEmulator(object):
-
-    def __init__(self, home):
-        self._home = home
-
-
-    @property
-    def _txn(self):
-        return self._home._txn
-
-
-    def create(self):
-        pass
-
-
-    def remove(self):
-        pass
-
-
-    def allRecords(self):
-        # This should have been a smart join that got all these columns at
-        # once, but let's not bother to fix it, since the actual query we
-        # _want_ to do (just look for addressbook binds in a particular homes) is
-        # much simpler anyway; we should just do that.
-        shareRows = self._txn.execSQL(
-            """
-            select ADDRESSBOOK_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME, MESSAGE
-            from ADDRESSBOOK_BIND
-                where ADDRESSBOOK_HOME_RESOURCE_ID = %s and
-                BIND_MODE != %s and
-                ADDRESSBOOK_RESOURCE_NAME is not null
-            """, [self._home._resourceID, _BIND_MODE_OWN])
-        for resourceID, resourceName, summary in shareRows:
-            [[shareuid]] = self._txn.execSQL(
-                """
-                select INVITE_UID
-                from INVITE
-                where RESOURCE_ID = %s and HOME_RESOURCE_ID = %s
-                """, [resourceID, self._home._resourceID])
-            sharetype = 'I'
-            [[ownerHomeID, ownerResourceName]] = self._txn.execSQL(
-                """
-                select ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME
-                from ADDRESSBOOK_BIND
-                where ADDRESSBOOK_RESOURCE_ID = %s and
-                    BIND_MODE = %s
-                """, [resourceID, _BIND_MODE_OWN]
-                )
-            [[ownerUID]] = self._txn.execSQL(
-                "select OWNER_UID from ADDRESSBOOK_HOME where RESOURCE_ID = %s",
-                [ownerHomeID])
-            hosturl = '/addressbooks/__uids__/%s/%s' % (
-                ownerUID, ownerResourceName
-            )
-            localname = resourceName
-            record = SharedCollectionRecord(
-                shareuid, sharetype, hosturl, localname, summary
-            )
-            yield record
-
-
-    def _search(self, **kw):
-        [[key, value]] = kw.items()
-        for record in self.allRecords():
-            if getattr(record, key) == value:
-                return record
-
-    def recordForLocalName(self, localname):
-        return self._search(localname=localname)
-
-    def recordForShareUID(self, shareUID):
-        return self._search(shareuid=shareUID)
-
-
-    def addOrUpdateRecord(self, record):
-#        print '*** SHARING***: Adding or updating this record:'
-#        import pprint
-#        pprint.pprint(record.__dict__)
-        # record.hosturl -> /addressbooks/__uids__/<uid>/<addressbookname>
-        splithost = record.hosturl.split('/')
-        ownerUID = splithost[3]
-        ownerAddressBookName = splithost[4]
-        ownerHome = self._txn.addressbookHomeWithUID(ownerUID)
-        ownerAddressBook = ownerHome.addressbookWithName(ownerAddressBookName)
-        addressbookResourceID = ownerAddressBook._resourceID
-
-        # There needs to be a bind already, one that corresponds to the
-        # invitation.  The invitation's UID is the same as the share UID.  I
-        # just need to update its 'localname', i.e.
-        # ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_NAME.
-
-        self._txn.execSQL(
-            """
-            update ADDRESSBOOK_BIND set ADDRESSBOOK_RESOURCE_NAME = %s
-            where ADDRESSBOOK_HOME_RESOURCE_ID = %s and ADDRESSBOOK_RESOURCE_ID = %s
-            """,
-            [record.localname, self._home._resourceID, addressbookResourceID]
-        )
-
-
-    def removeRecordForLocalName(self, localname):
-        self._txn.execSQL(
-            "update ADDRESSBOOK_BIND set ADDRESSBOOK_RESOURCE_NAME = NULL "
-            "where ADDRESSBOOK_RESOURCE_NAME = %s and ADDRESSBOOK_HOME_RESOURCE_ID = %s",
-            [localname, self._home._resourceID]
-        )
-
-
-    def removeRecordForShareUID(self, shareUID):
-        self._txn.execSQL(
-            "update ADDRESSBOOK_BIND set ADDRESSBOOK_RESOURCE_NAME = NULL "
-            "from INVITE "
-            "where INVITE.INVITE_UID = %s "
-            " and ADDRESSBOOK_BIND.ADDRESSBOOK_HOME_RESOURCE_ID = INVITE.HOME_RESOURCE_ID"
-            " and ADDRESSBOOK_BIND.ADDRESSBOOK_RESOURCE_ID = INVITE.RESOURCE_ID",
-            [shareUID,]
-        )
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100827/e8e72da0/attachment-0001.html>


More information about the calendarserver-changes mailing list