Abstract:
DBM files represent a quick and relatively standard method of retrieving data. The DBM files essentially contain a two-column table representing a key/value pair. The simplified relational database extension (SRDE) design described herein extends the value column to be further divided into indexed columns that can be manipulated using a modified SQL interface. SRDE offers a simple setup and maintenance scheme, provides a rich set of regular expression matching that can be applied to all searches.

Description:
BACKGROUND 
     DBM is a method to index data between two files with a hash key. Each record in the table has a unique hash key. This database methodology has been used for simple tables for many years, and is available on hundreds of different platforms. DBM is just a framework where one hash key is matched with one data field in another file. For instance, if a database full of names is desired, the hash key could be the last name. When a user types in “Miller”, for instance, a unique record for Miller is returned. The DBM framework is a one-to-one system, i.e., there is one key for one record. 
     The hash keys are in a hash table, and the data are just static records in a data file. Technically one could take the data file on its own with DBM and traverse it similar to the way one would traverse a flat file. The only difference between a DBM data file and the flat file is that the DBM data file has an index in another file that identified the offset of where to go to retrieve the data. A DBM file is just another way to access the data without having to use a whole database management system like Oracle® or Sybase®. 
     There are several database solutions today that extend DBM files, for instance Berkeley DB 1.85 and MySQL 3.23. Further information about Berkeley DB may be found at http://www.sleepycat.com and more information about MySQL can be found at http://www.mysql.com. Each of these systems has its advantages and disadvantages. 
     With the Berkley DB solution, the engine acts as a transport for the key/value pair. Indexing within the data area is not allowed, but can be accomplished using additional software. There are advantages with this method, i.e. abstraction of data, and de-referenced data types. Disadvantages include the following. The application must provide the interpretation for the data; it is not supplied directly. The Berkley DB process does not implement SQL, but is documented as an extension to the DBM hashing algorithm. If SQL is desired, it must be implemented as an additional layer. Searching is limited to the key and value pair, not regular expression matching is available directly. Since the distribution is a collection of C libraries, the source must be compiled for each platform. No binary distribution is known to be available as of the date of this writing. 
     MySQL requires the use of a database management server to handle the transactions. This server is responsible for managing all data transfer to and from the tables. The user of the server requires more technical knowledge from the administrator. It also requires specific processes to ensure that it initializes correctly and remains active after a system restart. MySQL installation is more complex and varies for each platform. Configuration files must be reviewed and edited. MySQL requires more than a basic knowledge of the internal processes to maintain data integrity. MySQL does support SQL, does not support regular expression matching on all fields defined in the table. MySQL requires the application developer to define the data types and sizes. MySQL trims string columns of trailing spaces. 
     SUMMARY 
     DBM files represent a quick and relatively standard method of retrieving data. The DBM files essentially contain a two-column table representing a key/value pair. The simplified relational database extension (SRDE) design outlined herein extends the value column to be further divided into indexed columns that can be manipulated using a modified SQL interface. SRDE offers a simple setup and maintenance scheme, provides a rich set of regular expression matching that can be applied to all searches, can be restructured quickly and easily, requires no strict type declarations, does not require a database management application, requires no special backup/recovery, and can be used on any platform supporting Perl and DBM. 
     A Perl script uses SQL calls directly into the database using native DBM commands and extends the hash table. There is a limit on what size records can be stored in DBM file. An embodiment of the present system and method uses external files to store larger records. An SQL parser accesses the DBM data as if it were a full relational database, but it doesn&#39;t need a database manager like most commercial database systems. All of the features of SQL are available to manage the DBM data. The extended database can be loaded on a server, for instance a web host service. 
    
    
     
       DESCRIPTION OF THE DRAWINGS 
       The detailed description will refer to the following drawings, wherein like numerals refer to like elements, and wherein: 
         FIG. 1  shows a sample schema file, defining an exemplary DBM database; 
         FIG. 2  shows a sample lookup script for accessing data in a DBM database; 
         FIG. 3  shows a block diagram illustrating a process overview for accessing a DBM database; 
         FIG. 4  illustrates the relationships to library routines and the calling process for a select function; 
         FIG. 5  illustrates the relationships to library routines and the calling process for a insert function; 
         FIG. 6  illustrates the relationships to library routines and the calling process for a update function; 
         FIG. 7  illustrates the relationships to library routines and the calling process for a delete function; 
         FIG. 8  illustrates the record layout within a DBM file and its relationship to a corresponding database schema; 
         FIGS. 9A and 9B  show an exemplary SQL syntax implemented for an embodiment of the present invention; 
         FIG. 10  shows a flow diagram for an exemplary resource locking method; and 
         FIG. 11  shows a flow diagram for an exemplary method of record insertion. 
     
    
    
     DETAILED DESCRIPTION 
     The present system and method solves several problems with methods of the prior art, including the requirements of a database manager service and strict data types. The use of a SQL interface allows the use of regular expression matching. The DBM is extended beyond 1024 byte key/value limit and table-level locking is implemented. 
     The present system and method does not require the use of a database manager running as a background process on the host machine. While a database (DB) manager can speed search and indexing times for transactions, it also complicates the database model somewhat. The DB manager forces applications to wait for its presence and proper functionality, essentially forcing a middleware process to handle transactions that the file system handles for present system and method. 
     The present system and method does not force the notion of data types on the calling application. An exemplary embodiment uses the powerful mapping functionality of Perl scripting language to load and maintain the data representation. The application can use the data however it need to. At no point in the process is data (externally) manipulated to fit data types. The data is returned as a vector array data stream. The library includes the capability for the application to dissect the data and deliver each row as an index array. In this way, specific data items can be referenced by column name and used in whatever context is required by the application. 
     An exemplary embodiment uses the Perl scripting language as an interface the DBM to provide a rich set of regular expression matching techniques. By using Perl, all the regular expression patterns are available in searching for data. This allows those managing the application to use the expressions they are already familiar with and not worry about the standard SQL syntax. 
     DBM is limited to 1024 bytes for each record to be shared with the key/value pair. An exemplary embodiment extends this limit by allowing a large data item to be maintained outside the DBM file pair. The placeholder is used to mark the column, but the schema directs the selection routine to an external location. In this way, large binary objects can be stored and indexed in the same way that simple text and numeric data can. 
     DBM does not provide a mechanism to lock multiple writes to the data. An exemplary embodiment of the present system and method uses a resource locking routine to lock writes and allow dirty reads of the data. 
     There are several advantages of the present system and method. No special backup and recovery procedures are required. Because no database service manager is required, managing the databases using the skills of a database administrator (DBA) are not required. Data can be moved easily from one platform to another. The present system and method has embedded functionality. File-system security, as implemented on host system, is used rather than adding an additional layer of security. Since a database management service is not used, setup is simplified. Table restructuring is simple and quick. 
     An exemplary embodiment is an extension of the DBM specification. Thus, the files can be stored and restored using any conventional storage device and software package. No recovery process is required to return the database to a normal level. Log files are available to review the status after a system event, but data is committed in real time, so there is no delay in the update sequence. 
     The present model is targeted for use in small, non mission-critical applications, where the expertise and expense of a large commercial database is not cost-effective. It is intended to be simple and easy to maintain, while still providing the functionality of a relational database. Individuals with minimal computer skills can now have a database that is transportable, extendable and easy to maintain. 
     Data files of the exemplary embodiment can be copied from one system or another without restructuring the data, as long as both systems implement DBM processing using the same specifications. In the event of a system failure, the database can be restored to another system and be accessed without installing any additional database software. The database can even be moved from a UNIX system to Windows™ or Linux by simply changing the directory path in the schema and copying the files. 
     By adding the require tag in a Perl application, the SQL calls are embedded automatically. For example, an application can use the SQL subroutine to issue commands to the database. The routine will return a return code and message for status. It will also return a vector array to be used by the calling process. 
     Internal security for the present system and method is not implemented. Instead, it uses the file system security to provide access to the tables. An Administrator does not need to learn a new security scheme to manage the database. This model will allow the application to add an additional layer of security before access may be granted. 
     The setup is made up of the following steps:
         1. copy the library to any directory on the system;   2. create the schema using any standard text editor;   3. add the schema location and library references to the Perl scripts.
 
