Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

=ASTACKINFO(laStack) gives error

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
542
MU
Dear friends,

I have a form bass class. In its ERROR method I have an error routine. I have the following lines it in (in between the full code)

LOCAL ARRAY laStack[1,6]
=ASTACKINFO(laStack)

Is there any possible situation that the line =ASTACKINFO(laStack) will produce an error?

Thanks
Rajesh
 
Error 43
There is not enough memory to complete this operation.



mJindrova
 
mJindrova is right,

That's always an error that can happen. It's a rare case, though. Which means ASTACKINFO() works in almost all circumstances. The main issue with ASTACKINFO is usually when you don't include debug info in your EXE, you get less information from the array this generates, but no error.

You might have a completely different problem. If you expect form.Error() to handle all errors that occur anywhere in the form, you err. If a click method of a button errors and the button has no error event code, the form.error event will not take over error handling, you get normal/system or ON ERROR handling.

If an error happens while you test in the IDE, click "SUSPEND" and then look into the debugger, where you are, actually. Is it the line ASTACKINFO? I doubt it. And the error message will also be available. So if ASTACKinfo errored already, why don't yo tell us which error message popped up?

In all error handling efforts you should always also have the ON ERROR handling active as a fallback general error handler. It's really easy to implement something - anything - on the general level.

Chriss
 
Thank you Jindrova and Chriss,

Yes, Chriss, actually my 'Save' method calls the 'Error' method programatically if my TABLEUPDATE call has an error.

The Error routine writes in detail to a log file. Also, I have a TRY...CATCH inside Error routine itself, in case there is any problem in the routine itself! This particular problem which I face now was actually captured by the TRY..CATCH and the log file was written from the CATCH section!

By the way, I am using AERROR() and referring to its 4th element. I see that the 4th one can be NULL, Numeric or Character depending upon the error type. But, I was checking only for ISNULL and then treating it as character. So, if 4th one gives a work area number, my code would end up in an error within the Error routine itself. So, this must be the cause somehow giving me =ASTACKINFO(laStack) as the line of error wrongly (Chriss you doubted it already that the error must be elsewhere).

Now, I have deployed the revised application and will keep an eye on the log file.

Thanks
Rajesh
 
Good,

I just would never advise not to call an event, but for sake of simplicity if your save button calls the form.error() code then you don't have an actual error triggered. In that case AERROR will have the direct result 0, as it generates no error rows. It could also just repoort the last errror that happend anytie before. So there you have another reason to split this up into two form methods, one - the error event- with code thaat only gets triggered by error events, one that's for the lgging purpoose and can be called from error handling or when tableupdate() returns .f.

Notice tableupdate returning .f. just reports a proble of storing the buffered data, in detail that doesn't need to be a dbf corruption, it could be a broken field or table rule, it could be due to a confliict tableupdate detects. For example if you make the update type keyfield and modified fields, the original record is searched by all those fields old value, not just the key. If anything changed - the key shouldn't - then this points out fields you modified were modified by another client, too, and that client already saved before you. You need to handle this, but not with error handlling and logging, you need to inform the user that someone else made a change of the same fields and you could let them decide what new value is actually the better new value.

Also with other reasons tbleupdate fails and returns .f. ,it's not an error and things like AERROR then don't work as expected. So you shouldn't call the error handler that expects AERROR to create an error array row, or more. Or you have to program it, so the case with no actual error also is covered.

Chriss
 
Chriss,

I think you're correct when you say if I call Error method programatically, actually the error event is not being analysed.

In our Save routine, I run TABLEUPDATE and if an error is returned, I call AERROR and pass its error number to the call to Error method. There are some checks in it to alert the user accordingly. In other general error cases, the Error event is being triggered, I believe.

I am aware TABLEUPDATE returning false may not be always because of a bug in code but could be update conflict etc. We also have a few other checks, for example, employing OLDVAL, CURVAL etc which alerts the user.

Thank you for showing more light to the scenarios

Rajesh


 
AERROR gives you info if SQLEXEC returns -1, but not anytime TABLEUPDATE() returns .F.

Whether AERROR() is having any relevant additional information after TABLEUPDATE() returns .F. depends on how you use TABLEUPDATE().
The help says:

VFP help said:
If an error other than a simple commit error occurs while updating records, the first element of cErrorArray will contain –1, and you can then use AERROR( ) to determine the why the changes could not be committed.

In first place thate means: Not always-
In second place this means only when you use TABLEUPDATE fully parameterized with its cErrrorArray parameter. This gives you an error array, that is not the same structure as the array AERROR() genertes, it's usually an array of record numbers that fail to update.
In third place, only and only if you use TABLEUPDATE that way and also the Array you sepcify is generated or extendded and also its first element is -1, only if all these three conditions are met, then AERROR() tells you additional info about what failed.

Are you even using TABLEUPDATE with full parameterization? If not, it's totlally useles to call AERROR.


Chriss
 

Chris Miller said:
AERROR gives you info if SQLEXEC returns -1, but not anytime TABLEUPDATE() returns .F.

VFP help - TABLEUPDATE( ) Function said:
To determine why the changes could not be committed, use the AERROR( ) function.


mJindrova
 
Okay, I see.

Still it's only true in conjunction with a) single record updates or b9 all rows and stopping at the first record that can't be committed.
vfp help said:
[highlight #FCE94F]When specifying 0 or 1 for nRows[/highlight], the record pointer remains on the record where changes could not be committed. To determine why the changes could not be committed, use the AERROR( ) function.
If you use tableupdate to change all buffered changes, I prefer to do it with nRows=2, then you don't get more detail info but the record numbers that failed.

It's still true to say AERROR does not generally give you more information.

Chriss
 
Chriss,

Usually or at least in the current application, I am using TABLEUPDATE only with first 2 parameters. I see that cErrorArray is relevant only if you pass 2 to the 1st parameters, but we use .F. or .T. in this application (for single row or multiple) and not bothered about cErrorArray. Also, cErrorArray only gives you the record numbers right? For full details, you have to go AERROR.

Chriss said:
Are you even using TABLEUPDATE with full parameterization? If not, it's totlally useles to call AERROR.

I did not fully understand what do you mean by this? I believe, AERROR will give you basic info in any error case.
Or, you must be saying, if I don't use the cErrorArray in TABLEUPDATE, a subsequent AERROR is never going to give additional information. Is that so?

Rajesh
 
Chriss,

Chriss said:
If you use tableupdate to change all buffered changes, I prefer to do it with nRows=2, then you don't get more detail info but the record numbers that failed.

Wouldn't that be a problem in some cases to use nRows=2 ?
I see that, in that case, even a record fails, saving will continue with the rest and so on.
I have never tried it.

So, nRows=2 won't suit our scenario I believe. We don't want to update any record, if at least one record fails. If there is error with TABLEUPDATE, I have a ROLLBACK. For any single error in header or lines tables on any record, we don't commit the changes at all.

In some forms, we have TRANSACTION...END TRANSACTION and in some forms we validate individual TABLEUPDATE and decide on our own accordingly. This application was written long back and I am making changes as and when required, plugging in new features etc etc...

Rajesh
 
You're saying it yourself, you keep control by wrapping all your tableupdates withiin a transaction. It depends on the use case and how you process the skipped record. After an application is mature, it's rarely more than a conflict of update you can resolve without needing to rollback and restart the whole transaction. If nRows=2 wouldn't make sense, then it wouldn't be a mode you can choose.





Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top