Provided by: libdbix-recordset-perl_0.26-4_all bug

NAME

       DBIx::Recordset - Perl extension for DBI recordsets

SYNOPSIS

        use DBIx::Recordset;

        # Setup a new object and select some recods...
        *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:Oracle:....',
                                           '!Table'      => 'users',
                                           '$where'      => 'name = ? and age > ?',
                                           '$values'     => ['richter', 25] }) ;

        # Get the values of field foo ...
        print "First Records value of foo is $set[0]{foo}\n" ;
        print "Second Records value of foo is $set[1]{foo}\n" ;
        # Get the value of the field age of the current record ...
        print "Age is $set{age}\n" ;

        # Do another select with the already created object...
        $set -> Search ({name => 'bar'}) ;

        # Show the result...
        print "All users with name bar:\n" ;
        while ($rec = $set -> Next)
           {
           print $rec -> {age} ;
           }

        # Setup another object and insert a new record
        *set2 = DBIx::Recordset -> Insert ({'!DataSource' => 'dbi:Oracle:....',
                                            '!Table'      => 'users',
                                            'name'        => 'foo',
                                            'age'         => 25 }) ;

        # Update this record (change age from 25 to 99)...
        $set -> Update ({age => 99}, {name => 'foo'}) ;

DESCRIPTION

       DBIx::Recordset is a perl module for abstraction and simplification of database access.

       The goal is to make standard database access (select/insert/update/delete) easier to
       handle and independend of the underlying DBMS. Special attention is made on web
       applications to make it possible to handle the state-less access and to process the posted
       data of formfields, but DBIx::Recordset is not limited to web applications.

       DBIx::Recordset uses the DBI API to access the database, so it should work with every
       database for which a DBD driver is available (see also DBIx::Compat).

       Most public functions take a hash reference as parameter, which makes it simple to supply
       various different arguments to the same function. The parameter hash can also be taken
       from a hash containing posted formfields like those available with CGI.pm, mod_perl,
       HTML::Embperl and others.

       Before using a recordset it is necessary to setup an object. Of course the setup step can
       be made with the same function call as the first database access, but it can also be
       handled separately.

       Most functions which set up an object return a typglob. A typglob in Perl is an object
       which holds pointers to all datatypes with the same name. Therefore a typglob must always
       have a name and can't be declared with my. You can only use it as global variable or
       declare it with local. The trick for using a typglob is that setup functions can return a
       reference to an object, an array and a hash at the same time.

       The object is used to access the object's methods, the array is used to access the records
       currently selected in the recordset and the hash is used to access the current record.

       If you don't like the idea of using typglobs you can also set up the object, array and
       hash separately, or just set the ones you need.

