DBD-Informix
view release on metacpan or search on metacpan
Informix.pm view on Meta::CPAN
# columns, and each sentence starts on a new line. The 'perldoc'
# program reformats the text to wrap sentences.
__END__
=head1 NAME
DBD::Informix - Informix Database Driver for Perl DBI
=head1 SYNOPSIS
use DBI;
=head1 DESCRIPTION
This document describes Informix Database Driver for Perl DBI Version 2018.1031 (2018-10-31).
You should also read the documentation for DBI C<perldoc DBI> as this
document qualifies what is stated there.
Note that this document was last fully updated for the DBI Version
0.85 specification, but the code requires features from DBI Version
1.14.
Consequently, both this document and DBD::Informix are probably
considerably out of line with some of the new features and minor
details of the DBI specification.
The definitive statement of what should be in the driver is in the
Cheetah book, as amended by any later versions of DBI.
If you don't have a copy of it, go and get it and read it.
Programming the Perl DBI
Alligator Descartes and Tim Bunce
O'Reilly (http://www.oreilly.com), February 2000, ISBN 1-56592-699-4
The primary URL for information about Perl and DBI is:
http://dbi.perl.org/
This document still has a biassed view of how to use DBI and
DBD::Informix and covers parts of DBI and most of DBD::Informix.
In late 1996, the DBI documentation was in a very confused state.
The DBI documentation has improved with each release of DBI, and the
comments in the DBI document about DBI and its drivers are a better
indication of what should happen.
However, this document might still be a better reflection of the
actual behavior of DBD::Informix.
Be aware that on occasion, the description in this document gets
complex because of differences between different versions of Informix
software and different types of Informix databases.
The key factor is the version of ESQL/C used when building
DBD::Informix.
Basically, there are two groups of versions to worry about, the 5.x
family of versions (5.00.UC1 through 5.20.UCx at the moment), and the 6.x
and later family of versions (6.00 through 9.53, and then 2.90 through 3.70
at the moment; yes, some clown in marketing decreased the version number).
All version families acquire extra versions on occasion.
Note that DBD::Informix does not work with Informix ESQL/C Version
4.1x or earlier versions because it uses both SQL descriptors and
strings for cursor names and statement names, and these features were
not available before Version 5.00.
For information about Informix software, you should also read the
Notes/FAQ file that is distributed with Informix Database Driver for Perl DBI.
=head2 TECHNICAL SUPPORT
For information on technical support for Informix Database Driver for Perl DBI, please run:
perldoc DBD::Informix::TechSupport
For information on reporting bugs in Informix Database Driver for Perl DBI, please review the
Notes/bug.reports file as well.
=head2 JAPANESE DOCUMENTATION
For a Japanese translation of a version of this documentation
(maintained by Kawai Takanori <kawai@nippon-rad.co.jp>), see the
following Web site:
http://member.nifty.ne.jp/hippo2000/perltips/DBD/informix.htm
=head1 USE OF DBD::Informix
=head2 LOADING DBD::Informix
To use the DBD::Informix software, you need to load the DBI software.
use DBI;
Under normal circumstances, you should then connect to your database
using the notation in the section "CONNECTING TO A DATABASE," which
calls DBI->connect().
Note that some of the DBD::Informix test code does not operate under
normal circumstances and therefore uses the nonpreferred techniques
in the section "Driver Attributes and Methods."
Note that you do not write:
use DBD::Informix; # !!BUGGY CODE!!
However, starting with version 1.03.PC1, you might write either or both
of the following:
use DBI qw(:sql_types);
use DBD::Informix qw(:ix_types);
This loads up some special type names (actually parameterless subs)
that you can use with $sth->bind_param() and $sth->bind_param_inout().
Using this allows you to update blobs (BYTE and TEXT), which was
previously not an option.
The Informix type names are:
IX_SMALLINT, IX_INTEGER, IX_SERIAL, IX_INT8, IX_SERIAL8,
IX_BIGINT, IX_BIGSERIAL,
IX_DECIMAL, IX_MONEY, IX_FLOAT, IX_SMALLFLOAT,
IX_CHAR, IX_VARCHAR, IX_NCHAR, IX_NVARCHAR, IX_LVARCHAR,
IX_BOOLEAN,
IX_DATE, IX_DATETIME, IX_INTERVAL,
IX_BYTE, IX_TEXT, IX_CLOB, IX_BLOB,
Informix.pm view on Meta::CPAN
You can execute an arbitrary statement with parameters using:
$dbh->do($stmt, undef, @parameters);
$dbh->do($stmt, undef, $param1, $param2);
The 'undef' represents an undefined reference to a hash of attributes
(\%attr) as documented in the DBI specification.
Again, the statement must not be a SELECT or EXECUTE PROCEDURE that
returns data.
The values in @parameters (or the separate values) are bound to the
question marks in the statement string.
$sth = $dbh->prepare($stmt);
$sth->execute(@parameters);
This function is implemented by the DBI package and therefore does not
use EXECUTE IMMEDIATE.
The only reliable way to embed an arbitrary string inside a statement
is to use the quote method:
$dbh->quote($string);
This method is provided by the DBI package implementation and is
inherited by the DBD::Informix package.
The string is enclosed in single quotes, and any embedded single
quotes are doubled up, which conforms to the SQL-92 standard.
You might typically use this method in a context such as:
$value = q{Doesn't work unless quotes ("'" and '"') are handled};
$stmt = "INSERT INTO SomeTable(SomeColumn) " .
"VALUES(" . $dbh->quote($value) . ")";
Doing this ensures that the data in $values will be interpreted
correctly, regardless of what quotes appear in $value (unless it
contains newline characters).
Note that the alternative assignment below does not work!
# !!BUGGY CODE!!
$stmt = "INSERT INTO SomeTable(SomeColumn) VALUES($dbh->quote($value))";
However, before using $dbh->quote, consider whether to use a
placeholder, '?', in instead.
You should probably use a placeholder if the string represents a value
in the WHERE clause of a SELECT, UPDATE or DELETE statement, or a
value in the VALUES list of an INSERT statement, or a value in the SET
clause of an UPDATE statement, or a parameter to a function or stored
procedure.
Note that you must use a placeholder if the string could be longer
than 255 characters, or if the underlying column is a blob (BYTE,
TEXT, BLOB or CLOB) type.
Otherwise, the string probably represents a table name or a column
name and you must use $dbh->quote.
=head2 CREATING STATEMENTS
You can also prepare a statement for multiple uses, and you can do
this for SELECT and EXECUTE PROCEDURE statements that return data
(cursory statements) as well as noncursory statements that return no data.
You create a statement handle (another reference) using:
$sth = $dbh->prepare($stmt);
If the statement is a SELECT that returns data (not SELECT...INTO TEMP) or
an EXECUTE PROCEDURE for a procedure that returns values, a cursor is
declared for the prepared statement.
The prepare call accepts an optional attributes parameter that is a
reference to a hash.
Starting with version 1.03.PC1, the following attributes are recognized:
{ix_InsertCursor => 1, ix_ScrollCursor => 1, ix_CursorWithHold => 1}
The ix_ScrollCursor is a placeholder that may become unnecessary with a
future revision of DBI.
The ix_CursorWithHold attribute is only of relevance if AutoCommit is
disabled.
When AutoCommit is enabled, all cursors have to be WITH HOLD (just one
more reason to hate AutoCommit).
$sth = $dbh->prepare("SELECT id, name FROM tablename", {'ix_CursorWithHold' => 1});
After the cursor is opened ($sth->execute), it is not closed by
$dbh->commit().
Either fetch all the rows or use $sth->finish() to close it.
The ix_InsertCursor attribute can be applied to an INSERT statement (but
generates an error -481 for other types of statement).
Subsequent uses of $sth->execute() will use the ESQL/C PUT statement to
insert the data, and $sth->finish() will close the INSERT cursor.
There is at present no mechanism to invoke the FLUSH statement.
It would be reasonable to add {ix_BlobLocation => 'InFile'} to support
per-statement blob location.
You need to check for errors unless you are using {RaiseError => 1}.
# Emphasizing the error handling.
die "Failed to prepare '$stmt'\n"
unless ($sth = $dbh->prepare($stmt));
# Emphasizing the SQL action.
$sth = $dbh->prepare($stmt) or die "Failed to prepare '$stmt'\n"
You can tell whether the statement is just executable or whether it is
a cursory (fetchable) statement by testing the
Informix-specific attribute ix_Fetchable.
The approved, canonical DBI method of doing this check is
"$sth->{NUM_OF_FIELDS} > 0".
Once the statement is prepared, you can execute it:
$sth->execute;
For a noncursory statement, this simply executes the statement.
If the statement is executed successfully, the number of rows
affected will be returned.
If an error occurs, the returned value will be undef.
If the statement does not affect any rows, the string returned is
"0E0", which evaluates to true but also to zero.
For a cursory statement, $sth->execute opens the cursor.
If the cursor is opened successfully, it returns the value "0E0",
which evaluates to true but also to zero.
If an error occurs, the returned value will be undef.
You can also specify the input parameters for a statement that contains
question-marks as place-holders using:
$sth->execute(@parameters);
The first parameter will be supplied as the value for the first
place-holder question mark in the statement, the second parameter for
the second place-holder, and so on.
You can also bind specific values for parameters with $sth->bind_param
method.
=over 4
Issue: At the moment, there is no checking by DBD::Informix on how many
input parameters are supplied and how many are needed.
Note that the Informix servers give no support for determining the
number of input parameters except in the VALUES clause of an INSERT
statement.
This needs to be resolved.
=back
The Informix servers give no support for determining the types of
input parameters of any SQL statement except in the VALUES clause of
an INSERT statement.
(Some versions have partial support for describing the input
parameters to an UPDATE statement, but PTS Bug 111987 asserts that
this is not actually usable, not least because the server has to be
specially configured to make it available at all.)
This means that DBD::Informix cannot handle blobs automatically in the
SET clause of an UPDATE statement.
However, starting with version 1.03.PC1, you can provide the necessary
information to DBD::Informix manually.
The $sth->bind_param() method can be used with a type attribute:
$upd = 'UPDATE SomeTable SET TextCol = ? WHERE Pkey = ?';
$sth = $dbh->prepare($upd);
$sth->bind_param(1, $blob_val, { ix_type => IX_TEXT });
$sth->bind_param(2, $pkey);
$sth->execute;
$sth->bind_param(1, $new_blob_val, { TYPE => SQL_LONGVARCHAR });
$sth->bind_param(2, $new_pkey, { TYPE => SQL_INTEGER });
The attribute tells DBD::Informix to treat the parameter specially.
The official, DBI sanctioned 'TYPE=>SQL_xyz' names are listed earlier
in this document.
Note that you cannot use $sth->execute($blob_val, $pkey) because there
is no way to convey the type information to the code.
Also note that Informix servers do provide information about blob
values in both the select-list of a SELECT statement and the VALUES
clause of the INSERT statement.
The INSERT statement is a special case, and it provides support for
code that implements the non-SQL statement 'LOAD FROM "file" INSERT
INTO SomeTable'.
For cursory statements, you can discover the returned column
names, types, nullability, and so on.
You do this with:
@name = @{$sth->{NAME}}; # Column names
@null = @{$sth->{NULLABLE}}; # True => accepts nulls
@type = @{$sth->{TYPE}}; # ODBC Data Type numbers
@prec = @{$sth->{PRECISION}}; # ODBC PRECISION numbers (or undef)
@scal = @{$sth->{SCALE}}; # ODBC SCALE numbers (or undef)
# Native (Informix) type equivalents
@tnam = @{$sth->{ix_NativeTypeName}}; # Type name
@tnum = @{$sth->{ix_ColType}}; # Type number from SysColumns.ColType
@tlen = @{$sth->{ix_ColLength}}; # Type length from SysColumns.ColLength
@tlen = @{$sth->{ix_ExtendedType}}; # Extended type number from SysColumns.Extended_ID
@tlen = @{$sth->{ix_ExtendedTypeName}}; # Extended type name from SysColumns.Extended_ID
=over 4
Note: Informix uses '(expression)' in the array $sth->{NAME} for any
nonaliased computed value in a SELECT list, and to describe the return
values from stored procedures, and so on.
This could be usefully improved.
There is also no guarantee that the names returned are unique.
For example, in "SELECT A.Column, B.Column FROM Table1 A, Table1 B
WHERE ...", both the return columns are described as 'column'.
=back
If the statement is a cursory statement, you can retrieve the
values in any of a number of ways, as described in the DBI
specification.
$ref = $sth->fetchrow_arrayref;
$ref = $sth->fetch; # Alternative spelling...
@row = @{$ref};
@row = @{$sth->fetchrow_arrayref}; # Shorthand for above...
@row = $sth->fetchrow_array;
$ref = $sth->fetchall_arrayref;
As usual, you have to worry about whether this worked or not.
You would normally, therefore, use:
while ($ref = $sth->fetch)
{
# We know we got some data here.
...
}
# Investigate whether an error occurred or the SELECT
# simply had nothing more to return.
if ($sth->{sqlcode} < 0)
{
# Process error...
}
The returned data includes blobs mapped into strings.
Note that byte blobs might contain ASCII NUL '\0' characters.
Perl knows how long the strings are and does preserve NUL in the
middle of a byte blob.
However, you might need to be careful when you decide how to
handle this string.
The returned data includes blobs mapped into strings.
Note that byte blobs might contain ASCII NUL '\0' characters.
Perl knows how long the strings are and does preserve NUL in the
middle of a byte blob.
However, you might need to be careful when you decide how to
handle this string.
There is provision to specify how you want blobs handled.
You can set the attribute:
$sth->{ix_BlobLocation} = 'InMemory'; # Default
$sth->{ix_BlobLocation} = 'InFile'; # In a named file
$sth->{ix_BlobLocation} = 'DummyValue'; # Return dummy values
$sth->{ix_BlobLocation} = 'NullValue'; # Return undefined
InFile mode returns the name of a file in the fetched array, and
that file can be accessed by Perl using normal file access methods.
DummyValue mode returns "<<TEXT VALUE>>" for text blobs or "<<BYTE
VALUE>>" for byte (binary) blobs.
NullValue mode returns undefined (meaning that the Perl "defined"
operator would return false) values.
Note that these two options do not necessarily prevent the Server from
returning the data to the application, but the user does not get to
see the data--this depends on the internal implementation of the
ESQL/C FETCH operation in conjunction with SQL descriptors.
You can also set the ix_BlobLocation attribute on the database,
overriding it at the statement level.
=over 4
BUG: ix_BlobLocation is not handled properly.
=back
When you have fetched as many rows as required, you close the cursor using:
$sth->finish;
You do not have to finish a cursor explicitly if you executed a fetch
that failed to retrieve any data.
Using $sth->finish simply closes the cursor but does not free the cursor
or the statement.
That is done when you destroy (undef) the statement handle:
undef $sth;
You can also implicitly rebind a statement handle to a new statement
by simply using the same variable again.
This does not cause any memory leaks.
You can use the (DBI standard) Statement attribute to discover (or
rediscover) the text of a statement:
$txt = $sth->{Statement};
=head2 CURSORS FOR UPDATE
You can use the (DBI standard) attribute $sth->{CursorName} to retrieve the name of a
cursor.
If the statement for $sth is actually a SELECT and the cursor is in a
MODE ANSI database or is declared with the 'FOR UPDATE [OF col,...'
tag, you can use the cursor name in a 'DELETE...WHERE CURRENT OF'
or 'UPDATE...WHERE CURRENT OF' statement.
$st1 = $dbh->prepare("SELECT * FROM SomeTable FOR UPDATE");
$wc = "WHERE CURRENT OF $st1->{CursorName}";
$st2 = $dbh->prepare("UPDATE SomeTable SET SomeColumn = ? $wc");
$st3 = $dbh->prepare("DELETE FROM SomeTable $wc");
$st1->execute;
$row = $st1->fetch;
$st2->execute("New Value");
$row = $st1->fetch;
$st3->execute();
=head2 ACCESSING THE SQLCA RECORD
You can access the SQLCA record via either a database handle or a
statement handle.
$sqlcode = $sth->{ix_sqlcode};
$sqlerrm = $sth->{ix_sqlerrm};
$sqlerrp = $sth->{ix_sqlerrp};
@sqlerrd = @{$sth->{ix_sqlerrd}};
@sqlwarn = @{$sth->{ix_sqlwarn}};
Note that the warning information is treated as an array (as in Informix
4GL) rather than as a bunch of separate fields (as in Informix ESQL/C).
However, the array is indexed from zero (as in ESQL/C, C, Perl, and so
on), rather than from one (as in Informix 4GL).
Also note that both $sth->{ix_sqlerrd} and $sth->{ix_sqlwarn} return a
reference to an array.
Inspect the code in the print_sqlca() function in
DBD::Informix::TestHarness for more ideas on the use of these
statements.
You cannot set the sqlca record.
The sqlerrd array has the following useful columns:
$sth->{ix_sqlerrd}[1] - serial value after insert or ISAM error code
$sth->{ix_sqlerrd}[3] - estimated cost
$sth->{ix_sqlerrd}[4] - offset of the error into the SQL statement
$sth->{ix_sqlerrd}[5] - rowid of the last row processed
=head2 OBTAINING THE VALUE INSERTED FOR A SERIAL COLUMN
The following example is a very useful and important technique with Informix.
However, it is also not portable to other databases because they do not have
the SERIAL data type.
# insert a row into a table with a primary key that is a SERIAL
$stmt = $dbh->do("insert into table (serial_id, number) values(0, 10)");
print "the new row has a serial_id of $sth->{ix_sqlerrd}[1]\n";
For more information, you can read the "Informix ESQL/C Programmer's
Manual" or "Informix Guide to SQL: Reference Manual."
The exact chapter and verse depends on which version you use.
As an extension, you can also access $sth->{ix_serial} as a synonym for
$sth->{ix_sqlerrd}[1] and $sth->{ix_serial8} to obtain the last SERIAL8
value that was generated, and if you have CSDK 3.50 (and IDS 11.50) with
support for BIGINT and BIGSERIAL, $sth->{ix_bigserial} too.
Informix.pm view on Meta::CPAN
$dbh->prepare('UPDATE ...'); # Group 4B
=back
Group 1 statements establish connections to databases.
The type of database to which you are connected has no effect on the
AutoCommit mode.
Group 1A is the primary means of connecting to a database; Group
1B statements can change the current database.
Group 1B statements, however, cannot be executed except on the ".DEFAULT."
connection when you use ESQL/C 6.00 or later.
For all types of databases, the default AutoCommit mode is On.
With a MODE ANSI or a Logged database, the value of AutoCommit can be
set to Off, which automatically starts a transaction (explicitly if
the database is Logged, implicitly if the database is MODE ANSI).
For an UnLogged database, the AutoCommit mode cannot be changed.
Any attempt to change AutoCommit mode to Off with an UnLogged database
generates a nonfatal warning.
Group 2 statements sever the connection to a database.
The Group 2A statement renders the database handle unusable; no
further operations are possible except 'undef' or reassigning with a
new connection.
The Group 2B statement means that no operations other than those in
Group 1B or 'DROP DATABASE' are permitted on the handle.
As with the Group 1B statements, the Group 2B statement can only be
used on a ".DEFAULT." connection.
The value of AutoCommit is irrelevant after the database is closed
but is not altered by DBD::Informix.
Group 3 and 4 statements interact in many complicated ways, but the
new style of operation considerably simplifies the interactions.
One side effect of the changes is that BEGIN WORK is completely
marginalized and will generally cause an error.
Although UPDATE is cited in Group 4B, it represents any statement
that is not a SELECT statement.
Note that 'SELECT...INTO TEMP' is a Group 4B statement because it
returns no data to the program.
An 'EXECUTE PROCEDURE' statement is in Group 4A if it returns data
and in Group 4B if it does not, and you cannot tell which of the two
groups applies until after the statement is prepared.
=head2 MODE ANSI DATABASES
Previously, MODE ANSI databases were regarded as being in a
transaction at all times, but this is not the only way to view the way
these databases work.
However, it is more satisfactory to regard the state immediately after
a database is opened, or immediately after a COMMIT WORK or ROLLBACK
WORK operation as being in the No-TX state.
Any statement other than a disconnection statement (Group 2) or a
commit or rollback (Group 3A or 3C) takes the databases into the
In-TX state.
In a MODE ANSI database, you can execute BEGIN WORK successfully.
However, if AutoCommit is On, the transaction is immediately
committed, so it does you no good.
If the user elects to switch to AutoCommit On, things get trickier.
All cursors need to be declared WITH HOLD so that Group 4B statements
being committed do not close the active cursors.
Whenever a Group 4B statement is executed, the statement needs to be
committed.
With OnLine (and theoretically with SE), if the statement fails there
is no need to do a rollback -- the statement failing did the rollback
anyway.
As before, the code does ROLLBACK WORK before disconnecting, though it
should not actually be necessary.
=head2 LOGGED DATABASES
Previously, there were some big distinctions between Logged and MODE
ANSI databases.
One major advantage of the changes is that now there is essentially no
distinction between the two.
Note that executing BEGIN WORK does not buy you anything; you have to
switch AutoCommit mode explicitly to get any useful results.
=head2 UNLOGGED DATABASES
The transaction state is No-TX and AutoCommit is On, and this cannot
be changed.
Any attempt to set AutoCommit to Off generates a nonfatal warning but
the program will continue; setting AutoCommit to On generates neither a
warning nor an error.
Both $dbh->commit and $dbh->rollback succeed but do nothing.
Executing any Group 3B or 3C statement will generate an error.
Ideally, if you attempt to connect to an UnLogged database with
AutoCommit Off, you would get a connect failure.
There are problems implementing this because of the way DBI 0.85
behaves when failures occur, so this is not actually implemented.
=head1 ATTRIBUTE NAME CHANGES
Early releases of DBD::Informix, some of the Informix-specific
attributes had names that did not start 'ix_', but these old-style
attribute names are no longer recognized and an error message is
generated (by DBI).
Sometimes, an attribute name is changed for other reasons.
If there is an old spelling, then the old name is eliminated over three
releases spanning a period of not less than 6 months.
In the first release, the old name is recognized and a warning is
emitted but the change takes effect as it always used to.
In the second release, the old name is recognized and a warning is
emitted but no change occurs.
In the third release, the old name is no longer recognized (which yields
an error message from DBI).
You are strongly counselled to eliminate the warnings ASAP (and to keep
more or less current with releases of DBD::Informix).
=head1 MAPPING BETWEEN ESQL/C AND DBD::INFORMIX
A crude form of the mapping between DBD::Informix functions and ESQL/C
equivalents follows--there are a number of ways in which it is not
quite precise (for example, the influence of AutoCommit), but the
mapping is accurate enough for most purposes.
DBI->connect => DATABASE in 5.0x
$dbh->disconnect => CLOSE DATABASE in 5.0x
DBI->connect => CONNECT in 6.0x and later
$dbh->disconnect => DISCONNECT in 6.0x and later
$dbh->commit => COMMIT WORK (+BEGIN WORK)
$dbh->rollback => ROLLBACK WORK (+BEGIN WORK)
$dbh->do => EXECUTE IMMEDIATE
$dbh->prepare => PREPARE, DESCRIBE (DECLARE)
$sth->execute => EXECUTE or OPEN
$sth->fetch => FETCH
$sth->fetchrow => FETCH
$sth->finish => CLOSE
undef $sth => FREE cursor, FREE statement, etc
=head1 KNOWN RESTRICTIONS
=over 2
=item *
Blobs (meaning BYTE and TEXT blobs) can only be located in memory.
The provision for locating them in files is not functional.
=item *
BLOB and CLOB smart blobs are not handled directly by DBD::Informix.
The workaround is to use LOTOFILE to extract blobs from the database to
a file, and to use FILETOBLOB or FILETOCLOB to insert blobs from file
into the database.
=item *
Support for the less common types, such as row types, is either less
than perfect or even non-existent.
Sometimes, it will work sufficiently well; you won't, however, get a
Perl structured value out of the system - at most you would get a string
representation of the value.
If you really need to use some feature and DBD::Informix screws it up
impossibly badly, then either (a) submit a patch that fixes it or (b)
contact the maintenance team with a request for help.
This situation has been ongoing for more than a decade, and few people
have reported problems, which is a main reason that it hasn't been
fixed.
=item *
[I<This was an issue in the 1990s; I've not seen the problem for a long time.>]
If you use Informix ESQL/C Version 6.00 or later
and do not set both the environment variables CLIENT_LOCALE
and DB_LOCALE, ESQL/C might set one or both of them during the
connect operation.
When ESQL/C does so, it makes Perl emit a "Bad free()" error if you
subsequently modify the %ENV hash in the Perl script.
This is nasty, but there is no easy solution.
To establish what values you should set, arrange for the
compilation to define DBD_IX_DEBUG_ENVIRONMENT:
make UFLAGS=-DDBD_IX_DEBUG_ENVIRONMENT
The code in dbdimp.ec will then call the function dbd_ix_printenv() in
dbd_ix_db_login(), which will help you identify what has been changed.
=back
=head1 AUTHOR
At various times:
=over 2
=item *
( run in 2.756 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )