Any way to find out which TField is raising EDBClient with message 'Field value required.'? - delphi

I have one TClientDataSet with several Fields and I'm getting this exception, I'm sure that I forgot to set one field value, but the question is, which Field?
Is there some way to find out quickly which field is raising this exception?
EDIT
I solved the problem, I was connecting the TClientDataSet to the wrong provider, which had a required field on the server but didn't have this field on the client.
But it still doesn't invalidate my question, I lost a lot of time to figure it out, and if I had some way to know which server side required field was raising this error it would be very quick to realise what was my mistake.
EDIT 2
Related QCs:
#5557 - Solved as "As Designed".
#54380 - Open

When the debugger notifies you of the exception, look at the call stack. Navigate to the routine that is iterating over the list of fields, and inspect the loop-control variable at that point to find out how far through the field list your program got before raising an exception.
If the loop-control variable isn't accurate, then set a breakpoint in that routine and re-run your program. Step through until you get the exception again.
Another option is to look at all the fields and see for yourself which one lacks a value.

Related

Complex T-SQL script executed via TADOQuery is firing "Multiple-step OLE DB operation generated errors."

I have a very large block of SQL that I am trying to execute inside of Delphi, against a Microsoft SQL Database. I am getting this:
Multiple-step OLE DB operation generated errors.
Check each OLE DB status value, if available. No work was done.
The script has multiple sql IF statements followed by BEGIN and END blocks with invocations of stored procedures, declaration of variables, and EXEC inside that. Finally it returns some of the variable values by SELECT #Variable1 AsName1,#Variable2 AsName2....
The above multi-step error is coming in as an OLEException from ADO, not from the Delphi code, and happens after all the SQL exec-stored-procedure have occurred, and therefore I suspect it's firing this OLE exception when it reaches the final stage which SELECT #Variable1 AsName1,... to get back a few variable values for my program to see them.
I know about this retired/deprecated MS KB article, and this is unfortunately not my actual issue:
http://support.microsoft.com/kb/269495
In short that KB article says to fix a registry key and remove "Persist Security Info" from the connection string. That's not my problem. I'm asking this question because I found the answer already and I think that someone else who gets stuck here might not want to waste several hours finding potential issues when there are several that I have found after searching for solutions for several hours. Anyone who wants to add another answer with different options, is fine, and I'll select yours if it's reproducible, and if necessary I'll turn this one into a Community Wiki because there could be a dozen obscure causes for this "ADO recordset is in a bad mood and is unhappy with your T-SQL" exception.
I have found several potential causes that are listed in various sources of documentation. The original KB article in the question suggests removing the 'Persist Security Info' from my ADO connection string, however in a standalone test in an application with just a TADOConnection and a single TADOQuery, the presence or absence of Persist Security Info had no effect, nor did explicitly setting it True or False.
What DID fix it was removing this CursorType declaration:
CursorType=ctKeyset
What I have learned is that bidirectional ADO datasets are fine for SELECT * FROM TABLE in ADO but are not so fine for complex SQL scripts.
Potential source of this error is updating char field with large value.
Example: Form has edit box with max length property set to 20 characters and Oracle database table has field defined as char(10).
Updating with 10 characters (or less) will work fine while updating with more then 10 characters will cause 'Multiple step...' error on ADOQuerry.UpdateBatch().
You also have to know that CHAR will allways have 20 characters. Consider Trimming value in edit box. CHAR behaves different than VARCHAR2 type.
If you have a query with parameter ,check the number of parameters in the query is matched with script...!

Rails validation fails but object memory remains unchanged?