ARGUMENTS

       Since most methods take a hash reference as argument, here is a description of the valid
       arguments first.

   Setup Parameters
       All parameters starting with an '!' are only recognized at setup time.  If you specify
       them in later function calls they will be ignored.  You can also preset these parameters
       with the TableAttr method of DBIx::Database.  This allows you to presetup most parameters
       for the whole database and they will be use every time you create a new DBIx::Recordset
       object, without specifying it every time.

       !DataSource
           Specifies the database to which to connect. This information can be given in the
           following ways:

           Driver/DB/Host.
               Same as the first parameter to the DBI connect function.

           DBIx::Recordset object
               Takes the same database handle as the given DBIx::Recordset object.

           DBIx::Database object
               Takes Driver/DB/Host from the given database object. See DBIx::Database for
               details about DBIx::Database object. When using more then one Recordset object,
               this is the most efficient method.

           DBIx::Datasbase object name
               Takes Driver/DB/Host from the database object which is saved under the given name
               ($saveas parameter to DBIx::Database -> new)

           an DBI database handle
               Uses given database handle.

       !Table
           Tablename. Multiple tables are comma-separated.

       !Username
           Username. Same as the second parameter to the DBI connect function.

       !Password
           Password. Same as the third parameter to the DBI connect function.

       !DBIAttr
           Reference to a hash which holds the attributes for the DBI connect function. See
           perldoc DBI for a detailed description.

       !Fields
           Fields which should be returned by a query. If you have specified multiple tables the
           fieldnames should be unique. If the names are not unique you must specify them along
           with the tablename (e.g. tab1.field).

           NOTE 1: Fieldnames specified with !Fields can't be overridden. If you plan to use
           other fields with this object later, use $Fields instead.

           NOTE 2: The keys for the returned hash normally don't have a table part.  Only the
           fieldname part forms the key. (See !LongNames for an exception.)

           NOTE 3: Because the query result is returned in a hash, there can only be one out of
           multiple fields with the same name fetched at once.  If you specify multiple fields
           with the same name, only one is returned from a query. Which one this actually is
           depends on the DBD driver.  (See !LongNames for an exception.)

           NOTE 4: Some databases (e.g. mSQL) require you to always qualify a fieldname with a
           tablename if more than one table is accessed in one query.

       !TableFilter
           The TableFilter parameter specifies which tables should be honoured when
           DBIx::Recordset searches for links between tables (see below). When given as parameter
           to DBIx::Database it filters for which tables DBIx::Database retrieves metadata. Only
           thoses tables are used which starts with prefix given by "!TableFilter". Also the
           DBIx::Recordset link detection tries to use this value as a prefix of table names, so
           you can leave out this prefix when you write a fieldname that should be detected as a
           link to another table.

       !LongNames
           When set to 1, the keys of the hash returned for each record not only consist of the
           fieldnames, but are built in the form table.field.

       !Order
           Fields which should be used for ordering any query. If you have specified multiple
           tables the fieldnames should be unique. If the names are not unique you must specify
           them among with the tablename (e.g. tab1.field).

           NOTE 1: Fieldnames specified with !Order can't be overridden. If you plan to use other
           fields with this object later, use $order instead.

       !TabRelation
           Condition which describes the relation between the given tables (e.g. tab1.id =
           tab2.id) (See also !TabJoin.)

             Example

             '!Table'       => 'tab1, tab2',
             '!TabRelation' => 'tab1.id=tab2.id',
             'name'         => 'foo'

             This will generate the following SQL statement:

             SELECT * FROM tab1, tab2 WHERE name = 'foo' and tab1.id=tab2.id ;

       !TabJoin
           !TabJoin allows you to specify an INNER/RIGHT/LEFT JOIN which is used in a SELECT
           statement. (See also !TabRelation.)

             Example

             '!Table'   => 'tab1, tab2',
             '!TabJoin' => 'tab1 LEFT JOIN tab2 ON (tab1.id=tab2.id)',
             'name'     => 'foo'

             This will generate the following SQL statement:

             SELECT * FROM tab1 LEFT JOIN tab2 ON  (tab1.id=tab2.id) WHERE name =
           'foo' ;

       !PrimKey
           Name of the primary key. When this key appears in a WHERE parameter list (see below),
           DBIx::Recordset will ignore all other keys in the list, speeding up WHERE expression
           preparation and execution. Note that this key does NOT have to correspond to a field
           tagged as PRIMARY KEY in a CREATE TABLE statement.

       !Serial
           Name of the primary key. In contrast to "!PrimKey" this field is treated as an
           autoincrement field. If the database does not support autoincrement fields, but
           sequences the field is set to the next value of a sequence (see "!Sequence" and
           "!SeqClass") upon each insert. If a "!SeqClass" is given the values are always
           retrived from the sequence class regardless if the DBMS supports autoincrement or not.
           The value from this field from the last insert could be retrieved by the function
           "LastSerial".

       !Sequence
           Name of the sequence to use for this table when inserting a new record and "!Serial"
           is defind. Defaults to <tablename>_seq.

       !SeqClass
           Name and Parameter for a class that can generate unique sequence values. This is a
           string that holds comma separated values. The first value is the class name and the
           following parameters are given to the new constructor. See also
           DBIx::Recordset::FileSeq and DBIx::Recordset::DBSeq.

           Example:  '!SeqClass' => 'DBIx::Recordset::FileSeq, /tmp/seq'

       !WriteMode
           !WriteMode specifies which write operations to the database are allowed and which are
           disabled. You may want to set !WriteMode to zero if you only need to query data, to
           avoid accidentally changing the content of the database.

           NOTE: The !WriteMode only works for the DBIx::Recordset methods. If you disable
           !WriteMode, it is still possible to use do to send normal SQL statements to the
           database engine to write/delete any data.

           !WriteMode consists of some flags, which may be added together:

           DBIx::Recordset::wmNONE (0)
               Allow no write access to the table(s)

           DBIx::Recordset::wmINSERT (1)
               Allow INSERT

           DBIx::Recordset::wmUPDATE (2)
               Allow UPDATE

           DBIx::Recordset::wmDELETE (4)
               Allow DELETE

           DBIx::Recordset::wmCLEAR (8)
               To allow DELETE for the whole table, wmDELETE must be also specified. This is
               necessary for assigning a hash to a hash which is tied to a table. (Perl will
               first erase the whole table, then insert the new data.)

           DBIx::Recordset::wmALL (15)
               Allow every access to the table(s)

           Default is wmINSERT + wmUPDATE + wmDELETE

       !StoreAll
           If present, this will cause DBIx::Recordset to store all rows which will be fetched
           between consecutive accesses, so it's possible to access data in a random order. (e.g.
           row 5, 2, 7, 1 etc.) If not specified, rows will only be fetched into memory if
           requested, which means that you will have to access rows in ascending order.  (e.g.
           1,2,3 if you try 3,2,4 you will get an undef for row 2 while 3 and 4 is ok) see also
           DATA ACCESS below.

       !HashAsRowKey
           By default, the hash returned by the setup function is tied to the current record. You
           can use it to access the fields of the current record. If you set this parameter to
           true, the hash will by tied to the whole database. This means that the key of the hash
           will be used as the primary key in the table to select one row. (This parameter only
           has an effect on functions which return a typglob.)

       !IgnoreEmpty
           This parameter defines how empty and undefined values are handled.  The values 1 and 2
           may be helpful when using DBIx::Recordset inside a CGI script, because browsers send
           empty formfields as empty strings.

           0 (default)
               An undefined value is treated as SQL NULL: an empty string remains an empty
               string.

           1   All fields with an undefined value are ignored when building the WHERE expression.

           2   All fields with an undefined value or an empty string are ignored when building
               the WHERE expression.

           NOTE: The default for versions before 0.18 was 2.

       !Filter
           Filters can be used to pre/post-process the data which is read from/written to the
           database.  The !Filter parameter takes a hash reference which contains the filter
           functions. If the key is numeric, it is treated as a type value and the filter is
           applied to all fields of that type. If the key if alphanumeric, the filter is applied
           to the named field.  Every filter description consists of an array with at least two
           elements.  The first element must contain the input function, and the second element
           must contain the output function. Either may be undef, if only one of them are
           necessary. The data is passed to the input function before it is written to the
           database. The input function must return the value in the correct format for the
           database. The output function is applied to data read from the database before it is
           returned to the user.

            Example:

                '!Filter'   =>
                   {
                   DBI::SQL_DATE     =>
                       [
                           sub { shift =~ /(\d\d)\.(\d\d)\.(\d\d)/ ; "19$3$2$1"},
                           sub { shift =~ /\d\d(\d\d)(\d\d)(\d\d)/ ; "$3.$2.$1"}
                       ],

                   'datefield' =>
                       [
                           sub { shift =~ /(\d\d)\.(\d\d)\.(\d\d)/ ; "19$3$2$1"},
                           sub { shift =~ /\d\d(\d\d)(\d\d)(\d\d)/ ; "$3.$2.$1"}
                       ],

                   }

           Both filters convert a date in the format dd.mm.yy to the database format 19yymmdd and
           vice versa. The first one does this for all fields of the type SQL_DATE, the second
           one does this for the fields with the name datefield.

           The !Filter parameter can also be passed to the function TableAttr of the
           DBIx::Database object. In this case it applies to all DBIx::Recordset objects which
           use these tables.

           A third parameter can be optionally specified. It could be set to
           "DBIx::Recordset::rqINSERT", "DBIx::Recordset::rqUPDATE", or the sum of both. If set,
           the InputFunction (which is called during UPDATE or INSERT) is always called for this
           field in updates and/or inserts depending on the value.  If there is no data specified
           for this field as an argument to a function which causes an UPDATE/INSERT, the
           InputFunction is called with an argument of undef.

           During UPDATE and INSERT the input function gets either the string 'insert' or
           'update' passed as second parameter.

       !LinkName
           This allows you to get a clear text description of a linked table, instead of (or in
           addition to) the !LinkField. For example, if you have a record with all your bills,
           and each record contains a customer number, setting !LinkName DBIx::Recordset can
           automatically retrieve the name of the customer instead of (or in addition to) the
           bill record itself.

           1 select additional fields
               This will additionally select all fields given in !NameField of the Link or the
               table attributes (see TableAttr).

           2 build name in uppercase of !MainField
               This takes the values of !NameField of the Link or the table attributes (see
               TableAttr) and joins the content of these fields together into a new field, which
               has the same name as the !MainField, but in uppercase.

           2 replace !MainField with the contents of !NameField
               Same as 2, but the !MainField is replaced with "name" of the linked record.

           See also !Links and WORKING WITH MULTIPLE TABLES below

       !Links
           This parameter can be used to link multiple tables together. It takes a reference to a
           hash, which has - as keys, names for a special "linkfield" and - as value, a parameter
           hash. The parameter hash can contain all the Setup parameters. The setup parameters
           are taken to construct a new recordset object to access the linked table. If
           !DataSource is omitted (as it normally should be), the same DataSource (and database
           handle), as the main object is taken. There are special parameters which can only
           occur in a link definition (see next paragraph). For a detailed description of how
           links are handled, see WORKING WITH MULTIPLE TABLES below.

   Link Parameters
       !MainField
           The !MailField parameter holds a fieldname which is used to retrieve a key value for
           the search in the linked table from the main table.  If omitted, it is set to the same
           value as !LinkedField.

       !LinkedField
           The fieldname which holds the key value in the linked table.  If omitted, it is set to
           the same value as !MainField.

       !NameField
           This specifies the field or fields which will be used as a "name" for the destination
           table.  It may be a string or a reference to an array of strings.  For example, if you
           link to an address table, you may specify the field "nickname" as the name field for
           that table, or you may use ['name', 'street', 'city'].

           Look at !LinkName for more information.

       !DoOnConnect
           You can give an SQL Statement (or an array reference of SQL statements), that will be
           executed every time, just after an connect to the db. As third possibilty you can give
           an hash reference. After every successful connect, DBIx::Recordset excutes the
           statements, in the element which corresponds to the name of the driver. '*' is
           executed for all drivers.

       !Default
           Specifies default values for new rows that are inserted via hash or array access. The
           Insert method ignores this parameter.

       !TieRow
           Setting this parameter to zero will cause DBIx::Recordset to not tie the returned rows
           to an DBIx::Recordset::Row object and instead returns an simple hash. The benefit of
           this is that it will speed up things, but you aren't able to write to such an row, nor
           can you use the link feature with such a row.

       !Debug
           Set the debug level. See DEBUGGING.

       !PreFetch
           Only for tieing a hash! Gives an where expression (either as string or as hashref)
           that is used to prefetch records from that database. All following accesses to the
           tied hash only access this prefetched data and don't execute any database queries. See
           "!Expires" how to force a refetch.  Giving a '*' as value to "!PreFetch" fetches the
           whole table into memory.

            The following example prefetches all record with id < 7:

            tie %dbhash, 'DBIx::Recordset::Hash', {'!DataSource'   =>  $DSN,
                                                   '!Username'     =>  $User,
                                                   '!Password'     =>  $Password,
                                                   '!Table'        =>  'foo',
                                                   '!PreFetch'     =>  {
                                                                        '*id' => '<',
                                                                        'id' => 7
                                                                       },
                                                   '!PrimKey'      =>  'id'} ;

            The following example prefetches all records:

            tie %dbhash, 'DBIx::Recordset::Hash', {'!DataSource'   =>  $DSN,
                                                   '!Username'     =>  $User,
                                                   '!Password'     =>  $Password,
                                                   '!Table'        =>  'bar',
                                                   '!PreFetch'     =>  '*',
                                                   '!PrimKey'      =>  'id'} ;

       !Expires
           Only for tieing a hash! If the values is numeric, the prefetched data will be
           refetched is it is older then the given number of seconds. If the values is a CODEREF
           the function is called and the data is refetched is the function returns true.

       !MergeFunc
           Only for tieing a hash! Gives an reference to an function that is called when more
           then one record for a given hash key is found to merge the records into one. The
           function receives a reference to both records a arguments. If more the two records are
           found, the function is called again for each following record, which is already merged
           data as first parameter.

            The following example sets up a hash, that, when more then one record with the same id is
            found, the field C<sum> is added and the first record is returned, where the C<sum> field
            contains the sum of B<all> found records:

            tie %dbhash, 'DBIx::Recordset::Hash', {'!DataSource'   =>  $DSN,
                                                   '!Username'     =>  $User,
                                                   '!Password'     =>  $Password,
                                                   '!Table'        =>  'bar',
                                                   '!MergeFunc'    =>  sub { my ($a, $b) = @_ ; $a->{sum} += $b->{sum} ; },
                                                   '!PrimKey'      =>  'id'} ;

   Where Parameters
       The following parameters are used to build an SQL WHERE expression

       $where
           Give an SQL WHERE expression literaly. If $where is specified, all other where
           parameters described below are ignored. The only expection is $values which can be
           used to give the values to bind to the placeholders in $where

       $values
           Values which should be bound to the placeholders given in $where.

            Example:

            *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:Oracle:....',
                                               '!Table'      => 'users',
                                               '$where'      => 'name = ? and age > ?',
                                               '$values'     => ['richter', 25] }) ;

           NOTE: Filters defined with "!Filter" are not applied to these values, because
           DBIx::Recordset has no chance to know with values belongs to which field.

       {fieldname}
           Value for field. The value will be quoted automatically, if necessary.  The value can
           also be an array ref in which case the values are put together with the operator
           passed via $valueconj (default: or)

             Example:

             'name' => [ 'mouse', 'cat'] will expand to name='mouse' or name='cat'

       '{fieldname}
           Value for field. The value will always be quoted. This is only necessary if
           DBIx::Recordset cannot determine the correct type for a field.

       #{fieldname}
           Value for field. The value will never be quoted, but will converted a to number.  This
           is only necessary if DBIx::Recordset cannot determine the correct type for a field.

       \{fieldname}
           Value for field. The value will not be converted in any way, i.e. you have to quote it
           before supplying it to DBIx::Recordset if necessary.

       +{fieldname}|{fieldname}..
           Values for multiple fields. The value must be in one/all fields depending on $compconj
            Example:
            '+name|text' => 'abc' will expand to name='abc' or text='abc'

       $compconj
           'or' or 'and' (default is 'or'). Specifies the conjunction between multiple fields.
           (see above)

       $valuesplit
           Regular expression for splitting a field value in multiple values (default is '\t')
           The conjunction for multiple values could be specified with $valueconj. By default,
           only one of the values must match the field.

            Example:
            'name' => "mouse\tcat" will expand to name='mouse' or name='cat'

            NOTE: The above example can also be written as 'name' => [ 'mouse', 'cat']

       $valueconj
           'or' or 'and' (default is 'or'). Specifies the conjunction for multiple values.

       $conj
           'or' or 'and' (default is 'and') conjunction between fields

       $operator
           Default operator if not otherwise specified for a field. (default is '=')

       *{fieldname}
           Operator for the named field

            Example:
            'value' => 9, '*value' => '>' expand to value > 9

           Could also be an array ref, so you can pass different operators for the values. This
           is mainly handy when you need to select a range

             Example:

               $set -> Search  ({id          => [5,    7   ],
                                '*id'        => ['>=', '<='],
                                '$valueconj' => 'and'})  ;

             This will expanded to "id >= 5 and id <= 7"

           NOTE: To get a range you need to specify the $valueconj parameter as "and" because it
           defaults to "or".

       $expr
           $expr can be used to group parts of the where expression for proper priority. To
           specify more the one sub expression, add a numerical index to $expr (e.g. $expr1,
           $expr2)

             Example:

               $set -> Search  ({id          => 5,
                                '$expr'      =>
                                   {
                                   'name'  => 'Richter',
                                   'country' => 'de',
                                   '$conj'   => 'or'
                                   }
                                 }) ;

               This will expand to

                   (name = 'Richter' or country = 'de') and id = 5

   Search parameters
       $start
           First row to fetch. The row specified here will appear as index 0 in the data array.

       $max
           Maximum number of rows to fetch. Every attempt to fetch more rows than specified here
           will return undef, even if the select returns more rows.

       $next
           Add the number supplied with $max to $start. This is intended to implement a next
           button.

       $prev
           Subtract the number supplied with $max from $start. This is intended to implement a
           previous button.

       $order
           Fieldname(s) for ordering (ORDER BY) (must be comma-separated, could also contain
           USING)

       $group
           Fieldname(s) for grouping (GROUP BY) (must be comma-separated, could also contain
           HAVING).

       $append
           String which is appended to the end of a SELECT statement, can contain any data.

       $fields
           Fields which should be returned by a query. If you have specified multiple tables the
           fieldnames should be unique. If the names are not unique you must specify them along
           with the tablename (e.g. tab1.field).

           NOTE 1: If !fields is supplied at setup time, this can not be overridden by $fields.

           NOTE 2: The keys for the returned hash normally don't have a table part.  Only the
           fieldname part forms the key. (See !LongNames for an exception.)

           NOTE 3: Because the query result is returned in a hash, there can only be one out of
           multiple fields  with the same name fetched at once.  If you specify multiple fields
           with same name, only one is returned from a query. Which one this actually is, depends
           on the DBD driver.  (See !LongNames for an exception.)

       $primkey
           Name of primary key. DBIx::Recordset assumes that if specified, this is a unique key
           to the given table(s). DBIx::Recordset can not verify this. You are responsible for
           specifying the right key. If such a primary exists in your table, you should specify
           it here, because it helps DBIx::Recordset optimize the building of WHERE expressions.

           See also !PrimKey

   Execute parameters
       The following parameters specify which action is to be executed:

       =search
           search data

       =update
           update record(s)

       =insert
           insert record

       =delete
           delete record(s)

       =empty
           setup empty object