There is nothing to build, nothing to start, nothing to configure. The database is ready to simply start inserting, updating, deleting, importing, and exporting records.
       

     When a change to a table is needed, i.e. add, or delete a column, all that is required is to define the new schema, issue the “restructure” command. Column names are only defined within the schema. To rename a column, simply edit the text in the schema file. 
     The database of an exemplary embodiment is composed of a key/value file pair representing the DBM .pag and .dir files. The .dir file contains the hash table for the data index and the .pag file contains the referenced data. An additional option is to use an external file to store data that may be larger that 1024 bytes. This external link is defined because DBM can only manage a record of 1024 bytes, including the key. A schema is used to define the column names and field separators within the data. Standard low-level lookup routines are used to retrieve and store the data items with the exception of the external data. Records are interrogated and compared with the SQL where clause on lookup and replacement. 
     Referring now the drawings, and in particular to  FIG. 1 , there is shown a sample schema file, defining an exemplary DBM database. The schema defines a phone  101  number table within the client database. It is stored in a location as defined by Dbfilename in /var/opt/phone/DB/phone  103 . The data file has three columns  105 , and the key for the hash table is the last name lname  107 . The first column is the phone number  109 . The second column is the first name fname  111 . The third column is the last name lname  113 . 
     The schema can be created by any text editor to define the database layout. The schema defines the directory location for the each table, the ownership definition and column names for external links, the number of columns, the key column, and the column names with their associated position. Below is an example of a phone number table within the client database. 
     This sample file could be saved as client.def, thus naming the database “client” and the table “phone”. An example lookup is in the form:
         select * from client.phone where lname=Miller.
 
