NAME

MPE::IMAGE - Access MPEs TurboIMAGE/XL databases from within Perl

SYNOPSIS

use MPE::IMAGE ':all';

my $db = DbOpen('Dbase.Group.Account','Password',5);
die "DbOpen Error: $DbError" unless $DbStatus[0] == 0;

my %record = DbGet($db,2,'dataset','items');
DbExplain unless $DbStatus[0] == 0;

$db->DbClose(1);
DbExplain unless $DbStatus[0] == 0;

DESCRIPTION

MPE::IMAGE is designed to make access to TurboIMAGE/XL databases fairly comfortable to the Perl programmer. Please note that the calls differ in certain ways from the native intrinsic calls. In specific:

  • Anywhere a "number of elements" was given, it is no longer necessary. Perl knows how many elements are in an array and passes that information to the appropriate intrinsic. An example of this is in passing an item-number list to DbGet.

  • The status array is a globally defined perl array and so does not get passed to any of the routines.

  • The data returned from DbGet and passed to DbPut and DbUpdate can be either a single scalar value containing the entire buffer exactly as it is gotten or put, or a hash mapping item names to their values.

  • MPE::IMAGE will handle all the translation to and from the various IMAGE datatypes transparently.

  • DbGet, DbPut and DbUpdate can each take a schema hash, allowing fields to be redefined.

  • Dataset and item names can be given in any case. They will be passed to the intrinsics uppercase.

The following are provided by MPE::IMAGE. Note that for each call which expects a database argument, that argument should be a database object as returned by DbOpen.

@DbStatus

The array @DbStatus contains the status values from the most recent intrinsic call.

$DbError

DBERROR is implemented as a readonly variable called $DbError. When used in a string context, $DbError gives the text returned by a call to DBERROR.

When used in a numeric context, it contains the same value as $DbStatus[0]. However, it is somewhat more expensive to use than $DbStatus[0] as using it includes the overhead of using a tied variable and, possibly, a call to DBERROR.

In any of the following usages, the overhead should be negligible

die "DbOpen Error: $DbError" unless $DbStatus[0] == 0;
die "DbOpen Error: $DbError" if $DbError;
dbfail($DbError) if $DbError != 0 and $DbError != 15;

I would be much less likely to use it in this fashion:

while ($DbError == 0) {
  %data = DbGet($db,5,'dataset');
  . . . 
}

because it makes a "method" call on every iteration and in the final pass, when the status comes up 15, it performs a DBERROR call to get an explanation for an expected condition, both problems which are avoided by using $DbStatus[0] instead:

while ($DbStatus[0] == 0) {
  %data = DbGet($db,5,'dataset');
  . . . 
}

DbBegin

DbBegin(Database,1);
DbBegin(Database,1,text);
$transid = DbBegin(Array of bases,3 or 4);
$transid = DbBegin(Array of bases,3 or 4,text);

Note that the $transid is more than just a number. It is the array, in binary form, containing not only the transaction id but all the base ids as well. Its only intended purpose is for passing to DbEnd.

DbClose

DbClose(Database);
DbClose(Database,mode);
DbClose(Database,mode,dataset);

If mode is omitted, it defaults to 1.

DbControl

DbControl(Database,mode);
$status = DbControl(Database,13,0);
$status = DbControl(Database,13,function,set);
$status = DbControl(Database,13,function,set,flags);
$status = DbControl(Database,14,function);
$status = DbControl(Database,14,7,wildcard);
DbControl(Database,15);
DbControl(Database,15,wildcard);
DbControl(Database,16);

DbDelete

DbDelete(Database,Dataset);

DbEnd

DbEnd(Database,1 or 2);
DbEnd(Database,1 or 2,text);
DbEnd(Array of bases,3 or 4);
DbEnd(Array of bases,3 or 4,text);
DbEnd($transid,3 or 4);
DbEnd($transid,3 or 4,text);

DbExplain

DbExplain;

DbFind

DbFind(Database,dataset,argument);  # Assumed find mode 1 on key item
DbFind(Database,dataset,item,argument);  # Assumed mode 1
DbFind(Database,dataset,mode,item,argument);
DbFind(Database,dataset,argument,type);  # Assumed find mode 1 on key item
DbFind(Database,dataset,item,argument,type);  # Assumed mode 1
DbFind(Database,dataset,mode,item,argument,type);