METHODS

       *set = DBIx::Recordset -> Setup (\%params)
           Setup a new object and connect it to a database and table(s). Collects information
           about the tables which are needed later. Returns a typglob which can be used to access
           the object ($set), an array (@set) and a hash (%set).

           params: setup

       $set = DBIx::Recordset -> SetupObject (\%params)
           Same as above, but setup only the object, do not tie anything (no array, no hash)

           params: setup

       $set = tie @set, 'DBIx::Recordset', $set
       $set = tie @set, 'DBIx::Recordset', \%params
           Ties an array to a recordset object. The result of a query which is executed by the
           returned object can be accessed via the tied array. If the array contents are
           modified, the database is updated accordingly (see Data access below for more
           details). The first form ties the array to an already existing object, the second one
           setup a new object.

           params: setup

       $set = tie %set, 'DBIx::Recordset::Hash', $set
       $set = tie %set, 'DBIx::Recordset::Hash', \%params
           Ties a hash to a recordset object. The hash can be used to access/update/insert single
           rows of a table: the hash key is identical to the primary key value of the table. (see
           Data access below for more details)

           The first form ties the hash to an already existing object, the second one sets up a
           new object.

           params: setup

       $set = tie %set, 'DBIx::Recordset::CurrRow', $set
       $set = tie %set, 'DBIx::Recordset::CurrRow', \%params
           Ties a hash to a recordset object. The hash can be used to access the fields of the
           current record of the recordset object.  (See Data access below for more details.)

           The first form ties the hash to an already existing object, the second one sets up a
           new object.

           params: setup

       *set = DBIx::Recordset -> Select (\%params, $fields, $order)
       $set -> Select (\%params, $fields, $order)
       $set -> Select ($where, $fields, $order)
           Selects records from the recordsets table(s).

           The first syntax setups a new DBIx::Recordset object and does the select.

           The second and third syntax selects from an existing DBIx::Recordset object.

           params: setup (only syntax 1), where  (without $order and $fields)

           where:  (only syntax 3) string for SQL WHERE expression

           fields: comma separated list of fieldnames to select

           order:  comma separated list of fieldnames to sort on

       *set = DBIx::Recordset -> Search (\%params)
       set -> Search (\%params)
           Does a search on the given tables and prepares data to access them via @set or %set.
           The first syntax also sets up a new object.

           params: setup (only syntax 1), where, search

       *set = DBIx::Recordset -> Insert (\%params)
       $set -> Insert (\%params)
           Inserts a new record in the recordset table(s). Params should contain one entry for
           every field for which you want to insert a value.

           Fieldnames may be prefixed with a '\' in which case they are not processed (quoted) in
           any way.

           params: setup (only syntax 1), fields

       *set = DBIx::Recordset -> Update (\%params, $where)
       *set = DBIx::Recordset -> Update (\%params, $where)
       set -> Update (\%params, $where)
       set -> Update (\%params, $where)
           Updates one or more records in the recordset table(s). Parameters should contain one
           entry for every field you want to update. The $where contains the SQL WHERE condition
           as a string or as a reference to a hash. If $where is omitted, the where conditions
           are buily from the parameters. If !PrimKey is given for the table, only that !PrimKey
           is used for the WHERE clause.

           Fieldnames may be prefixed with a '\', in which case they are not processed (quoted)
           in any way.

           params: setup (only syntax 1+2), where (only if $where is omitted), fields

       *set = DBIx::Recordset -> Delete (\%params)
       $set -> Delete (\%params)
           Deletes one or more records from the recordsets table(s).

           params: setup (only syntax 1), where

       *set = DBIx::Recordset -> DeleteWithLinks (\%params)
       $set -> DeleteWithLinks (\%params)
           Deletes one or more records from the recordsets table(s).  Additonal all record of
           links with have the "!OnDelete" set, are either deleted or the correspending field is
           set to undef. What to do is determinated by the constants "odDELETE" and "odCLEAR".
           This is very helpful to guaratee the inetgrity of the database.

           params: setup (only syntax 1), where

       *set = DBIx::Recordset -> Execute (\%params)
       $set -> Execute (\%params)
           Executes one of the above methods, depending on the given arguments.  If multiple
           execute parameters are specified, the priority is
            =search
            =update
            =insert
            =delete
            =empty

           If none of the above parameters are specified, a search is performed.  A search is
           always performed.  On an "=update", the "!PrimKey", if given, is looked upon and used
           for the where part of the SQL statement, while all other parameters are updated.

           params: setup (only syntax 1), execute, where, search, fields

       $set -> do ($statement, $attribs, \%params)
           Same as DBI. Executes a single SQL statement on the open database.

       $set -> Reset ()
           Set the record pointer to the initial state, so the next call to

           "Next" returns the first row.

       $set -> First ()
           Position the record pointer to the first row and returns it.

       $set -> Next ()
           Position the record pointer to the next row and returns it.

       $set -> Prev ()
           Position the record pointer to the previous row and returns it.

       $set -> Curr ()
           Returns the current row.

       $set -> AllNames ()
           Returns a reference to an array of all fieldnames of all tables used by the object.

       $set -> Names ()
           Returns a reference to an array of the fieldnames from the last query.

       $set -> AllTypes ()
           Returns a reference to an array of all fieldtypes of all tables used by the object.

       $set -> Types ()
           Returns a reference to an array of the fieldtypes from the last query.

       $set -> Add ()
       $set -> Add (\%data)
           Adds a new row to a recordset. The first one adds an empty row, the second one will
           assign initial data to it.  The Add method returns an index into the array where the
           new record is located.

             Example:

             # Add an empty record
             $i = $set -> Add () ;
             # Now assign some data
             $set[$i]{id} = 5 ;
             $set[$i]{name} = 'test' ;
             # and here it is written to the database
             # (without Flush it is written, when the record goes out of scope)
             $set -> Flush () ;

           Add will also set the current record to the newly created empty record. So, you can
           assign the data by simply using the current record.

             # Add an empty record
             $set -> Add () ;
             # Now assign some data to the new record
             $set{id} = 5 ;
             $set{name} = 'test' ;

       $set -> MoreRecords ([$ignoremax])
           Returns true if there are more records to fetch from the current recordset. If the
           $ignoremax parameter is specified and is true, MoreRecords ignores the $max parameter
           of the last Search.

           To tell you if there are more records, More actually fetches the next record from the
           database and stores it in memory. It does not, however, change the current record.

       $set -> PrevNextForm ($prevtext, $nexttext, \%fdat)
       $set -> PrevNextForm (\%param, \%fdat)
           Returns a HTML form which contains a previous and a next button and all data from
           %fdat, as hidden fields. When calling the Search method, You must set the $max
           parameter to the number of rows you want to see at once. After the search and the
           retrieval of the rows, you can call PrevNextForm to generate the needed buttons for
           scrolling through the recordset.

           The second for allows you the specifies addtional parameter, which creates first,
           previous, next, last and goto buttons. Example:

            $set -> PrevNextForm ({-first => 'First',  -prev => '<<Back',
                                   -next  => 'Next>>', -last => 'Last',
                                   -goto  => 'Goto #'}, \%fdat)

           The goto button lets you jump to an random record number. If you obmit any of the
           parameters, the corresponding button will not be shown.

       $set -> Flush
           The Flush method flushes all data to the database and therefore makes sure that the db
           is up-to-date. Normally, DBIx::Recordset holds the update in memory until the row is
           destroyed, by either a new Select/Search or by the Recordsetobject itself is
           destroyed. With this method you can make sure that every update is really written to
           the db.

       $set -> Dirty ()
           Returns true if there is at least one dirty row containing unflushed data.

       DBIx::Recordset::Undef ($name)
           Undef takes the name of a typglob and will destroy the array, the hash, and the
           object. All unwritten data is  written to the db.  All db connections are closed and
           all memory is freed.

             Example:
             # this destroys $set, @set and %set
             DBIx::Recordset::Undef ('set') ;

       $set -> Begin
           Starts a transaction. Calls the DBI method begin.

       $set -> Rollback
           Rolls back a transaction. Calls the DBI method rollback and makes sure that all
           internal buffers of DBIx::Recordset are flushed.

       $set -> Commit
           Commits a transaction. Calls the DBI method commit and makes sure that all internal
           buffers of DBIx::Recordset are flushed.

       $set -> DBHdl ()
           Returns the DBI database handle.

       $set -> StHdl ()
           Returns the DBI statement handle of the last select.

       $set -> TableName ()
           Returns the name of the table of the recordset object.

       $set -> TableNameWithOutFilter ()
           Returns the name of the table of the recordset object, but removes the string given
           with !TableFilter, if it is the prefix of the table name.

       $set -> PrimKey ()
           Returns the primary key given in the !PrimKey parameter.

       $set -> TableFilter ()
           Returns the table filter given in the !TableFilter parameter.

       $set -> StartRecordNo ()
           Returns the record number of the record which will be returned for index 0.

       $set -> LastSQLStatement ()
           Returns the last executed SQL Statement.

       $set -> LastSerial ()
           Return the last value of the field defined with !Serial

       $set -> Disconnect ()
           Closes the connection to the database.

       $set -> Link($linkname)
           If $linkname is undef, returns reference to a hash of all links of the object.
           Otherwise, it returns a reference to the link with the given name.

       $set -> Links()
           Returns reference to a hash of all links of the object.

       $set -> Link4Field($fieldname)
           Returns the name of the link for that field, or <undef> if there is no link for that
           field.

       $set -> TableAttr ($key, $value, $table)
           get and/or set an attribute of the table

           $key
               key to set/get

           $value
               if present, set key to this value

           $table
               Optional, let you specify another table, then the one use by the recordset object.

       $set -> Stats ()
           Returns an hash ref with some statistical values.

       $set -> LastError ()
       DBIx::Recordset -> LastError ()
           Returns the last error message, if any. If called in an array context the first
           element receives the last error message and the second the last error code.

