{******************************************************************************}
 "gb_DataSets Components" - a set of additional components for IBX and FIBPlus
                          - libraries.
{******************************************************************************}

 CAREFULLY READ THIS FILE BEFORE INSTALLATION OF COMPONENTS AND START
 OF WORK!!!

--------------------------------------------------------------------------------
CONTENTS

1. Introduction
2. About necessity of these components
3. Description of properties, methods, restrictions
4. Performance
5. Installation
6. Registration and technical support.

--------------------------------------------------------------------------------
1. INTRODUCTION

  " gb_DataSets Components " is a set of components providing an opportunity
of NORMAL navigation on large data sources - tables and queries. The set
consists of two components: TgbDataSet and TgbTable. The first one provides
caching, navigation, editing on a random data set which has returned SQL-query,
the second provides similar functionality on a separate table. Unlike standard
IBX- and FIBPlus-DataSets, gb_DataSets NEVER download the all data from
the InterBase server. So, the basic distinction between such components as
IBTable, IBDataSet, IBQuery, pFIBDataSet, consists in cache architecture and
server request technique.

The distinctive features of "gb_DataSets Components " are as follows:

  Basic:
  - Fast "Last" at any count of records.
  - Fast "Refresh" (It means FullRefresh).
  - Correct record positioning after "Insert"/"Edit" without any local
    sorting.
  - Fast "Locate" regardless a required record position.

  In the table of 30 fields, containing 100000 records, the above operations
  occupy less then 1 second (with correct organization of indexes, see below).
  If to use, for example, IBTable on such table, "Last" command will result in
  appearing a memory lack message approximately in 5 minutes. pFIBDataSet
  handles this situation a little bit better, but it remains being unacceptable
  for normal work.

  Smaller differences (from IBX, in FIBPlus a lot exists) are as follows:
  - "Post" in a separate transaction (optional).
  - Replacement =:NULL' by 'IS NULL' in edit, delete, refresh queries.
  - "Insert" only on entered values (without NULLs)
  - Pseudo-blocking record at Edit (optional).
  - Opportunity to set COLLATE used in "Locate".
  - Opportunity to use FIRST in "Locate" (for Firebird).
  - Macro support.

--------------------------------------------------------------------------------
2. ABOUT NECESSITY OF THESE COMPONENTS

  The technology realized in "gb_DataSets Components ", is not quite new. TTable
from BDE, having being tested for years, uses this technology. Thus, this
technology can be considered as reliable and checked up. The essence of it is as
follows. For example, we have SQL-query:

   select * from TABLE
   order by FIELD

After executing the query and repeatedly executing "fetch", we receive the first
records from the TABLE. Let's assume we need to see the last query records. The
standard decision is to do "fetch" as many time, as there are records in the
table. That is precisely how DataSet-components operate in IBX and FIBPlus.
However, if the TABLE has one million records then one million will be
downloaded to a client, resulting in the system crash. Other decision is
"to ruse". It is possible to execute "off screen" the second query which start
will for sure coincide with the last records of the first query.

  select * from TABLE
  order by FIELD DESC

Now we do "fetch" several times and receive the last records of the first query.
A random positioning in any point x will have the view as follows:

  select * from TABLE
  where (FIELD = x)

To receive records, higher than a current one:

  select * from TABLE
  where (FIELD < x)
  order by FIELD DESC

To receive records, lower than a current one:

  select * from TABLE
  where (FIELD > x)
  order by FIELD

  So, there are more queries but a little "fetches". Practically, we have a
system with a random access to any part of the TABLE. But a system like this
sets some restrictions, fortunately being not critical. In the first place, the
first query has to contain a statement "order by". The field FIELD should be
unique. And for normal performance TWO INDEXES (!!!) should be on the FIELD - by
increase (ASC) and by decrease (DESC). Restrictions existing in "gb_DataSets
Components" will be considered in details below.

  The described approach for a wide range of tasks is not simply a more proper
