def forMultipleResourcesWithResourceIDs(cls, defaultUser, txn, resourceIDs): """ Load all property stores for all specified resources. This is used to optimize Depth:1 operations on that collection, by loading all relevant properties in a single query. Note that the caller of this method must make sure that the number of items being queried for is within a reasonable batch size. If the caller is itself batching related queries, that will take care of itself. @param defaultUser: the UID of the user who owns / is requesting the property stores; the ones whose per-user properties will be exposed. @type defaultUser: C{str} @param txn: the transaction within which to fetch the rows. @type txn: L{IAsyncTransaction} @param resourceIDs: The set of resource ID's to query. @return: a L{Deferred} that fires with a C{dict} mapping resource ID (a value taken from C{childColumn}) to a L{PropertyStore} for that ID. """ query = Select([ prop.RESOURCE_ID, prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop, Where=prop.RESOURCE_ID.In(Parameter("resourceIDs", len(resourceIDs))) ) rows = yield query.on(txn, resourceIDs=resourceIDs) stores = cls._createMultipleStores(defaultUser, txn, rows) returnValue(stores)
def test_removeAddressBookPropertiesOnDelete(self): """ L{IAddressBookHome.removeAddressBookWithName} clears an address book that already exists and makes sure added properties are also removed. """ prop = schema.RESOURCE_PROPERTY _allWithID = Select([prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop, Where=prop.RESOURCE_ID == Parameter("resourceID")) # Create address book and add a property home = yield self.homeUnderTest() addressbook = home.addressbook() resourceID = home._addressbookPropertyStoreID rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) addressbookProperties = addressbook.properties() prop = carddavxml.AddressBookDescription.fromString( "Address Book prop to be removed") addressbookProperties[PropertyName.fromElement(prop)] = prop yield self.commit() # Check that two properties are present home = yield self.homeUnderTest() rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 1) yield self.commit() # Remove address book and check for no properties home = yield self.homeUnderTest() yield home.removeAddressBookWithName(addressbook.name()) rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit() # Recheck it rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit()
def test_removeAddressBookPropertiesOnDelete(self): """ L{IAddressBookHome.removeAddressBookWithName} clears an address book that already exists and makes sure added properties are also removed. """ prop = schema.RESOURCE_PROPERTY _allWithID = Select( [prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop, Where=prop.RESOURCE_ID == Parameter("resourceID") ) # Create address book and add a property home = yield self.homeUnderTest() addressbook = home.addressbook() resourceID = home._addressbookPropertyStoreID rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) addressbookProperties = addressbook.properties() prop = carddavxml.AddressBookDescription.fromString("Address Book prop to be removed") addressbookProperties[PropertyName.fromElement(prop)] = prop yield self.commit() # Check that two properties are present home = yield self.homeUnderTest() rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 1) yield self.commit() # Remove address book and check for no properties home = yield self.homeUnderTest() yield home.removeAddressBookWithName(addressbook.name()) rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit() # Recheck it rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit()
def test_removeAddressBookObjectPropertiesOnDelete(self): """ L{IAddressBookHome.removeAddressBookWithName} removes an address book object that already exists and makes sure properties are also removed (which is always the case as right now address book objects never have properties). """ # Create address book object adbk1 = yield self.addressbookUnderTest() name = "4.vcf" component = VComponent.fromString(vcard4_text) addressobject = yield adbk1.createAddressBookObjectWithName(name, component, options={}) resourceID = addressobject._resourceID prop = schema.RESOURCE_PROPERTY _allWithID = Select([prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop, Where=prop.RESOURCE_ID == Parameter("resourceID")) # No properties on existing address book object rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit() # Remove address book object and check for no properties adbk1 = yield self.addressbookUnderTest() obj1 = yield adbk1.addressbookObjectWithName(name) yield obj1.remove() rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit() # Recheck it rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit()
def test_removeAddressBookObjectPropertiesOnDelete(self): """ L{IAddressBookHome.removeAddressBookWithName} removes an address book object that already exists and makes sure properties are also removed (which is always the case as right now address book objects never have properties). """ # Create address book object adbk1 = yield self.addressbookUnderTest() name = "4.vcf" component = VComponent.fromString(vcard4_text) addressobject = yield adbk1.createAddressBookObjectWithName(name, component, options={}) resourceID = addressobject._resourceID prop = schema.RESOURCE_PROPERTY _allWithID = Select( [prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop, Where=prop.RESOURCE_ID == Parameter("resourceID") ) # No properties on existing address book object rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit() # Remove address book object and check for no properties adbk1 = yield self.addressbookUnderTest() obj1 = yield adbk1.addressbookObjectWithName(name) yield obj1.remove() rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit() # Recheck it rows = yield _allWithID.on(self.transactionUnderTest(), resourceID=resourceID) self.assertEqual(len(tuple(rows)), 0) yield self.commit()
def forMultipleResourcesWithResourceIDs(cls, defaultUser, shareeUser, proxyUser, txn, resourceIDs): """ Load all property stores for all specified resources. This is used to optimize Depth:1 operations on that collection, by loading all relevant properties in a single query. Note that the caller of this method must make sure that the number of items being queried for is within a reasonable batch size. If the caller is itself batching related queries, that will take care of itself. @param defaultUser: the UID of the user who owns / is requesting the property stores; the ones whose per-user properties will be exposed. @type defaultUser: C{str} @param txn: the transaction within which to fetch the rows. @type txn: L{IAsyncTransaction} @param resourceIDs: The set of resource ID's to query. @return: a L{Deferred} that fires with a C{dict} mapping resource ID (a value taken from C{childColumn}) to a L{PropertyStore} for that ID. """ query = Select( [prop.RESOURCE_ID, prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop, Where=prop.RESOURCE_ID.In( Parameter("resourceIDs", len(resourceIDs)))) rows = yield query.on(txn, resourceIDs=resourceIDs) stores = cls._createMultipleStores(defaultUser, shareeUser, proxyUser, txn, rows) # Make sure we have a store for each resourceID even if no properties exist for resourceID in resourceIDs: if resourceID not in stores: store = cls.__new__(cls) super(PropertyStore, store).__init__(defaultUser, shareeUser, proxyUser) store._txn = txn store._resourceID = resourceID store._cached = {} stores[resourceID] = store returnValue(stores)
def forMultipleResources(cls, defaultUser, shareeUser, proxyUser, txn, childColumn, parentColumn, parentID): """ Load all property stores for all objects in a collection. This is used to optimize Depth:1 operations on that collection, by loading all relevant properties in a single query. @param defaultUser: the UID of the user who owns / is requesting the property stores; the ones whose per-user properties will be exposed. @type defaultUser: C{str} @param txn: the transaction within which to fetch the rows. @type txn: L{IAsyncTransaction} @param childColumn: The resource ID column for the child resources, i.e. the resources of the type for which this method will loading the property stores. @param parentColumn: The resource ID column for the parent resources. e.g. if childColumn is addressbook object's resource ID, then this should be addressbook's resource ID. @return: a L{Deferred} that fires with a C{dict} mapping resource ID (a value taken from C{childColumn}) to a L{PropertyStore} for that ID. """ childTable = TableSyntax(childColumn.model.table) query = Select( [ childColumn, # XXX is that column necessary? as per the 'on' clause it has to be # the same as prop.RESOURCE_ID anyway. prop.RESOURCE_ID, prop.NAME, prop.VIEWER_UID, prop.VALUE ], From=prop.join(childTable, prop.RESOURCE_ID == childColumn, 'right'), Where=parentColumn == parentID) rows = yield query.on(txn) stores = cls._createMultipleStores(defaultUser, shareeUser, proxyUser, txn, rows) returnValue(stores)
def _needsNormalizationUpgrade(txn): """ Determine whether a given store requires a UUID normalization data upgrade. @param txn: the transaction to use @type txn: L{CommonStoreTransaction} @return: a L{Deferred} that fires with C{True} or C{False} depending on whether we need the normalization upgrade or not. """ for x in [schema.CALENDAR_HOME, schema.ADDRESSBOOK_HOME, schema.NOTIFICATION_HOME]: slct = Select([x.OWNER_UID], From=x, Where=x.OWNER_UID != Upper(x.OWNER_UID)) rows = yield slct.on(txn) if rows: for [uid] in rows: if normalizeUUIDOrNot(uid) != uid: returnValue(True) returnValue(False)
def forMultipleResources(cls, defaultUser, shareeUser, proxyUser, txn, childColumn, parentColumn, parentID): """ Load all property stores for all objects in a collection. This is used to optimize Depth:1 operations on that collection, by loading all relevant properties in a single query. @param defaultUser: the UID of the user who owns / is requesting the property stores; the ones whose per-user properties will be exposed. @type defaultUser: C{str} @param txn: the transaction within which to fetch the rows. @type txn: L{IAsyncTransaction} @param childColumn: The resource ID column for the child resources, i.e. the resources of the type for which this method will loading the property stores. @param parentColumn: The resource ID column for the parent resources. e.g. if childColumn is addressbook object's resource ID, then this should be addressbook's resource ID. @return: a L{Deferred} that fires with a C{dict} mapping resource ID (a value taken from C{childColumn}) to a L{PropertyStore} for that ID. """ childTable = TableSyntax(childColumn.model.table) query = Select([ childColumn, # XXX is that column necessary? as per the 'on' clause it has to be # the same as prop.RESOURCE_ID anyway. prop.RESOURCE_ID, prop.NAME, prop.VIEWER_UID, prop.VALUE], From=prop.join(childTable, prop.RESOURCE_ID == childColumn, 'right'), Where=parentColumn == parentID ) rows = yield query.on(txn) stores = cls._createMultipleStores(defaultUser, shareeUser, proxyUser, txn, rows) returnValue(stores)
def _needsNormalizationUpgrade(txn): """ Determine whether a given store requires a UUID normalization data upgrade. @param txn: the transaction to use @type txn: L{CommonStoreTransaction} @return: a L{Deferred} that fires with C{True} or C{False} depending on whether we need the normalization upgrade or not. """ for x in [ schema.CALENDAR_HOME, schema.ADDRESSBOOK_HOME, schema.NOTIFICATION_HOME ]: slct = Select([x.OWNER_UID], From=x, Where=x.OWNER_UID != Upper(x.OWNER_UID)) rows = yield slct.on(txn) if rows: for [uid] in rows: if normalizeUUIDOrNot(uid) != uid: returnValue(True) returnValue(False)