DATA ACCESS

       The data which is returned by a Select or a Search can be accessed in two ways:

       1.) Through an array. Each item of the array corresponds to one of the selected records.
       Each array-item is a reference to a hash containing an entry for every field.

       Example:
        $set[1]{id}       access the field 'id' of the second record found
        $set[3]{name}     access the field 'name' of the fourth record found

       The record is fetched from the DBD driver when you access it the first time and is stored
       by DBIx::Recordset for later access. If you don't access the records one after each other,
       the skipped records are not stored and therefore can't be accessed anymore, unless you
       specify the !StoreAll parameter.

       2.) DBIx::Recordset holds a current record which can be accessed directly via a hash. The
       current record is the one you last accessed via the array. After a Select or Search, it is
       reset to the first record. You can change the current record via the methods Next, Prev,
       First, Add.

       Example:
        $set{id}     access the field 'id' of the current record
        $set{name}        access the field 'name' of the current record

       Instead of doing a Select or Search you can directly access one row of a table when you
       have tied a hash to DBIx::Recordset::Hash or have specified the !HashAsRowKey Parameter.
       The hashkey will work as primary key to the table. You must specify the !PrimKey as setup
       parameter.

       Example:
        $set{4}{name}     access the field 'name' of the row with primary key = 4

MODIFYING DATA DIRECTLY

       One way to update/insert data into the database is by using the Update, Insert or Execute
       method of the DBIx::Recordset object. A second way is to directly assign new values to the
       result of a previous Select/Search.

       Example:
         # setup a new object and search all records with name xyz
         *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:db:tab',
       '!PrimKey => 'id',                          '!Table'  => 'tabname',
       'name'    => 'xyz'}) ;

         #now you can update an existing record by assigning new values
         #Note: if possible, specify a PrimKey for update to work faster
         $set[0]{'name'} = 'zyx' ;

         # or insert a new record by setting up an new array row
         $set[9]{'name'} = 'foo' ;
         $set[9]{'id'}   = 10 ;

         # if you don't know the index of a new row you can obtain
         # one by using Add
         my $i = $set -> Add () ;
         $set[$i]{'name'} = 'more foo' ;
         $set[$i]{'id'}   = 11 ;

         # or add an empty record via Add and assign the values to the current
         # record
         $set -> Add () ;
         $set{'name'} = 'more foo' ;
         $set{'id'}   = 11 ;

         # or insert the data directly via Add
         $set -> Add ({'name' => 'even more foo',
                       'id'   => 12}) ;

         # NOTE: up to this point, NO data is actually written to the db!

         # we are done with that object,  Undef will flush all data to the db
         DBIx::Recordset::Undef ('set') ;

       IMPORTANT: The data is not written to the database until you explicitly call flush, or a
       new query is started, or the object is destroyed. This is to keep the actual writes to the
       database to a minimum.

