# the two sql statements must function as one single, atomic transaction
# we check for errors after the eval block.
LABEL_START_TRANSACTION:
eval
{
# AutoCommit must be off for transaction handling, it is put back on
# after the transaction.
$dbh->{AutoCommit} = 0;
$dbh->{RaiseError} = 1;
# if nothing is being updated, then we don't want to fail
if ($setFields)
{
$sql = "UPDATE $table SET $setFields WHERE mrID=$mrNumber";
# prepare the sql statement
$sth = $dbh->prepare($sql);
# bind the parameters (description and any multi-line fields)
for (my $i=0; $i<=$#projValuesToBind; $i++)
{
$sth->bind_param($i+1, $projValuesToBind[$i], DBI::SQL_LONGVARCHAR);
}
# execute the sql statement to insert row into MASTERx table
$sth->execute();
}
# get the new address book fields
if($ENV{'ABMASTER'} && $setABFields)
{
$sql = "UPDATE ${table}_ABDATA SET $setABFields WHERE mrID=$mrNumber";
# prepare the sql statement
$sth = $dbh->prepare($sql);
# bind the parameters (any multi-line fields)
for (my $i=0; $i<=$#ABValuesToBind; $i++)
{
$sth->bind_param($i+1, $ABValuesToBind[$i], DBI::SQL_LONGVARCHAR);
}
# execute the sql statement to update row into MASTERx_ABDATA table
$sth->execute();
}
# there are sql statements that need to be comitted
if (($setABFields && $ENV{'ABMASTER'}) || $setFields)
{
# everything worked, so commit the database changes.
$dbh->commit();
}
};
if ($@) # error during transaction, rollback and report information
{
$errorCount++;
my $originalError = $@;
# retry for up to five errors
if ($errorCount <= $DBI_RETRY_COUNT)
{
# roll back the transaction
# (catch errors from rolling back. otherwise the script will just die.)
eval {
$dbh->rollback();
};
if ($@) # error rolling back!
{
$errStr .= "$originalError
\n";
$errStr .= "$sql
\n $ABsql
\n";
&errorExit(203, "mrChange transaction error: ", $errStr, "
\nalso failed while rolling back: $@
\n");
}
# sleep a random max of $DBI_RETRY_SECONDS
my $retrySeconds = int(rand($DBI_RETRY_SECONDS)+1);
$errStr .= "Slept ${retrySeconds}s... ";
sleep $retrySeconds;
$errStr .= "Trying again after reconnect.
\n";
# reconnect
&disconnectFromDBD;
&connectToDBD;
goto LABEL_START_TRANSACTION;
}
# roll back the transaction
# (catch errors from rolling back. otherwise the script will just die.)
eval {
$dbh->rollback();
};
if ($@) # error rolling back!
{
$errStr .= "$originalError
\n";
$errStr .= "$sql
\n $ABsql
\n";
&errorExit(203, "mrChange transaction error: ", $errStr, "
\nalso failed while rolling back: $@
\n");
}
# rollback was successful:
# append warning from dbi to error string
$errStr .= "$originalError
\n";
$errStr .= "$sql
\n $ABsql
\n";
&errorExit(203, "mrChange transaction error: ", $errStr);
}
# AutoCommit MUST get turned back on, as the rest of FootPrints does not
# use transactions.
$dbh->{AutoCommit} = 1;
$dbh->{RaiseError} = 0;