FreeIBComponents and all associated source code is free! But that doesn't mean that it is public domain. In fact, it is not. See section Licensing for a detailed explanation of the license you are granted for using FreeIBComponents.
This suite of components is for easily accessing InterBase without using third-party products (although I supposed this is a third-party product...). This product was written entirely in Delphi, and has been designed to work with Delphi. I have heard some rumors that these components will work with C++-Builder. I don't have C++-builder, so I can't test this rumor, but it might be worth a shot!
FreeIBComponents is a great jumping stone for all of us Delphi/InterBase developers. It frees us from using the BDE, and allows us to marry Delphi and InterBase even more tightly. Best of all, this tool comes to developers free of charge, with all source code included.
Why did I write FreeIBComponents? After all, there are a great many tools out there which marry InterBase and Delphi quite well. For example, Jason Wharton has a commercial product out there which avoids the use of the BDE, and the BDE itself is a wonderful product for accessing InterBase from Delphi. I could have bought Mr. Wharton's product or just continued using the BDE.
I'll give you a bit of background first. I and my company chose to use InterBase because of its superior transaction handling, it's small footprint and its ease of administration. We also chose to use Delphi for client development because Delphi is a wonderful Windows development tool. The BDE has proven useful, but, among many other reasons, I have grown tired of distributing megabytes of files (that I didn't create) just to run my applications.
Because I have such faith in InterBase's product, it is only reasonable to do all I can to advocate its use, and to support it by building tools that exploit as many of InterBase's features as possible. The only way we, as a developer community, can expect other developers to share the burden for advocating InterBase is to provide free tools which will further enable all developers to produce great InterBase applications.
By getting developers to use InterBase more and more, we solidify and further justify our own decisions to use (and sell) the product.
To that end, I have created FreeIBComponents, my own little shot at benefiting the InterBase and Delphi developer community.
Hoagland, Longo, Moran, Dunst & Doukas is a law firm in New Brunswick, NJ. This law firm is one of the most technologically advanced law firms in New Jersey, due largely to the fact that their management team has a uniquely clear vision of the future use of technology in the legal field.
Hoagland, Longo, Moran, Dunst & Doukas is dedicated to providing quality legal services to the business community, healthcare and insurance industries. Since our founding in 1977 we have handled thousands of matters spanning the spectrum of business transactions and civil litigation including automobile negligence, commercial litigation, construction claims, coverage, D and O liability, employment practices liability, environmental claims, general liability, municipal liability, products liability, professional liability and workers compensation.
Very special thanks goes to Hoagland, Longo, Moran, Dunst & Doukas. If you ever require legal representation in the New Jersey area, you might want to look these guys up.
InterBase corporation has provided their support by providing a home for both FreeIBComponents and FreeUDFLib (see section About the author).
Obviously, without InterBase, FreeIBComponents wouldn't be worth a thing, so a special thanks goes to all at InterBase, with a strong vote of support to please continue the outstanding work!
Here is a list of all who have contributed or otherwise supported the project. If your name has been omitted, it is not on purpose!
Since FreeIBComponents is free, it is important to give developers a sense of what kind of support they can expect. Although there are no guarantees of any kind, I want to give developers reasonable assurances of what they can, in general, expect from me.
I believe that there are four basic levels of support developers require:
FreeIBComponents is intended to be used in production environments! To that end, a demonstrated bug will be fixed as promptly as possible.
Because FreeIBComponents is completely free, developers also have access to the source code. If a bug is fixed, send it to me, and I will incorporate it in future "official releases" of the product.
If a bug cannot be replicated, I will have a difficult time finding it, so I can't guarantee resolution of so-called phantom bugs, but I will do my best to resolve them.
If you provide me with a bug fix, your name will be included in the acknowledgements section of this manual. Bug reports should be submitted as e-mail messages only.
The policy on resolving source code bugs also stands for correcting and maintaining good documentation. Please send me any and all corrections and/or enhancements to the documentation. Every product needs thorough and complete documentation. Even though this product is free, I have a desire to see it used in all environments. I can't expect a developer to use it if there is no documentation.
I can't guarantee that I will respond to you, only that your comments will be heard and possibly included in future releases.
Users can feel free to provide me with wish list requests and/or FreeIBComponents enhancements.
If you send me a wish list request, you will not receive a response from me, but you can be assured that your request will be considered for future releases.
If you send me an enhancement or extension to FreeIBComponents that you would like included in the distribution, I will consider it and respond accordingly. Keep in mind, however, that FreeIBComponents and all source code is free. Do not even think about asking to distribute proprietary products with FreeIBComponents.
If I distribute product enhancements written by others than myself, their names will be included in the acknowledgements section of this manual, and their source code will be acknowledged appropriately.
I don't do help desk support, at least not in general. You can feel free to e-mail me with questions, but it is more likely than not that you will not receive a response from me.
Help desk style questions should be directed to an appropriate Internet support group. The mailing list INTERBASE@mers.com, for example, provides excellent support for InterBase related questions. Also, I tend to make all of my announcements exclusively to this list. (This list is also a newsgroup. See www.mers.com for more information.)
If you absolutely require my assistance for some issue, I can provide services for standard consulting rates.
I have used a product called texinfo to produce all documentation for FreeIBComponents.
From a single source file, I can produce a formatted manual, ready for print-out (using tex), I can produce html, ready for viewing in a browser, and I can produce rich-text for the production of a help file.
I don't see the need for producing a help file, so I haven't included one... just the original texinfo documentation, a ready-produced Acrobat file, and a single HTML manual.
If the reader wishes to find more information on using texinfo with Windows, search the internet for "GNU tex texinfo Windows". (O yeah, texinfo is free, protected under the GNU Public License)
A bunch of people have made requests like: What about a TFIBTable? What about a RequestLive property as opposed to the select- update- insert- delete- refresh- queries?
Well, in short, I'm not sure I see the real value in doing any of these. If anyone has some thoughts on these as well as other feature requests, I'm very interested!
Bug fix release...
FreeIBComponents works with Delphi 4! Installation hasn't changed a bit, either... Just install the FIBComponents.dpk, and everything is taken care of!
Also, using FreeIBComponents with C++-Builder should be a bit simpler than before...
I have high hopes that this release is all that it says it is, but being the pessimist that I am, I know that it isn't... With all the new features and fixes in this release, you might come across some stumbling blocks. Let me know when you find them, and better yet, let me know how to fix it. It'll be fixed in my next release which will be devoted primarily to "maintaining" this release.
New features:
False. (i.e., ensure it in
code)
Bug fixes:
Known/possible bugs:
I believe it is now safe to call this software BETA quality...
Yes, we're now in beta!
This release contains no new features, only bug fixes:
FIB_VERSION to `FIB.pas'. This is the date
stamp (and official version number) of the release of
FreeIBComponents.
Enhancements:
IndexOfDBParam "public". See docs,
see section Methods.
Bug fixes:
TFIBQuery.Close attempts to close any style query, whether it is
a SQLSelect statement or not, but only SQLSelect statements can
be "closed", as they are the only statements that can be "opened".
TFIBDataSet was told that the database is disconnecting,
it forgot to set Prepared to false. This reaks havoc with the
system when the user tries to re-activate the dataset, after having
disconnected the database and reconnected. Luckily, this problem was
quite simple to solve...
TFIBTransaction doesn't handle design-time activation properly.
Courtesy of Adrian ? (adrian@softly.demon.co.uk)
InternalInitFieldefs method. This declaration is required
for C++-Builder releases.
Documentation fixes/enhancements:
Code fixes/enhancements:
Timeout properties of TFIBDatabase and
TFIBTransaction are now implemented.
EFIBError constructor, and the next fix
entailed modifying some code in the InternalInitFieldDefs
procedure in `FIBDataSet.pas'. To use FreeIBComponents with
C++-Builder, see see section Installation.
ForceClose of TFIBDatabase is now cleaner.
DataSource property of TFIBDataSet can now be used for
establishing master-detail style relationships between queries.
TFIBStringField class was not entirely defined. It has now
been fixed.
TFIBTransaction now includes a published property Active
for starting and rolling back transactions.
TFIBDataSets can now be activated at design time.
BookmarkSize needs to be set to SizeOf(Integer) in
the create method. Then... GetBookmarkData needs to move the
record number to the "pointed-to" data and SetBookmarkData needs to
treat Data as a PInteger.
ActiveBuffer might not always return the correct value. This has
been fixed.
Installation of FreeIBComponents is really very simple:
c:\develop\Lib -or- c:\Program Files\FreeIBComponents
That's it. FreeIBComponents are installed!
FreeIBComponents is currently a Delphi-only release; however, I also intend to support C++-Builder. As far as I know, this release might work with C++-Builder (at least that's the rumour). I'm not experienced using C++-Builder, so if someone wants to provide some docs just like the above for getting FreeIBComponents up and running in a C++-Builder environment, I will be happy to include them here.
What I do know about getting the C++-Builder environment to work? the
way I understand it, the compiler define for C++-Builder is
$VER110, so all C++-Builder specific code is wrapped within those
constraints. You must also make sure that `GDS32.LIB' is in your
include path.
I do my best to keep this documentation up to date, and relatively comprehensive. You must keep in mind, however, that this is a free product, and since all source code is provided, you can always figure out how something works by looking into the code yourself.
As a general note to the reader, the license to use this software can be simply stated as: "This product comes to you at no cost, but you are being given a bunch of free source code. Please take care to give credit where credit is due." This code is protected under copyright, and its distribution is restricted as set forth in the below license agreement. It is not meant to hinder your use of it. In fact, it is meant to protect all of us, so that we can all continue to use this free software.
Here is my own plain english interpretation of the below license. Just remember, though, that this interpretation is unofficial--You are bound by the below agreement, not my interpretation of it!
If you develop a tool whose intended audience is the developer community (a derivative of FIB, or another developer tool which makes use of FIB), then you must give me credit. I don't really care if you give me credit when developing an application whose intended audience is the general user community; however, the license agreement does require you to give me credit for any product which makes use of FreeIBComponents.
In any case, FreeIBComponents comes to you for free, and you can sell your derivative products without worrying about compensating me.
GENERAL SOFTWARE LICENSE AGREEMENT
CAUTION: THE COPYING, MODIFICATION, TRANSLATION OR DISTRIBUTION OF
THE OBJECT CODE, PROGRAM, SOFTWARE OR SOURCE CODE IMPLIES
ACCEPTANCE OF THE TERMS OF THIS GENERAL SOFTWARE PROGRAM LICENSE
AGREEMENT. YOU SHOULD READ CAREFULLY THE FOLLOWING TERMS AND
CONDITIONS BEFORE YOU COPY, MODIFY, TRANSLATE OR DISTRIBUTE THE
OBJECT CODE, PROGRAM, SOFTWARE OR SOURCE CODE.
1.0 DEFINITIONS
1.1 Licensee - The person who has the privilege to copy,
modify, translate or distribute the object code, program, software
and source code, subject to the terms and conditions of this
General Software License Agreement.
1.2 Object Code - The version of a computer program in
machine language, and therefore, ready to be executed by the
computer.
1.3 Program - A sequence of instructions for executions by a
computer.
1.4 Software - The computer program plus program
documentation, if applicable.
1.5 Source Code - The version of a computer program in
assembly language or high-level language, and therefore, not ready
to be executed by the computer.
1.6 Work - All forms of tangible or intangible property,
based whole, in part or derived from the object code, program,
software or source code.
1.7 You - The person who has the privilege to copy, modify,
translate or distribute the object code, program, software and
source code, subject to the terms and conditions of this General
Software License Agreement.
2.0 LICENSE
2.1 The copyright holder hereby extends a license to you to
use its copyrighted object code, program, software and source code,
subject to the terms and conditions of this General Software
License Agreement.
2.2 This license is applicable to the object code, program,
software and source code distributed under the terms of this
General Software License Agreement, any work containing the object
code, program, software or source code distributed under the terms
of this General Software License Agreement, any modification of the
object code, program, software or source code distributed under the
terms of this General Software License Agreement, any translation
of the object code, program, software or source code distributed
under the terms of this General Software License Agreement and any
work containing a modification or translation of the object code,
program, software or source code distributed pursuant to the terms
and conditions of this General Software License Agreement.
2.3 You may copy, modify, translate and distribute the object
code, program, software or source code distributed under the terms
of this General Software License Agreement, subject to the terms
and conditions of this General Software License Agreement.
2.4 If you copy, modify, translate or distribute the object
code, program, software or source code distributed under the terms
of this General Software License Agreement, you must publish and
make known in a clear and conspicuous manner on each copy,
modification, translation or distribution of the object code,
program, software or source code that the copy, modification,
translation or distribution of the object code, program, software
or source code is subject to the terms and conditions of this
General Software License Agreement and provide a copy of this
General Software License Agreement with each copy, modification,
translation or distribution of the object code, program, software
or source code.
2.5 If you derive, publish or distribute any work that is
based whole or in part on the object code, program, software or
source code distributed under the terms of this General Software
License Agreement, or any modification or translation thereof, you
must publish and make known in a clear and conspicuous manner on
each such work that the work is subject to the terms and conditions
of this General Software License Agreement and provide a copy of
this General Software License Agreement with each work.
2.6 If you copy, modify, translate or distribute the object
code, program, software or source code distributed under the terms
and conditions of this General Software License Agreement, you must
provide clear and conspicuous notice that you have copied,
modified, translated or distributed the object code, program,
software or source code distributed under the terms of this General
Software License Agreement, and indicate the date of each such
copy, modification, translation or distribution.
2.7 If you copy, modify, translate or distribute the object
code, program, software or source code distributed under the terms
of this General Software License Agreement, or publish or
distribute any work that is derived, in whole or in part, from any
copy, modification, translation or distribution of the object code,
program, software or source code distributed under the terms of
this General Software License Agreement, you cannot impose any
further obligations or restrictions on any third person or entity
other than what is contained in this General Software License
Agreement.
3.0 NO WARRANTY
3.1 THE OBJECT CODE, PROGRAM, SOFTWARE AND SOURCE CODE ARE
PROVIDED "AS IS" WITHOUT ANY WARRANT OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR USE. THE ENTIRE
RISK AS TO THE QUALITY AND PERFORMANCE OF THE OBJECT CODE, PROGRAM,
SOFTWARE AND SOURCE CODE IS WITH YOU. SHOULD THE OBJECT CODE,
PROGRAM, SOFTWARE AND SOURCE CODE PROVE DEFECTIVE, YOU ASSUME THE
ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
4.0 LIMITATION OF DAMAGES
4.1 IN NO EVENT WILL THE COPYRIGHT HOLDER OR ANY OTHER PERSON
OR ENTITY BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST
PROFITS, LOST SAVINGS, COMPENSATORY, GENERAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR THE INABILITY TO
USE THE OBJECT CODE, PROGRAM, SOFTWARE AND SOURCE CODE, EVEN IF THE
COPYRIGHT HOLDER OR ANY OTHER PERSON OR ENTITY HAS BEEN ADVISED OF
THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER
PARTY.
5.0 MISCELLANEOUS
5.1 The article and paragraph headings appearing in this
General Software License Agreement have been asserted for the
purpose of convenience and ready reference. They do not purport to,
and shall not be deemed to define, limit, or extend the scope or
intent of the articles and paragraphs to which they pertain.
5.2 This General Software License Agreement embodies the
entire agreement respecting its subject matter. There are no
promises, terms, conditions or obligations other than those
expressly set forth herein. Unless otherwise expressly set forth
herein, this General Software License Agreement supersedes all
previous communications, representations, agreements, either verbal
or written, warranties, promises, covenants or undertakings.
5.3 This General Software License Agreement shall not be
modified, altered, amended or supplemented, except in writing
signed by all parties hereto.
5.4 This General Software License Agreement shall be governed
by the laws of the State of New Jersey.
TFIBDatabase abstracts the process of getting connected to
InterBase. It's purpose is virtually identical to that of the Delphi's
TDatabase, but TFIBDatabase does not directly manage
transactions. Transactions are managed in the TFIBTransaction
component (see section TFIBTransaction -- managing transactions).
TFIBQueries
and TFIBDatasets.
<server name>:<file name on server>
To connect to an InterBase database on a remote server using NetBeui, this is
\\<server name\<file name on server>.
For example DBParamByDPB[isc_dpb_user_name] is used to set and inspect the user name.
isc_dpb_user_name=SYSDBA isc_dpb_password=masterkey isc_dpb_role=whatever
See the InterBase API Guide for further documentation on database
parameters. For some understanding of how database parameter buffers are
generated in FreeIBComponents, take a look at the GenerateDPB
procedure defined in `FIB.pas'.
When trying to create a database, DBParams contains the parameters
part of the InterBase CREATE DATABASE DDL command. For example,
to create a database as shown in the below DDL example,
CREATE DATABASE 'c:\test\exampleDB.gdb' USER "SYSDBA" PASSWORD "masterkey" PAGE_SIZE 4096
you would set the DBName property to `c:\test\exampleDB.gdb', and set DBParams to
USER "SYSDBA" PASSWORD "masterkey" PAGE_SIZE 4096
Then, invoke the CreateDatabase method.
The following is a list of properties that return interesting
information about the state of the database. These are just wrappers for
the API call, isc_database_info. To get more information on what
these properties mean, refer to the InterBase documentation.
isc_info_allocation in the InterBase API Guide.
isc_info_base_level in the InterBase API Guide.
isc_info_db_id in the InterBase API Guide.
isc_info_db_id in the InterBase API Guide.
isc_info_implementation in the InterBase API Guide.
isc_info_implementation in the InterBase API Guide.
isc_info_no_reserve in the InterBase API Guide
isc_info_ods_minor_version in the InterBase API Guide
isc_info_ods_version in the InterBase API Guide
isc_info_page_size
isc_info_info_version in the InterBase API Guide
isc_info_current_memory in the InterBase API Guide
isc_info_forced_writes in the InterBase API Guide
isc_info_max_memory in the InterBase API Guide
isc_info_num_buffers in the InterBase API Guide
isc_info_sweep_interval in the InterBase API Guide
isc_info_user_names in the InterBase API Guide
isc_info_fetches in the InterBase API Guide
isc_info_marks in the InterBase API Guide
isc_info_reads in the InterBase API Guide
isc_info_writes in the InterBase API Guide
isc_info_backout_count in the InterBase API Guide
isc_info_delete_count in the InterBase API Guide
isc_info_expunge_count in the InterBase API Guide
isc_info_insert_count in the InterBase API Guide
isc_info_purge_count in the InterBase API Guide
isc_info_read_idx_count in the InterBase API Guide
isc_info_read_seq_count in the InterBase API Guide
isc_info_update_count in the InterBase API Guide
isc_info_log_file in the InterBase API Guide
isc_info_cur_logfile_name in the InterBase API Guide
isc_info_cur_log_part_offset in the InterBase API Guide
isc_info_num_wal_buffers in the InterBase API Guide
isc_info_wal_buffer_size in the InterBase API Guide
isc_info_wal_ckpt_length in the InterBase API Guide
isc_info_wal_cur_ckpt_interval in the InterBase API Guide
isc_info_wal_prv_ckpt_fname in the InterBase API Guide
isc_info_wal_prv_ckpt_poffset in the InterBase API Guide
isc_info_wal_grpc_wait_usecs in the InterBase API Guide
isc_info_wal_num_id in the InterBase API Guide
isc_info_wal_avg_io_size in the InterBase API Guide
isc_info_wal_num_commits in the InterBase API Guide
isc_info_wal_avg_grpc_size in the InterBase API Guide
TFIBDatabase.
TFIBBase to the components list of attached
sets. It returns the index where it entered the set.
CREATE DATABASE command.
See the InterBase API Guide for the names of the parameters to provide.
TFIBTransaction.
TFIBQuery is the first step on the way to developing a descendant
of TDataSet. This component is an extremely simple component that
will quickly and efficiently execute an InterBase SQL statement.
FreeIBComponents includes to query-style components: TFIBQuery
and TFIBDataSet (see section TFIBDataSet -- The fun part!). Either of these components
can execute any valid DSQL statement.
Many developers will ask the obvious question: "When is desirable to
use TFIBQuery and when is it desirable to use
TFIBDataSet?"
TFIBQuery is an extremely simple component which is a very
light-weight layer on top of the InterBase API. When used to execute
SQL-Selects, its results are unbuffered, hence
uni-directional. TFIBDataSet, on the other hand, is built
primarily for SQL-Select statements. It buffers its result set, so that
the result set is completely scrollable. Also, it is a descendant of
TDataSet, which exposes FreeIBComponents to all data-aware
components.
So, use TFIBDataSet when you require the use of data-aware
components or a scrollable result set. In any other situation, however,
it is advisable that you use TFIBQuery, which requires much less
overhead.
FreeIBComponents uses an extended SQL syntax for its SQL statements. The extended syntax is strictly for the purposes of naming parameters. The extension is quite simple, but it is important that you note this for writing parameterized queries.
In standard InterBase SQL, a parameterized query would be entered as follows:
select ... from ... where <field> = ?
In FreeIBComponents, this query must be written as:
select ... from ... where <field> = ?<param_name>
Where <param_name> is made up of alphanumerics, the character
`_', and the character `$'.
If you do not use this syntax for parameterized queries, the query will not execute correctly.
The passing of parameters to TFIBDataSet and TFIBQuery is
handled in a like manner.
The property Params exposes the raw InterBase extended SQL
descriptor through an object, not too interestingly named
TFIBXSQLDA.
When I get the time, I'll try to explain all the gory details of using
the TFIBXSQLDA class. For now, you can refer to the source code,
and I'll just provide some silly examples of its use:
var
MyDataSet: TFIBDataSet;
MyQuery: TFIBQuery;
...
MyDataSet.SelectSQL.Text := 'select * from t1 '+
'where f1 = ?f1 and ' +
'f2 = ?f2 and ' +
'f3 = ?f3 and ' +
'f4 = ?f4';
MyQuery.SQL.Assign(MyDataSet.SelectSQL);
// Assign f1 the value 1
MyDataSet.Params[0].AsLong := 1;
// Assign f2 the value 3
MyDataSet.Params.ByName['f2'].AsLong := 3;
// Assign f3 the value 'hello world'
MyDataSet.Params.ByName['F3'].AsString := 'hello world';
// Assign f4 the date 3/4/98
MyDataSet.Params[3].AsDateTime := StrToDate('3/4/98');
// Assign f1 the value 1
MyQuery.Params[0].AsLong := 1;
// Assign f2 the value 3
MyQuery.Params.ByName['f2'].AsLong := 3;
// Assign f3 the value 'hello world'
MyQuery.Params.ByName['F3'].AsString := 'hello world';
// Assign f4 the date 3/4/98
MyQuery.Params[3].AsDateTime := StrToDate('3/4/98');
...
Just so you know, the Params property is run-time editable only. If someone wants to write a property editor for params, it would be nice.
i := qry.FieldIndex['INT_FIELD'];
By default, this property is set to true. It exists primarily for use in
TFIBDataSet, which sets this value to False for its
internal TFIBQuery's.
TFIBXSQLDA is a FreeIBComponents extension to InterBase's
extended SQL descriptor. For the time-being, you're stuck looking at the
source code and the InterBase API Guide for more information.
Possible values are:
TFIBSQLTypes = (SQLUnknown, SQLSelect, SQLInsert,
SQLUpdate, SQLDelete, SQLDDL,
SQLGetSegment, SQLPutSegment,
SQLExecProcedure,SQLStartTransaction,
SQLCommit, SQLRollback,
SQLSelectForUpdate, SQLSetGenerator);
TFIBQuery.
BatchInput executes the parameterized query in SQL for all
input in the referenced InputObject.
See section Batching input and output for more information on batching streams.
BatchOutput outputs the select query in SQL to the
referenced OutputObject.
See section Batching input and output for more information.
Next returns nil if there are
no records left in the result set.
For the time-being, you will have to refer to InterBase documentation on
extended SQL descriptors, and the FreeIBComponents source for
information on TFIBXSQLDA
It is well recognized that a good set of database components needs to have some convenient mechanism for migrating data back and forth from the database.
The two abstract classes, TFIBBatchInputStream and
TFIBBatchOutputStream make it possible to input and output data
in virtually any format.
The TFIBBatch abstract class is the base for the two stream
classes below. It's declaration is as follows:
TFIBBatch = class(TObject)
protected
FFilename: String;
FColumns: TFIBXSQLDA;
FParams: TFIBXSQLDA;
public
procedure ReadyStream; virtual; abstract;
property Columns: TFIBXSQLDA read FColumns;
property Filename: String read FFilename write FFilename;
property Params: TFIBXSQLDA read FParams;
end;
Descendants of this class can specify a file name (for input or output),
and a TFIBXSQLDA representing a record or parameters. The
ReadyStream procedure is called right before performing the batch
input or output.
This is an abstract class, thus all discussions of it are a bit "abstract". By referring to the concrete examples in section Migrating data to and from delimited files and section Migrating data to and from raw files, the reader will gain a deeper understanding of their usage.
The TFIBBatchInputStream abstract class provides the basis for
performing all batch input. Here is its declaration in
`FIBQuery.pas'.
TFIBBatchInputStream = class(TFIBBatch)
public
function ReadParameters: Boolean; virtual; abstract;
end;
To get a sense of how a TFIBBatchInputStream is used, let's have
a look at the source for TFIBQuery's BatchInput method:
procedure TFIBQuery.BatchInput(InputObject: TFIBBatchInputStream);
begin
if not Prepared then
Prepare;
InputObject.FParams := Self.FSQLParams;
InputObject.ReadyStream;
if FSQLType in [SQLInsert, SQLUpdate, SQLDelete] then
while InputObject.ReadParameters do
ExecQuery;
end;
An example of how a developer would use this method is as follows:
...
var
InputObject: TFIBInputRawFile;
...
InputObject := TFIBInputRawFile.Create;
try
InputObject.Filename := 'Test.txt';
(*
* Qry is some previously declared TFIBQuery that is connected
* to some existing database, etc...
*)
Qry.SQL.Text := 'insert into t1 ' +
'(int_field, str_field, memo_field) ' +
'values ' +
'(?a, ?b, ?c)';
Qry.BatchInput(InputObject);
finally
InputObject.Free;
end;
Once again, refer to section Delimited file input and section Migrating data to and from raw files for a concrete example of batch input streams.
Just like TFIBBatchInputStream, the TFIBBatchOutputStream
abstract class provides the basis for performing all batch output. Here
is its declaration in `FIBQuery.pas':
TFIBBatchOutputStream = class(TFIBBatch)
public
function WriteColumns: Boolean; virtual; abstract;
end;
To get a sense of how a TFIBBatchOutputStream is used, let's have
a look at the source for TFIBQuery's BatchOutput method:
procedure TFIBQuery.BatchOutput(OutputObject: TFIBBatchOutputStream);
begin
CheckClosed;
if not Prepared then
Prepare;
if FSQLType = SQLSelect then begin
try
ExecQuery;
OutputObject.FColumns := Self.FSQLRecord;
OutputObject.ReadyStream;
while (Next <> nil) and (OutputObject.WriteColumns) do ;
finally
Close;
end;
end;
end;
An example of how a developer would use this method is as follows:
...
var
OutputObject: TFIBOutputRawFile;
...
OutputObject := TFIBOutputRawFile.Create;
try
OutputObject.Filename := 'Test.txt';
(*
* Qry is some previously declared TFIBQuery that is connected
* to some existing database, etc...
*)
Qry.SQL.Text := 'select int_field, str_field, memo_field '
'from t1';
Qry.BatchOutput(OutputObject);
finally
OutputObject.Free;
end;
Once again, refer to section Delimited file output and section Migrating data to and from raw files for a concrete example of batch output streams.
The class TFIBInputDelimitedFile, defined in
`FIBMiscellaneous.pas' is used for performing batch inputs of data
from pipe-tilde or tab-crlf delimited files.
There are three important properties (aside from those already in the ancestor class) that affect the resulting delimited file.
fdfTabs or
fdfPipes. If AutoDetect is set to True, this
property is ignored.
TFIBOutputDelimitedFile has two important properties (aside from those properties already discussed in its ancestor class).
TFIBInputRawFile and TFIBOutputRawFile are the respective
input and output classes for migrating data to and from raw files.
A raw file is the equivalent of what InterBase outputs in its external files. The great thing about raw files in FreeIBComponents is that they are not limited to straight character format.
Whatever structure is defined by your query is what goes into the file!
Raw files have no available options, and they are probably the fastest way (aside from an external tables themselves) to get data in and out of InterBase. Their only drawback is that fixed-width files can be a chore to deal with.
Well, I guess you win some and lose some...
FreeIBComponents supports InterBase blobs through the use of two blob
streams called TFIBBlobStream and TFIBDSBlobStream.
When the developer wishes to read an write to blobs in a
TFIBQuery he or she should always use
TFIBBlobStream. TFIBDSBlobStream is strictly for internal
use by TFIBDataSet.
It is important to mention TFIBDSBlobStream, but it will not be
documented here, as it is strictly an internal class.
Right now, I haven't got time to go into detail on the
TFIBBlobStream class. If you have grown comfortable studying my
code, then hopefully you will have some luck studying its source code in
`FIBMiscellaneous.pas'
Possibly the coolest aspect of FreeIBComponents is that developers can avoid the BDE but still make use of the plethora of data-aware components that are out there, including reporting tools such as ReportPrinterPro and QuickReports.
Delphi (and Borland) did a great thing by putting together the
TDataSet abstract class, and I will do my best to document not
only the use of TFIBDataSet, but how I built it as well.
Note: When outlining properties, methods and events for
TFIBDataSet, I will only document those properties, events and
methods that are not inherited from TDataSet.
Overriding Delphi's TDataSet is a challenging task! But, it is
not terribly difficult. Hopefully, this manual, in conjunction with the
source code, will give you a deeper understanding and greater
appreciation for the elegance, simplicity and power in Delphi. Kudos to
the Borland Delphi development team!
Below is a list of all methods that were overridden to get to
TFIBDataSet:
TDataSet
never directly reads this buffer. It is the job of the rest of
the abstract methods below to return comprehensible information to
TDataSet.
TFIBDataSet must
override it. A TBlobField uses blob streams to read and write
blob data, so this function is absolutely essential if
TFIBDataSet expects to provide blob access.
TFIBDataSet overrides them is so that it can
do preliminary checks to see if the underlying data set is updatable.
AllocRecordBuffer.
This routine copies the bookmark data in Buffer to the buffer pointed to by Data.
TStringField won't look at strings longer than
dsMaxStringSize. FreeIBComponents defines a
TFIBStringField which allows strings of any length.
This function simply overrides the default behavior of TDataSet
to use a TFIBStringField for all strings instead of a
TStringField.
TField (Field),
copy the data for that field into the TField.
grOK,
grEOF, grBOF or grError depending on what happens.
Important note: GetRecordSize returns a Word which has a
maximum value of 65536. This means that even though an InterBase
record could certainly be wider than this, Delphi's TDataSet
cannot support InterBase records any larger.
FreeIBComponents ignores the Append parameter, as new records are always appended.
TDataSet needs to close the data set.
TFIBDataSet to jump to the referenced record.
Application.HandleException(Self),
which is the "default" behavior of most components.
InternalInitFieldDefs is
called to ensure that the correct TField's are created for
displaying data back to the user.
TDataSet needs to open the data set.
InternalPost is called when a record must be "posted" to the
server. Depending on the state of the data set, this will either call an
UPDATE routine or and INSERT routine.
TFIBDataSet is
buffered, this always returns true if the data set is open.
This is it! Obviously, quite a bit more of new code was added to
TFIBDataSet, but the above method descriptions give a reasonable
explanation of what has been overridden. You are cordially invited to
study the source code at your leisure. I invite comments and bug fixes!
There are many features of a TDataSet that have been exposed in
TFIBDataSet, but I have not had the time, nor the inclination to
test them. As developers come across inconsistencies in the way that
TFIBDataSet behaves and the way it should behave, I'd like
to know.
Making a TFIBDataSet updatable is extremely easy. The primary SQL
property of TFIBDataSet is SelectSQL, but there are four
other SQL properties that allow the user to treat a query as an
updatable data set: DeleteSQL, InsertSQL,
RefreshSQL, and UpdateSQL.
Each of these queries allow the user to delete a row, insert a row, refresh a row, and update a row.
Let's assume that you have a table in your database called t1:
create table t1 ( f1 integer constraint primary key, f2 integer, f3 varchar(128) );
Now, your SelectSQL property says:
select * from t1
To be capable of deleting data, just make the DeleteSQL
property say this:
delete from t1 where f1 = ?old_f1
To be capable of inserting data, just make the InsertSQL
property say this:
insert into t1 (f1, f2, f3) values (?f1, ?f2, ?f3)
To be capable of refreshing data, just set the RefreshSQL
to
select f1, f2, f3 from t1 where f1 = ?f1
To be capable of updating data, just set the UpdateSQL
property to
update t1
set f1 = ?f1,
f2 = ?f2,
f3 = ?f3
where f1 = ?old_f1
It's that easy! You will notice the use of "OLD_" and "NEW_". This is to refer to the "old" field value or the "new" field value, respectively.
You should also note that this convention for setting up "live"
queries is a bit more complicated than merely setting a
RequestLive property, but it offers complete flexibility. For
example, you might want to set it up so that users don't have the option
to modify the primary key, so you could set the UpdateSQL
property to the following
update t1
set f2 = ?f2,
f3 = ?f3
where f1 = ?old_f1
As you explore using this method for establishing "live queries", you will find that this is rather simple and intuitive.
See ApplyUpdates, CancelUpdates, RevertRecord, UpdateRecordTypes, UpdateStatus, CachedUpdateStatus, Undelete, UpdatesPending.
The rest of the queries are intended to allow the developer to make a query delete-able (DeleteSQL), insert-able (InsertSQL), row-level-refresh-able (RefreshSQL), and updatable (UpdateSQL).
For more detailed information on creating updatable data sets, see section Making a TFIBDataSet updatable.
TFIBQuery's that underly the TFIBDataSet.
cusUnmodified, cusModified,
cusInserted, cusDeleted, cusUninserted).
UpdateRecordTypes indicates those records that are visible to the user when CachedUpdates is True.
If CachedUpdates is False, this property means nothing.
Input(Output)Object.
In a TFIBDataSet, the batch input/output routines operate against
the QSelect query.
It is basically a way of cancelling an update on an individual record, as opposed to the entire dataset with CancelUpdates.
This applies only to data sets that have CachedUpdates enabled.
The file `FIB.pas' contains some miscellaneous constants that are of some interest:
FIB_VERSION contains the current working version of
FreeIBComponents. The version number is noted by the official release
date.
FIBLocalBufferLength, FIBBigLocalBufferLength, and
FIBHugeLocalBufferLength are used for declaring various sized
buffers when the client expects to receive information back from the
server. (See `FIB.pas' to see the actual values.)
FIBErrorMessages is a list of all of the canned error messages
posted by the FIBError routine.
Gregory Deatz is a senior programmer/analyst at Hoagland, Longo, Moran, Dunst & Doukas, a law firm in New Brunswick, NJ. He has been working with Delphi and InterBase for approximately two and a half years and has been developing under the Windows API for approximately five years. His current focus is in legal billing and case management applications. He is the author of FreeUDFLib, a free UDF library for InterBase written entirely in Delphi, and FreeIBComponents, a set of native InterBase components for use with Delphi 3.0. Both of these tools can be found at http://www.interbase.com/download. He can be reached via e-mail at gdeatz@hlmdd.com, by voice at (732) 545-4717, or by fax at (732) 545-4579.
This document was generated on 14 July 1998 using the texi2html translator version 1.51a.