First time user long time reader. I have thoroughly looked for an explanation for the problem I'm having via the mighty search engine Google, but alas I have failed to produce any significant insight.
I need to be able to ensure that a model form is not reloaded with invalid data. Since the model stored in memory on the server is edited directly with the parameters of the web form first, and THEN checked for validity, without additional code invalid model data will ALWAYS be sent back to the form. This is less than desirable to me. My question is this: how do I ensure this doesn't happen?
What I'm thinking is I need some mechanism for saving the state of the object before it's modified with the parameters sent from the web form, and then after a failed validation restore the object to it's previous, correct and unmodified state of being.
Help!
Thanks,
Les
The object isn't actually modified in the db if validation fails, even though the object is in an invalid state in the form ... the thinking behind this is that the user wants to see the errors they made so they can correct them.
If you don't want that to be the case, then just read back the object with a WhateverObject.find(x) and assign it to the variable that the form is referencing and it will 'restore' the object to its previous unmodified state.
To add to what concept47 said you can also get the value for a particular field using
object.field_was
Have a look at ActiveRecord::Dirty for details (http://ar.rubyonrails.org/classes/ActiveRecord/Dirty.html)
Using that you could retrieve the original values for just those fields that had validation errors.

insert to a different table onNewRecord

got an ADOQuery that has OnNewRecord event.
on the procedure i try to add data automaticaly to another table. the data is a few rows that are needed and handled in clientDataSet in case of cancellation.
at the loc
OtherAdoQuery.insert;
I get error that ADOQuery failed to insert null into a non null field. I am in insert mode, however I NEVER ASKED DELPHI TO POST! i dont find why it posts.
Edit: could you help me find a hint on this problem?
some more clarification:
at
ADOQuery.onNewRecord();
begin
CliendDataSet.insert; //here goes to post for ADOQueryPost. where ClientDataSet was in Browse State
end;
Edit:
this bug does not make sense! look at the stack trace:
beforePost
newRecord
myFunc
where myFunc does cause NewRecord with the Insert.
I'm not too familiar with TAdoQuery, but I know how to track down an error like this. First, if you don't already have it set, go into Project Options and turn on Use Debug DCUs under the Compile tab, then run a full build and run it. When you get that exception report in the debugger, hit Break and you should end up inside the code for the TAdoQuery or one of its sub-objects. Try examining the call stack. If you look up a few calls you'll probably find something that you did is calling something else that's calling Post. Follow the stack trace back until you reach your code and you'll get an idea of what's going on, and if you analyze it a little you should find some way to prevent the problem.
Having said that, let me make a quick guess as to the cause of your problem: When you call Insert on a dataset, if the dataset is already in appending mode because you previously called Insert or Append and didn't follow up with a Post, it will call Post itself before setting up a new row for you to work on. Maybe this is what's happening to you?
the answer was from a connection between the tables.
the ADOQuery.dataSource was set the DataSet of the ClientDataSet.
this mad so much damage, and no hint by the delphi.

How to track down access violation "at address 00000000"

I know how to create a .map file to track down access violation errors when the error message includes an actual address.
But what if the error message says
Access violation at address 00000000. Read of address 00000000.
Where do I start looking for the cause of this problem... ?
The accepted answer does not tell the entire story.
Yes, whenever you see zeros, a NULL pointer is involved. That is because NULL is by definition zero. So calling zero NULL may not be saying much.
What is interesting about the message you get is the fact that NULL is mentioned twice. In fact, the message you report looks a little bit like the messages Windows-brand operating systems show the user.
The message says the address NULL tried to read NULL. So what does that mean? Specifically, how does an address read itself?
We typically think of the instructions at an address reading and writing from memory at certain addresses. Knowing that allows us to parse the error message. The message is trying to articulate that the instruction at address NULL tried to read NULL.
Of course, there is no instruction at address NULL, that is why we think of NULL as special in our code. But every instruction can be thought of as commencing with the attempt to read itself. If the CPUs EIP register is at address NULL, then the CPU will attempt to read the opcode for an instruction from address 0x00000000 (NULL). This attempt to read NULL will fail, and generate the message you have received.
In the debugger, notice that EIP equals 0x00000000 when you receive this message. This confirms the description I have given you.
The question then becomes, "why does my program attempt to execute the NULL address." There are three possibilities which spring to mind:
You have attempt to make a function call via a function pointer which you have declared, assigned to NULL, never initialized otherwise, and are dereferencing.
Similarly, you may be calling an "abstract" C++ method which has a NULL entry in the object's vtable. These are created in your code with the syntax virtual function_name()=0.
In your code, a stack buffer has been overflowed while writing zeros. The zeros have been written beyond the end of the stack buffer, over the preserved return address. When the function later executes its ret instruction, the value 0x00000000 (NULL) is loaded from the overwritten memory spot. This type of error, stack overflow, is the eponym of our forum.
Since you mention that you are calling a third-party library, I will point out that it may be a situation of the library expecting you to provide a non-NULL function pointer as input to some API. These are sometimes known as "call back" functions.
You will have to use the debugger to narrow down the cause of your problem further, but the above possiblities should help you solve the riddle.
An access violation at anywhere near adress '00000000' indicates a null pointer access. You're using something before it's ever been created, most likely, or after it's been FreeAndNil()'d.
A lot of times this is caused by accessing a component in the wrong place during form creation, or by having your main form try and access something in a datamodule that hasn't been created yet.
MadExcept makes it pretty easy to track these things down, and is free for non-commercial use. (Actually, a commercial use license is pretty inexpensive as well, and well worth the money.)
You start looking near that code that you know ran, and you stop looking when you reach the code you know didn't run.
What you're looking for is probably some place where your program calls a function through a function pointer, but that pointer is null.
It's also possible you have stack corruption. You might have overwritten a function's return address with zero, and the exception occurs at the end of the function. Check for possible buffer overflows, and if you are calling any DLL functions, make sure you used the right calling convention and parameter count.
This isn't an ordinary case of using a null pointer, like an unassigned object reference or PChar. In those cases, you'll have a non-zero "at address x" value. Since the instruction occurred at address zero, you know the CPU's instruction pointer was not pointing at any valid instruction. That's why the debugger can't show you which line of code caused the problem — there is no line of code. You need to find it by finding the code that lead up to the place where the CPU jumped to the invalid address.
The call stack might still be intact, which should at least get you pretty close to your goal. If you have stack corruption, though, you might not be able to trust the call stack.
If you get 'Access violation at address 00000000.', you are calling a function pointer that hasn't been assigned - possibly an event handler or a callback function.
for example
type
TTest = class(TForm);
protected
procedure DoCustomEvent;
public
property OnCustomEvent : TNotifyEvent read FOnCustomEvent write FOnCustomEvent;
end;
procedure TTest.DoCustomEvent;
begin
FOnCustomEvent(Self);
end;
Instead of
procedure TTest.DoCustomEvent;
begin
if Assigned(FOnCustomEvent) then // need to check event handler is assigned!
FOnCustomEvent(Self);
end;
If the error is in a third party component, and you can track the offending code down, use an empty event handler to prevent the AV.
When I've stumbled upon this problem I usually start looking at the places where I FreeAndNil() or just xxx := NIL; variables and the code after that.
When nothing else has helped I've added a Log() function to output messages from various suspect places during execution, and then later looked at that log to trace where in the code the access violation comes.
There are ofcourse many more elegant solutions available for tracing these violations, but if you do not have them at your disposal the old-fashioned trial & error method works fine.
It's probably because you are directly or indirectly through a library call accessing a NULL pointer. In this particular case, it looks like you've jumped to a NULL address, which is a b bit hairier.
In my experience, the easiest way to track these down are to run it with a debugger, and dump a stack trace.
Alternatively, you can do it "by hand" and add lots of logging until you can track down exactly which function (and possibly LOC) this violation occurred in.
Take a look at Stack Tracer, which might help you improve your debugging.
Use MadExcept. Or JclDebug.
I will second madExcept and similar tools, like Eurekalog, but I think you can come a good way with FastMM also. With full debugmode enabled, it should give you some clues of whats wrong.
Anyway, even though Delphi uses FastMM as default, it's worth getting the full FastMM for it's additional control over logging.
Here is a real quick temporary fix, at least until you reboot again but it will get rid of a persistent access. I had installed a program that works fine but for some reason, there is a point that did not install correctly in the right file. So when it cannot access the file, it pops up the access denied but instead of just one, it keeps trying to start it up so even searching for the location to stop it permanently, it will continue to pop up more and more and more every 3 seconds. To stop that from happening at least temporarily, do the following...
Ctl+Alt+Del
Open your Task Manager
Note down the name of the program that's requesting access (you may see it in your application's tab)
Click on your Processes tab
Scroll through until you find the Process matching the program name and click on it
Click End Process
That will prevent the window from persistently popping up, at least until you reboot. I know that does not solve the problem but like anything, there is a process of elimination and this step here will at least make it a little less annoying.

