Posts Tagged ‘Delphi’

FireDAC MsSQL server compound field/column

Thursday, March 17th, 2016

So I bumped into this problem with firedac (8.0.x) where I had a table like


CREATE TABLE test(
col1 integer,
col2 integer,
col3 AS ISNULL(col1, col2)
)

and when inserting or updating the col1 or col2 fields, the dataset would not update the col3.
I did quite some debugging and found that there is no support in FireDAC for mssql server for compound fields. There is some in firebird though.
So spending some more time in debugging, I managed to find a workaround by subclassing the dataset like this:


type
TADQuery = class(uADCompClient.TADQuery)
private
FOnAfterInitFieldDefs: TNotifyEvent;
protected
procedure InternalInitFieldDefs; override;
public
property OnAfterInitFieldDefs: TNotifyEvent read FOnAfterInitFieldDefs write FOnAfterInitFieldDefs;
end;

procedure TADQuery.InternalInitFieldDefs;
begin
inherited;

if Assigned(FOnAfterInitFieldDefs) then
FOnAfterInitFieldDefs(self);
end;

... in formcreate or wherever ...

qrySomething.OnAfterInitFieldDefs := DoAfterInitFieldDefs;

procedure TForm1.DoAfterInitFieldDefs(Sender: TObject);
var i: integer;
col: TADDatSColumn;
begin
for i := 0 to TDataSet(Sender).FieldDefs.Count - 1 do
if TDataSet(Sender).FieldDefs[i].Name = 'col3' then
begin
col := TADDataSet(Sender).Table.Columns.ColumnByName('col3');
col.Options := col.Options + [coAfterInsChanges, coAfterUpdChanged];
col.Attributes := col.Attributes + [caDefault];
end;
end;

Enjoy.

Related posts

Delphi: Unit X was compiled with a different version of Y

Thursday, May 29th, 2014

The dreaded message everybody gets every now and then.

The classic solution is:
– find all related pas and dcu files on your HDD and make sure there is only 1 copy of each.

However, sometimes this is not sufficient and that is because there is also a DCP and/or a BPL that was built with that unit somewhere on the IDE searchPath found before the one you are building. So you delete all pas/dcu, build the package and still get the error. This happens when you build a package which depends on the package in which the unit resides. And that is because when building packages, delphi will look at the DCP, not the DCUs (when the DCP is linked of course).
So basically the same problem as with the DCU.

In conclusion, the actual complete solution is to
– search and remove all affected DCUs
– make sure there is only 1 version of the PAS
– search and remove all affected BPLs and DCPs

Sometimes, you will need to close the IDE, and then when you start it again you may receive the other dreaded message: “Cannot load package”.

Now, it’s time to search for that package in the registry, specifically in the
– “Disabled Packages” key
– “Known Packages” key
– “Package Cache” key
Best is to remove it from everywhere. Then you re-install it once you manage to compile everything.

Related posts

Delphi Loader Lock while debugging dll

Tuesday, July 31st, 2012

I’m working on a big project with several COM DLLs, used from inside autocad. Now, the other day I was debugging one of them and I started getting these messages in the debug output saying stuff like

Attempting managed execution inside OS Loader lock. Do not attempt to run managed code yada yada

Solution? Debug the correct DLL πŸ™‚ Seriously. Look on the call stack to see which is the last dll that is yours called there and debug that one.

There is also some considerations on the net about not calling LoadLibrary from the initialization section but I’m sure you already read that and not doing it.

Related posts

Delphi XE2 bug: memory leak

Friday, February 17th, 2012

That’s an easy one to reproduce if you are building a lot. All you need to do is keep building. Same project, or different one. Just keep building and watch the memory grow, grow until you get an Out of memory error.

Xe2 SP3. seriously? is this your level? The basic operations in your second version of XE at the 3rd service pack are still not working right? When in Gods name are you going to release a XE2 IDE that builds right? Am I really asking for too much? I haven’t even gotten to test the unicode and 64 bit support as I’m still migrating (way too many projects) and I’m already sick of this. All I want is to build. A very simple and basic command. The first one you use when you are building your application in order to be able to test it.

I just can’t believe this. Memory leak? COME ON!!!

Related posts

Delphi XE2 bug: nested option set depth limitation

Wednesday, February 8th, 2012

Some time ago I bumped into a very odd limitation on option sets (beside the bug I posted earlier). It’s about nested usage, when you have nested build targets, each with its own option set. You can see a more descriptive example in the stackoverflor post below:

http://stackoverflow.com/questions/8863041/delphi-xe2-option-set-nested-limit

I got to tell you, there are quite a lot of annoying bugs I keep bumping into with this XE2. I was so happy to see all the supported features that ease building so that I won’t have to write up complex batch files for it but bummer, they are buggy or don’t work at all.

The stupid thing is that if I modify one common file located some 10 packages up in the groupproject, I have to rebuild ALL the 10 packages, with ALL the 8-10 build targets.

Oh well, back to batch files.

Related posts

Delphi XE2 bug: build events not saved in option set

