[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