The table can now be created using the SQL command create table.
       

     Referring now to  FIG. 2 , there is shown a sample lookup script for accessing data in the DBM database. A “require” tag  201 A and  201 B is required to define the data location global variable $_dbdefdir to the Perl application script. This tells DBM where the database files are located. The Perl script defines a subroutine lookup_phone  203  to execute a phone number lookup in the phone table. The lookup function uses an SQL command  205  to effectuate the lookup. 
     Referring now to  FIG. 3 , there is shown a block diagram illustrating a process overview for accessing a DBM database. The present system and method utilizes the key/value pair to store and retrieve data, with the exception of external data, as discussed below. The schema  301  defines the data in the table  303  and  305 . The table includes the key file  303  and the data file  305 . A split character divides each record column in the data file  305 . By default the character is ASCII 0 (NULL character), but it can be defined in the schema to be anything that is not used within the record data itself. If the data is large and must be stored externally, a pointer in the data file  307  identifies the external file and location  309 . 
     When storing a long record externally, there is a tag on the external table for the column heading. This table is an additional file outside the data file. In DBM there is an index file, and there is a data file. In the extension provided by the present method and system, there is an index file  303 , there is a data file  305 , and then there is an additional data file  308 . The data file is indexed on top with a column heading. The data falls below that. There is a different column heading down the table itself too. The data is stored in binary, but there are column headings in between the data. The external fields are defined in the schema. 
     When the database is defined, the fields that are going to be external fields outside the data file are identified. Within the record, within the hash, in the data file itself, the specified column heading will be blank. As the records are pulled in, a routine determines whether an external records has been requested. If so, the external record, is pulled in and added to this array. When an external record is selected, the routine performs the selection and the comparison for the requested criteria, then brings all of the data back in and it stores it in an associative array, so that each column in the associative array is indexed in memory. 
     In an exemplary embodiment, the filename is based on the table name. Suppose there is a table name called “employee.” It is desired to store comments in the employee table. The comments can be large. In the directory where the DBM files are stored, there is an associated index file. There is a data file but also a directory is created when the table is built. The exemplary embodiment creates a directory called employee. In the employee directory, there is a file created for each record/key corresponding to the key field. Thus, DBM is similar to traditional relational databases where a unique key is necessary for each table. Within a database, there also needs to be a unique key for each table but the key does not necessarily have to be one of the table columns. It could be anything that can be unique. 
     The data manipulation implemented within the present system and method is centered on the SQL subroutine. Although direct access is available via the GetRecord and PutRecord routines, SQL is the basis for most transactions.  FIGS. 4–7  illustrate the relationships to the library routines and the calling process. In an exemplary embodiment, the processes of  FIGS. 4–7  are encoded in Perl script. 
     Referring now to  FIG. 4 , there is shown a process flow diagram for a Select function. First, the SRDE.pl library is loaded at  401 . The SQL select call is made at  403 . The SQL is parsed  404  and it is determined that a select call is made and is passed off to the SQL select routine  405 . Processing the SQLSelect command requires the execution of a getdbdef  407 , Getwheres  409 , and Getfields  411 . The data is filtered through a data filter  413 . If the index points to an external file  421  for large data, the GetExternal routine  423  is used to access the data. Ultimately, the data is retrieved using native DBM commands  415  which access the index file  417  and the data file  419 . 
     Referring now to  FIG. 5 , there is shown a process flow diagram for an Insert function. First, the SRDE.pl library is loaded at  401 . The SQL Insert call is made at  403 . The SQL is parsed  404  and it is determined that an insert call is made and is passed off to the SQLInsert routine  505 . An advantage of the present system and method over DBM is the ability to lock the database. It is necessary to lock the database before an Insert to maintain database integrity. Processing the SQLInsert  505  command requires the execution of a getclbdef  407  to get the database definition information, and AcquireLock/ClearLock  507  command to lock or unlock the database. If the index points to an external file  421  for large data, the GetExternal routine  423  is used to access the data, and PutExternal  525  is used to put the data into the external file. Ultimately, the data is retrieved using native DBM commands  415  which access the index file  417  and the data file  419 . 
     The GetRecord  531  and PutRecord  533  routines allow the calling process direct access to the table using the DBM hash key. GetRecord  531  uses the native DBM commands  415  to retrieve a record. The data is then coupled with any external data. After retrieval, the record is reformatted into an associative array. PutRecord  533  reformats the associative array into a DBM record, then uses the native DBM commands  415  to store the data into the DBM file. External data is then placed in the external record file  421 . A check is made to ensure that a duplicate record is not added on insertion  535 . 
     Referring now to  FIG. 6 , there is shown a process flow diagram for an Update function. First, the SRDE.pl library is loaded at  401 . The SQL Update call is made at  403 . The SQL is parsed  404  and it is determined that an Update call is made and is passed off to the SQL Update routine  605 . It is necessary to lock the database before an Update to maintain database integrity. Processing the SQL Update  605  command requires the execution of a getdbdef  407  to get the database definition information, and AcquireLock/ClearLock  507  command to lock or unlock the database. If the index points to an external file  421  for large data, the GetExternal routine  423  is used to access the data, and PutExternal  525  is used to put the data into the external file. Ultimately, the data is retrieved using native DBM commands  415  which access the index file  417  and the data file  419 . 
     The GetRecord  531  and PutRecord  533  routines allow the calling process direct access to the table using the DBM hash key. GetRecord  531  uses the native DBM commands  415  to retrieve a record. The data is then coupled with any external data. After retrieval, the record is reformatted into an associative array. PutRecord  533  reformats the associative array into a DBM record, then uses the native DBM commands  415  to store the data into the DBM file. External data is then placed in the external record file  421 . 
     Referring now to  FIG. 7 , there is shown a process flow diagram for a Delete function. First, the SRDE.pl library is loaded at  401 . The SQL Delete call is made at  403 . The SQL is parsed  404  and it is determined that a Delete call is made and is passed off to the SQLDelete routine  705 . It is necessary to lock the database before a Delete to maintain database integrity. Processing the SQLDelete  705  command requires the execution of a getdbdef  407  to get the database definition information, and AcquireLock/ClearLock  507  command to lock or unlock the database. If the index points to an external file  421  for large data, the Unlink  707  command is used delete the data file from the file system. Ultimately, the data is deleted using native DBM commands  415  which access the index file  417  and the data file  419 . 
     In addition to the main operations of select, insert, update, and delete, the present system and method also provides for importing and exporting of data. The CSVImport subroutine reads an import ASCII file, formats and validates the data, then calls GetRecord and PutRecord to update or replace the data. The CSVExport routine is simply an additional format option from the select call. 
     The present system and method is built upon seven core algorithms: record structure, SQL parsing, locking, record insertion/update (including import), record deletion, record selection (including export). The speed of each of the algorithms is derived primarily from the use of system memory to store the manipulated data. Each process and the steps involved in managing the data is described below. 
     Record Structure: 
     Referring now to  FIG. 8 , there is shown a block diagram illustrating the exemplary record structure. Each record in the database is stored in the DBM data file  800 . If one or more columns are expected to extend beyond the DBM 1024 byte limit, external columns are defined to store the data in an additional external data file  805 . The external “pointer”  811  is found within the database schema  810  and a placeholder is maintained within the DBM file. Each item in the record is separated by a user-defined ASCII character, ASCII(0)/NULL is used by default.  FIG. 8  illustrates the record layout within the DBM file and its relationship to the database schema. 
     Each record is located in the DBM file using the built-in hash table. The key  813  is designated within the schema and stored in the DBM index file  801  along with the absolute position of the corresponding data in the data file  803 . Each column is defined within the record based on its offset position from the record pointer. During data processing, each column can then be addressed as an indexed subset. External data  805  is retrieved after the initial record has been acquired. It is inserted within the vector array at the proper index location. To the calling process, it retrieves the entire record in one pass as a vector array. If the record is returned to the calling process, the column headers are inserted at the top of the array. This allows other subroutines to splice the data and convert it to an associative array referencing each column by name. 
     SQL Parsing: 
     The parsing algorithm interprets a modified SQL syntax and returns an associative array to be used by the calling process. The SQL syntax implemented in the present system and method is shown in  FIG. 9 , in EBNF (Extended Backus-Naur Form) format. All items are treated as text strings during the parsing phase. 
     Referring now to  FIG. 9A , valid commands  901  are create  902 , delete  904 , import  906 , insert  908 , export  910 , select  912 , and update  914 . A column list  921  has column names  922  separated by commas. A valid expression consists of a column name  922 , one of a plurality of operators (“=”|“!=”|“&lt;”|“&gt;”|“&lt;=”|“&gt;=”|“=˜)  925  and a quoted value  927 . A valid procedure is one of unique  928 , sum  930 , min  932 , max  934 , avg  936  and count  938 . The procedures use a column name  922  as a parameter, or argument. 
     The syntax for the seven valid commands in the exemplary embodiment is shown in  FIGS. 9A and 9B . Referring now to  FIG. 9A , the syntax for create  902 A includes a database table name  941  for creation. The delete command  904 A defines from which database table the item is to be removed and uses an expression to describe the item. The import command  906 A defines from which database table the item is to be imported, and where the item is to be imported. Insert  908 A defines a set and into what database table that set should be inserted. Export  910 A is similar to import, but in the opposite direction. The export command defines from which database table the item is to be found, and into what filename. 
     Referring now to  FIG. 9B , the select command  912 A defines a column list and procedure in order to uniquely identify the items for selection. Update  914 A defines the database table for updating and a set and expression to uniquely identify the items for updating. 
     The elements returned from the ParseSQL subroutine are:
         SQL{JOIN}: A subordinate clause to be executed against another table following the initial select command. The supplemental data is merged into each record of the initial select, based on a foreign key defined within the join statement. The foreign key is not forced in the schema, but a designated relationship defined by the calling process. An example is:
           select name, addressfrom persondb. location join owner-name,phonefrom persondb.phone where owner-name=name   
           The join item will contain “owner-name,phone from persondb.phone where owner-name=nam”   SQL{COMMAND}: The requested operation (create, select, insert, update, delete, import, or export).   SQL{CSVFILE}: The filename to be imported or exported.   SQL{FIELDS}: The contents of the fields to perform action against. The FIELDS item is parsed using the GetFields subroutine. GetFields checks to ensure that correct column names are used in the SQL command, and removes any duplicate fields requested. It returns a vector array with the list of fields to be operated against.   SQL{SET}: Contains the list of column names and their associated values used during and insert or update command.   SQL{SORTBY}: Optional column name representing the key used to perform output sorting.   SQL{TABLE}: The table to be operated on, the expected syntax is database-name.table-name.   SQL{WHERE}: The contents of the “where” clause. The WHERE item is parsed again in the subroutine GetWheres to determine database operation types such as unique, sum, min, max, avg, and count. GetWheres also converts operators (&lt;, &gt;,&lt;=,&gt;=,!=,=,=˜) to its respective two-character comparison operator (It, gt, ,Ie, ne, ge, eq). The purpose of the conversion is to enable all comparisons to be done as a string or numeric comparison as required by the data. Since the present system and method requires no strict data typing, the data comparison must be determined at the time of the examination. GetWheres returns an associative array broken into each column name, its operator and the operand column name. An example is: where name=fred and date=Dec. 31, 2002 will return an associative array containing: where {NAME}=“fred”   where{NAME::META}=“eq” where {DATE}=“Dec.  31 ,  2002 ”   where{DATE::META}=“eq”.
 
