I found bug in new IB/FB driver (AD 2.0.4): It gets AV while changing the Connection property for TADTransaction when there are another active transactions attached to that TADConnection.
Currently I use FIB+ to access my FB2.0 DB.
It has TpFIBQuery component (in IBX - TIBSQL) - non TDataSet.
And this component can be used to fetch multi-row selects,
also to execute procedures, inserts, updates and so on.
IMHO. It's advantage - it uses single call and retrieve system for "selectebles"
and "executables".
In FB many "executables" can return values:
- execute procedure ....
- insert/update/merge ...
returning ...
Also EXECUTE BLOCK - which can be excuted or selected depending on it's body.
So methods Execute, Next, Eof, FieldByName are comfortable in these cases.
In AnyDAC there is an analogue of TpFIBQuery - TADCommand.
But I didn't found how to retrieve by it executed query output.
When opening "executable" query it catchs "resync error"
It wolud be nice to have functionality like TpFIBQuery.
And some sugestions:
1. The connection editor for TADConnection closes by the ENTER key.
Having ObjInspector like params editor (where ENTER simply "posts" change)
I think it would by nice that it closed by Ctrl+ENTER.
2. May be it is time to change year in AboutBox (IDE)
PS. I have made my project's branch using AnyDAC FB/IB driver (neighbouring FIB+). I use my own wrapers, so I think it would need virtualy no code change in mest cases. I hope so
It gets AV Fixed. It's advantage - it uses single call and retrieve system for "selectebles" and "executables". AnyDAC has the same functionality, just it is not presented in TADCommand. Now I made it accessible through TADcommand too. See method OpenOrExecute. But I didn't found how to retrieve by it executed query output. AnyDAC has different approach to fetch data from command. That is the basic idea:
var
oTab: TADDatSTable;
...
// open command
ADCommand1.Open;
// create and define DatS table
oTab := ADCommand1.Define;
try
// fetch all dataset
ADCommand1.Fetch(oTab, True);
// walk through rows
for i := 0 to oTab.Rows.Count - 1 do
oTab.Rows[i].GetData('ID');
finally
oTab.Free;
end;
If you will look into AnyDAC dataset internals, then you will see that they are doing similar things.
1. The connection editor ... it closed by Ctrl+ENTER Done.
2. May be it is time to change year in AboutBox (IDE) Done.
AnyDAC has the same functionality, just it is not presented in TADCommand. Now I made it accessible through TADcommand too. See method OpenOrExecute.
OK. Does this mean that I can use common approach for rerieving retuned values from executed and selected queries (e.g. the executed query retuns may look like a single row select fetch). For EXECUTE BLOCK it is hard to guess what it would look like. Any way, I use wrappers for TAD... (also for TpFIB...), so I would like any executables results retrive system with correct CommandKind.
Does this mean that I can use common approach for rerieving retuned values from executed and selected queries Yes, you can. If there will be issues, then report them and I will fix.
Firebird supports some other "executable" statements where user may expect results. For example
[code sql]
insert into TABLE1(ID, TXT)
values(gen_id(gen_table1_id, 1), '1111')
returning ID
and the others
I think Open would be rather strange name for executing it.
Creating TADDatSTable, fetching and destroying for geting single value
looks too complicated, doesn't it?
May be it would be better to return these values like OUT params?
Or create separate property smth like Returns: TADParams to avoid mixing
really OUT/INOUT params?
Also a little question:
I use TADMemTable and in some cases I may need to share single TADDatSTable for two TADMemTables.
It works fine using AttachTable method (only small issue while deleting row
wnen ControlsEnabled=true).
So on, I wanted to use notification to inform about changes between two holders. After having some investigation of the AnyDAC, I decided to create
descendant of TADDatSTable overriding Notification method.
But it there is small problem: in some cases AnyDAC uses ClassType instead of IS. In my case the show stopper was
function TADDatSRow.GetTable: TADDatSTable;
begin
if FOwner.ClassType = TADDatSTable then
Result := TADDatSTable(FOwner)
else
Result := TADDatSTable(FOwner.FOwner);
ASSERT((Result <> nil) and (Result is TADDatSTable));
end;
Is any reason of using ClassType? Making little test I discovered that ClassType is about 3 times slower than IS operator.
Thank you, I like the AnyDAC's architecture.
Regards, SSW.
if ADCommand1.OpenOrExecute then begin
oTab := ADCommand1.Define;
ADCommand1.Fetch(oTab, True);
ShowMessage(oTab.Rows[0].DumRow(True));
oTab.Free;
end;
Command must be in active state Open or OpenOrExecute must be called before Fetch.
request synchronization error Fixed.
May be it would be better to return these values like OUT params? It was implement - see first sample. Just you should add output parameters by hands. Later I will try to create output parameters inside of Execute call.
Is any reason of using ClassType? Making little test I discovered that ClassType is about 3 times slower than IS operator. Hmm ... I had completely oposite experience in Delphi 7. ClassType = xxx is faster than IS operator. What is your Delphi version ?