+ Start a Discussion
philbophilbo 

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:
  • 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.
So it's breaking in two different (but presumably somehow related) ways. 

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
philbophilbo
Bumping this.  Did this ring a bell with anybody?  Any chance it was fixed in Spring '09?
philbophilbo

Hey again -

 

I did a bit of experimentation - looks like this WAS fixed in Spring '09.