Wednesday, February 8th, 2012

As I’m working on a groupproject with a lot of projects each having a lot of (the same) build targets, I decided to go with option sets to have a good centralized control over things.
The surprise came when the build events didn’t work anymore the next day after I added them. Took me a little to figure out they were not saved. A little googling turned out he issue to be reported since well over a year on D2010. It’s “good” to see the bug to have gone by over 2 versions and a lot of updates.

Related posts

Delphi XE2 bug: build multiple targets

Wednesday, February 8th, 2012

When Building multiple targets on a project (like release and debug, in the same time (that is you select them all, shift select) and rightclick and then build, you will notice that the configurations used are those of the active configuration. So if you have the release active, then even though it builds the debug, it will do it with the release configurations (that includes option sets as well).
How to reproduce?
Have a project with multiple targets. Set different conditional defines in each (either directly or via option set, doesn’t matter), select them all, right click, and build. After the build, check the command line in the output and try not to curse. Took me about 2 hours to figure out why one of my projects was using a unit even though the conditional compiler directive was flagging to use another.

PS: if you think that using a build group saves you, surprise: it has the exact same bug.

Related posts

How to write an infinite recursion … elegantly

Wednesday, February 2nd, 2011

I’m working on a DB Lookup Combo with filter, sorting and most important: instance search (like winamp).

So, I figured I’d use a TClientDataSet as a proxy dataset for my combo and just descend from TDBLookupComboBox

All nice and dandy until the part where I have to respond to changes in the original dataset and update my proxy one. As always I did it like


dataset.disableControls;

try

dataset.first;

while not dataset.eof do blabla

finally

datasert.enableControls;

end;

The component was integrated into a financial application and for some reason I got the freeze, but only for a few seconds. For the life of me I couldn’t figure out what it was wrong, especially because from about 10 similar adotables and about the same number of forms, similar in construction and components, it only happened with one and only one. MadExcept by itself was not useful as setting the freeze timeout to 2 second it didn’t fire. Then I remembered madTraceProcess.exe and that did it: it showed the issue being in my component. A few breakpoints in the right spot (trial and error) got me seeing the recursion happening on the dataset.enableControls line. A few more minutes of debugging proved that the issue was caused by that usage as I was doing it in the DataLink.DataSetChanged method which is called when the dataset “changes”. But if you look through the code in DB.pas you’ll notice that the datasetChanged is called in a lot more other situations, but most notably in EnableControls.

Long story short, this is probably the “best” infinite recursion I’ve ever seen till now. and it was caused because my assumption that datasetChanged is called when the dataset changes. Wrong, it is called in EnableControls as well.

Related posts

Row cannot be located for updating. Some values may have been changed since it was last read.

Thursday, January 13th, 2011

Yet another one of those cryptic messages that basically says “you’re screwed”.

So what was I doing this time? Well, I had my mysql tables designed as having different fields as float. It just came natural to me that way. Everything went well until today when I had to modify that field on a record which had some fractional part (until now I did modifications but only to values with no fractional part) and boom. Took me a while to figure it out that it was the float type of the mysql table field that caused this because you see, float in mysql at least is not exact. It’s an approximation. That means that ADO will have a hard time to find hte modified record if you modify the value with a fractional part. It will actually raise ”

Row cannot be located for updating. Some values may have been changed since it was last read.”

Happy me. Solution? Just change the mysql column float into decimal(M,L). I use Decimal(15,2) as it works fine for my application. Yeah, have a laugh at all those people suggesting cursor type changes, ado property modifications and so on. People, first find THE CAUSE, and then find a way to fix it.

Related posts

Multiple Step Operation Generated Errors – Check each status value

Wednesday, January 12th, 2011

Yet another cryptic error with an unusual/weird test case and solution.

So, my setup:

– a table with a date field marked null/not null (tried both, same thing)

– an TADOTable to work with the above

– added all fields in the field editor

– a TDBDateEdit from RXLib with DefaultToday set to true

You make an append. You don’t touch the date as it’s set for today. You change everything else. You post. And you get the error:

“Multiple Step Operation Generated Errors – Check each status value”

Why? Well, thing is that when you make the append, the underlying TDataSet will set the state of itself to dsInsert, at which point TDBDateEdit will notice that a new record is added and set the date to today which makes the date field to be added to the internal modified field list of the TCustomADODataSet.

Now, the code runs further and calls DoOnNewRecord which clears the above mentioned internal modified field list and hence, when you do post, the date field is not in the list and hence it is not posted.

Now, since on the client side the field is set and has a value, on DB side the field was not sent and is either null or lots of zeros (if field is set not null) and hence they do not match (in this latter case delphi will also error because it cannot convert it to date. Not sure when this is done, but it is done). So, ADO will now raise this error BUT, the record was already added, just with an invalid date value. And if you are in the not null scenario and reload the grid, you will surely get the “ Data provider or other service returned an E_FAIL status.

There you go, yet another scenario for that cryptic error message πŸ™‚

Related posts