NAME

CodeBase - Perl module for accessing dBASE files

ABSTRACT

The CodeBase module provides a Perl 5 class for accessing dBASE files. It is a development of an earlier unpublished Perl 4 extension.

SYNOPSIS

Programs using the CodeBase module must include the line:

use CodeBase;

The functions that the module provides are listed below, grouped according to type of function.

File manipulation functions

$fh = CodeBase::open($filename, @options);
$fh = CodeBase::create($filename, @fielddefs);
$fh->DESTROY();

File information functions

$n_recs    = $fh->reccount();
$recsize   = $fh->recsize();
$n_fields  = $fh->fldcount();
@names     = $fh->names();
$type      = $fh->type($fieldname);
@fieldinfo = $fh->fieldinfo();
$recno = $fh->recno();
$fh->goto($recno);
$fh->skip($n_recs);
$fh->bof();
$fh->eof();

Record manipulation functions

@values = $fh->fields();
$value  = $fh->field($fieldname);
$fh->set_field($fieldname, $value);
$fh->new_record(@values);
$fh->replace_record(@values);

$fh->deleted();
$fh->delete_record($recno);

$fh->flush($tries);
$fh->pack($compress_memo);

$fh->lock($what, $tries);
$fh->unlock();

Index manipulation functions

$n_tags  = $fh->tag_count();
@tags    = $fh->tags();
@taginfo = $fh->taginfo($index_name);
$fh->open_index($name);
$fh->create_index($name, $taginfo);
$fh->reindex();
$fh->set_tag();
$fh->seek($key);

$q = $fh->prepare_query($expr [, $sortexpr [, $desc]]);
$q->execute;
$q->next([$skip]);

Miscellaneous functions

CodeBase::option(@options);
$errno   = CodeBase::errno();
$errmsg  = CodeBase::errmsg($errno);
$version = CodeBase::libversion;
$dbtype  = CodeBase::dbtype;

DESCRIPTION

Each function provided by the CodeBase module is described below. The module uses the CodeBase library from Sequiter Software Inc., which is a C library providing database management functions for dBASE files.

File manipulation functions

Existing dBASE files can be opened with open() and new files created with create(). Files are implicit closed by the DESTROY method, which is called when all references to the internal file handle go out of scope.

open FILENAME [, OPTION-KEYWORD ...]

Opens the named dBASE file and returns a file handle which can be used in other CodeBase functions. The filename should omit the .dbf extension. The following options keywords are recognized: "readonly", "noindex" or "exclusive" ("ro" is a synonym for "readonly" and "x" is a synonym for "exclusive"). Option keywords are case-insensitive. For example to open the file books.dbf in read-only mode, without opening the production index:

$fh = CodeBase::open("books", "readonly", "noindex");
create FILENAME, FIELD-DEFS =item create FILENAME, FIELD-DEF-ARRAY, INDEX-TAG

Creates a new dBASE file using the field definitions specified and returns a file that can be used in other CodeBase functions. The field definitions consist of an array of alternating pairs of field name and field type.

@field_defs = ( "F1" => "C10",
                "F2" => "N4" );
$fh = CodeBase::create("test", @field_defs);

The field types are as follows:

Type       Code      Length    Decimals
-------------------------------------------
Character    C     1 to 65533     0
Date         D     8              0
F.P.         F     1 to 19     0 to len - 2
Logical      L     1              0
Memo         M     10             0
Numeric      N     1 to 19     0 to len - 2

Note: create does not create a production index file -- use create_index with an empty filename. The facility to create a production index at the same time that a database is created may be added later. Field and tag information arguments would then be specified as references.

DESTROY FILEHANDLE

The DESTROY function is not normally called explicitly. It is invoked automatically when all copies of the file handle generated by open() or create() go out of scope. For example:

 {
     my($fh2);
     {
         $fh1 = CodeBase::open("test");
         $fh2 = $fh1;
     }
     # $fh1 is destroyed here, but $fh2 contains a copy of the file
     # handle so CodeBase::DESTROY is not called yet.
}
# $fh2 is destroyed as it goes out of scope, so CodeBase::DESTROY
# is invoked. 
recno