type is a string containing an IMAGE type (such as "2X10") and is necessary only when searching on a TPI index (for which MPE::IMAGE cannot look up the type).

DbGet

DbGet(Database,mode,dataset);
DbGet(Database,mode,dataset,list);
DbGet(Database,mode,dataset,undef,undef,schema);
DbGet(Database,mode,dataset,list,undef,schema);

If mode is 4, 7 or 8:

DbGet(Database,mode,dataset,argument);
DbGet(Database,mode,dataset,list,argument);
DbGet(Database,mode,dataset,undef,argument,schema);
DbGet(Database,mode,dataset,list,argument,schema);

list can be either an array of or a comma-separated list of item names or numbers (or a mixture of both). It can also be "0", "*" or "@" and can be semicolon/space-terminated or not as preferred. If list is omitted, it is assumed to be "*;" if the dataset has previously be used and "@;" if not.

schema is the description of the fields and must describe a space of exactly the same size as the fields in list. There will be a helper function to allow a schema to be checked prior to use and this is highly recommended. If the schema is omitted, a schema derived from the IMAGE item descriptions is used instead. See the section on schemata for more information.

When used in scalar context, DbGet returns the retrieved values as a single block. Otherwise it returns a hash where the keys are the item names (or the fields described in the schema) and the values are the values of those items/fields.

DbInfo

Since the return values from DbInfo must be parsed, and since the necessary buffer size varies widely depending on the mode, only the modes listed in the August 1997 (sixth) edition of the Image manual are supported (third-party indexing modes are not currently supported).

$item_num = DbInfo(Database,101,item name or number);

%item_info = DbInfo(Database,102,item name or number);

%item_info will have elements with the following keys: "name", "type", "length", "count".

@item_nums = DbInfo(Database,103);

@item_nums will contain the item numbers (positive and negative). As with other modes which return arrays, the first element is *not* the number of items. Rather, the number of items is reflected in the size of the array.

@item_nums = DbInfo(Database,104,set name or number);

@btree_info = DbInfo(Database,113);

@btree_info will be a six-element array, the 2nd and 6th elements of which contain the respective wild-card characters (see Image documentation).

$set_num = DbInfo(Database,201,set name or number);

%set_info = DbInfo(Database,202,set name or number);

%set_info will have elements with the following keys: "name", "type", "length", "block fact", "entries", "capacity".

@set_nums = DbInfo(Database,203);

@set_nums = DbInfo(Database,204,item name or number);

%set_info = DbInfo(Database,205,set name or number);

%set_info will have elements with the following keys: "name", "type", "length", "block fact", "entries", "capacity", "hwm", "max cap", "init cap", "increment", "inc percent", "dynamic cap".

$num_chunks = DbInfo(Database,206,set name or number);

@chunk_sizes = DbInfo(Database,207,set name or number);

@set_info = DbInfo(Database,208,set name or number);

@set_info will be a seven-element array.

@btree_info = DbInfo(Database,209,set name or number);

@btree_info will be a two-element array.

@path_array = DbInfo(Database,301,set name or number);

@path_array will be an n-element array, where n is the number of paths for the specified dataset. Each element will be a reference to a hash containing elements with the following keys: "set", "search", and "sort". To report which sets are connected by paths to MYDETAIL, you could do something like this:

my @path_array = DbInfo($db,301,'MYDETAIL');
foreach (@path_array) {
  print $_->{'set'},"\n";
}
# end of example

@key_array = DbInfo(Database,302,set name or number);

@key_array will be a two-element array.

%log_info = DbInfo(Database,401);

%log_info will have elements with the following keys: "logid", "base log flag", "user log flag", "trans flag", "user trans num".

%ILR_info = DbInfo(Database,402);

%ILR_info will have elements with the following keys: "ILR log flag", "ILR date", "ILR time".

%log_info = DbInfo(Database,403);

%log_info will have elements with the following keys: "logid", "base log flag", "user log flag", "trans flag", "user trans num", "log set size", "log set type", "base attached", "dynamic trans", "log set name".

