Ticket #1312 (closed defect: fixed)

Opened 2 years ago

Last modified 1 year ago

dCursorMixin.deleteAll() method breaks multiuser environment

Reported by: JacekK Assigned to: somebody
Priority: critical Milestone: 0.9.2
Component: db Version: 0.9.1
Keywords: Cc:

Description

I found another critical bug.
Let's assume we have parent and child table.
If remote user delete one record from the child table, then if we try to delete parent record, deleteAll() method goes into infinite loop trying to delete non existing child record. Here is a part of code:

if pk in self._newRecords:
			res = True
			del self._newRecords[pk]
		else:
			pkWhere = self.makePkWhere()
			# some backends(PostgreSQL) don't return information about number of deleted rows
			# try to fetch it before
			sql = "select count(*) as cnt from %s where %s" % (self.Table, pkWhere)
			aux = self.AuxCursor
			aux.execute(sql)
			res = aux.getFieldVal('cnt')
			if res:
				sql = "delete from %s where %s" % (self.Table, pkWhere)
				aux.execute(sql)

		if not res:
			# Nothing was deleted
			self.BackendObject.noResultsOnDelete()
		else:
			# Delete the record from the current dataset
			if pk in self._mementos:
				del self._mementos[pk]
			self._removeRow(delRowNum)

In such situation, res variable equals "0", so noResultsOnDelete() method is executed instead of removing row from dataset.
I think that last three lines of code should be executed uncoditionally.

Change History

02/21/10 05:13:32 changed by JacekK

There is yet another side effect of this bug.
When there is in use cascade delete integrity on backend, 'res' becomes zero and framework dataset remains unchanged.
Normally it doesn't affect application behaviour because there is no PK in parent bizobj for such child cursor, but makes data inconsistent since garbage remains.

02/01/11 14:25:59 changed by JacekK

  • status changed from new to closed.
  • resolution set to fixed.