Paul,
I am not surprised that you wrote "it is more difficult than I thought".
When I set out to upgrade IBX for Lazarus to the new Firebird 3 OO API,
I thought that it would be a relatively straightforward task. My
intention was to separate out the parts of IBX that were specific to the
VCL/LCL from those that were concerned with converting Firebird data
types to Pascal data types and for handling the intricacies of the low
level API - surely moving to the new API was just a matter of moving
from the XSQLDA oriented approach to unpacking and packing buffers.
I ended up creating a new (Firebird Pascal) API with almost 37K lines of
Pascal code of which 4K was specific to the support of the legacy
Firebird API and another 4K for the test suite. The "sloccount" utility
reckons it would cost $1.1M to create. Some of this code is there
because of a decision to use COM interface types for the API (driven by
a desire to have a common core API for both Firebird 2.5 and Firebird 3
OO style interfaces). However, this is only a small part of the codebase.
I did not set out intending to create such a large codebase - it simply
the result of what needed to be done - and its size will hopefully give
some perspective to your task. I have positioned the API at the same
level as IBPP and I believe that that is the correct level for
programmers that want direct access to the Firebird API but without
having to work out how to use the low level API.
As to the question about VCL integration - my advice is do not even go
there unless you are intending to create a rival to IBX (which weighs in
at a further 51K lines). The TDataset model is not for the faint-hearted
and takes you into a whole new realm of buffer management and SQL
manipulation. The TDataset model is also grossly OTT unless you want to
use Delphi's data aware controls. In practice, I have found myself using
my Firebird Pascal API for all programmatic database access other than
GUI support.
Having gone through all this pain, I have published the Firebird Pascal
API as an API separate from IBX for Lazarus, and under the Interbase
Public Licence. It compiles and is tested for both FPC and Delphi, and
comes with a comprehensive user manual. You can find it at
https://mwasoftware.co.uk/fb-pascal-api
The real question is who is the audience for the examples? Is it the
application programmer or is it the maintainers of packages such as
IBPP, Jaybird and the Firebird Pascal API? The answer to that question
should determine your objectives for the examples.
Notes:
When you look at what has to be done for a comprehensive native Pascal
API for Firebird you find that:
1. You need data type conversion rules for all Firebird data types. This
includes character strings where the Firebird character set has to be
translated into an AnsiString code page (a property of the AnsiString
type) with transliteration if necessary.
2. Input/output buffer management from the statement metadata. My API
additionally includes an intermediate layer for the Firebird OO API
(like an XSQLDA) so that the user does not have to read/write the values
in strict column order.
3. Code to manage the myriad parameter block formats (input and output)
each with their own idiosyncrasies. I found Pascal Generic (template)
classes very useful here. The issues here are all about converting from
Pascal data types to the encoding format used for each class of
parameter block - it is amazing how many different ways Firebird
parameter blocks have for encoding integer and string types.
4. Event Management requires thread management and process
synchronisation - and the resulting platform dependencies that you could
introduce.
5. Blobs have their own handling issues with text blobs having to appear
as Pascal AnsiStrings (codepage and transliteration issues as above)
while binary blobs are best converted into TStream descendents.
6. Arrays are do-able but there is no documentation that I could find
and had to reverse engineer the legacy Firebird API to work out the SDL
format.
7. At least the database connection and transaction APIs are pretty
straightforward - once you have a way of handling the parameter blocks.
8. And then there is the services API... Client side database
backup/restore is another fun problem.
9. Finally, you also need to think about how you load and access the
Firebird Client library from a Pascal Program. The Firebird.pas source
code takes a basic approach which only really works well with static
linking. IBX traditionally used dynamic loading and dynamic API binding.
I have kept with that style for the Firebird Pascal API. It allows the
API to search for the Firebird DLL/SO according to a platform specific
algorithm and then to determine the version number of the low level
interface and adapt accordingly. This was original useful for deciding
if the Interbase 6 extensions were present. It is now used to determine
if the Firebird 3 OO API is present and in the latest (beta) versions to
adapt to the use of the Firebird 4 extensions. It also allows the same
system to host multiple copies of the Firebird library - I exploit this
to readily permit automated testing against different versions of the
Firebird Client library.
I guess examples will only scratch the surface of these issues. You will
probably end up concentrating on opening an example database using a
basic DPB and reading/writing a limited set of data types.
Regards
Tony Whyman
MWA
On 17/08/2020 16:25, Paul Reeves wrote:
I thought I would port the OO API examples to Object Pascal. After all, they
are quite simple, so how hard could it be?
In fact it is more difficult than I thought and I am not happy with the
results. I've done two examples - update and select - and I would like to
commit them but before doing so I'd like to discuss how we should proceed.
In my opinion we should start a new sub-directory to contain all the object
pascal code. This is because the examples will actually need several
supporting files in a common directory. It would be best if the were kept
clearly separate from other examples.
But the main problem I have found is that if I try to copy the C++ style too
closely all we end up with is very bad object pascal. It succeeds in
demonstrating the new API but does not demonstrate good programming practice.
However, if we want to demonstrate good programming practice we should
probably integrate the examples into the VCL. And that might be a step too
far.
Does anyone have any thoughts on this?
Paul
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel