Ticket #1311 (closed defect: fixed)

Opened 2 years ago

Last modified 1 year ago

dBizobj.deleteAll fails deleting new rows after key field value change

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

Description

I encountered serious problem deleting new rows from dataset after changing value of key field.
It happens because, although dCursorMixin.setFieldVal() modifies _mementos dictionary keys, it doesn't modify _newRecords dictionary keys at all.
This causing that dBizobj.deleteAll() method enters endless loop when cursor object doesn't find record to delete, but RowCount property still is greater than zero.
It's especially visible with tables with compound keys, when part of the key changes.

Attachments

dCursorMixin.2.patch (2.3 kB) - added by JacekK on 02/19/2010 10:33:55 AM.
dCursorMixin.patch (2.3 kB) - added by JacekK on 05/27/2010 12:35:07 PM.

Change History

12/16/2009 07:31:33 AM changed by ed

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

Changing PK values is not supported in Dabo, and is a terrible idea in any system.

12/16/2009 08:47:11 AM changed by paul

  • status changed from closed to reopened.
  • resolution deleted.

I agree that changing key values should not be supported, however I reopened the ticket because I think we should fix the behavior of the endless loop that Jacek describes. We should instead raise an explicit exception, such as dException.ModifiedKeyValueException?.

This may or may not be easy to detect. I guess it could be raised from dCursor.setFieldVal() if the field to modify is the key field or part of the compound key. That way the exception happens the moment the change happens, and the developer knows immediately what the problem is and that it isn't supported.

12/16/2009 10:35:34 AM changed by JacekK

I'm afraid we misunderstand each other.
I didn't want to change PK of existing records.
I'm telling about situation when AutoPopulatePK equals False and I provide PK myself for new records.
In such situation, changing PK value of unsaved row, causes application hang when deleting such rows.
Your answer should be: use dCursorMixin.setNewFlag() method.

12/16/2009 11:15:29 AM changed by paul

Interesting Jacek, sorry I misunderstood. I don't know why I've never encountered this: my bizobj supplies my PK's too (in DefaultValues?). I can delete the new unsaved records without issue.

12/16/2009 02:29:23 PM changed by JacekK

Your code works, because default values are set before setNewFlag() call in _onNew() method.
It's my case.
I have two tables, parent with PK generated by backend (AutoPopulatePK=True) and child with PK generated separately manually (AutoPopulatePK=False).
After child.new(), it's PK is set to e.g. "0", then in onNew() method I change it to "1".
Although the _mementos key is updated, the _newRecords key remains unchanged.
And dCursorMixin.delete() methods take care about _newRecords not the _mementos.
If you delete:
- an existing record
- record with auto generated PK
- record in parent table with no new record in child table
everything is working correctly.
After digging in framework code, I found setNewFlag() method, which is a solution of my problem.
But I think, there should be a protection/information against such mistakes at last.
Setting PK as default value isn't the perfect solution, and can't be used for join tables in many to many relations.
So, it will be nice if e.g. framework take care about keys in _newRecords too, as like it do it for _mementos.

Thanks guys.

12/16/2009 04:52:33 PM changed by paul

Any chance you can give a proposed patch?

I still don't understand why you can't use DefaultValues?, because I have many:many relations working where every table (parent, child, grandchild, etc.) has AutoPopulatePK=False and gets its PK in DefaultValues?. The link to the parent gets filled automatically with FillLinkFromParent?=True.

12/17/2009 03:09:00 PM changed by JacekK

I included patch for few issues with dCursorMixin class:
- fix new record detection issue, since _newRecords contains None values, self._newRecords.get(recKey, None) always returns None value;
- improved blob field handling, so setting blob value from buffer type value isn't treated as error;
- fix improper compound keys handling, where elements of key weren't recognised and garbaged _mementos and _newRecords dictionaries.

And Paul, you asked why I can't use DefaultValues for PK?
Imagine there exist tables with no PK or where PK consist of many FK fields.
Here is an example from real world, OpenERP project:

CREATE TABLE product_taxes_rel
(
  prod_id integer NOT NULL,
  tax_id integer NOT NULL,
  CONSTRAINT product_taxes_rel_prod_id_fkey FOREIGN KEY (prod_id)
      REFERENCES product_template (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT product_taxes_rel_tax_id_fkey FOREIGN KEY (tax_id)
      REFERENCES account_tax (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT product_taxes_rel_uniq UNIQUE (prod_id, tax_id)
);

There is no possibility to set second part of PK (prod_id, tax_id) in DefaultValues because it's variable.

Best regards.

12/17/2009 04:49:12 PM changed by ed

Just a quick note looking at the patch: don't use the 'has_key' method of dicts anymore; it's deprecated, and should not be used.

Instead of:

if somedict.has_key("foo"):

use:

if "foo" in somedict:

(follow-up: ↓ 10 ) 12/18/2009 12:55:38 AM changed by JacekK

You are right Ed, I'll take it in mind, although it's since Python 3.0.
But do you count its occurrences in Dabo :)

(in reply to: ↑ 9 ) 12/18/2009 10:46:50 AM changed by paul

Replying to JacekK:

You are right Ed, I'll take it in mind, although it's since Python 3.0.
But do you count its occurrences in Dabo :)

It would be great for someone to clean up this kind of thing. We started developing Dabo in Python 2.2 IIRC, and didn't keep up with the changes. So, do we have a volunteer? :)

12/18/2009 10:48:11 AM changed by paul

By the way, the patch seems fine to me after a quick reading, but I didn't write any of the compound key stuff. +1 on committing it from me.

12/19/2009 04:36:41 AM changed by JacekK

I think, that I should add CURSOR_TMPKEY_FIELD key update to my patch.
Improved patch included.
But I have one question. What method detecting of new record is preferred, because you use two?
First, checking CURSOR_TMPKEY_FIELD key in row and second, checking PK existence in _newRecords.

02/19/2010 10:12:48 AM changed by JacekK

Because r5696 fixes some errors, I posted updated patch.

02/19/2010 10:33:55 AM changed by JacekK

  • attachment dCursorMixin.2.patch added.

05/21/2010 11:26:00 AM changed by nate

Jacek,

Does r5833 help the problem in respect to compound keys?

Regards,

Nate

05/27/2010 12:35:07 PM changed by JacekK

  • attachment dCursorMixin.patch added.

05/27/2010 12:35:38 PM changed by JacekK

Your code works, but you don't make _newRecords cleanup.
Currently I'm using my version of code, see patch.

02/10/2011 11:12:45 AM changed by JacekK

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