Resource Locking:
       

     An exemplary embodiment does not physically lock the database, but rather locks an implied resource. The AcquireLock and ClearLock take the resource name as a parameter. The parameter represents the resource to be controlled for access. Once a resource is locked, all other lock requests are queued until a call to ClearLock is made, or the calling process dies. AcquireLock checks the status of the locking process and will grant the next lock request on its termination. 
     Referring now to  FIG. 10 , there is shown a flow diagram for an exemplary resource locking method. First, it is determined whether the resource is clear, in step  1001 . If it is, then it is determined whether it is the requesting process&#39; turn with the resource in step  1005 . If so, then the resource is locked. If the resource was not clear, then a determination is made as to whether the current lock is valid in step  1003 . If so, then the step  1001  is repeated until the lock resource is clear to be locked. If the current lock is not valid, as determined in step  1003 , then a determination is made as to whether it is the requesting process&#39; turn with the resource in step  1005 . Thus, the requesting process keeps checking the status of the resource until it can be locked in step  1007 . 
     Record Insertion and Updates: 
     Inserting a record into the database is a matter of packing the items in a row and using the features of DBM to add the data into the database. If large columns are required in the implementation, a call to PutExternalRecord is made to insert each item into the associated file. A check is made to ensure that a duplicate record is not added on insertion. If the record is not found on update, the data will be inserted as if the insert command were issued. Insertion and updates are handled primarily through the GetRecord and PutRecord subroutines. 
     Referring now to  FIG. 11 , there is shown a flow diagram for an exemplary method of record insertion. The GetValues routine  1101  matches each column value with the associated column name, and loads them into an associative array. This method allows the process to build the record for insertion or update by directly accessing the column data instead of indexing by column offset. The database table definition is retrieved in step  1103  with the getdbdef function. The record is retrieved in step  1105  with the GetRecord function. A determination is made as to whether the record is a duplicate by examining the primary key and comparing it with keys already stored in the hash file. in step  1107 . If it is not duplicated, then the record is inserted in step  1109  with the PutRecord function. If it is duplicated, then the process returns. 
     Record Deletion: 
     Deleting records from the database involves calling DBM&#39;s delete function and unlinking the file block if external records are defined. The specific keys are located by making a call to SQLSelect with the “keys” option. In this way, the calling process can supply a where clause identifying a subset of records which are marked for deletion. 
     Importing: 
     The import algorithm can read files on a comma-separated value format and insert the new record, replace an existing record, or merge supplied fields into an existing record. The latter option is invoked with the merge option in the SQL command. If the merge option is selected, all columns supplied within the CSV file will replace matching columns in the database. The remaining columns will be left intact. If a matching record is not found, the CSV record will become a new record in the database with the missing columns left empty. Importing records involves an initial step to convert the CSV-formatted data into a record item. The CSVImport subroutine reads one line of the import file at a time. The CSVFields subroutine converts each line into a vector array. A call to GetRecord will return either a blank associative array (indicating no match was found), or a record with the matching primary key. Each matching column from the database is replaced with the associated field from the CSV file if the merge option is supplied. If the merge option is not supplied, the record will be cleared and all fields are replaced with the imported data. 
     Exporting: 
     Exporting data is accomplished as a formatted selection from the database. Export retrieves the data from the database via the SQLSelect subroutine, then calls CSVFormat to convert the vector array into a CSV-formatted line. The resulting line is written to a file specified in the SQL command. 
     Selection: 
     Selecting records from the database is accomplished by examining each data item suggested by the where clause of the SQL statement. If external columns are required from the select they are retrieved and merged with the DBM data into a vector array. If the table key is supplied in the where clause, non-matching keys are eliminated before the associated values are compared. This step speeds the selection phase by ignoring DBM and external records that have been eliminated with the index-key comparison. After the initial comparison, each possible record is examined and compared using the information in the where clause. The SQLParse subroutine returns the associative array with the operators required to compare each column. Regular expression matching is inserted using the // terminators when comparing based on a regular expression operator. Procedure calls, (unique, sum, min, max, avg, and count) are invoked if the item passes the matching criteria for all columns specified in the where clause. And finally, a join clause can return linked data between two tables using the SQLJoin subroutine. Outlined below is the pseudo code used in the selection algorithm.
         Localize/Initialize variables   Convert where clause to associative array   Convert fields clause to associative array   Determine if external columns are required   Determine if procedure is requested—(unique, sum, min, max, avg,count)   Determine the number of columns that will be returned   If key is used in where clause
           Compare keys with DBM index   Create “dbkeys” vector array with matching keys   
           Else
           Create “dbkeys” vector array of all keys   
           EndIf   For each key in “dbkeys” array
           Get record from DBM data file   Convert record to indexed vector array “seldata”   If External record needed
               Get External portion of record   Insert external record into indexed vector array “seldata”   
               Endif   For Each field in where clause
               Compare each field in the array requested from the   where clause   
               EndFor   If all comparisons matched
               If sumo, min( ), max( ), count( ), avg( ) were requested
                   sum( ): Add numeric data to existing “sum” variable   min( ): Replace existing min” value with new minimum if less than existing   max( ): Replace existing “max” value with new maximum if greater than existing   count( ): Update existing “count” value by  1     avg( ): Update existing “average” variable with new average   
                   
               
           EndIf   If unique requested
           update “unique” variable with new value   
           EndIf   Push record into vector array “data”
           EndIf   
           EndFor   If sort requested
           sort “data”   
           EndIf   If join requested
           Call select and merge with “data”   
           EndIf   return (return-code, message, num-columns, “data”)       

     The terms and descriptions used herein are set forth by way of illustration only and are not meant as limitations. Those skilled in the art will recognize that many variations are possible within the spirit and scope of the invention as defined in the following claims, and their equivalents, in which all terms are to be understood in their broadest possible sense unless otherwise indicated.