decision than usual fetching, but in fact the sole possibility. Absence of the
tool implementing this approach in IBX(FIBPlus) makes these libraries
essentially insufficient for serious projects. Let's explain this.

 - Practically in any non-ordinary system, the size of data is not controlled
   by developer. Tables containing 50 - 100 thousand records are normal, tables
   containing 200 - 300 thousand records are not rare also. And we are not
   speaking about the class of tasks where InterBase/Firebird is inapplicable.
   It may be a usual automation of small and medium enterprises, which is a
   native niche for this server.
 - The sample size from these tables in a general view is unpredictable.
   In addition, in any developed system an opportunity exists of random (users')
   queries, where "The_Sum <> 0 ", "Date between
   (the Beginning of the period, the End of the period)", "The_Note < >
   'something exotic'" queries is a daily practice.
 - Any serious project has a history and users related to it. As a rule, this
   history has the following names: Clipper, FoxPro, dBase, Paradox, etc. It
   means that such "innovations" as the button "Abort fetching ", buttons of
   "Next 100 records" type, or impossibility to go to the last records  will be
   interpreted by these users as deterioration, degradation of the system.
 - And at last, any project has chiefs, who have grown on that
   history, for them the impossibility to call Last on any table means only one
   conclusion - InterBase/Firebird + IBX/FIBPlus is a poor system and it is
   necessary to consider other variants for the project.

   There is only one "recipe from this disgrace" that all developers give: "it
is necessary to work by small samples!". It is obvious, that it is easier to
say than to make. On some primitive cases everything can be handled without
problems, for example workstation automation for an operator, whose duties
contain only enter of some documents. But as soon as the task becomes more
difficult, for example an accountant, working with a post book, feasibility of
such recipe becomes completely not trivial. Actually, "gb_DataSets Components"
is the realization of this recipe, gb_DataSets always work only by small
samples.

--------------------------------------------------------------------------------

3. DESCRIPTION OF PROPERTIES, METHODS, RESTRICTIONS.

  BufferChunks - unlike IBX (FIBPlus), in gb-components this number means
not a record count on which cache is increased, if required, but a maximum
record count stored in cache. There is no increment in cache. Thus, the memory
size allocated for a gb-component is always constant.

  Database, Transaction, SelectSQL, DeleteSQL, UpdateSQL, RefreshSQL, InsertSQL-
- are the same as in IBX (FIBPlus). Some nuances: RefreshSQL should return a
current record, only the first record in query is significant. If such record is
not already present on the server, the attempt will be done to make Refresh on
the next record, etc. Parameterization of searches is similar to IBX, i.e. a
colon plus a field name, for old name of the field to be modified with a prefix
'OLD _'.

  GeneratorDefs - with unknown reason IBX-developers are sure that more than one
generator in a dataset can not be used. Practice shows, that is wrong. So it is
convenient to work with a set of generators as with a collection. In the rest it
is similar to IBX.

  SQLWaitCursor - is a screen cursor appearing for the period of query executing
(in gb-DataSets the queries occur more often), by default - crSQLWait.

  KeyFieldsForBookmark - field names divided by a comma. Unlike IBX(FIBPlus),
where Bookmark is a number of record, in gb_DataSets Bookmark it is a
value of one or several fields in a record. In gbTable it always has a primary
key value. In gbDataSet, if the property is not assigned, field names of
listed in the statement ORDER By are used.

  PlanForDescQuerys - in gb-DataSets not only the query described in SelectSQL
is executed, but also its derivatives. Therefore, if a plan is present in the
query, it cannot be used for queries with reverse sorting. Set up the plan for
such queries in the property.

  Options:

   opUseFirstStatement - works with Firebird only, puts ' First 1 ' in
                         Locate-query, that essentially raises productivity in
                         non-indexed fields.

   opUseCyrCollate     - to provide a register-independent search on string
                         fields this option puts the CyrCollate constant in
                         Locate-query. The value of the constant is
                         'COLLATE PXW_CYRL', but naturally, it can be changed
                         (module gb_dataConst).

   opCheckNullsInRefreshWhere - if this option is included, then at Refresh-
                         query the statement WHERE is analyzed and all entry
                         '=:NULL' are changed by 'IS NULL'. It does not matter
                         in gbTable where Refresh is based on primary key.

  UpdateOptions:

   opCommitOnPost      - if this option is included, all updates of the data are
                         made in a separate transaction (public property
                         PostTransaction) and the call of Post is equivalent to
                         the call of Commit for this transaction. Obviously, the
                         basic transaction for such operation scheme should be
                         "read_commited".

   opCheckNullsInWhere - if this option is included, similarly to
                         opCheckNullsInRefreshWhere all entry '=:NULL' are
                         changed for 'IS NULL' in UpdateSQL and DeleteSQL.

   opLockRecOnEdit     - if this option is included, calling Edit leads to the
                         pseudo-blocking of the current record, which means that
                         before calling Post or Cancel nobody can change this
                         record.

   opWhereChangeOnInsert - if this option is included, all fields containing
                         NULL will be excluded from InsertSQL, that allows not
                         to cover possible default values, or the values
                         generated in triggers.

  ReadOnly - defines, whether updating of the data is accessible, unlike IBX
change of the property does not close active DataSet.


  The properties available only in gbTable:

  IndexFieldNames - fields of current sorting. These fields check a unique index
for availability. If the index is unavailable, fields from the primary key are
added at the right.

  Filter - the value of this property is put in WHERE statement of the basic
query that allows to limit a dataset by any condition.

  MasterFields, MasterSource - are similar to the same properties in IBTable.

  Methods.

function LocateExt (const KeyFields: string; const KeyValues: Variant;
       Options: TLocateOptionsExt): Boolean;
  In the whole it is similar to usual Locate (which is supported too) except
that TlocateOptionExt is used instead of TlocateOption, which can contain the
values leCaseInsensitive, lePartialKey and leContaining. The first two are
similar to standard ones, the third means a search by part of string.

function LocateNext (const KeyFields: string; const KeyValues: Variant;
   Options: TLocateOptionsExt): Boolean;
  It is the same that LocateExt, but searches only in records below the current
one.

function LocatePrior (const KeyFields: string; const KeyValues: Variant;
   Options: TLocateOptionsExt): Boolean;
   the Same, that
  It is the same that LocateExt, but searches only in records above the current
one.

function LocateNearest(const KeyFields: string;
                                 const KeyValues: Variant): Boolean;
  It searches the nearest value. Works only on fields included in the current
sorting and in this case returns True always, in other case works as usual
Locate (on non-sorted fields Nearest-search returns the results, which
interpretation is difficult, so the decision was made not to use it).

function Lookup (const KeyFields: string; const KeyValues: Variant;
                 const ResultFields: string): Variant; override;
  Returns the search result in a variant array, active record being not changed.
No "additional" fetchs occur (unlike IBX (FIBPlus)).

function GetQSelect: {$IFDEF VER_IBX} TIBSQL; {$ELSE} TFIBQuery; {$ENDIF}
  The service function that returns TIBSQL (TFIBQuery) of Select-search. It can
be necessary, if direct access to its properties is needed.

  All inherited methods of navigation and editing - First, Last, Next, Prior,
Edit, Insert, Delete, Post, Cancel, Refresh, and also all methods of Bookmark
and BookmarkStr are supported. Calculate and Lookup fields are supported too.

  There are also two separate functions - ExtractIdent and CheckQuotes. They are
completely similar to IBX functions  - ExtractIdentifier and QuoteIdentifier and
are transferred to provide a uniform approach in IBX/FIBPlus versions.

  Properties, methods that was added in versions after 1.01, look in a file -
history.txt.


  Restrictions.

  There are queries in gbDataSet that differ from the initial query which
formation occurs automatically, so all set of queries possible for SelectSQL
is covered with some restrictions. Let's list them:

  1. The query should be Select-query (SQLType = SQLSelect), any other types
     are not supported.
  2. The query should be sorted. It is means that ORDER BY statement should
     present in a query.
  3. In the 1.01 version descending sorting (DESC) was not allowed. In 1.02 this
     restriction was removed.
  4. The fields listed in ORDER BY, should form a unique combination and
     no field here should contain NULL (it is not necessary to be NOT NULL).
  5. The fields listed in ORDER BY statement should be present in
     SELECT statement as well.
  6. it is not allowed entering pseudonyms of the tables, being set up
     in FROM statement, in ORDER BY statement. If it is necessary to specify a
     table name, it should be written in full.

  Because gbDataSets is developed as a tool for navigation on large tables,
there is no support of CachedUpdates. Until version 1.03 there was no support of
Blob-fields. Since version 1.03 this support is added.

--------------------------------------------------------------------------------

4. PERFORMANCE

  If for IBX (FIBPlus) - components performance, for example of Last commands,
will be determined by a list of factors, such as: ability of the server to
execute query quickly, ability of the network hardware to download fast the
all data, availability of a sufficient operative memory size to store
this data, etc., performance of gb_DataSets depends ON ONLY ONE FACTOR
- ABILITY OF THE SERVER TO EXECUTE QUERIES QUICKLY!
   The only nuance is gb_DataSets executes more queries, than other components.
It is possible to offer the following simple way of optimization of gb-queries.
Use a program of IBExpert type. Enter your query, execute it and be sure, that
it is optimized, i.g. an indexed reading prevails. In the opposite case add a
missing index. Then, add 'DESC' in ORDER BY statement of the query after the
name of each field. Again execute and, if necessary, optimize the query. That is
all. If the both queries operate quite fast, the will operate with the equal
speed on ANY record count in queries Last, Locate, Refresh, etc. Usually, the
optimization consists of addition of one new index, which coincides with the
basic index used in the query), but is ordered by decrease. It can be named the
RULE of the DOUBLE INDEX. If you use TgbTable, for optimization use the
following query:
  select * from TABLENAME
  order by INDEXFIELDNAMES (or PrimaryKey if IndexFieldNames it is not assigned)

  But all this concerns really or potentially large tables. On small and
