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).