%log_info = DbInfo(Database,404);

%log_info will have elements with the following keys: "base log flag", "user log flag", "rollback flag", "ILR log flag", "mustrecover", "base remote", "trans flag", "logid", "log index", "trans id", "trans bases", "base ids". "base ids" will be a reference to an array containing the ids of the bases being used in a multiple-base transaction.

%db_info = DbInfo(Database,406);

%db_info will have elements with the following keys: "name", "mode", "version"

$subsys_access = DbInfo(Database,501);

@ci_update = DbInfo(Database,502);

@ci_update will be a two-element array.

$language_id = DbInfo(Database,901);

DbLock

DbLock(Database,1 or 2);
DbLock(Database,3 or 4,Dataset);
DbLock(Database,5 or 6,Desc1,Desc2,...);

The Descriptors are either hashes or arrays. If they are hashes, they must contain a 'set' key and may optionally contain a 'cond' key. The value for the 'set' key should be the dataset, either numeric or alphabetic. The condition should be given as item, relop and value value in a single string. For example, 'ID=12345' would be a valid condition. If the descriptor is an array, it should contain the dataset in slot 0 and the conditional, if any, in slot 1.

DbMemo

DbMemo(Database);
DbMemo(Database,text);

DbOpen

$db = DbOpen(BaseName,Password,Mode);

DbOpen returns a database object which can be passed to the other calls.

DbPut

DbPut(Database,Dataset,Data);
DbPut(Database,Dataset,List,Data);

Data may either be a hash or a scalar. If it is a hash, the keys of the hash will be used to construct the list. If it is a scalar and no list is specified, the current list will be used.

DbUnlock

DbUnlock(Database);

DbUpdate

DbUpdate(Database,Dataset,Data);
DbUpdate(Database,Dataset,List,Data);

Data may either be a hash or a scalar. If it is a hash, the keys of the hash will be used to construct the list. If it is a scalar and no list is specified, the current list will be used.

DbXBegin

DbXBegin(Database,1);
DbXBegin(Database,1,text);
$transid = DbXBegin(Array of bases,3);
$transid = DbXBegin(Array of bases,3,text);

Note that the $transid is more than just a number. It is the array, in binary form, containing not only the transaction id but all the base ids as well. Its only intended purpose is for passing to DbXEnd or DbXUndo.

DbXEnd

DbXEnd(Database,1 or 2);
DbXEnd(Database,1 or 2,text);
DbXEnd($transid,3);
DbXEnd($transid,3,text);

DbXUndo

DbXUndo(Database,1);
DbXUndo(Database,1,text);
DbXUndo($transid,3);
DbXUndo($transid,3,text);

HELPER FUNCTIONS

MPE::IMAGE also provides a set of helper functions

  • dset_info(Database,Dataset Num)

  • dset_name(Database,Dataset)

  • dset_num(Database,Dataset)

  • item_info(Database,Item Num)

  • item_name(Database,Item)

  • item_num(Database,Item)

These functions return information about datasets or items either by making the necessary DbInfo calls or from cache, so they can be considerably faster that making a DbInfo call. dset_info returns all of the mode 205 information except number of entries, capacity and high-water mark--those things which cannot be safely cached. item_info returns the mode 102 information. The *_name and *_num calls can take either a dataset/item name or number. That way, one can use, for example, item_num passing it whatever item identification one currently has and receive back an item number.

SCHEMAS

Yet to be written. Note that schemas do NOT yet work for DbPut or DbUpdate, only DbGet (and in a small way for DbFind).

NOTES

  • ONLY those calls/modes which are in the test suite are guaranteed to be tested. There are some things, such as Priv Mode DbControl calls and things relating to B-Trees and Jumbo sets which I couldn't very well test.

  • MPE::IMAGE can handle packed-decimal fields of any length, but as a P28, for example, can hold a larger number than a 64-bit integer, P fields are always translated into strings. If the number is within range, Perl will translate it into binary format when necessary.

  • IMAGE allows the definition of I, J and K types greater than 64 bits. MPE::IMAGE, however, gets very confused by such things.

AUTHOR

Ted Ashton, ashted@southern.edu

SEE ALSO

perl(1).