WORKING WITH MULTIPLE TABLES

       DBIx::Recordset has some nice features to make working with multiple tables and their
       relations easier.

   Joins
       First, you can specify more than one table to the !Table parameter. If you do so, you need
       to specify how both tables are related. You do this with !TabRelation parameter. This
       method will access all the specified tables simultanously.

   Join Example:
       If you have the following two tables, where the field street_id is a pointer to the table
       street:

         table name
         name      char (30),
         street_id  integer

         table street
         id        integer,
         street    char (30),
         city      char (30)

       You can perform the following search:

         *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db',
                            '!Table'      => 'name, street',
                            '!TabRelation'=> 'name.street_id = street.id'}) ;

       The result is that you get a set which contains the fields name, street_id, street, city
       and id, where id is always equal to street_id. If there are multiple streets for one name,
       you will get as many records for that name as there are streets present for it. For this
       reason, this approach works best when you have a 1:1 relation.

       It is also possible to specify JOINs. Here's how:

         *set = DBIx::Recordset -> Search ({
                   '!DataSource' => 'dbi:drv:db',
                   '!Table'   => 'name, street',
                   '!TabJoin' => 'name LEFT JOIN street ON (name.street_id=street.id)'}) ;

       The difference between this and the first example is that this version also returns a
       record even if neither table contains a record for the given id. The way it's done depends
       on the JOIN you are given (LEFT/RIGHT/INNER) (see your SQL documentation for details about
       JOINs).

   Links
       If you have 1:n relations between two tables, the following may be a better way to handle
       it:

         *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db',
                            '!Table'      => 'name',
                            '!Links'      => {
                               '-street'  => {
                                   '!Table' => 'street',
                                   '!LinkedField' => 'id',
                                   '!MainField'   => 'street_id'
                                   }
                               }
                           }) ;

       After that query, every record will contain the fields name and street_id.  Additionally,
       there is a pseudofield named -street, which could be used to access another recordset
       object, which is the result of a query where street_id = id. Use

         $set{name} to access the name field
         $set{-street}{street} to access the first street (as long as the
                                           current record of the subobject isn't
                                           modified)

         $set{-street}[0]{street}      first street
         $set{-street}[1]{street}      second street
         $set{-street}[2]{street}      third street

         $set[2]{-street}[1]{street} to access the second street of the
                                           third name

       You can have multiple linked tables in one recordset; you can also nest linked tables or
       link a table to itself.

       NOTE: If you select only some fields and not all, the field which is specified by
       '!MainField' must be also given in the '!Fields' or '$fields' parameter.

       NOTE: See also Automatic detection of links below

   LinkName
       In the LinkName feature you may specify a "name" for every table. A name is one or more
       fields which gives a human readable "key" of that record. For example in the above example
       id is the key of the record, but the human readable form is street.

         *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db',
                            '!Table'      => 'name',
                            '!LinkName'   => 1,
                            '!Links'      => {
                               '-street'  => {
                                   '!Table' => 'street',
                                   '!LinkedField' => 'id',
                                   '!MainField'   => 'street_id',
                                   '!NameField'   => 'street'
                                   }
                               }
                           }) ;

       For every record in the table, this example will return the fields:

         name  street_id  street

       If you have more complex records, you may also specify more than one field in !NameField
       and pass it as an reference to an array e.g. ['street', 'city'].  In this case, the result
       will contain

         name  street_id  street  city

       If you set !LinkName to 2, the result will contain the fields

         name  street_id  STREET_ID

       where STREET_ID contains the values of the street and city fields joined together. If you
       set !LinkName to 3, you will get only

         name  street_id

       where street_id contains the values of the street and city fields joined together.

       NOTE: The !NameField can also be specified as a table attribute with the function
       TableAttr. In this case you don't need to specify it in every link. When a !NameField is
       given in a link description, it overrides the table attribute.

   Automatic detection of links
       DBIx::Recordset and DBIx::Database will try to automatically detect links between tables
       based on the field and table names. For this feature to work, the field which points to
       another table must consist of the table name and the field name of the destination joined
       together with an underscore (as in the above example name.street_id). Then it will
       automatically recognized as a pointer to street.id.

         *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db',
                                            '!Table'      => 'name') ;

       is enough. DBIx::Recordset will automatically add the !Links attribute.  Additionally,
       DBIx::Recordset adds a backlink (which starts with a star ('*')), so for the table street,
       in our above example, there will be a link, named *name, which is a pointer from table
       street to all records in the table name where street.id is equal to name.street_id.

       You may use the !Links attribute to specify links which can not be automatically detected.

       NOTE: To specify more then one link from one table to another table, you may prefix the
       field name with an specifier followed by two underscores. Example:  first__street_id,
       second__street_id.  The link (and backlink) names are named with the prefix, e.g.
       -first__street and the backlink *first__name.

