How to catch duplicate key field

Hello,

Does anybody know how to catch in which field is duplicate key error when using TryInsert() from FileManagerClass?

What I mean is, when I use Access:File.Insert(), if there is duplicate key it shows you where. Message is:

Adding this record creates duplicate entry for the key: FILE:Key

Since I don’t want to see error message, I only want to catch which field is duplicate entry and save it in log, I am using TryInsert() method.

But how to get value of the field? I have tried with GlobalErrors.GetError(), but it returns empty string.

There is Access:File.GetError.ToString() method, but I get compile error - No matching prototype available and Field not found: TOSTRING.

So, question is, what goes inside IF statement?

IF Access:File.TryInsert() <> Level:Benign
  ! What goes here to catch which field is duplicate value?
END

Other solution is DUPLICATE(), for every field. But that seems inefective, since Insert() knows which field is duplicate value, so should TryInsert()?

Thanks for any help.

FileManager.Insert loops thru all file keys and calls DUPLICATE for each key, see abfile.clw.

If the user can enter data that can create a dup error I’ll add code to check and help him fix it by identifying the exact problem field and selecting it.

E.g. we only allow an SSN to be entered once, and same if they use the time keeping Clock Number:

IF DUPLICATE(Emp:KeySSN) THEN
    SELECT(?EMP:SSN)  
    Message('SSN is already entered on another record....')
    CYCLE
ELSIF Emp:ClockNo AND DUPLICATE(Emp:KeyClockNo) THEN 
    SELECT(?Emp:ClockNo)
    Message('Clock Number is already entered on another record....')
    CYCLE
END

The question of which field is causing the duplicate doesn’t really make sense.
Instead the question becomes which KEY(s) are duplicates for this record, is what does make sense.

The closest you get is to determine that a given key is considered a duplicate, and then display the components of that key, or simply skip showing the internals to your users, and instead make it more user friendly.
That said, you might find the two FileManager.GetFieldName( … ) methods to be interesting.

On a side note, you talked about Access:File.GetError.ToString() not compiling.
I think it’s a valid assumption that Access:File is a FileManager
The prototype for GetError is FileManager.GetError PROCEDURE(),SIGNED

Clarion does not support stringing methods together like Object.MethodA().MethodB()
I’ve recall this syntax being called “dotting through” but I cannot find this definition online.
Typically for this syntax to work, MethodA needs to return a class (or interface) so everything to the left of the .MethodB() is an expression which results in an object which has a MethodB() method.

FileManager.GetError() returns a ,SIGNED so dotting through wasn’t going to work.

What’s more is I can’t find a .ToString method in Libscr\win
except for in SystemString and in CWInt.INT

Lastly even if Clarion did support dotting through, then you’d need to change
.GetError.ToString() to
.GetError().ToString()

Thank you all for help.

This is not user initiated data input, so I do not want any message about error. That is why I am using log file.

I have looked into ABFILE.CLW. Methods Insert() and TryInsert() call the same procedure - FileManager.InsertServer PROCEDURE(BYTE HandleError). HandleError is 1 for Insert(), and 0 for TryInsert().

And the answer to my question is that TryInsert() does not know where is the error.

Only solution is to use DUPLICATE().

Thank you.

The KEY has the Duplicate but it is caused by the component fields. If it is a Form you want to tell the User as directly as possible which Entry in the Form is causing the problem and select it for him so he can can fix it. It is possible the Form Entry USE() is not the field but used to calculate it. I have tried to think of a generic way to code that but it seems too hard when the goal is to make a super obvious message to the user.

Blue you can check DUPLICATE(File) which checks all keys. I will sometimes use that as an ELSE in case a key is added not handled by the code e.g.

IF DUPLICATE(Transaction) THEN 
   IF DUPLICATE(Tran:KeyID) THEN
      LogIt('ID dup ....')
      !Fix it
   ELSIF DUPLICATE(Tran:KeyReference) THEN 
      LogIt('Reference dup ....')
      !Fix it
   ELSE
      LogIt('Transaction File has unexpected Dup key I do not handle ....')    
   END 
END