Returns the current record number. It is equivalent to the dBASE RECNO() function.

$recno = $fh->recno

If the file has just been opened, created or packed there is no current record number and recno() will return undef.

goto RECNO

Positions the current record of the database file to the specified record. It is equivalent to the dBASE GOTO statement.

$fh->goto($recno);

The record number for CodeBase::goto should be an integer between 1 and CodeBase::reccount. It can also take one of the keywords: "TOP" or "BOTTOM". The keywords "START" and "FIRST" are accepted as synonyms for "TOP", and "END" and "LAST" as synonyms for "BOTTOM". Only the first character of a keyword is significant and case is not significant.

Normally goto returns 1 to signify success; if an error occurs it returns undef. The error code can then be retrieved with errno.

skip N_RECORDS

Skips forwards or backwards in the database file by the specified number of fields. It is equivalent to the dBASE SKIP statement. The number of fields defaults to one.

$fh->skip($n_records);

Normally skip returns the new record number; if an error occurs it returns undef. The error code can then be retrieved with errno.

bof

Returns a boolean value indicating whether the current record is positioned before the first record. It is equivalent to the dBASE BOF() function.

if ($fh->bof()) ...
eof

Returns a boolean value indicating whether the current record is positioned at the end of the file. It is equivalent to the dBASE EOF() function.

while (!$fh->eof()) ...

Record handling functions

reccount

Returns the number of records in the database file. It is equivalent to the dBASE RECCOUNT() function.

$n_recs = $fh->reccount();
recsize

Returns the size in bytes of records in the database file (including the deletion flag). It is equivalent to the dBASE RECWIDTH() function.

$recsize = $fh->recsize();
fldcount

Returns the number of fields per record for the database file.

$n_fields = $fh->fldcount();

It is equivalent to the dBASE FLDCOUNT() function.

names

Returns the field names as an array.

@names = $fh->names();
type FIELD

Returns the type of the named field as a string.

$type = $fh->type("field1");
fieldinfo [NAMES]

Returns an array containing information about the specified fields or about all fields if no fields are specified. For example if the database open on $fh contains, amongst others, the fields field1 and field2 as a 12 character field and a 10 byte numeric field with 3 decimal places respectively then:

