[CalendarServer-changes] [11945] CalendarServer/branches/users/cdaboo/sharing-in-the-store
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:18:32 PDT 2014
Revision: 11945
http://trac.calendarserver.org//changeset/11945
Author: cdaboo at apple.com
Date: 2013-11-13 19:47:16 -0800 (Wed, 13 Nov 2013)
Log Message:
-----------
Switch notifications to be stored as JSON in the DB but re-written to XML in the app.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/sharing-in-the-store/calendarserver/tap/caldav.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/customxml.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/sharing.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/storebridge.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/caldav/datastore/test/common.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/file.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current.sql
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/test/util.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrade.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/util.py
Added Paths:
-----------
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/oracle-dialect/v28.sql
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/postgres-dialect/v28.sql
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_28_to_29.sql
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_28_to_29.sql
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py
CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/test/test_notification_upgrade_from_0_to_1.py
Property Changed:
----------------
CalendarServer/branches/users/cdaboo/sharing-in-the-store/
Property changes on: CalendarServer/branches/users/cdaboo/sharing-in-the-store
___________________________________________________________________
Modified: svn:mergeinfo
- /CalDAVTester/trunk:11193-11198
/CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/json:11622-11912
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
/CalendarServer/branches/users/glyph/hang-fix:11465-11491
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
+ /CalDAVTester/trunk:11193-11198
/CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/json:11622-11912
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
/CalendarServer/branches/users/glyph/hang-fix:11465-11491
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:11935-11938
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/calendarserver/tap/caldav.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/calendarserver/tap/caldav.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -72,8 +72,7 @@
from txdav.common.datastore.upgrade.sql.upgrade import (
UpgradeDatabaseSchemaStep, UpgradeDatabaseAddressBookDataStep,
UpgradeDatabaseCalendarDataStep, UpgradeDatabaseOtherStep,
- UpgradeAcquireLockStep, UpgradeReleaseLockStep
-)
+ UpgradeAcquireLockStep, UpgradeReleaseLockStep, UpgradeDatabaseNotificationDataStep)
from txdav.common.datastore.upgrade.migrate import UpgradeToDatabaseStep
from txdav.caldav.datastore.scheduling.imip.inbound import MailRetriever
from txdav.caldav.datastore.scheduling.imip.inbound import scheduleNextMailPoll
@@ -1420,6 +1419,12 @@
)
pps.addStep(
+ UpgradeDatabaseNotificationDataStep(
+ store, uid=overrideUID, gid=overrideGID
+ )
+ )
+
+ pps.addStep(
UpgradeToDatabaseStep(
UpgradeToDatabaseStep.fileStoreFromPath(
CachingFilePath(config.DocumentRoot)
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/customxml.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/customxml.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -639,8 +639,9 @@
name = "dtstamp"
def __init__(self, *children):
- super(DTStamp, self).__init__(children)
- self.children = (PCDATAElement(DateTime.getNowUTC().getText()),)
+ super(DTStamp, self).__init__(*children)
+ if not self.children:
+ self.children = (PCDATAElement(DateTime.getNowUTC().getText()),)
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/sharing.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/sharing.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -48,7 +48,9 @@
from pycalendar.datetime import DateTime
+import json
+
# FIXME: Get rid of these imports
from twistedcaldav.directory.util import TRANSACTION_KEY
# circular import
@@ -706,19 +708,16 @@
def sendInviteNotification(self, invitation, request, notificationState=None, displayName=None):
ownerPrincipal = (yield self.ownerPrincipal(request))
- # FIXME: use urn:uuid in all cases
- if self.isCalendarCollection():
- owner = ownerPrincipal.principalURL()
- else:
- owner = "urn:uuid:" + ownerPrincipal.principalUID()
- ownerCN = ownerPrincipal.displayName()
- hosturl = (yield self.canonicalURL(request))
# Locate notifications collection for user
sharee = self.principalForUID(invitation.shareeUID())
if sharee is None:
raise ValueError("sharee is None but principalUID was valid before")
+ hosturl = self._newStoreObject.name()
+ if self.sharedResourceType() == "group":
+ hosturl = self._newStoreObject.parentCollection().name() + "/" + hosturl
+
# We need to look up the resource so that the response cache notifier is properly initialized
notificationResource = (yield request.locateResource(sharee.notificationURL()))
notifications = notificationResource._newStoreNotifications
@@ -733,32 +732,31 @@
'''
# Generate invite XML
- userid = "urn:uuid:" + invitation.shareeUID()
state = notificationState if notificationState else invitation.status()
summary = invitation.summary() if displayName is None else displayName
- typeAttr = {'shared-type': self.sharedResourceType()}
- xmltype = customxml.InviteNotification(**typeAttr)
- xmldata = customxml.Notification(
- customxml.DTStamp.fromString(DateTime.getNowUTC().getText()),
- customxml.InviteNotification(
- customxml.UID.fromString(invitation.uid()),
- element.HRef.fromString(userid),
- invitationBindStatusToXMLMap[state](),
- customxml.InviteAccess(invitationBindModeToXMLMap[invitation.mode()]()),
- customxml.HostURL(
- element.HRef.fromString(hosturl),
- ),
- customxml.Organizer(
- element.HRef.fromString(owner),
- customxml.CommonName.fromString(ownerCN),
- ),
- customxml.InviteSummary.fromString(summary),
- self.getSupportedComponentSet() if self.isCalendarCollection() else None,
- **typeAttr
- ),
- ).toxml()
+ xmltype = {
+ "notification-type": "invite-notification",
+ "shared-type": self.sharedResourceType(),
+ }
+ xmldata = {
+ "notification-type": "invite-notification",
+ "shared-type": self.sharedResourceType(),
+ "dtstamp": DateTime.getNowUTC().getText(),
+ "owner": ownerPrincipal.principalUID(),
+ "sharee": invitation.shareeUID(),
+ "uid": invitation.uid(),
+ "status": state,
+ "access": invitation.mode(),
+ "name": hosturl,
+ "summary": summary,
+ }
+ if self.isCalendarCollection():
+ xmldata["supported-components"] = self._newStoreObject.getSupportedComponents()
+ xmltype = json.dumps(xmltype)
+ xmldata = json.dumps(xmldata)
+
# Add to collections
yield notifications.writeNotificationObject(invitation.uid(), xmltype, xmldata)
@@ -1333,52 +1331,41 @@
def sendReply(self, request, shareePrincipal, sharedResource, state, hostUrl, replytoUID, displayname=None):
# Locate notifications collection for owner
- owner = (yield sharedResource.ownerPrincipal(request))
- if owner is None:
+ ownerPrincipal = (yield sharedResource.ownerPrincipal(request))
+ if ownerPrincipal is None:
# FIXME: have to return here rather than raise to allow removal of a share for a sharer
# whose principal is no longer valid yet still exists in the store. Really we need to get rid of
# locateResource calls and just do everything via store objects.
returnValue(None)
- notificationResource = (yield request.locateResource(owner.notificationURL()))
+ hosturl = sharedResource._newStoreObject.name()
+ if sharedResource.sharedResourceType() == "group":
+ hosturl = sharedResource._newStoreObject.parentCollection().name() + "/" + hosturl
+
+ notificationResource = (yield request.locateResource(ownerPrincipal.notificationURL()))
notifications = notificationResource._newStoreNotifications
# Generate invite XML
notificationUID = "%s-reply" % (replytoUID,)
- xmltype = customxml.InviteReply()
- # FIXME: use urn:uuid in all cases
- if self._newStoreHome and self._newStoreHome._homeType == EADDRESSBOOKTYPE:
- cua = "urn:uuid:" + shareePrincipal.principalUID()
- else:
- # Prefer mailto:, otherwise use principal URL
- for cua in shareePrincipal.calendarUserAddresses():
- if cua.startswith("mailto:"):
- break
- else:
- cua = shareePrincipal.principalURL()
+ xmltype = {
+ "notification-type": "invite-reply",
+ }
- commonName = shareePrincipal.displayName()
- record = shareePrincipal.record
+ xmldata = {
+ "notification-type": "invite-reply",
+ "shared-type": sharedResource.sharedResourceType(),
+ "dtstamp": DateTime.getNowUTC().getText(),
+ "owner": ownerPrincipal.principalUID(),
+ "sharee": shareePrincipal.principalUID(),
+ "status": state,
+ "name": hosturl,
+ "in-reply-to": replytoUID,
+ "summary": displayname if displayname is not None else "",
+ }
- xmldata = customxml.Notification(
- customxml.DTStamp.fromString(DateTime.getNowUTC().getText()),
- customxml.InviteReply(
- *(
- (
- element.HRef.fromString(cua),
- invitationBindStatusToXMLMap[state](),
- customxml.HostURL(
- element.HRef.fromString(hostUrl),
- ),
- customxml.InReplyTo.fromString(replytoUID),
- ) + ((customxml.InviteSummary.fromString(displayname),) if displayname is not None else ())
- + ((customxml.CommonName.fromString(commonName),) if commonName is not None else ())
- + ((customxml.FirstNameProperty(record.firstName),) if record.firstName is not None else ())
- + ((customxml.LastNameProperty(record.lastName),) if record.lastName is not None else ())
- )
- ),
- ).toxml()
+ xmltype = json.dumps(xmltype)
+ xmldata = json.dumps(xmldata)
# Add to collections
yield notifications.writeNotificationObject(notificationUID, xmltype, xmldata)
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/storebridge.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/twistedcaldav/storebridge.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -70,10 +70,10 @@
UIDExistsElsewhereError, InvalidUIDError, InvalidResourceMove, \
InvalidComponentForStoreError
from txdav.idav import PropertyChangeNotAllowedError
-from txdav.xml import element as davxml
+from txdav.xml import element as davxml, element
from txdav.xml.base import dav_namespace, WebDAVUnknownElement, encodeXMLName
-from urlparse import urlsplit
+from urlparse import urlsplit, urljoin
import hashlib
import time
import uuid
@@ -84,6 +84,9 @@
TooManyInstancesError
from twistedcaldav.util import bestAcceptType
import collections
+from twistedcaldav.sharing import invitationBindStatusToXMLMap, \
+ invitationBindModeToXMLMap
+import json
"""
Wrappers to translate between the APIs in L{txdav.caldav.icalendarstore} and
@@ -3717,7 +3720,16 @@
qname = prop.qname()
if qname == customxml.NotificationType.qname():
- returnValue(self._newStoreObject.xmlType())
+ jsontype = self._newStoreObject.xmlType()
+ jsontype = json.loads(jsontype)
+ if jsontype["notification-type"] == "invite-notification":
+ typeAttr = {"shared-type": jsontype["shared-type"]}
+ xmltype = customxml.InviteNotification(**typeAttr)
+ elif jsontype["notification-type"] == "invite-reply":
+ xmltype = customxml.InviteReply()
+ else:
+ raise HTTPError(responsecode.INTERNAL_SERVER_ERROR)
+ returnValue(customxml.NotificationType(xmltype))
returnValue((yield super(StoreNotificationObjectFile, self).readProperty(prop, request)))
@@ -3730,11 +3742,99 @@
return succeed(self._newStoreObject.size())
+ @inlineCallbacks
def text(self, ignored=None):
assert ignored is None, "This is a notification object, not a notification"
- return self._newStoreObject.xmldata()
+ jsondata = (yield self._newStoreObject.xmldata())
+ jsondata = json.loads(jsondata)
+ if jsondata["notification-type"] == "invite-notification":
+ ownerPrincipal = self.principalForUID(jsondata["owner"])
+ ownerCN = ownerPrincipal.displayName()
+ ownerHomeURL = ownerPrincipal.calendarHomeURLs()[0] if jsondata["shared-type"] == "calendar" else ownerPrincipal.addressBookHomeURLs()[0]
+ # FIXME: use urn:uuid always?
+ if jsondata["shared-type"] == "calendar":
+ owner = ownerPrincipal.principalURL()
+ else:
+ owner = "urn:uuid:" + ownerPrincipal.principalUID()
+ shareePrincipal = self.principalForUID(jsondata["sharee"])
+
+ if "supported-components" in jsondata:
+ comps = jsondata["supported-components"]
+ if comps:
+ comps = comps.split(",")
+ else:
+ comps = ical.allowedStoreComponents
+ supported = caldavxml.SupportedCalendarComponentSet(
+ *[caldavxml.CalendarComponent(name=item) for item in comps]
+ )
+ else:
+ supported = None
+
+ typeAttr = {"shared-type": jsondata["shared-type"]}
+ xmldata = customxml.Notification(
+ customxml.DTStamp.fromString(jsondata["dtstamp"]),
+ customxml.InviteNotification(
+ customxml.UID.fromString(jsondata["uid"]),
+ element.HRef.fromString("urn:uuid:" + jsondata["sharee"]),
+ invitationBindStatusToXMLMap[jsondata["status"]](),
+ customxml.InviteAccess(invitationBindModeToXMLMap[jsondata["access"]]()),
+ customxml.HostURL(
+ element.HRef.fromString(urljoin(ownerHomeURL, jsondata["name"])),
+ ),
+ customxml.Organizer(
+ element.HRef.fromString(owner),
+ customxml.CommonName.fromString(ownerCN),
+ ),
+ customxml.InviteSummary.fromString(jsondata["summary"]),
+ supported,
+ **typeAttr
+ ),
+ )
+ elif jsondata["notification-type"] == "invite-reply":
+ ownerPrincipal = self.principalForUID(jsondata["owner"])
+ ownerHomeURL = ownerPrincipal.calendarHomeURLs()[0] if jsondata["shared-type"] == "calendar" else ownerPrincipal.addressBookHomeURLs()[0]
+
+ shareePrincipal = self.principalForUID(jsondata["sharee"])
+
+ # FIXME: use urn:uuid always?
+ if jsondata["shared-type"] == "calendar":
+ # Prefer mailto:, otherwise use principal URL
+ for cua in shareePrincipal.calendarUserAddresses():
+ if cua.startswith("mailto:"):
+ break
+ else:
+ cua = shareePrincipal.principalURL()
+ else:
+ cua = "urn:uuid:" + shareePrincipal.principalUID()
+
+ commonName = shareePrincipal.displayName()
+ record = shareePrincipal.record
+
+ xmldata = customxml.Notification(
+ customxml.DTStamp.fromString(jsondata["dtstamp"]),
+ customxml.InviteReply(
+ *(
+ (
+ element.HRef.fromString(cua),
+ invitationBindStatusToXMLMap[jsondata["status"]](),
+ customxml.HostURL(
+ element.HRef.fromString(urljoin(ownerHomeURL, jsondata["name"])),
+ ),
+ customxml.InReplyTo.fromString(jsondata["in-reply-to"]),
+ ) + ((customxml.InviteSummary.fromString(jsondata["summary"]),) if jsondata["summary"] else ())
+ + ((customxml.CommonName.fromString(commonName),) if commonName else ())
+ + ((customxml.FirstNameProperty(record.firstName),) if record.firstName else ())
+ + ((customxml.LastNameProperty(record.lastName),) if record.lastName else ())
+ )
+ ),
+ )
+ else:
+ raise HTTPError(responsecode.INTERNAL_SERVER_ERROR)
+ returnValue(xmldata.toxml())
+
+
@requiresPermissions(davxml.Read())
@inlineCallbacks
def http_GET(self, request):
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/caldav/datastore/test/common.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/caldav/datastore/test/common.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -48,14 +48,15 @@
ICalendar, ICalendarTransaction,
ComponentUpdateState)
-from twistedcaldav.customxml import InviteNotification, InviteSummary
from txdav.common.datastore.test.util import transactionClean
from txdav.common.icommondatastore import ConcurrentModification
from twistedcaldav.ical import Component
from twistedcaldav.config import config
from calendarserver.push.util import PushPriority
+import json
+
storePath = FilePath(__file__).parent().child("calendar_store")
homeRoot = storePath.child("ho").child("me").child("home1")
@@ -374,9 +375,11 @@
def notificationUnderTest(self):
txn = self.transactionUnderTest()
notifications = yield txn.notificationsWithUID("home1")
- inviteNotification = InviteNotification()
- yield notifications.writeNotificationObject("abc", inviteNotification,
- inviteNotification.toxml())
+ yield notifications.writeNotificationObject(
+ "abc",
+ "{\"notification-type\":\"invite-notification\"}",
+ "{\"notification-type\":\"invite-notification\"}"
+ )
notificationObject = yield notifications.notificationObjectWithUID("abc")
returnValue(notificationObject)
@@ -399,10 +402,9 @@
"""
txn = self.transactionUnderTest()
coll = yield txn.notificationsWithUID("home1")
- invite1 = InviteNotification()
- yield coll.writeNotificationObject("1", invite1, invite1.toxml())
+ yield coll.writeNotificationObject("1", "{\"notification-type\":\"invite-notification\"}", "{\"notification-type\":\"invite-notification\"}")
st = yield coll.syncToken()
- yield coll.writeNotificationObject("2", invite1, invite1.toxml())
+ yield coll.writeNotificationObject("2", "{\"notification-type\":\"invite-notification\"}", "{\"notification-type\":\"invite-notification\"}")
rev = self.token2revision(st)
yield coll.removeNotificationObjectWithUID("1")
st2 = yield coll.syncToken()
@@ -424,14 +426,21 @@
notifications = yield self.transactionUnderTest().notificationsWithUID(
"home1"
)
- inviteNotification = InviteNotification()
- yield notifications.writeNotificationObject("abc", inviteNotification,
- inviteNotification.toxml())
- inviteNotification2 = InviteNotification(InviteSummary("a summary"))
yield notifications.writeNotificationObject(
- "abc", inviteNotification, inviteNotification2.toxml())
+ "abc",
+ "{\"notification-type\":\"invite-notification\"}",
+ "{\"notification-type\":\"invite-notification\"}",
+ )
+ yield notifications.writeNotificationObject(
+ "abc",
+ "{\"notification-type\":\"invite-notification\"}",
+ "{\"notification-type\":\"invite-notification\",\"summary\":\"a summary\"}",
+ )
abc = yield notifications.notificationObjectWithUID("abc")
- self.assertEquals((yield abc.xmldata()), inviteNotification2.toxml())
+ self.assertEquals(
+ json.loads((yield abc.xmldata())),
+ json.loads("{\"notification-type\":\"invite-notification\",\"summary\":\"a summary\"}"),
+ )
@inlineCallbacks
@@ -450,9 +459,11 @@
"home1"
)
self.notifierFactory.reset()
- inviteNotification = InviteNotification()
- yield notifications.writeNotificationObject("abc", inviteNotification,
- inviteNotification.toxml())
+ yield notifications.writeNotificationObject(
+ "abc",
+ "{\"notification-type\":\"invite-notification\"}",
+ "{\"notification-type\":\"invite-notification\"}",
+ )
# notify is called prior to commit
self.assertEquals(
@@ -492,12 +503,16 @@
notifications = yield self.transactionUnderTest().notificationsWithUID(
"home1"
)
- inviteNotification = InviteNotification()
- yield notifications.writeNotificationObject("abc", inviteNotification,
- inviteNotification.toxml())
- inviteNotification2 = InviteNotification(InviteSummary("a summary"))
yield notifications.writeNotificationObject(
- "def", inviteNotification, inviteNotification2.toxml())
+ "abc",
+ "{\"notification-type\":\"invite-notification\"}",
+ "{\"notification-type\":\"invite-notification\"}",
+ )
+ yield notifications.writeNotificationObject(
+ "def",
+ "{\"notification-type\":\"invite-notification\"}",
+ "{\"notification-type\":\"invite-notification\",\"summary\":\"a summary\"}",
+ )
yield self.commit()
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/file.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/file.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -1509,7 +1509,7 @@
self._cachedObjectResources[name] = objectResource
# Update database
- self.retrieveOldIndex().addOrUpdateRecord(NotificationRecord(uid, name, xmltype.name))
+ self.retrieveOldIndex().addOrUpdateRecord(NotificationRecord(uid, name, xmltype))
self.notifyChanged()
@@ -1576,7 +1576,7 @@
rname = uid + ".xml"
self._parentCollection.retrieveOldIndex().addOrUpdateRecord(
- NotificationRecord(uid, rname, xmltype.name)
+ NotificationRecord(uid, rname, xmltype)
)
self._xmldata = xmldata
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -50,7 +50,6 @@
from twisted.python.util import FancyEqMixin
from twistedcaldav.config import config
-from twistedcaldav.customxml import NotificationType
from twistedcaldav.dateops import datetimeMktime, pyCalendarTodatetime
from txdav.base.datastore.util import QueryCacher
@@ -72,7 +71,6 @@
from txdav.common.idirectoryservice import IStoreDirectoryService
from txdav.common.inotifications import INotificationCollection, \
INotificationObject
-from txdav.xml.parser import WebDAVDocument
from txdav.idav import ChangeCategory
from uuid import uuid4, UUID
@@ -639,6 +637,14 @@
return NotificationCollection.notificationsWithUID(self, uid, create)
+ @memoizedKey("rid", "_notificationHomes")
+ def notificationsWithResourceID(self, rid):
+ """
+ Implement notificationsWithResourceID.
+ """
+ return NotificationCollection.notificationsWithResourceID(self, rid)
+
+
@classproperty
def _insertAPNSubscriptionQuery(cls): #@NoSelf
apn = schema.APN_SUBSCRIPTIONS
@@ -4914,6 +4920,7 @@
self._txn = txn
self._uid = uid
self._resourceID = resourceID
+ self._dataVersion = None
self._notifications = {}
self._notificationNames = None
self._syncTokenRevision = None
@@ -4926,6 +4933,10 @@
[_homeSchema.RESOURCE_ID], From=_homeSchema,
Where=_homeSchema.OWNER_UID == Parameter("uid"))
+ _UIDFromResourceIDQuery = Select(
+ [_homeSchema.OWNER_UID], From=_homeSchema,
+ Where=_homeSchema.RESOURCE_ID == Parameter("rid"))
+
_provisionNewNotificationsQuery = Insert(
{_homeSchema.OWNER_UID: Parameter("uid")},
Return=_homeSchema.RESOURCE_ID
@@ -4984,7 +4995,20 @@
returnValue(collection)
+ @classmethod
@inlineCallbacks
+ def notificationsWithResourceID(cls, txn, rid):
+ rows = yield cls._UIDFromResourceIDQuery.on(txn, rid=rid)
+
+ if rows:
+ uid = rows[0][0]
+ result = (yield cls.notificationsWithUID(txn, uid, create=False))
+ returnValue(result)
+ else:
+ returnValue(None)
+
+
+ @inlineCallbacks
def _loadPropertyStore(self):
self._propertyStore = yield PropertyStore.load(
self._uid,
@@ -5009,6 +5033,23 @@
return self._resourceID
+ @classproperty
+ def _dataVersionQuery(cls): #@NoSelf
+ nh = cls._homeSchema
+ return Select(
+ [nh.DATAVERSION], From=nh,
+ Where=nh.RESOURCE_ID == Parameter("resourceID")
+ )
+
+
+ @inlineCallbacks
+ def dataVersion(self):
+ if self._dataVersion is None:
+ self._dataVersion = (yield self._dataVersionQuery.on(
+ self._txn, resourceID=self._resourceID))[0][0]
+ returnValue(self._dataVersion)
+
+
def name(self):
return "notification"
@@ -5233,6 +5274,11 @@
class NotificationObject(FancyEqMixin, object):
+ """
+ This used to store XML data and an XML element for the type. But we are now switching it
+ to use JSON internally. The app layer will convert that to XML and fill in the "blanks" as
+ needed for the app.
+ """
log = Logger()
implements(INotificationObject)
@@ -5266,12 +5312,12 @@
DAL query to load all columns by home ID.
"""
obj = cls._objectSchema
- return Select([obj.RESOURCE_ID, obj.NOTIFICATION_UID, obj.MD5,
- Len(obj.XML_DATA), obj.XML_TYPE, obj.CREATED,
- obj.MODIFIED],
- From=obj,
- Where=(obj.NOTIFICATION_HOME_RESOURCE_ID == Parameter(
- "homeID")))
+ return Select(
+ [obj.RESOURCE_ID, obj.NOTIFICATION_UID, obj.MD5,
+ Len(obj.XML_DATA), obj.XML_TYPE, obj.CREATED, obj.MODIFIED],
+ From=obj,
+ Where=(obj.NOTIFICATION_HOME_RESOURCE_ID == Parameter("homeID"))
+ )
@classmethod
@@ -5434,20 +5480,20 @@
Set the object resource data and update and cached metadata.
"""
- self._xmlType = NotificationType(xmltype)
+ self._xmlType = xmltype
self._md5 = hashlib.md5(xmldata).hexdigest()
self._size = len(xmldata)
if inserting:
rows = yield self._newNotificationQuery.on(
self._txn, homeID=self._home._resourceID, uid=uid,
- xmlType=self._xmlType.toxml(), xmlData=xmldata, md5=self._md5
+ xmlType=self._xmlType, xmlData=xmldata, md5=self._md5
)
self._resourceID, self._created, self._modified = rows[0]
self._loadPropertyStore()
else:
rows = yield self._updateNotificationQuery.on(
self._txn, homeID=self._home._resourceID, uid=uid,
- xmlType=self._xmlType.toxml(), xmlData=xmldata, md5=self._md5
+ xmlType=self._xmlType, xmlData=xmldata, md5=self._md5
)
self._modified = rows[0][0]
self._objectText = xmldata
@@ -5482,11 +5528,6 @@
def xmlType(self):
- # NB This is the NotificationType property element
- if isinstance(self._xmlType, str):
- # Convert into NotificationType property element
- self._xmlType = WebDAVDocument.fromString(self._xmlType).root_element
-
return self._xmlType
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current-oracle-dialect.sql 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current-oracle-dialect.sql 2013-11-14 03:47:16 UTC (rev 11945)
@@ -49,7 +49,8 @@
create table NOTIFICATION_HOME (
"RESOURCE_ID" integer primary key,
- "OWNER_UID" nvarchar2(255) unique
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
);
create table NOTIFICATION (
@@ -367,9 +368,10 @@
"VALUE" nvarchar2(255)
);
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '28');
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '29');
insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
+insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');
create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
DEFAULT_EVENTS
);
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current.sql 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/current.sql 2013-11-14 03:47:16 UTC (rev 11945)
@@ -109,7 +109,8 @@
create table NOTIFICATION_HOME (
RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
- OWNER_UID varchar(255) not null unique -- implicit index
+ OWNER_UID varchar(255) not null unique, -- implicit index
+ DATAVERSION integer default 0 not null
);
create table NOTIFICATION (
@@ -699,6 +700,7 @@
VALUE varchar(255)
);
-insert into CALENDARSERVER values ('VERSION', '28');
+insert into CALENDARSERVER values ('VERSION', '29');
insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
+insert into CALENDARSERVER values ('NOTIFICATION-DATAVERSION', '1');
Added: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/oracle-dialect/v28.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/oracle-dialect/v28.sql (rev 0)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/oracle-dialect/v28.sql 2013-11-14 03:47:16 UTC (rev 11945)
@@ -0,0 +1,501 @@
+create sequence RESOURCE_ID_SEQ;
+create sequence INSTANCE_ID_SEQ;
+create sequence ATTACHMENT_ID_SEQ;
+create sequence REVISION_SEQ;
+create sequence WORKITEM_SEQ;
+create table NODE_INFO (
+ "HOSTNAME" nvarchar2(255),
+ "PID" integer not null,
+ "PORT" integer not null,
+ "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null,
+ primary key("HOSTNAME", "PORT")
+);
+
+create table NAMED_LOCK (
+ "LOCK_NAME" nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table CALENDAR (
+ "RESOURCE_ID" integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
+ "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
+ "DEFAULT_POLLS" integer default null references CALENDAR on delete set null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "AVAILABILITY" nclob default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
+ "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+ "RESOURCE_ID" integer primary key,
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
+ "NOTIFICATION_UID" nvarchar2(255),
+ "XML_TYPE" nvarchar2(255),
+ "XML_DATA" nclob,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
+);
+
+create table CALENDAR_BIND (
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+ "CALENDAR_RESOURCE_NAME" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ "TRANSP" integer default 0 not null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "TIMEZONE" nclob default null,
+ primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
+ unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
+);
+
+create table CALENDAR_BIND_MODE (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
+create table CALENDAR_BIND_STATUS (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
+create table CALENDAR_TRANSP (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
+create table CALENDAR_OBJECT (
+ "RESOURCE_ID" integer primary key,
+ "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob,
+ "ICALENDAR_UID" nvarchar2(255),
+ "ICALENDAR_TYPE" nvarchar2(255),
+ "ATTACHMENTS_MODE" integer default 0 not null,
+ "DROPBOX_ID" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "RECURRANCE_MIN" date,
+ "RECURRANCE_MAX" date,
+ "ACCESS" integer default 0 not null,
+ "SCHEDULE_OBJECT" integer default 0,
+ "SCHEDULE_TAG" nvarchar2(36) default null,
+ "SCHEDULE_ETAGS" nclob default null,
+ "PRIVATE_COMMENTS" integer default 0 not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
+create table CALENDAR_ACCESS_TYPE (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(32) unique
+);
+
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
+create table TIME_RANGE (
+ "INSTANCE_ID" integer primary key,
+ "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+ "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
+ "FLOATING" integer not null,
+ "START_DATE" timestamp not null,
+ "END_DATE" timestamp not null,
+ "FBTYPE" integer not null,
+ "TRANSPARENT" integer not null
+);
+
+create table FREE_BUSY_TYPE (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
+create table TRANSPARENCY (
+ "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
+ "USER_ID" nvarchar2(255),
+ "TRANSPARENT" integer not null
+);
+
+create table ATTACHMENT (
+ "ATTACHMENT_ID" integer primary key,
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "DROPBOX_ID" nvarchar2(255),
+ "CONTENT_TYPE" nvarchar2(255),
+ "SIZE" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PATH" nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+ "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
+ "MANAGED_ID" nvarchar2(255),
+ "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
+ primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"),
+ unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
+);
+
+create table RESOURCE_PROPERTY (
+ "RESOURCE_ID" integer not null,
+ "NAME" nvarchar2(255),
+ "VALUE" nclob,
+ "VIEWER_UID" nvarchar2(255),
+ primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
+);
+
+create table ADDRESSBOOK_HOME (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table SHARED_ADDRESSBOOK_BIND (
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
+ "OWNER_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "ADDRESSBOOK_RESOURCE_NAME" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "OWNER_HOME_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
+);
+
+create table ADDRESSBOOK_OBJECT (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "VCARD_TEXT" nclob,
+ "VCARD_UID" nvarchar2(255),
+ "KIND" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "RESOURCE_NAME"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "VCARD_UID")
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('person', 0);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('group', 1);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
+create table ABO_MEMBERS (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT,
+ primary key("GROUP_ID", "MEMBER_ID")
+);
+
+create table ABO_FOREIGN_MEMBERS (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ADDRESS" nvarchar2(255),
+ primary key("GROUP_ID", "MEMBER_ADDRESS")
+);
+
+create table SHARED_GROUP_BIND (
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
+ "GROUP_RESOURCE_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "GROUP_ADDRESSBOOK_NAME" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_ADDRESSBOOK_NAME")
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "CALENDAR_RESOURCE_ID" integer references CALENDAR,
+ "CALENDAR_NAME" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
+ "OWNER_HOME_RESOURCE_ID" integer references ADDRESSBOOK_HOME,
+ "ADDRESSBOOK_NAME" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null,
+ unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table APN_SUBSCRIPTIONS (
+ "TOKEN" nvarchar2(255),
+ "RESOURCE_KEY" nvarchar2(255),
+ "MODIFIED" integer not null,
+ "SUBSCRIBER_GUID" nvarchar2(255),
+ "USER_AGENT" nvarchar2(255) default null,
+ "IP_ADDR" nvarchar2(255) default null,
+ primary key("TOKEN", "RESOURCE_KEY")
+);
+
+create table IMIP_TOKENS (
+ "TOKEN" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALUID" nvarchar2(255),
+ "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ primary key("ORGANIZER", "ATTENDEE", "ICALUID")
+);
+
+create table IMIP_INVITATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "FROM_ADDR" nvarchar2(255),
+ "TO_ADDR" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table IMIP_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PUSH_ID" nvarchar2(255),
+ "PRIORITY" integer not null
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+ "NAME" nvarchar2(255) primary key,
+ "VALUE" nvarchar2(255)
+);
+
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '28');
+insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
+create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
+ DEFAULT_EVENTS
+);
+
+create index CALENDAR_HOME_METADAT_d55e5548 on CALENDAR_HOME_METADATA (
+ DEFAULT_TASKS
+);
+
+create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
+ DEFAULT_POLLS
+);
+
+create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
+ NOTIFICATION_HOME_RESOURCE_ID
+);
+
+create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
+ CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
+ CALENDAR_RESOURCE_ID,
+ ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
+ CALENDAR_RESOURCE_ID,
+ RECURRANCE_MAX
+);
+
+create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
+ ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
+ DROPBOX_ID
+);
+
+create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
+ CALENDAR_RESOURCE_ID
+);
+
+create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
+ CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
+ TIME_RANGE_INSTANCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
+ CALENDAR_HOME_RESOURCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
+ CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index SHARED_ADDRESSBOOK_BI_e9a2e6d4 on SHARED_ADDRESSBOOK_BIND (
+ OWNER_HOME_RESOURCE_ID
+);
+
+create index ABO_MEMBERS_ADDRESSBO_4effa879 on ABO_MEMBERS (
+ ADDRESSBOOK_ID
+);
+
+create index ABO_MEMBERS_MEMBER_ID_8d66adcf on ABO_MEMBERS (
+ MEMBER_ID
+);
+
+create index ABO_FOREIGN_MEMBERS_A_1fd2c5e9 on ABO_FOREIGN_MEMBERS (
+ ADDRESSBOOK_ID
+);
+
+create index SHARED_GROUP_BIND_RES_cf52f95d on SHARED_GROUP_BIND (
+ GROUP_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
+ CALENDAR_HOME_RESOURCE_ID,
+ CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_6d9d929c on CALENDAR_OBJECT_REVISIONS (
+ CALENDAR_RESOURCE_ID,
+ RESOURCE_NAME,
+ DELETED,
+ REVISION
+);
+
+create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
+ CALENDAR_RESOURCE_ID,
+ REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_2bfcf757 on ADDRESSBOOK_OBJECT_REVISIONS (
+ ADDRESSBOOK_HOME_RESOURCE_ID,
+ OWNER_HOME_RESOURCE_ID
+);
+
+create index ADDRESSBOOK_OBJECT_RE_00fe8288 on ADDRESSBOOK_OBJECT_REVISIONS (
+ OWNER_HOME_RESOURCE_ID,
+ RESOURCE_NAME,
+ DELETED,
+ REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_45004780 on ADDRESSBOOK_OBJECT_REVISIONS (
+ OWNER_HOME_RESOURCE_ID,
+ REVISION
+);
+
+create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
+ NOTIFICATION_HOME_RESOURCE_ID,
+ REVISION
+);
+
+create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
+ RESOURCE_KEY
+);
+
+create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
+ TOKEN
+);
+
+create index CALENDAR_OBJECT_SPLIT_af71dcda on CALENDAR_OBJECT_SPLITTER_WORK (
+ RESOURCE_ID
+);
+
Added: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/postgres-dialect/v28.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/postgres-dialect/v28.sql (rev 0)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/old/postgres-dialect/v28.sql 2013-11-14 03:47:16 UTC (rev 11945)
@@ -0,0 +1,704 @@
+-- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
+
+----
+-- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+
+-----------------
+-- Resource ID --
+-----------------
+
+create sequence RESOURCE_ID_SEQ;
+
+
+-------------------------
+-- Cluster Bookkeeping --
+-------------------------
+
+-- Information about a process connected to this database.
+
+-- Note that this must match the node info schema in twext.enterprise.queue.
+create table NODE_INFO (
+ HOSTNAME varchar(255) not null,
+ PID integer not null,
+ PORT integer not null,
+ TIME timestamp not null default timezone('UTC', CURRENT_TIMESTAMP),
+
+ primary key (HOSTNAME, PORT)
+);
+
+-- Unique named locks. This table should always be empty, but rows are
+-- temporarily created in order to prevent undesirable concurrency.
+create table NAMED_LOCK (
+ LOCK_NAME varchar(255) primary key
+);
+
+
+-------------------
+-- Calendar Home --
+-------------------
+
+create table CALENDAR_HOME (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+ OWNER_UID varchar(255) not null unique, -- implicit index
+ DATAVERSION integer default 0 not null
+);
+
+--------------
+-- Calendar --
+--------------
+
+create table CALENDAR (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
+);
+
+----------------------------
+-- Calendar Home Metadata --
+----------------------------
+
+create table CALENDAR_HOME_METADATA (
+ RESOURCE_ID integer primary key references CALENDAR_HOME on delete cascade, -- implicit index
+ QUOTA_USED_BYTES integer default 0 not null,
+ DEFAULT_EVENTS integer default null references CALENDAR on delete set null,
+ DEFAULT_TASKS integer default null references CALENDAR on delete set null,
+ DEFAULT_POLLS integer default null references CALENDAR on delete set null,
+ ALARM_VEVENT_TIMED text default null,
+ ALARM_VEVENT_ALLDAY text default null,
+ ALARM_VTODO_TIMED text default null,
+ ALARM_VTODO_ALLDAY text default null,
+ AVAILABILITY text default null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
+ CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
+create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
+ CALENDAR_HOME_METADATA(DEFAULT_TASKS);
+create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
+ CALENDAR_HOME_METADATA(DEFAULT_POLLS);
+
+-----------------------
+-- Calendar Metadata --
+-----------------------
+
+create table CALENDAR_METADATA (
+ RESOURCE_ID integer primary key references CALENDAR on delete cascade, -- implicit index
+ SUPPORTED_COMPONENTS varchar(255) default null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+---------------------------
+-- Sharing Notifications --
+---------------------------
+
+create table NOTIFICATION_HOME (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+ OWNER_UID varchar(255) not null unique -- implicit index
+);
+
+create table NOTIFICATION (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+ NOTIFICATION_HOME_RESOURCE_ID integer not null references NOTIFICATION_HOME,
+ NOTIFICATION_UID varchar(255) not null,
+ XML_TYPE varchar(255) not null,
+ XML_DATA text not null,
+ MD5 char(32) not null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+
+ unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
+);
+
+create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
+ NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
+
+
+-------------------
+-- Calendar Bind --
+-------------------
+
+-- Joins CALENDAR_HOME and CALENDAR
+
+create table CALENDAR_BIND (
+ CALENDAR_HOME_RESOURCE_ID integer not null references CALENDAR_HOME,
+ CALENDAR_RESOURCE_ID integer not null references CALENDAR on delete cascade,
+ CALENDAR_RESOURCE_NAME varchar(255) not null,
+ BIND_MODE integer not null, -- enum CALENDAR_BIND_MODE
+ BIND_STATUS integer not null, -- enum CALENDAR_BIND_STATUS
+ BIND_REVISION integer default 0 not null,
+ MESSAGE text,
+ TRANSP integer default 0 not null, -- enum CALENDAR_TRANSP
+ ALARM_VEVENT_TIMED text default null,
+ ALARM_VEVENT_ALLDAY text default null,
+ ALARM_VTODO_TIMED text default null,
+ ALARM_VTODO_ALLDAY text default null,
+ TIMEZONE text default null,
+
+ primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
+ unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME) -- implicit index
+);
+
+create index CALENDAR_BIND_RESOURCE_ID on
+ CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+
+-- Enumeration of calendar bind modes
+
+create table CALENDAR_BIND_MODE (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_MODE values (0, 'own' );
+insert into CALENDAR_BIND_MODE values (1, 'read' );
+insert into CALENDAR_BIND_MODE values (2, 'write');
+insert into CALENDAR_BIND_MODE values (3, 'direct');
+
+-- Enumeration of statuses
+
+create table CALENDAR_BIND_STATUS (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_STATUS values (0, 'invited' );
+insert into CALENDAR_BIND_STATUS values (1, 'accepted');
+insert into CALENDAR_BIND_STATUS values (2, 'declined');
+insert into CALENDAR_BIND_STATUS values (3, 'invalid');
+
+
+-- Enumeration of transparency
+
+create table CALENDAR_TRANSP (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_TRANSP values (0, 'opaque' );
+insert into CALENDAR_TRANSP values (1, 'transparent');
+
+
+---------------------
+-- Calendar Object --
+---------------------
+
+create table CALENDAR_OBJECT (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+ CALENDAR_RESOURCE_ID integer not null references CALENDAR on delete cascade,
+ RESOURCE_NAME varchar(255) not null,
+ ICALENDAR_TEXT text not null,
+ ICALENDAR_UID varchar(255) not null,
+ ICALENDAR_TYPE varchar(255) not null,
+ ATTACHMENTS_MODE integer default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+ DROPBOX_ID varchar(255),
+ ORGANIZER varchar(255),
+ RECURRANCE_MIN date, -- minimum date that recurrences have been expanded to.
+ RECURRANCE_MAX date, -- maximum date that recurrences have been expanded to.
+ ACCESS integer default 0 not null,
+ SCHEDULE_OBJECT boolean default false,
+ SCHEDULE_TAG varchar(36) default null,
+ SCHEDULE_ETAGS text default null,
+ PRIVATE_COMMENTS boolean default false not null,
+ MD5 char(32) not null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+
+ unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+
+ -- since the 'inbox' is a 'calendar resource' for the purpose of storing
+ -- calendar objects, this constraint has to be selectively enforced by the
+ -- application layer.
+
+ -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
+);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
+ CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
+ CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
+
+create index CALENDAR_OBJECT_ICALENDAR_UID on
+ CALENDAR_OBJECT(ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_DROPBOX_ID on
+ CALENDAR_OBJECT(DROPBOX_ID);
+
+-- Enumeration of attachment modes
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
+
+
+-- Enumeration of calendar access types
+
+create table CALENDAR_ACCESS_TYPE (
+ ID integer primary key,
+ DESCRIPTION varchar(32) not null unique
+);
+
+insert into CALENDAR_ACCESS_TYPE values (0, '' );
+insert into CALENDAR_ACCESS_TYPE values (1, 'public' );
+insert into CALENDAR_ACCESS_TYPE values (2, 'private' );
+insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
+insert into CALENDAR_ACCESS_TYPE values (4, 'restricted' );
+
+
+-----------------
+-- Instance ID --
+-----------------
+
+create sequence INSTANCE_ID_SEQ;
+
+
+----------------
+-- Time Range --
+----------------
+
+create table TIME_RANGE (
+ INSTANCE_ID integer primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
+ CALENDAR_RESOURCE_ID integer not null references CALENDAR on delete cascade,
+ CALENDAR_OBJECT_RESOURCE_ID integer not null references CALENDAR_OBJECT on delete cascade,
+ FLOATING boolean not null,
+ START_DATE timestamp not null,
+ END_DATE timestamp not null,
+ FBTYPE integer not null,
+ TRANSPARENT boolean not null
+);
+
+create index TIME_RANGE_CALENDAR_RESOURCE_ID on
+ TIME_RANGE(CALENDAR_RESOURCE_ID);
+create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
+ TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
+
+
+-- Enumeration of free/busy types
+
+create table FREE_BUSY_TYPE (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into FREE_BUSY_TYPE values (0, 'unknown' );
+insert into FREE_BUSY_TYPE values (1, 'free' );
+insert into FREE_BUSY_TYPE values (2, 'busy' );
+insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
+insert into FREE_BUSY_TYPE values (4, 'busy-tentative' );
+
+
+------------------
+-- Transparency --
+------------------
+
+create table TRANSPARENCY (
+ TIME_RANGE_INSTANCE_ID integer not null references TIME_RANGE on delete cascade,
+ USER_ID varchar(255) not null,
+ TRANSPARENT boolean not null
+);
+
+create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
+ TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
+
+
+----------------
+-- Attachment --
+----------------
+
+create sequence ATTACHMENT_ID_SEQ;
+
+create table ATTACHMENT (
+ ATTACHMENT_ID integer primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
+ CALENDAR_HOME_RESOURCE_ID integer not null references CALENDAR_HOME,
+ DROPBOX_ID varchar(255),
+ CONTENT_TYPE varchar(255) not null,
+ SIZE integer not null,
+ MD5 char(32) not null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ PATH varchar(1024) not null
+);
+
+create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
+ ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
+
+-- Many-to-many relationship between attachments and calendar objects
+create table ATTACHMENT_CALENDAR_OBJECT (
+ ATTACHMENT_ID integer not null references ATTACHMENT on delete cascade,
+ MANAGED_ID varchar(255) not null,
+ CALENDAR_OBJECT_RESOURCE_ID integer not null references CALENDAR_OBJECT on delete cascade,
+
+ primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
+ unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
+);
+
+create index ATTACHMENT_CALENDAR_OBJECT_CALENDAR_OBJECT_RESOURCE_ID on
+ ATTACHMENT_CALENDAR_OBJECT(CALENDAR_OBJECT_RESOURCE_ID);
+
+-----------------------
+-- Resource Property --
+-----------------------
+
+create table RESOURCE_PROPERTY (
+ RESOURCE_ID integer not null, -- foreign key: *.RESOURCE_ID
+ NAME varchar(255) not null,
+ VALUE text not null, -- FIXME: xml?
+ VIEWER_UID varchar(255),
+
+ primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
+);
+
+
+----------------------
+-- AddressBook Home --
+----------------------
+
+create table ADDRESSBOOK_HOME (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+ ADDRESSBOOK_PROPERTY_STORE_ID integer default nextval('RESOURCE_ID_SEQ') not null, -- implicit index
+ OWNER_UID varchar(255) not null unique, -- implicit index
+ DATAVERSION integer default 0 not null
+);
+
+
+-------------------------------
+-- AddressBook Home Metadata --
+-------------------------------
+
+create table ADDRESSBOOK_HOME_METADATA (
+ RESOURCE_ID integer primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
+ QUOTA_USED_BYTES integer default 0 not null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+-----------------------------
+-- Shared AddressBook Bind --
+-----------------------------
+
+-- Joins sharee ADDRESSBOOK_HOME and owner ADDRESSBOOK_HOME
+
+create table SHARED_ADDRESSBOOK_BIND (
+ ADDRESSBOOK_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME,
+ OWNER_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME on delete cascade,
+ ADDRESSBOOK_RESOURCE_NAME varchar(255) not null,
+ BIND_MODE integer not null, -- enum CALENDAR_BIND_MODE
+ BIND_STATUS integer not null, -- enum CALENDAR_BIND_STATUS
+ BIND_REVISION integer default 0 not null,
+ MESSAGE text, -- FIXME: xml?
+
+ primary key (ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID), -- implicit index
+ unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME) -- implicit index
+);
+
+create index SHARED_ADDRESSBOOK_BIND_RESOURCE_ID on
+ SHARED_ADDRESSBOOK_BIND(OWNER_HOME_RESOURCE_ID);
+
+
+------------------------
+-- AddressBook Object --
+------------------------
+
+create table ADDRESSBOOK_OBJECT (
+ RESOURCE_ID integer primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+ ADDRESSBOOK_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME on delete cascade,
+ RESOURCE_NAME varchar(255) not null,
+ VCARD_TEXT text not null,
+ VCARD_UID varchar(255) not null,
+ KIND integer not null, -- enum ADDRESSBOOK_OBJECT_KIND
+ MD5 char(32) not null,
+ CREATED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ MODIFIED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+
+ unique (ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME), -- implicit index
+ unique (ADDRESSBOOK_HOME_RESOURCE_ID, VCARD_UID) -- implicit index
+);
+
+
+-----------------------------
+-- AddressBook Object kind --
+-----------------------------
+
+create table ADDRESSBOOK_OBJECT_KIND (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
+insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
+insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
+insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
+
+
+---------------------------------
+-- Address Book Object Members --
+---------------------------------
+
+create table ABO_MEMBERS (
+ GROUP_ID integer not null references ADDRESSBOOK_OBJECT on delete cascade, -- AddressBook Object's (kind=='group') RESOURCE_ID
+ ADDRESSBOOK_ID integer not null references ADDRESSBOOK_HOME on delete cascade,
+ MEMBER_ID integer not null references ADDRESSBOOK_OBJECT, -- member AddressBook Object's RESOURCE_ID
+
+ primary key (GROUP_ID, MEMBER_ID) -- implicit index
+);
+
+create index ABO_MEMBERS_ADDRESSBOOK_ID on
+ ABO_MEMBERS(ADDRESSBOOK_ID);
+create index ABO_MEMBERS_MEMBER_ID on
+ ABO_MEMBERS(MEMBER_ID);
+
+------------------------------------------
+-- Address Book Object Foreign Members --
+------------------------------------------
+
+create table ABO_FOREIGN_MEMBERS (
+ GROUP_ID integer not null references ADDRESSBOOK_OBJECT on delete cascade, -- AddressBook Object's (kind=='group') RESOURCE_ID
+ ADDRESSBOOK_ID integer not null references ADDRESSBOOK_HOME on delete cascade,
+ MEMBER_ADDRESS varchar(255) not null, -- member AddressBook Object's 'calendar' address
+
+ primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
+);
+
+create index ABO_FOREIGN_MEMBERS_ADDRESSBOOK_ID on
+ ABO_FOREIGN_MEMBERS(ADDRESSBOOK_ID);
+
+-----------------------
+-- Shared Group Bind --
+-----------------------
+
+-- Joins ADDRESSBOOK_HOME and ADDRESSBOOK_OBJECT (kind == group)
+
+create table SHARED_GROUP_BIND (
+ ADDRESSBOOK_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME,
+ GROUP_RESOURCE_ID integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ GROUP_ADDRESSBOOK_NAME varchar(255) not null,
+ BIND_MODE integer not null, -- enum CALENDAR_BIND_MODE
+ BIND_STATUS integer not null, -- enum CALENDAR_BIND_STATUS
+ BIND_REVISION integer default 0 not null,
+ MESSAGE text, -- FIXME: xml?
+
+ primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
+ unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_NAME) -- implicit index
+);
+
+create index SHARED_GROUP_BIND_RESOURCE_ID on
+ SHARED_GROUP_BIND(GROUP_RESOURCE_ID);
+
+
+---------------
+-- Revisions --
+---------------
+
+create sequence REVISION_SEQ;
+
+
+-------------------------------
+-- Calendar Object Revisions --
+-------------------------------
+
+create table CALENDAR_OBJECT_REVISIONS (
+ CALENDAR_HOME_RESOURCE_ID integer not null references CALENDAR_HOME,
+ CALENDAR_RESOURCE_ID integer references CALENDAR,
+ CALENDAR_NAME varchar(255) default null,
+ RESOURCE_NAME varchar(255),
+ REVISION integer default nextval('REVISION_SEQ') not null,
+ DELETED boolean not null
+);
+
+create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
+ on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
+ on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+ on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
+
+
+----------------------------------
+-- AddressBook Object Revisions --
+----------------------------------
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+ ADDRESSBOOK_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME,
+ OWNER_HOME_RESOURCE_ID integer references ADDRESSBOOK_HOME,
+ ADDRESSBOOK_NAME varchar(255) default null,
+ RESOURCE_NAME varchar(255),
+ REVISION integer default nextval('REVISION_SEQ') not null,
+ DELETED boolean not null
+);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_HOME_RESOURCE_ID
+ on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
+ on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_REVISION
+ on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, REVISION);
+
+
+-----------------------------------
+-- Notification Object Revisions --
+-----------------------------------
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+ NOTIFICATION_HOME_RESOURCE_ID integer not null references NOTIFICATION_HOME on delete cascade,
+ RESOURCE_NAME varchar(255),
+ REVISION integer default nextval('REVISION_SEQ') not null,
+ DELETED boolean not null,
+
+ unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+);
+
+create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+ on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
+
+
+-------------------------------------------
+-- Apple Push Notification Subscriptions --
+-------------------------------------------
+
+create table APN_SUBSCRIPTIONS (
+ TOKEN varchar(255) not null,
+ RESOURCE_KEY varchar(255) not null,
+ MODIFIED integer not null,
+ SUBSCRIBER_GUID varchar(255) not null,
+ USER_AGENT varchar(255) default null,
+ IP_ADDR varchar(255) default null,
+
+ primary key (TOKEN, RESOURCE_KEY) -- implicit index
+);
+
+create index APN_SUBSCRIPTIONS_RESOURCE_KEY
+ on APN_SUBSCRIPTIONS(RESOURCE_KEY);
+
+
+-----------------
+-- IMIP Tokens --
+-----------------
+
+create table IMIP_TOKENS (
+ TOKEN varchar(255) not null,
+ ORGANIZER varchar(255) not null,
+ ATTENDEE varchar(255) not null,
+ ICALUID varchar(255) not null,
+ ACCESSED timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+
+ primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
+);
+
+create index IMIP_TOKENS_TOKEN
+ on IMIP_TOKENS(TOKEN);
+
+
+----------------
+-- Work Items --
+----------------
+
+create sequence WORKITEM_SEQ;
+
+
+---------------------------
+-- IMIP Inivitation Work --
+---------------------------
+
+create table IMIP_INVITATION_WORK (
+ WORK_ID integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+ NOT_BEFORE timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ FROM_ADDR varchar(255) not null,
+ TO_ADDR varchar(255) not null,
+ ICALENDAR_TEXT text not null
+);
+
+
+-----------------------
+-- IMIP Polling Work --
+-----------------------
+
+create table IMIP_POLLING_WORK (
+ WORK_ID integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+ NOT_BEFORE timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+---------------------
+-- IMIP Reply Work --
+---------------------
+
+create table IMIP_REPLY_WORK (
+ WORK_ID integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+ NOT_BEFORE timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ ORGANIZER varchar(255) not null,
+ ATTENDEE varchar(255) not null,
+ ICALENDAR_TEXT text not null
+);
+
+
+------------------------
+-- Push Notifications --
+------------------------
+
+create table PUSH_NOTIFICATION_WORK (
+ WORK_ID integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+ NOT_BEFORE timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ PUSH_ID varchar(255) not null,
+ PRIORITY integer not null -- 1:low 5:medium 10:high
+);
+
+-----------------
+-- GroupCacher --
+-----------------
+
+create table GROUP_CACHER_POLLING_WORK (
+ WORK_ID integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+ NOT_BEFORE timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+--------------------------
+-- Object Splitter Work --
+--------------------------
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+ WORK_ID integer primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+ NOT_BEFORE timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+ RESOURCE_ID integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create index CALENDAR_OBJECT_SPLITTER_WORK_RESOURCE_ID on
+ CALENDAR_OBJECT_SPLITTER_WORK(RESOURCE_ID);
+
+--------------------
+-- Schema Version --
+--------------------
+
+create table CALENDARSERVER (
+ NAME varchar(255) primary key, -- implicit index
+ VALUE varchar(255)
+);
+
+insert into CALENDARSERVER values ('VERSION', '28');
+insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
Added: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_28_to_29.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_28_to_29.sql (rev 0)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_28_to_29.sql 2013-11-14 03:47:16 UTC (rev 11945)
@@ -0,0 +1,27 @@
+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 28 to 29 --
+---------------------------------------------------
+
+-- Push notification work related updates
+
+alter table NOTIFICATION_HOME
+ add ("DATAVERSION" integer default 0 not null);
+
+-- Now update the version
+update CALENDARSERVER set VALUE = '29' where NAME = 'VERSION';
Added: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_28_to_29.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_28_to_29.sql (rev 0)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_28_to_29.sql 2013-11-14 03:47:16 UTC (rev 11945)
@@ -0,0 +1,27 @@
+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 28 to 29 --
+---------------------------------------------------
+
+-- Push notification work related updates
+
+alter table NOTIFICATION_HOME
+ add column DATAVERSION integer default 0 not null;
+
+-- Now update the version
+update CALENDARSERVER set VALUE = '29' where NAME = 'VERSION';
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/test/util.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/test/util.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -726,7 +726,7 @@
return "/%s/%s/%s/" % (prefix, self.hostname, id)
- def send(self, prefix, id, txn, priority):
+ def send(self, prefix, id, txn, priority):
self.history.append((self.pushKeyForId(prefix, id), priority))
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrade.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrade.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrade.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -414,6 +414,34 @@
+class UpgradeDatabaseNotificationDataStep(_UpgradeDatabaseDataStep):
+ """
+ Checks and upgrades the database data. This assumes there are a bunch of
+ upgrade python modules that we can execute against the database to
+ accomplish the upgrade.
+
+ @ivar sqlStore: The store to operate on.
+
+ @type sqlStore: L{txdav.idav.IDataStore}
+ """
+
+ def __init__(self, sqlStore, **kwargs):
+ """
+ Initialize the service.
+
+ @param sqlStore: The store to operate on. Can be C{None} when doing unit tests.
+ @param service: Wrapped service. Can be C{None} when doing unit tests.
+ """
+ super(UpgradeDatabaseNotificationDataStep, self).__init__(sqlStore, **kwargs)
+
+ self.versionKey = "NOTIFICATION-DATAVERSION"
+ self.versionDescriptor = "notification data"
+ self.upgradeFilePrefix = "notification_"
+ self.upgradeFileSuffix = ".py"
+ self.defaultKeyValue = 0
+
+
+
class UpgradeDatabaseOtherStep(UpgradeDatabaseCoreStep):
"""
Do any other upgrade behaviors once all the schema, data, file migration upgraders
Added: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -0,0 +1,168 @@
+# -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
+##
+# Copyright (c) 2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twisted.internet.defer import inlineCallbacks
+
+from twistedcaldav import caldavxml, customxml
+from twistedcaldav.config import config
+
+from txdav.common.datastore.sql_tables import schema, _BIND_STATUS_INVITED
+from txdav.common.datastore.upgrade.sql.upgrades.util import updateNotificationDataVersion, \
+ doToEachHomeNotAtVersion
+from txdav.xml import element
+from txdav.xml.parser import WebDAVDocument
+from twistedcaldav.sharing import invitationBindStatusFromXMLMap, \
+ invitationBindModeFromXMLMap
+import json
+
+"""
+Data upgrade from database version 0 to 1
+"""
+
+UPGRADE_TO_VERSION = 1
+
+ at inlineCallbacks
+def doUpgrade(sqlStore):
+ """
+ Do the required upgrade steps.
+ """
+ yield updateNotificationHomes(sqlStore, config.UpgradeHomePrefix)
+
+ # Don't do remaining upgrade if we are only process a subset of the homes
+ if not config.UpgradeHomePrefix:
+ # Always bump the DB value
+ yield updateNotificationDataVersion(sqlStore, UPGRADE_TO_VERSION)
+
+
+
+ at inlineCallbacks
+def updateNotificationHomes(sqlStore, prefix=None):
+ """
+ For each calendar home, update the associated properties on the home or its owned calendars.
+ """
+
+ yield doToEachHomeNotAtVersion(sqlStore, schema.NOTIFICATION_HOME, UPGRADE_TO_VERSION, updateNotificationHome, "Update Notification Home", filterOwnerUID=prefix)
+
+
+
+ at inlineCallbacks
+def updateNotificationHome(txn, homeResourceID):
+ """
+ For this notification home, update the associated child resources.
+ """
+
+ home = yield txn.notificationsWithResourceID(homeResourceID)
+ notifications = (yield home.notificationObjects())
+ for notification in notifications:
+ yield updateNotification(txn, notification)
+
+
+
+ at inlineCallbacks
+def updateNotification(txn, notification):
+ """
+ For this notification home, update the associated child resources.
+ """
+
+ # Convert the type value to JSON
+ xmltype = WebDAVDocument.fromString(notification._xmlType).root_element
+ shared_type = "calendar"
+ if xmltype.children[0].qname() == customxml.InviteNotification.qname():
+ jsontype = {"notification-type": "invite-notification"}
+ if "shared-type" in xmltype.children[0].attributes:
+ shared_type = xmltype.children[0].attributes["shared-type"]
+ jsontype["shared-type"] = shared_type
+ elif xmltype.children[0].qname() == customxml.InviteReply.qname():
+ jsontype = {"notification-type": "invite-reply"}
+
+ # Convert the data value to JSON
+ xmldata = (yield notification.xmldata())
+ xmldata = WebDAVDocument.fromString(xmldata).root_element
+
+ def _extract_UID(uri):
+ if uri.startswith("urn:uuid:"):
+ return uri[len("urn:uuid:"):]
+ elif uri[0] == "/":
+ return uri.rstrip("/").split("/")[-1]
+ elif uri.startswith("mailto:"):
+ return uri[7:].split("@")[0]
+ else:
+ return ""
+
+ if xmldata.childOfType(customxml.InviteNotification) is not None:
+ ntype = xmldata.childOfType(customxml.InviteNotification)
+ dtstamp = str(xmldata.childOfType(customxml.DTStamp))
+ owner = _extract_UID(str(ntype.childOfType(customxml.Organizer).childOfType(element.HRef)))
+ sharee = _extract_UID(str(ntype.childOfType(element.HRef)))
+ uid = str(ntype.childOfType(customxml.UID))
+ for xml in invitationBindStatusFromXMLMap.keys():
+ if ntype.childOfType(xml) is not None:
+ state = invitationBindStatusFromXMLMap[xml]
+ break
+ else:
+ state = _BIND_STATUS_INVITED
+ mode = invitationBindModeFromXMLMap[type(ntype.childOfType(customxml.InviteAccess).children[0])]
+ name = str(ntype.childOfType(customxml.HostURL).childOfType(element.HRef)).rstrip("/").split("/")[-1]
+ summary = str(ntype.childOfType(customxml.InviteSummary))
+
+ jsondata = {
+ "notification-type": "invite-notification",
+ "shared-type": shared_type,
+ "dtstamp": dtstamp,
+ "owner": owner,
+ "sharee": sharee,
+ "uid": uid,
+ "status": state,
+ "access": mode,
+ "name": name,
+ "summary": summary,
+ }
+ if ntype.childOfType(caldavxml.SupportedCalendarComponentSet):
+ comps = [child.attributes["name"] for child in ntype.childOfType(caldavxml.SupportedCalendarComponentSet).children]
+ jsondata["supported-components"] = ",".join(comps)
+
+ elif xmldata.childOfType(customxml.InviteReply) is not None:
+ ntype = xmldata.childOfType(customxml.InviteReply)
+ dtstamp = str(xmldata.childOfType(customxml.DTStamp))
+ sharee = _extract_UID(str(ntype.childOfType(element.HRef)))
+ for xml in invitationBindStatusFromXMLMap.keys():
+ if ntype.childOfType(xml) is not None:
+ state = invitationBindStatusFromXMLMap[xml]
+ break
+ else:
+ state = _BIND_STATUS_INVITED
+ name = str(ntype.childOfType(customxml.HostURL).childOfType(element.HRef)).rstrip("/").split("/")[-1]
+ inreplyto = str(ntype.childOfType(customxml.InReplyTo))
+ summary = str(ntype.childOfType(customxml.InviteSummary)) if ntype.childOfType(customxml.InviteSummary) is not None else ""
+
+ owner = str(ntype.childOfType(customxml.HostURL).childOfType(element.HRef)).rstrip("/").split("/")[-2]
+
+ jsondata = {
+ "notification-type": "invite-reply",
+ "shared-type": shared_type,
+ "dtstamp": dtstamp,
+ "owner": owner,
+ "sharee": sharee,
+ "status": state,
+ "name": name,
+ "in-reply-to": inreplyto,
+ "summary": summary,
+ }
+
+ jsontype = json.dumps(jsontype)
+ jsondata = json.dumps(jsondata)
+ yield notification.setData(notification.uid(), jsontype, jsondata)
Added: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/test/test_notification_upgrade_from_0_to_1.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/test/test_notification_upgrade_from_0_to_1.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/test/test_notification_upgrade_from_0_to_1.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -0,0 +1,196 @@
+##
+# Copyright (c) 2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twext.enterprise.dal.syntax import Update
+
+from twisted.internet.defer import inlineCallbacks
+
+from txdav.caldav.datastore.test.util import CommonStoreTests
+from txdav.common.datastore.sql_tables import _BIND_STATUS_INVITED, \
+ _BIND_MODE_WRITE, _BIND_STATUS_ACCEPTED, _BIND_MODE_READ
+from txdav.common.datastore.upgrade.sql.upgrades.notification_upgrade_from_0_to_1 import doUpgrade
+
+import json
+
+"""
+Tests for L{txdav.common.datastore.upgrade.sql.upgrade}.
+"""
+
+class Upgrade_from_0_to_1(CommonStoreTests):
+ """
+ Tests for notification upgrade.
+ """
+
+ @inlineCallbacks
+ def test_upgrade_invite(self):
+
+ data = (
+ (
+ "uid1",
+ """<?xml version='1.0' encoding='UTF-8'?>
+<CS:notification xmlns:CS='http://calendarserver.org/ns/'>
+ <CS:invite-notification shared-type='calendar'/>
+</CS:notification>
+""",
+ {
+ "notification-type": "invite-notification",
+ "shared-type": "calendar",
+ },
+ """<?xml version='1.0' encoding='UTF-8'?>
+<notification xmlns='http://calendarserver.org/ns/'>
+ <dtstamp>20131113T153109Z</dtstamp>
+ <invite-notification shared-type='calendar'>
+ <uid>uid1</uid>
+ <href xmlns='DAV:'>urn:uuid:user02</href>
+ <invite-noresponse/>
+ <access>
+ <read-write/>
+ </access>
+ <hosturl>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/calendar</href>
+ </hosturl>
+ <organizer>
+ <href xmlns='DAV:'>urn:uuid:user01</href>
+ <common-name>User 01</common-name>
+ </organizer>
+ <summary>Shared</summary>
+ <supported-calendar-component-set xmlns='urn:ietf:params:xml:ns:caldav'>
+ <comp name='VEVENT'/>
+ <comp name='VTODO'/>
+ </supported-calendar-component-set>
+ </invite-notification>
+</notification>
+""",
+ {
+ "notification-type": "invite-notification",
+ "shared-type": "calendar",
+ "dtstamp": "20131113T153109Z",
+ "owner": "user01",
+ "sharee": "user02",
+ "uid": "uid1",
+ "status": _BIND_STATUS_INVITED,
+ "access": _BIND_MODE_WRITE,
+ "name": "calendar",
+ "summary": "Shared",
+ "supported-components": "VEVENT,VTODO",
+ },
+ ),
+ (
+ "uid2",
+ """<?xml version='1.0' encoding='UTF-8'?>
+<CS:notification xmlns:CS='http://calendarserver.org/ns/'>
+ <CS:invite-notification shared-type='addressbook'/>
+</CS:notification>
+""",
+ {
+ "notification-type": "invite-notification",
+ "shared-type": "addressbook",
+ },
+ """<?xml version='1.0' encoding='UTF-8'?>
+<notification xmlns='http://calendarserver.org/ns/'>
+ <dtstamp>20131113T153110Z</dtstamp>
+ <invite-notification shared-type='addressbook'>
+ <uid>uid2</uid>
+ <href xmlns='DAV:'>/principals/users/user02/</href>
+ <invite-accepted/>
+ <access>
+ <read/>
+ </access>
+ <hosturl>
+ <href xmlns='DAV:'>/addressbooks/__uids__/user01/addressbook/</href>
+ </hosturl>
+ <organizer>
+ <href xmlns='DAV:'>/principals/users/user01/</href>
+ <common-name>User 01</common-name>
+ </organizer>
+ <summary>Shared 2</summary>
+ </invite-notification>
+</notification>
+""",
+ {
+ "notification-type": "invite-notification",
+ "shared-type": "addressbook",
+ "dtstamp": "20131113T153110Z",
+ "owner": "user01",
+ "sharee": "user02",
+ "uid": "uid2",
+ "status": _BIND_STATUS_ACCEPTED,
+ "access": _BIND_MODE_READ,
+ "name": "addressbook",
+ "summary": "Shared 2",
+ },
+ ),
+ (
+ "uid3",
+ """<?xml version='1.0' encoding='UTF-8'?>
+<CS:notification xmlns:CS='http://calendarserver.org/ns/'>
+ <CS:invite-reply/>
+</CS:notification>
+""",
+ {
+ "notification-type": "invite-reply",
+ },
+ """<?xml version='1.0' encoding='UTF-8'?>
+<notification xmlns='http://calendarserver.org/ns/'>
+ <dtstamp>20131113T153111Z</dtstamp>
+ <invite-reply shared-type='calendar'>
+ <href xmlns='DAV:'>mailto:user02 at example.com</href>
+ <invite-accepted/>
+ <hosturl>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/calendar</href>
+ </hosturl>
+ <in-reply-to>uid1</in-reply-to>
+ </invite-reply>
+</notification>
+""",
+ {
+ "notification-type": "invite-reply",
+ "shared-type": "calendar",
+ "dtstamp": "20131113T153111Z",
+ "owner": "user01",
+ "sharee": "user02",
+ "status": _BIND_STATUS_ACCEPTED,
+ "name": "calendar",
+ "in-reply-to": "uid1",
+ "summary": "",
+ },
+ ),
+ )
+
+ for uid, xmltype, _ignore_jtype, xmldata, _ignore_jdata in data:
+ notifications = yield self.transactionUnderTest().notificationsWithUID("user01")
+ yield notifications.writeNotificationObject(uid, xmltype, xmldata)
+
+ # Force data version to previous
+ nh = notifications._homeSchema
+ yield Update(
+ {nh.DATAVERSION: 0},
+ Where=None,
+ ).on(self.transactionUnderTest())
+
+ yield self.commit()
+ yield doUpgrade(self._sqlCalendarStore)
+
+ notifications = yield self.transactionUnderTest().notificationsWithUID("user01")
+ version = (yield notifications.dataVersion())
+ self.assertEqual(version, 1)
+
+ for uid, _ignore_xmltype, jtype, _ignore_xmldata, jdata in data:
+ notification = (yield notifications.notificationObjectWithUID(uid))
+ self.assertTrue(notification is not None, msg="Failed {uid}".format(uid=uid))
+ self.assertEqual(json.loads(notification.xmlType()), jtype, msg="Failed {uid}".format(uid=uid))
+ data = (yield notification.xmldata())
+ self.assertEqual(json.loads(data), jdata, msg="Failed {uid}".format(uid=uid))
Modified: CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/util.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/util.py 2013-11-14 03:37:20 UTC (rev 11944)
+++ CalendarServer/branches/users/cdaboo/sharing-in-the-store/txdav/common/datastore/upgrade/sql/upgrades/util.py 2013-11-14 03:47:16 UTC (rev 11945)
@@ -128,6 +128,11 @@
+def updateNotificationDataVersion(store, version):
+ return _updateDataVersion(store, "NOTIFICATION-DATAVERSION", version)
+
+
+
@inlineCallbacks
def doToEachHomeNotAtVersion(store, homeSchema, version, doIt, logStr, filterOwnerUID=None):
"""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/0fa5df0c/attachment.html>
More information about the calendarserver-changes
mailing list