You need to sign in to do that
Don't have an account?
philbo
Unique Fields, Apex Triggers and Database.insert
Hey,
Here's a new one:
I have a custom object Obj__c, one of whose fields UniqFld__c is flagged as unique. This field gets populated in a Before Insert/Update trigger on the object - its value is derived from a couple of other (reference) fields Ref1__c and Ref2__c on the object. The idea is to ensure that no two Obj__c records can exist linked to the same combination of Ref1__c and Ref2__c records.
This works correctly in a whole bunch of different scenarios - creating/updating from the GUI, inserting/updating via anonymous Apex - it throws an error any time a duplicate UniqFld__c value is detected.
But here's a problem I found, starting with the following Obj__c records:
Obj__c obj1 = new Obj__c ( Ref1__c = ref1_1.Id , Ref2__c = ref2_1.Id );
Obj__c obj2 = new Obj__c ( Ref1__c = ref1_2.Id , Ref2__c = ref2_2.Id );
...I already have an Obj__c record matching the first of these (obj1), but not the second.
If I go
insert new Obj__c[] { obj1 , obj2 };
then the resulting duplicate UniqFld__c is created by the trigger, caught by SF and the whole thing craps out like it's supposed to.
And if I go
Database.saveResult[] resList = Database.insert ( new Obj__c[] { obj1 , obj2 } , True );
the second 'True' arg indicating All or None, then the same behavour happens - the whole thing fails, as expected.
But if I change that arg to indicate NOT All or None:
Database.saveResult[] resList = Database.insert ( new Obj__c[] { obj1 , obj2 } , False );
expecting obj1 to fail and obj2 to succeed - something unexpected happens instead:
If I pass a single 'duplicate' Obj__c record into Database.insert(), it works as expected, as it also does with multiple 'good' or multiple 'duplicate' records. It's only when the list is a mixture of 'good' and 'duplicate' records that this unexpected behaviour happens.
Oh - and if I call Database.update() with a 'good' record and a more blatantly 'bad' record (e.g. a bogus value in the Ref1__c field), then it works like it's supposed to - one rejected record and one inserted record whose UniqFld__c field is correctly filled out.
Has anyone experienced anything similar along these lines? I can't help but think it's a SF bug but who knows, maybe it's something subtle I'm doing wrong.
Any input/commentary/whatever - would be MOST appreciated.
Message Edited by philbo on 11-19-2008 03:59 PM
Message Edited by philbo on 11-19-2008 04:08 PM
Here's a new one:
I have a custom object Obj__c, one of whose fields UniqFld__c is flagged as unique. This field gets populated in a Before Insert/Update trigger on the object - its value is derived from a couple of other (reference) fields Ref1__c and Ref2__c on the object. The idea is to ensure that no two Obj__c records can exist linked to the same combination of Ref1__c and Ref2__c records.
This works correctly in a whole bunch of different scenarios - creating/updating from the GUI, inserting/updating via anonymous Apex - it throws an error any time a duplicate UniqFld__c value is detected.
But here's a problem I found, starting with the following Obj__c records:
Obj__c obj1 = new Obj__c ( Ref1__c = ref1_1.Id , Ref2__c = ref2_1.Id );
Obj__c obj2 = new Obj__c ( Ref1__c = ref1_2.Id , Ref2__c = ref2_2.Id );
...I already have an Obj__c record matching the first of these (obj1), but not the second.
If I go
insert new Obj__c[] { obj1 , obj2 };
then the resulting duplicate UniqFld__c is created by the trigger, caught by SF and the whole thing craps out like it's supposed to.
And if I go
Database.saveResult[] resList = Database.insert ( new Obj__c[] { obj1 , obj2 } , True );
the second 'True' arg indicating All or None, then the same behavour happens - the whole thing fails, as expected.
But if I change that arg to indicate NOT All or None:
Database.saveResult[] resList = Database.insert ( new Obj__c[] { obj1 , obj2 } , False );
expecting obj1 to fail and obj2 to succeed - something unexpected happens instead:
- Both records are successfully inserted into the database.
- Although the Before trigger does run, supposedly populating the UniqFld__c field on both obj1 and obj2 (as confirmed by substantial System.debug()s), the field is NOT SET in the resulting Obj__c records in the database.
If I pass a single 'duplicate' Obj__c record into Database.insert(), it works as expected, as it also does with multiple 'good' or multiple 'duplicate' records. It's only when the list is a mixture of 'good' and 'duplicate' records that this unexpected behaviour happens.
Oh - and if I call Database.update() with a 'good' record and a more blatantly 'bad' record (e.g. a bogus value in the Ref1__c field), then it works like it's supposed to - one rejected record and one inserted record whose UniqFld__c field is correctly filled out.
Has anyone experienced anything similar along these lines? I can't help but think it's a SF bug but who knows, maybe it's something subtle I'm doing wrong.
Any input/commentary/whatever - would be MOST appreciated.
Message Edited by philbo on 11-19-2008 03:59 PM
Message Edited by philbo on 11-19-2008 04:08 PM
Hey again -
I did a bit of experimentation - looks like this WAS fixed in Spring '09.