About the TQDB component

Purpose
The QDB components offer you a way to store data in a proprietary format without, at one extreme, having to construct the file-management from scratch or, at the other, using the Borland Database Engine with its various overheads.

The QDB components provide flat-file database storage for variable-sized items of data accessible via a single alphabetical, in-memory index. TQDB, itself, handles the general, low-level manipulation of such data. TQDBItem and TQDBView build upon TQDB to offer simpler, more automatic, and in the case of TQDBView visual, access to QDB data.

Database Structure
QDB files do not have a structure! It is very important to realize thisuntil you do you'll be wondering how to create QDB files or define what fields they have. They don't have fields: each item is a free-form block of bytes which you, the programmer, can decide to interpret anyway you please. QDB thus offers you the ability to define your own proprietary database format uniquely adapted to your needs. The demonstration programs supplied with QDB show several ways of parceling up program data into a QDB item.

(Note, however, that the TQDBView component can be used to automatically provide a structure to a QDB file based on the layout of ordinary Delphi controls on a panel.)

Accessing QDB Files
To use the TQDB component just drop it onto a form. Alternatively you can Create it on the fly and Free it when necessary. When you set the FileName property to the name of an existing QDB file that file is opened for access. Setting FileName to a name that does not exist creates a new QDB file. Setting FileName to nothing (i.e. to '') closes an open QDB file (saving its contents automatically if SaveOnClose is set). When a QDB file is open the Ready property is true. If you attempt to use a TQDB component when it is not Ready it will raise an exception. To protect a QDB file from accidental changes set its ReadOnly property.

Getting Around
You can navigate through the file with the FirstItem, LastItem, NextItem, & PrevItem methods. These methods navigate the list of keys (i.e., the index) which is held in memory and are usually very efficient. If the Filter property is set the navigation methods only access keys that match the filter pattern (which can slow things down considerably). The filtering mechanism can always be circumvented, however, by setting the ItemIndex property directly.

An Item can also be located via its key. KeyExists, ExactMatch and CloseMatch perform a fast binary search of the index. PartialMatch & PatternMatch perform a more methodical check of each key from the next item onward until a match is found with the start of the key or with a filter pattern respectively. A choice of pattern matching protocols is available.

Access to Items
Once an item has been selected (i.e., been made the current item) it can be manipulated in many ways. The Key property holds the 'name' of the current item. The Get method retrieves the data as a Delphi memory stream. Memory streams are convenient since they handle huge blocks of memory transparently in all versions of Delphi. (ItemSize, GetItem, & GetStreamItem are only provided for compatibility and should be avoided) An internal cache of items (see CacheSize) attempts to speed up repeated access to the same items. Delete and Change operate on the current item. Items can be added to the QDB file using Add (AddItem, AddStreamItem, ChangeItem, ChangeStreamItem, & DeleteItem are provided for compatibility but should be avoided). You should sandwich batches of repeated operations between BeginUpdate and EndUpdate to enhance performance (see also PrepareToAdd).

An alternative way to access items is via the CurrentItem, Items, & ItemsByKey properties. These treat items as strings. Since Delphi strings know their own length and may contain any characters (including nulls) they can be used to handle any kind of data.

Housekeeping
Count contains the number of items in a QDB file. AssignKeyList generates a list (which may be filtered) of all the keys. Save commits the in-memory list of keys to disk. SaveAs creates a new QDB file with a new name. Pack tidies up the QDB file on disk, removing any defunct records. Kill (to be used with obvious care!) closes and deletes the QDB file.

Putting it Together
Integration of these various activities is achieved using TQDB's many events. In particular, the OnNavigate event is often an appropriate place to do any updating of a screen display.

In addition there are warning events which occur if operations are attempted on an empty or protected file or if the ItemIndex is set out of bounds. Warning events are, however, only triggered if event handlers have been provided. If no handler is provided for these events an exception is raised instead. An empty warning-event handler can be used to suppress such exceptions.

QDBNavigator
Navigation around the QDB file can be automated with the TQDBNavigator visual control which provides vcr-style buttons for the four navigation methods(FirstItem, LastItem, NextItem, and PrevItem) and other buttons to trigger events which can be handled in any way you like.

Multi-User Awareness
A QDB file can be opened by any number of users at once. Each user gets a private snapshot of the file as it was when opened. If a TQDB component detects that a QDB file has been opened by another user in the meantime it is careful not to overwrite the file without permission. Actions that would overwrite the file trigger a BeforeOverWrite event which can be handled to prevent or permit the overwrite.

Administrative Information
Often you'll want to store items in a QDB file which don't really belong with the regular data but are, for want of a better word, administrative. The case-sensitivity of a QDB file is such an "admin" item. You might want to store information about users, about dates and times of access, or about field or record structuresanything that should be stored with a particular file but kept apart from its data items.

Admin items can be stored and retrieved in the form of booleans, integers, or strings via the AdminAsBoolean, AdminAsInteger, and AdminAsString array properties. The array index is a string of type TKey. The number of admin items is given by AdminCount. A particular admin item can be removed by AdminDelete and a group of items (or all of them) by AdminClear. You can check for a particular admin item with AdminKeyExists or obtain a list of admin keys via AdminKeys.

Specifications
QDB files have the following characteristics:

   data items can be any size and contain any kind of information
   items are not structured into fields
   only one index is permitted
   the index is held in memory which makes for speed but limits the number of items
   the key to the index is a Delphi string up to 255 characters in length
   keys are sorted in ascending alphabetic order
   duplicate keys are not allowed
   multi-user awareness is limited
   does not work with Delphi data-aware controls (but see TQDBView)