DBIx::Database

       The DBIx::Database object gathers information about a datasource. Its main purpose is to
       create, at startup, an object which retrieves all necessary information from the database.
       This object detects links between tables and stores this information for use by the
       DBIx::Recordset objects. There are additional methods which allow you to add kinds of
       information which cannot be retrieved automatically.

       Example:

         $db = DBIx::Database -> new ({'!DataSource'   =>  $DSN,
                                       '!Username'     =>  $User,
                                       '!Password'     =>  $Password,
                                       '!KeepOpen'     => 1}) ;

          *set = DBIx::Recordset -> Search ({'!DataSource'   =>  $db,
                                             '!Table'        =>  'foo',
                                            })  ;

   new ($data_source, $username, $password, \%attr, $saveas, $keepopen)
       $data_source
           Specifies the database to which to connect.  Driver/DB/Host. Same as the first
           parameter to the DBI connect function.

       $username
           Username (optional)

       $password
           Password (optional)

       \%attr
           Attributes (optional) Same as the attribute parameter to the DBI connect function.

       $saveas
           Name for this DBIx::Database object to save as.  The name can be used in
           DBIx::Database::Get, or as !DataSource parameter in call to the DBIx::Recordset
           object.

           This is intended as mechanism to retrieve the necessary metadata; for example, when
           your web server starts (e.g. in the startup.pl file of mod_perl).  Here you can give
           the database object a name. Later in your mod_perl or Embperl scripts, you can use
           this metadata by specifying this name. This will speed up the setup of DBIx::Recordset
           object without the need to pass a reference to the DBIx::Database object.

       $keepopen
           Normaly the database connection will be closed after the metadata has been retrieved
           from the database. This makes sure you don't get trouble when using the new method in
           a mod_perl startup file. You can keep the connection open to use them in further setup
           calls to DBIx::Recordset objects. When the database is not kept open, you must specify
           the "!Password" parameter each time the recordset has to be reopend.

       $tabfilter
           same as setup parameter !TableFilter

       $doonconnect
           same as setup parameter !DoOnConnect

       $reconnect
           If set, forces DBIx::Database to "undef" any preexisting database handle and call
           connect in any case. This is useful in together with Apache::DBI. While the database
           connection are still kept open by Apache::DBI, Apache::DBI preforms a test if the
           handle is still vaild (which DBIx::Database itself wouldn't).

       You also can specify a hashref which can contain the following parameters:

       !DataSource, !Username, !Password, !DBIAttr, !SaveAs, !KeepOpen, !TableFilter,
       !DoOnConnect, !Reconnect

   $db = DBIx::Database -> DBHdl
       returns the database handle (only if you specify !KeepOpen when calling "new").

   $db = DBIx::Database -> Get ($name)
       $name = The name of the DBIx::Database object you wish to retrieve

       Get a DBIx::Database object which has already been set up based on the name.

   $db -> TableAttr ($table, $key, $value)
       get and/or set an attribute for an specfic table.

       $table
           Name of table(s). You may use '*' instead of the table name to specify a default value
           which applies to all tables for which no other value is specified.

       $key
           key to set/get

       $value
           if present, set key to this value

   $db -> TableLink ($table, $linkname, $value)
       Get and/or set a link description for an table. If no $linkname is given, returns all
       links for that table.

       $table
           Name of table(s)

       $linkname
           Name of link to set/get

       $value
           if present, this must be a reference to a hash with the link decription.  See !Links
           for more information.

   $db -> MetaData ($table, $metadata, $clear)
       Get and/or set the meta data for the given table.

       $table
           Name of table(s)

       $metadata
           If present, this must be a reference to a hash with the new metadata. You should only
           use this if you really know what you are doing.

       $clear
           Clears the metadata for the given table, The next call to DBIx::Database -> new will
           recreate the metadata. Useful if your table has changed (e.g. by ALTER TABLE).

   $db -> AllTables
       This returns a reference to a hash of the keys to all the tables of the datasource.

   $db -> AllNames ($table)
       Returns a reference to an array of all fieldnames for the given table.

   $db -> AllTypes ($table)
       Returns a reference to an array of all fieldtypes for the given table.

       $db -> do ($statement, $attribs, \%params)
           Same as DBI. Executes a single SQL statement on the open database.

   $db -> CreateTables ($dbschema, $schemaname, $user, $setpriv, $alterconstraints)
       The CreateTables method is used to create an modify the schema of your database.  The idea
       is to define the schema as a Perl data structure and give it to this function, it will
       compare the actual schema of the database with the one provided and creates new tables,
       new fields or drop fields as necessary. It also sets the permission on the tables and is
       able to create indices for the tables. It will never drop a whole table!  NOTE: Create
       tables cannot deteminate changes of the datatype of a fields, because DBI is not able to
       provide this information in a standard way.

       $dbschema
           Either the name of a file which contains the schema or a array ref. See below how this
           schema must look like.

       $schemaname
           schemaname (only used for Oracle)

       $user
           User that should be granted access. See "!Grant" parameter.

       $setpriv
           If set to true, access privilegs are revoked and granted again for already existing
           tables.  That is necessary when $user changes.

       $alterconstraints
           If set to true contrains are cleared/set for already existing fields. DBI doesn't
           provide a database independ way to check which contrains already exists.

   Schema definition
       If give as a filename, the file must contain an hash %DBDefault and an array @DBSchema.
       The first gives default and the second is an array of hashs. Every of this hash defines
       one table.

       Example:

         %DBDefault =

           (
           '!Grant' =>
               [
               'select',
               'insert',
               'update',
               'delete',
               ],
           )
            ;

         @DBSchema = (

           {
           '!Table' => 'language',
           '!Fields' =>
               [
               'id'            => 'char (2)',
               'directory'     => 'varchar(40)',
               'name'          => 'varchar(40)',
               'europe'        => 'bool',
               ],
           '!PrimKey' => 'id',
           '!Default' =>
               {
               'europe'    => 1,
               },
           '!Init' =>
               [
               {'id' => 'de', 'directory' => 'html_49', 'name' => 'deutsch'},
               {'id' => 'en', 'directory' => 'html_76', 'name' => 'english'},
               {'id' => 'fr', 'directory' => 'html_31', 'name' => 'french'},
               ],
          '!Index' =>
               [
               'directory' => '',
               ]

           },

         );

       The hash which defines a table can have the following keys:

       !Table
           Gives the table name

       !Fields
           Array with field names and types. There a some types which a translated database
           specifc. You can define more database specific translation in Compat.pm.

           bit boolean

           counter
               If an autoincrementing integer. For databases (like Oracle) that doesn't have such
               a datatype a sequence is generated to provide the autoincrement value and the
               fields will be of type integer.

           tinytext
               variables length text with up to 255 characters

           text
               variables length text

       !PrimKey
           Name of the primary key

       !For
           Can contain the same key as the table definintion, but is only executed for a specifc
           database.

           Example:

               '!For' => {
                   'Oracle' => {
                       '!Constraints' =>
                           {
                           'web_id'           => ['foreign key' => 'REFERENCES web (id)'],

                           'prim__menu_id'    => ['!Name'       => 'web_prim_menu_id',
                                                  'foreign key' => 'REFERENCES menu (id)',
                                                  'not null'    => ''],
                           }
                       },
                   },

       !Contraints
           Used to define constraints. See example under "!For".

           !Name => <name>
           <constraint> => <second part>
       !Init
           Used to initialy populate the table.

       !Default
           Used to set a default value for a field, when the table is created.  This doesn't have
           any affect for further INSERTs/UPDATEs.

       !Grant
           Give the rights that should be grant to $user

       !Index
           Gives the names for the fields for which indices should be created.  If the second
           parameter for an index is not empty, it gives the index name, otherwise a default name
           is used.

   $db -> DropTables ($schemaname, $user)
       Drops all tables. Use with care!

       $schemaname
           schemaname (only used for Oracle)

       $user
           User that should be revoked access. See "!Grant" parameter.

Casesensitive/insensitiv

       In SQL all names (field/tablenames etc.) should be case insensitive. Various DBMS handle
       the case of names differently. For that reason DBIx::Recordset translates all names to
       lower case, ensuring your application will run with any DBMS, regardless of whether names
       are returned in lower/uppercase by the DBMS. Some DBMS are case-sensitive (I know at least
       Sybase, depending on your collate settings). To use such a case-sensitive DBMS, it is best
       to create your database with all names written in lowercase. In a situation where this
       isn't possible, you can set $PreserveCase to 1. In this case DBIx::Recordset will not
       perform any case translation. NOTE: $PreserveCase is still experimental and may change in
       future releases.

FETCHSIZE / $FetchsizeWarn

       Some operations in Perl (i.e. "foreach", assigning arrays) need to know the size of the
       whole array. When Perl needs to know the size of an array it call the method "FETCHSIZE".
       Since not all DBD drivers/DBMS returns the number of selected rows after an SQL "SELECT",
       the only way to really determine the number of selected rows would be to fetch them all
       from the DBMS. Since this could cause a lot of work, it may be very inefficent. Therefore
       DBIx::Recordset by default calls die() when Perl calls FETCHSIZE. If you know your DBD
       drivers returns the correct value in $sth -> "rows" after the execution of an "SELECT",
       you can set $FetchsizeWarn to zero to let "FETCHSIZE" return the value from $sth ->
       "rows". Setting it to 1 will cause DBIx::Recordset to only issue a warning, but perform
       the operation.

       NOTE: Since I don't have enough experience with the behaviour of this feature with
       different DBMS, this is considered experimental.

DEBUGGING

       DBIx::Recordset is able to write a logfile so you can see what's happening inside. There
       are two public variables and the "!Debug" parameter used for this purpose:

       $DBIx::Recordset::Debug or !Debug
           Debuglevel
            0 = off
            1 = log only errors
            2 = show connect, disconnect and SQL Statements
            3 = some more infos
            4 = much infos

           $DBIx::Recordset::Debug sets the default debug level for new objects, "!Debug" can be
           used to set the debuglevel on a per object basis.

       DBIx::Recordset::LOG
           The filehandle used for logging. The default is STDOUT, unless you are running under
           HTML::Embperl, in which case the default is the Embperl logfile.

        Example:

           # open the log file
           open LOG, ">test.log" or die "Cannot open test.log" ;

           # assign filehandle
           *DBIx::Recordset::LOG = \*LOG ;

           # set debugging level
           $DBIx::Recordset::Debug = 2 ;

           # now you can create a new DBIx::Recordset object

SECURITY

       Since one possible application of DBIx::Recordset is its use in a web-server environment,
       some attention should paid to security issues.

       The current version of DBIx::Recordset does not include extended security management, but
       some features can be used to make your database access safer. (More security features will
       come in future releases.)

       First of all, use the security feature of your database. Assign the web server process as
       few rights as possible.

       The greatest security risk is when you feed DBIx::Recordset a hash which contains the
       formfield data posted to the web server. Somebody who knows DBIx::Recordset can post other
       parameters than those you would expect a normal user to post. For this reason, a primary
       issue is to override all parameters which should never be posted by your script.

       Example:
        *set = DBIx::Recordset -> Search ({%fdat,
       ('!DataSource' => "dbi:$Driver:$DB",                                          '!Table' =>
       "$Table")}) ;

       (assuming your posted form data is in %fdat). The above call will make sure that nobody
       from outside can override the values supplied by $Driver, $DB and $Table.

       It is also wise to initialize your objects by supplying parameters which can not be
       changed.

       Somewhere in your script startup (or at server startup time) add a setup call:

        *set = DBIx::Recordset-> Setup ({'!DataSource'  =>  "dbi:$Driver:$DB",
                                                       '!Table'          =>  "$Table",
                                                       '!Fields'         =>  "a, b, c"}) ;

       Later, when you process a request you can write:

        $set -> Search (\%fdat) ;

       This will make sure that only the database specified by $Driver, $DB, the table specified
       by $Table and the Fields a, b, and c can be accessed.

Compatibility with different DBD drivers

       I have put a great deal of effort into making DBIx::Recordset run with various DBD
       drivers.  The problem is that not all necessary information is specified via the DBI
       interface (yet).  So I have made the module DBIx::Compat which gives information about the
       difference between various DBD drivers and their underlying database systems.  Currently,
       there are definitions for:

       DBD::mSQL
       DBD::mysql
       DBD::Pg
       DBD::Solid
       DBD::ODBC
       DBD::CSV
       DBD::Oracle (requires DBD::Oracle 0.60 or higher)
       DBD::Sysbase
       DBD::Informix
       DBD::InterBase

       DBIx::Recordset has been tested with all those DBD drivers (on Linux 2.0.32, except
       DBD::ODBC, which has been tested on Windows '95 using Access 7 and with MS SQL Server).

       If you want to use another DBD driver with DBIx::Recordset, it may be necessary to create
       an entry for that driver.  See perldoc DBIx::Compat for more information.

EXAMPLES

       The following are some examples of how to use DBIx::Recordset. The Examples are from the
       test.pl. The examples show the DBIx::Recordset call first, followed by the generated SQL
       command.

        *set = DBIx::Recordset-> Setup ({'!DataSource'  =>  "dbi:$Driver:$DB",
                                                   '!Table'      =>  "$Table"}) ;

       Setup a DBIx::Recordset for driver $Driver, database $DB to access table $Table.

        $set -> Select () ;

        SELECT * from <table> ;

        $set -> Select ({'id'=>2}) ;
        is the same as
        $set1 -> Select ('id=2') ;

        SELECT * from <table> WHERE id = 2 ;

        $set -> Search({ '$fields' => 'id, balance AS paid - total ' }) ;

        SELECT id, balance AS paid - total FROM <table>

        $set -> Select ({name => "Second Name\tFirst Name"}) ;

        SELECT * from <table> WHERE name = 'Second Name' or name = 'First Name' ;

        $set1 -> Select ({value => "9991 9992\t9993",
                              '$valuesplit' => ' |\t'}) ;

        SELECT * from <table> WHERE value = 9991 or value = 9992 or value = 9993 ;

        $set -> Select ({'+name&value' => "9992"}) ;

        SELECT * from <table> WHERE name = '9992' or value = 9992 ;

        $set -> Select ({'+name&value' => "Second Name\t9991"}) ;

        SELECT * from <table> WHERE (name = 'Second Name' or name = '9991) or
                                   (value = 0 or value = 9991) ;

        $set -> Search ({id => 1,name => 'First Name',addon => 'Is'}) ;

        SELECT * from <table> WHERE id = 1 and name = 'First Name' and addon = 'Is' ;

        $set1 -> Search ({'$start'=>0,'$max'=>2, '$order'=>'id'})  or die "not ok
       ($DBI::errstr)" ;

        SELECT * from <table> ORDER BY id ;
        B<Note:> Because of the B<start> and B<max> only records 0,1 will be returned

        $set1 -> Search ({'$start'=>0,'$max'=>2, '$next'=>1, '$order'=>'id'})  or die "not ok
       ($DBI::errstr)" ;

        SELECT * from <table> ORDER BY id ;
        B<Note:> Because of the B<start>, B<max> and B<next> only records 2,3 will be
       returned

        $set1 -> Search ({'$start'=>2,'$max'=>1, '$prev'=>1, '$order'=>'id'})  or die "not ok
       ($DBI::errstr)" ;

        SELECT * from <table> ORDER BY id ;
        B<Note:> Because of the B<start>, B<max> and B<prev> only records 0,1,2 will be
       returned

        $set1 -> Search ({'$start'=>5,'$max'=>5, '$next'=>1, '$order'=>'id'})  or die "not ok
       ($DBI::errstr)" ;

        SELECT * from <table> ORDER BY id ;
        B<Note:> Because of the B<start>, B<max> and B<next> only records 5-9 will be
       returned

        *set6 = DBIx::Recordset -> Search ({  '!DataSource'   =>  "dbi:$Driver:$DB",
                                                               '!Table'            =>  "t1, t2",
                                                               '!TabRelation'  =>
               "t1.value=t2.value",
                                               '!Fields'       =>  'id, name, text',
                                               'id'            =>  "2\t4" }) or die "not ok
       ($DBI::errstr)" ;

        SELECT id, name, text FROM t1, t2 WHERE (id=2 or id=4) and t1.value=t2.value ;

        $set6 -> Search ({'name'            =>  "Fourth Name" }) or die "not ok
       ($DBI::errstr)" ;
        SELECT id, name, text FROM t1, t2 WHERE (name = 'Fourth Name') and
       t1.value=t2.value
       ;

        $set6 -> Search ({'id'            =>  3,
                         '$operator'     =>  '<' }) or die "not ok ($DBI::errstr)" ;

        SELECT id, name, text FROM t1, t2 WHERE (id < 3) and t1.value=t2.value ;

        $set6 -> Search ({'id'            =>  4,
                         'name'          =>  'Second Name',
                         '*id'           =>  '<',
                         '*name'         =>  '<>' }) or die "not ok ($DBI::errstr)" ;

        SELECT id, name, text FROM t1, t2 WHERE (id<4 and name <> 'Second Name') and
       t1.value=t2.value ;

        $set6 -> Search ({'id'            =>  2,
                         'name'          =>  'Fourth Name',
                         '*id'           =>  '<',
                         '*name'         =>  '=',
                         '$conj'         =>  'or' }) or die "not ok ($DBI::errstr)" ;

        SELECT id, name, text FROM t1, t2 WHERE (id<2 or name='Fourth Name') and
       t1.value=t2.value ;

        $set6 -> Search ({'+id|addon'     =>  "7\tit",
                         'name'          =>  'Fourth Name',
                         '*id'           =>  '<',
                         '*addon'        =>  '=',
                         '*name'         =>  '<>',
                         '$conj'         =>  'and' }) or die "not ok ($DBI::errstr)" ;

        SELECT id, name, text FROM t1, t2 WHERE (t1.value=t2.value) and (  ((name <>
       Fourth
       Name)) and (  (  id < 7  or  addon = 7)  or  (  id < 0  or  addon = 0)))

        $set6 -> Search ({'+id|addon'     =>  "6\tit",
                         'name'          =>  'Fourth Name',
                         '*id'           =>  '>',
                         '*addon'        =>  '<>',
                         '*name'         =>  '=',
                         '$compconj'     =>  'and',
                         '$conj'         =>  'or' }) or die "not ok ($DBI::errstr)" ;

        SELECT id, name, text FROM t1, t2 WHERE (t1.value=t2.value) and (  ((name =
       Fourth
       Name)) or (  (  id > 6 and addon <> 6)  or  (  id > 0 and addon <> 0))) ;

        *set7 = DBIx::Recordset -> Search ({  '!DataSource'   =>  "dbi:$Driver:$DB",
                                           '!Table'        =>  "t1, t2",
                                           '!TabRelation'  =>  "t1.id=t2.id",
                                           '!Fields'       =>  'name, typ'}) or die "not ok
       ($DBI::errstr)" ;

        SELECT name, typ FROM t1, t2 WHERE t1.id=t2.id ;

        %h = ('id'    => 22,
             'name2' => 'sqlinsert id 22',
             'value2'=> 1022) ;

        *set9 = DBIx::Recordset -> Insert ({%h,
                                           ('!DataSource'   =>  "dbi:$Driver:$DB",
                                            '!Table'        =>  "$Table[1]")}) or die "not ok
       ($DBI::errstr)" ;

        INSERT INTO <table> (id, name2, value2) VALUES (22, 'sqlinsert id 22', 1022) ;

        %h = ('id'    => 22,
             'name2' => 'sqlinsert id 22u',
             'value2'=> 2022) ;

        $set9 -> Update (\%h, 'id=22') or die "not ok ($DBI::errstr)" ;

        UPDATE <table> WHERE id=22 SET id=22, name2='sqlinsert id 22u', value2=2022 ;

        %h = ('id'    => 21,
             'name2' => 'sqlinsert id 21u',
             'value2'=> 2021) ;

        *set10 = DBIx::Recordset -> Update ({%h,
                                           ('!DataSource'   =>  "dbi:$Driver:$DB",
                                            '!Table'        =>  "$Table[1]",
                                            '!PrimKey'      =>  'id')}) or die "not ok
       ($DBI::errstr)" ;

        UPDATE <table> WHERE id=21 SET name2='sqlinsert id 21u', value2=2021 ;

        %h = ('id'    => 21,
             'name2' => 'Ready for delete 21u',
             'value2'=> 202331) ;

        *set11 = DBIx::Recordset -> Delete ({%h,
                                           ('!DataSource'   =>  "dbi:$Driver:$DB",
                                            '!Table'        =>  "$Table[1]",
                                            '!PrimKey'      =>  'id')}) or die "not ok
       ($DBI::errstr)" ;

        DELETE FROM <table> WHERE id = 21 ;

        *set12 = DBIx::Recordset -> Execute ({'id'  => 20,
                                          '*id' => '<',
                                          '!DataSource'   =>  "dbi:$Driver:$DB",
                                          '!Table'        =>  "$Table[1]",
                                          '!PrimKey'      =>  'id'}) or die "not ok
       ($DBI::errstr)" ;

        SELECT * FROM <table> WHERE id<20 ;

        *set13 = DBIx::Recordset -> Execute ({'=search' => 'ok',
                           'name'  => 'Fourth Name',
                           '!DataSource'   =>  "dbi:$Driver:$DB",
                           '!Table'        =>  "$Table[0]",
                           '!PrimKey'      =>  'id'}) or die "not ok ($DBI::errstr)" ;

        SELECT * FROM <table>  WHERE   ((name = Fourth Name))

        $set12 -> Execute ({'=insert' => 'ok',
                           'id'     => 31,
                           'name2'  => 'insert by exec',
                           'value2'  => 3031,
        # Execute should ignore the following params, since it is already setup
                           '!DataSource'   =>  "dbi:$Driver:$DB",
                           '!Table'        =>  "quztr",
                           '!PrimKey'      =>  'id99'}) or die "not ok ($DBI::errstr)" ;

        SELECT * FROM <table> ;

        $set12 -> Execute ({'=update' => 'ok',
                           'id'     => 31,
                           'name2'  => 'update by exec'}) or die "not ok ($DBI::errstr)" ;

        UPDATE <table> SET name2=update by exec,id=31 WHERE id=31 ;

        $set12 -> Execute ({'=insert' => 'ok',
                           'id'     => 32,
                           'name2'  => 'insert/upd by exec',
                           'value2'  => 3032}) or die "not ok ($DBI::errstr)" ;

        INSERT INTO <table> (name2,id,value2) VALUES (insert/upd by exec,32,3032) ;

        $set12 -> Execute ({'=delete' => 'ok',
                           'id'     => 32,
                           'name2'  => 'ins/update by exec',
                           'value2'  => 3032}) or die "not ok ($DBI::errstr)" ;

        DELETE FROM <table> WHERE id=32 ;

SUPPORT

       As far as possible for me, support will be available via the DBI Users' mailing list.
       (dbi-user@fugue.com)

AUTHOR

       G.Richter (richter@dev.ecos.de)

SEE ALSO

       Perl(1)
       DBI(3)
       DBIx::Compat(3)
       HTML::Embperl(3) http://perl.apache.org/embperl/
       Tie::DBI(3) http://stein.cshl.org/~lstein/Tie-DBI/