@names = ("field1, "field2");
$fh->fieldinfo(@names);

would return an array containing the values:

("field1", "C12", "field2", "N10.3")

This is a shortcut function. The same information can be built up by using names and type:

foreach $name ($fh->names)
{
    push(@results, ($name, $fh->type($name)));
}
values [NAMES]

Returns an array containing the values of each of the specified fields, or of all fields if no field names are specified.

@values = $fh->values("field1", "field3");
field NAME

Returns the value of the named field.

$value = $fh->field("field1");
set_field NAME, VALUE

Sets the value of the named field to the specified value.

$fh->set_field("field1", $value);

If the field is a date field the value should be formatted in dBASE date format (e.g. "YYYYMMDD") or should be one of the keywords "YESTERDAY", "TODAY" or "TOMORROW" (the keywords are not case sensitive) or may be a number of days to the current date specified as +num or -num. For example to set a date field to a week's time:

$fh->set_field("date", "+7");
new_record VALUES

Creates a new record using the values specified. VALUES may be an array of field values:

$fh->new_record({ firstname => "Fred",
                  surname   => "Bloggs"  });

or a reference to a hash, the keys of which are the field names:

$fh->new_record("Bloggs", "Fred");

If the values are supplied as an array, a value must be supplied for each field. If the values are supplied as a hash unspecified fields are filled with blanks. Excess array values or hash keys that are not names of fields are simply ignored. The handling of date fields is as described under set_field.

replace_record VALUES

Replaces the fields of the current record with the values specified. As with new_record VALUES may be an array of field values:

$fh->replace_record("Bloggs", "Fred");

or a reference to a hash, the keys of which are the field names.

$fh->replace_record({ firstname => "Fred",
                      surname   => "Bloggs"  });

In the former case a value must be supplied for each field, while in the latter case unspecified fields are unchanged. Excess values or hash keys that are not names of fields are ignored. The handling of date fields is as described under set_field.

deleted

Returns a boolean value indicating whether the current record is deleted.

if ($fh->deleted()) ...

This function is equivalent to the dBASE DELETED() function.

delete_record [RECNO]

Deletes the record specified or the current record if called without a record number.

$fh->delete_record($recno);
recall_record [RECNO]

Recalls the record specified or the current record if called without a record number. (Not yet implemented).

flush [TRIES]

Flushes to file any outstanding changes (made by set_field(). Records need to be locked while changes are written. TRIES is the number of attempts that should be made to aquire the lock. Subsequent attempts are made with a one second interval.

pack COMPRESS-MEMO-FLAG

Packs the database file removing deleted records. If flag parameter is specified as true then memo fields are compressed at the same time:

$fh->pack(1);
lock WHAT [, TRIES]

Locks the specified record or the whole file. WHAT should either be "FILE" or a record number (the current record can be referred to as ".". TRIES is the number of attempts that should be made to aquire the lock. Subsequent attempts are made with a one second interval.

unlock

Removes any existing locks on the file.

Index Handling Functions

A production index file is automatically opened when a database file is opened, if it exists unless the noindex option is specified. An index file can be opened with the open_index method.

tagcount

Returns the number of index tags.

$n_tags = $fh->tagcount();
tags

Returns an array containing the names of all the tags associated with the database file.

@tags = $fh->tags();
set_tag TAG

Sets the current index tag to the named tag. If no tag is specified the currently selected tag is deselected.

$fh->set_tag("TAG1") || die "Cannot set index tag.\n";
taginfo

Returns an array containing information about tags. Each element of the array is a reference to a hash containing attributes of the tag. The attributes are name, expression, filter, order and duplicates.

This array is suitable for passing to create_index, for example for copying the index structure of a file:

@taginfo = $fh1->taginfo;
$fh2->create_index(undef, \@taginfo); 
create_index NAME, TAGINFO

Creates a new index file. The index file name is specified by NAME and should not include the .mdx extension. If NAME is specified as undef or "" a production index is created.

The new index file will contain the tags specified in the TAGINFO argument: an array passed by reference, each element of which is a hash containing attributes of the particular tag. Valid attributes are: name, expression, filter, duplicates and order.

For example to create a production index with three tags:

$fh->create_index( undef,
                   [ { name       => "TAG1",
                       expression => "F1",
                       duplicates => "KEEP" },
                     { name       => "TAG2",
                       expression => "F2",
                       order      => "DESCENDING" },
                     { name       => "TAG3",
                       expression => "UPPER(F3)" }
                   ] );
open_index [ NAME ]

Opens the specified index file. The name should not include the .mdx extension. If the name is not specified then the production index is opened.

seek VALUE

Seeks in the currently selected index tag for a match for the specified value. Returns 1 if a match is found otherwise the undefined value is returned and the error code can be retrieved with CodeBase::errno.

The search value must be formatted correctly for the index, for example if an index is generted on STR(F1), where F1 is a numeric field of width 6, the value be formatted as a right aligned 6-character integer:

$fh->seek("    42");

For string valued index keys a search value shorter than the tag expression length will be matched on the initial substring, e.g. "FRED" would match "FREDERICK".

Query functions

The query functions interface to the CodeBase Relate/Query module. The interface is currently incomplete. All that is provided is the facility to query a single file.

A query is prepared (in a similar manner to the Perl DBI query) and then executed and the result set stepped through. The functions are:

$q = $fh->prepare_query($expr [, $sortexpr [, $desc]]);
$q->execute;
$q->next([$skip]);

An example of the usage would be:

$q = $fh->prepare_query('AGE >= 18 .AND. AGE <= 65', 'AGE', 1);
$q->execute;
while (my $r = $q->next) {
    @fields = $r->values;
    # do some processing.
}

I intend to allow more complex queries to be built up in a Perl-ish manner, but I haven't come up with an interface yet.

Miscellaneous functions

CodeBase::option OPTIONS

Sets configuration options for the CodeBase module. The only option currently offered is trace. Setting this to a non-zero value enables the output of tracing, which can be helpful in debugging.

# Enable tracing
CodeBase::option("trace=1");

# Disable tracing
CodeBase::option("trace=0");
CodeBase::errno

Returns the error code for the last operation.

CodeBase::errmsg ERRNO

Returns an explanatory string for the error code ERRNO

CodeBase::libversion

Returns the version of the CodeBase library that the module was compiled and linked against.

CodeBase::dbformat

Returns the XBase file format that the library and module were compiled for. This will be one of "dBASE IV", "FoxPro" or "Clipper".

ERRORS

Functions return a value on success and undef on error. The error code can be determined by calling CodeBase::errno, and the equivalent error message by calling CodeBase::errmsg.

A number of variables are defined as symbolic names for the CodeBase error codes. Thes variables are all defined in the CodeBase package and so need to be referred with the package prefix (e.g. $CodeBase::e4close).

General disk access errors

$e4close          =  -10;  # Closing file
$e4create         =  -20;  # Creating file
$e4len            =  -30;  # Determining file length
$e4len_set        =  -40;  # Setting file length
$e4lock           =  -50;  # Locking file
$e4open           =  -60;  # Opening file
$e4read           =  -70;  # Reading file
$e4remove         =  -80;  # Removing file
$e4rename         =  -90;  # Renaming file
$e4seek           = -100;  # Seeking to a file position
$e4unlock         = -110;  # Unlocking file
$e4write          = -120;  # Writing to file

Data file specific errors

$e4data           = -200;  # File is not a data file
$e4field_name     = -210;  # Unrecognized field name
$e4field_type     = -220;  # Unrecognized field type
$e4record_len     = -230;  # Record length too large

Index file specific errors

$e4entry          = -300;  # Tag entry missing
$e4index          = -310;  # Not a correct index file
$e4tag_name       = -330;  # Tag name not found
$e4unique         = -340;  # Unique key error

Expression evaluation errors

$e4comma_expected = -400;  # Comma or bracket expected
$e4complete       = -410;  # Expression not complete
$e4data_name      = -420;  # Data file name not located
$e4length_err     = -422;  # IIF() needs parameters of same length
$e4not_constant   = -425;  # SUBSTR() and STR() need constant parameters
$e4num_params     = -430;  # Number of parameters is wrong
$e4overflow       = -440;  # Overflow while evaluating expression
$e4right_missing  = -450;  # Right bracket missing
$e4type_sub       = -460;  # Sub-expression type is wrong
$e4unrec_function = -470;  # Unrecognized function
$e4unrec_operator = -480;  # Unrecognized operator
$e4unrec_value    = -490;  # Unrecognized value
$e4unterminated   = -500;  # Unterminated string

Optimization errors

$e4opt            = -610;  # Optimization error
$e4opt_suspend    = -620;  # Optimization removal error
$e4opt_flush      = -630;  # Optimization file flushing failure

Relation errors (not used)

$e4relate         = -710;  # Relation error
$e4lookup_err     = -720;  # Matching slave record not located

Severe errors

$e4info           = -910;  # Unexpected information
$e4memory         = -920;  # Out of memory
$e4parm           = -930;  # Unexpected parameter
$e4result         = -950;  # Unexpected result

For detailed explanations of these codes refer to the CodeBase Reference Guide by Sequiter Software Inc.

RESTRICTIONS

Tags cannot be added to existing index files -- the entire index file must be recreated. This is a restriction imposed by CodeBase 5.1.

FUTURE DIRECTIONS

Record fields may be made into an associative array allowing their values to be accessed and set with the following syntax:

$val = $file->{"F1"};       
# rather than:  $val = $file->value("F1");

$file->{"F1"} = $newval;
# rather than:  $file->set_value("F1", $newval);

The query functionality will be expanded.

COMPATIBILTY

CodeBase Functions

CodeBase 6.4        CodeBase 5.1         CodeBase.pm
============        ============         ===========

code4calcCreate     expr4calc_create
code4calcReset      expr4calc_reset
code4close          d4close_all	    implicit on exit
code4connect
code4data           d4data
code4dateFormat
code4dateFormatSet
code4exit           e4exit
code4flush          d4flush_files
code4indexExtension
code4init           d4init
code4initUndo       d4init_undo
code4lock
code4lockClear
code4lockFileName
code4lockItem
code4lockNetworkId
code4lockUserId
code4logCreate
code4logFileName
code4logOpen
code4logOpenOff
code4optAll
code4optStart       d4opt_start
code4optSuspend     d4opt_suspend
code4timeout
code4timeoutSet
code4tranCommit
code4tranRollback
code4tranStart
code4tranStatus
code4unlock         d4unlock_files
code4unlockAuto
code4unlockAutoSet

Data File Functions

CodeBase 6.4        CodeBase 5.1         CodeBase.pm
============        ============         ===========

d4alias             d4alias
d4aliasSet          d4alias_set
d4append
d4appendBlank       d4append_blank
d4appendStart       d4append_start
d4blank
d4bottom
d4changed
d4check
d4close             d4close              undef $fh
d4create
d4delete
d4deleted
d4eof
d4field
d4fieldInfo         d4field_info
d4fieldJ            d4field_j
d4fieldNumber       d4field_number
d4fileName
d4flush             d4flush               $fh->flush
d4flushData         d4flush_data
d4freeBlocks        d4free_blocks
d4go                d4go                  $fh->go
d4goBof             d4go_bof
d4goData            d4go_data
d4goEof             d4go_eof
d4index
d4lock
d4lockAdd
d4lockAddAll
d4lockAddAppend
d4lockAddFile
d4lockAll           d4lock_all
d4lockAppend        d4lock_append
d4lockFile          d4lock_file		$fh->lock('FILE')
d4lockIndex         d4lock_index
d4lockTest          d4lock_test
d4lockTestAppend    d4lock_test_append
d4lockTestFile      d4lock_test_file
d4log
d4logStatus
d4memoCompress      d4memo_compress
d4numFields         d4num_fields		$fh->fldcount
d4open              d4open                   $fh = CodeBase::open($file ...)
d4openClone
d4optimize
d4optimizeWrite     d4optimize_write
d4pack              d4pack
d4packData          d4pack_data
d4position          d4position
d4positionSet       d4position_set
d4recall            d4recall
d4recCount          d4reccount
d4recNo             d4recno			$fh->recno
d4record
d4recPosition       d4record_position
d4recWidth          d4record_width		$fh->recsize
d4refresh           d4refresh                $fh->refresh
d4refreshRecord     d4refresh_record
d4reindex           d4reindex
d4remove
d4seek              d4seek                   $fh->seek
d4seekDouble        d4seek_double
d4seekN             d4seek_n
d4seekNext
d4seekNextDouble
d4seekNextN
d4skip              d4skip                   $fh->skip
d4tag               d4tag
d4tagDefault        d4tag_default
d4tagNext           d4tag_next
d4tagPrev           d4tag_prev
d4tagSelect         d4tag_select
d4tagSelected       d4tag_selected
d4tagSync
d4top               d4top
d4unlock            d4unlock
d4write             d4write
d4writeData         d4write_data
d4writeKeys         d4write_keys
d4zapData           d4zap_data

Date Functions

date4formatMdx      date4format_mdx
date4formatMdx2     date4format_mdx2
date4timeNow        date4time_now

dfile4updateHeader  d4update_header
e4exitTest          e4exit_test
error4code          e4code
error4set           e4set

expr4calcDelete     expr4calc_delete
expr4calcLookup     expr4calc_lookup
expr4calcMassage    expr4calc_massage
expr4calcModify     expr4calc_modify
expr4calcNameChange expr4calc_name_change
expr4keyConvert     expr4key_convert
expr4keyLen         expr4key_len

Field Functions

f4assignChar        f4assign_char		$fh->field_set($name, $value)
f4assignDouble      f4assign_double
f4assignField       f4assign_field
f4assignInt         f4assign_int
f4assignLong        f4assign_long
f4assignN           f4assign_n
f4assignPtr         f4assign_ptr
f4memoAssign        f4memo_assign
f4memoAssignN       f4memo_assign_n
f4memoFree          f4memo_free
f4memoLen           f4memo_len
f4memoNcpy          f4memo_ncpy
f4memoPtr           f4memo_ptr
f4memoSetLen        f4memo_set_len
f4memoStr           f4memo_str

file4lenSet         file4len_set
file4lockHook       file4lock_hook
file4optimizeWrite  file4optimize_write
file4readAll        file4read_all
file4readError      file4read_error
file4seqRead        file4seq_read
file4seqReadAll     file4seq_read_all
file4seqReadInit    file4seq_read_init
file4seqWrite       file4seq_write
file4seqWriteFlush  file4seq_write_flush
file4seqWriteInit   file4seq_write_init
file4seqWriteRepeat file4seq_write_repeat

i4tagAdd            i4add_tag
i4tagInfo           i4tag_info


relate4createSlave  relate4create_slave
relate4doAll        relate4do
relate4doOne        relate4do_one
relate4errorAction  relate4error_action
relate4freeRelate   relate4free_relate
relate4matchLen     relate4match_len
relate4querySet     relate4query_set
relate4skipEnable   relate4skip_enable
relate4sortSet      relate4sort_set


t4addCalc           t4add_calc
t4uniqueSet         t4unique_set

tfile4add           t4add(a)->tagFile, b, c
tfile4block         t4block(a)->tagFile
tfile4bottom        t4bottom( (a)->tagFile
tfile4down          t4down( (a)->tagFile
tfile4dskip         t4dskip(a)->tagFile, b
tfile4dump          t4dump(a)->tagFile, b, c
tfile4eof           t4eof(a)->tagFile
tfile4flush         t4flush(a)->tagFile
tfile4freeAll       t4free_all(a)->tagFile
tfile4go            t4go(a)->tagFile, b, c, 0
tfile4isDescending  t4is_descending(a)->tagFile
tfile4key           t4key(a)->tagFile
tfile4position      t4position(a)->tagFile
tfile4positionSet   t4position_set(a)->tagFile, b
tfile4recNo         t4recno(a)->tagFile
tfile4remove        t4remove(a)->tagFile, b, c
tfile4removeCalc    t4remove_calc(a)->tagFile, b
tfile4seek          t4seek(a)->tagFile, b, c
tfile4skip          t4skip(a)->tagFile, b
tfile4top           t4top(a)->tagFile
tfile4up            t4up(a)->tagFile
tfile4upToRoot      t4up_to_root(a)->tagFile

Unsupported functions

Many lower level functions are not directly accessible from CodeBase.pm. These include:

  • conversion functions (c4xxx)

  • linked list functions (l4xxx)

  • memory functions (m4xxx)

  • sort functions (sort4xxx)

  • utility functions (u4xxx)

COPYRIGHT AND TRADEMARKS

The CodeBase module is Copyright (C) 1996-1999, Andrew Ford and Ford & Mason Ltd. All rights reserved. The CodeBase library is copyright Sequiter Software, Inc.

CodeBase is a trademark of Sequiter Software, Inc.

AUTHOR

Andrew Ford (andrew@icarus.demon.co.uk)

SEE ALSO

The Perl reference manual, especially the following sections: perlmod (modules), perldata (data types), perlobj (objects), perlref (references and nested data structures), perldsc (data structures cookbook), perllol (manipulating lists of lists).

The second edition of Programming Perl by Larry Wall and Randal L. Schwarz (O'Reilly and Associates) covers Perl 5.

The CodeBase Reference Guide and the CodeBase User Guide, both from Sequiter Software Inc. cover the underlying C library.