medium tables (10 - 20 thousand records), if you can stand a 3-10 second delay
in IBX (FIBPlus)-components, you will easily stand a half a second delay in
gb_DataSets:).

--------------------------------------------------------------------------------

5. INSTALLATION

  To install " gb_DataSets Components " do the following.

  1. Unpack a gbDataSets.zip archive into any directory (YourDir).

  2. If you use the FIBPlus library, in the file gb_DataInc.inc
     delete comment at {$DEFINE VER_FIBPLUS} and
     comment           {$DEFINE VER_IBX}

  3. In Delphi, choose "File","Open", in dialog choose YourDir\Source and open
     an appropriate dpk/bpk-file:

      for Delphi5 - FIBPlus    -  gb_DataSets5_fp.dpk
      for Delphi6 - IBX        -  gb_DataSets6_ibx.dpk
      for Delphi6 - FIBPlus    -  gb_DataSets6_fp.dpk
      for Delphi7 - IBX        -  gb_DataSets7_ibx.dpk
      for Delphi7 - FIBPlus    -  gb_DataSets7_fp.dpk
      for C++Builder5 - FIBPlus    -  gb_DataSetsCB5_fp.bpk
      for C++Builder6 - IBX        -  gb_DataSetsCB6_ibx.bpk
      for C++Builder6 - FIBPlus    -  gb_DataSetsCB6_fp.bpk

  4. Click "Compile" and then click "Install"

  5. For convenience add in "Tools"\"Environment Options" \"Library" to Library
     Path a path to YourDir\Source.

     Unfortunately, in variants C++Builder + IBX,  SQL-editor  from IBX will not
     work. The reason for this - features of assembly IBX in C++Builder.

--------------------------------------------------------------------------------

6. REGISTRATION AND TECHNICAL SUPPORT.

  All terms of the license agreement are described in file License.txt.
Please, read this file attentively! For registration, and also in case of any
questions, please contact the author by e-mail:

   spirin@paritetsoft.ru

  At 10, December, 2002 the price on "gb_DataSets Components":
    - single license - 40$
    - shared license  - 160$


The same e-mail is accessible for consultations: spirin@paritetsoft.ru.


            I hope that "gb_DataSets Components" will help you in your work.

Spirin Sergey
"Paritet Soft" LTD, Moscow, 2001-2004