The 'invalid field type' error with TClientDataSets I don't understand

I use nested database stuctures with TClientDataSets. I'm new to programming so my lingo is ten-to-one wrong.
My problem is as follows: I defined my database stucture and all the fields of the nested stuctures and then I called the CreatDataSet method of the master clientDataSet and it worked. I then wanted to add another data field to the master ClientDataSet. I then called the ClearData method of the Master ClientDataSet and then tried to create the new stucture by calling CreateDataSet again. It is here where I encounter my problem. I get the 'Invalid field type error' and I don't really know or understand what what the problem is.
So how do I create an exsta field after I called the createdata set method, then called the cleardata method, then added a field and then calling the createdataset method again without getting the 'invalid field type error?
Does anybody have any information about this problem. I use Delphi 2007
Kind Rgards
Riaan de Villiers
It is a Delphi bug.
Call YourDataset.FieldDefs.Clear before calling CreateDataSet and it should work.
For more infomation please look at this QC Report:
http://qc.codegear.com/wc/qcmain.aspx?d=38984
EDIT:
After reading your problem more carefully, the problem might be something else, but please try the FieldDefs.Clear and let me know the results.
It has been a long time since you asked this question, but I believe the problem has specifically to do with the nested dataset fields. I've seen this error before, and I believe that it has to do with the order in which the particular fields are created. If I remember correctly, if you try to create the master dataset before the nested dataset fields are defined or created, you get this invalid field type error.
Begin by removing your nested dataset fields from the equation and see if you still get the problem. If not, then add them back. Try creating the master dataset and its nested datasets in different orders.
I know this is late, but I hope it helps.

Resources