From a practical view there are two types of error messages when using transactions:
-"Normal" errors: in this case, the application should stop the current process and show an error message to the user.
-Deadlock errors. This shows that the deadlock detection process of PostgreSQL found a circle of dependency, and broke it by rolling back the transaction in one of the processes, which gets this error msg. In this case, the application should not stop, but repeat the transaction.
I found no discrete way to find out which case are we dealing with. This interface doesn't support error codes, so we have to search for patterns in the message text.
Here is an example for PostgreSQL database connection class. It throws a PostgresException on "normal" errors, and DependencyException in the case of a broken deadlock, when we have to repeat the transaction.
postgres.php:
<?php
class PostgresException extends Exception {
function __construct($msg) { parent::__construct($msg); }
}
class DependencyException extends PostgresException {
function __construct() { parent::__construct("deadlock"); }
}
class pg {
public static $connection;
private static function connect() {
self::$connection = @pg_connect("dbname=foodb user=foouser password=foopasswd");
if (self::$connection === FALSE) {
throw(new PostgresException("Can't connect to database server."));
}
}
public static function query($sql) {
if (!isset(self::$connection)) {
self::connect();
}
$result = @pg_query(self::$connection, $sql);
if ($result === FALSE) {
$error = pg_last_error(self::$connection);
if (stripos($error, "deadlock detected") !== false) throw(new DependencyException());
throw(new PostgresException($error.": ".$sql));
}
$out = array();
while ( ($d = pg_fetch_assoc($result)) !== FALSE) {
$out[] = $d;
}
return $out;
}
}
?>
It should be used in this way:
test.php:
<?php
include("postgres.php");
do {
$repeat = false;
try {
pg::query("begin");
...
$result = pg::query("SELECT * FROM public.kitten");
...
pg::query("commit");
}
catch (DependencyException $e) {
pg::query("rollback");
$repeat = true;
}
} while ($repeat);
?>
The normal errors should be caught at the frontend.
Tamas
pg_last_error
(PHP 4 >= 4.2.0, PHP 5)
pg_last_error — Zwraca łańcuch ostatniego komunikatu błędu dla połączenia
Opis
$polaczenie
] )
pg_last_error() zwraca ostatni komunikat błędu
dla połączenia danego parametrem polaczenie.
Komunikaty błędów mogą być zamazane przez wewnętrzne wywołania funkcji PostgreSQL(libpq). Funkcja może nie zwrócić właściwego komunikatu, jeśli wewnątrz modułu PostgreSQL wystąpiło wiele błędów.
Stosuj pg_result_error(), pg_result_error_field(), pg_result_status() i pg_connection_status() dla lepszej obsługi błędów.
Informacja:
Ta funkcja była poprzednio nazwana pg_errormessage().
Parametry
-
polaczenie -
Identyfikator połączenia do bazy danych PostgreSQL. Gdy
polaczenienie został podany, domyślne połączenie jest użyte. Domyślnym połączeniem jest ostatnie, stworzone przez pg_connect() lub pg_pconnect().
Zwracane wartości
Łańcuch (ang. string) zawierający ostatni komunikat błędu dla
danego poprzez parametr polaczenie połączenia, lub FALSE w razie niepowodzenia.
Przykłady
Przykład #1 pg_last_error() - przykład
<?php
$polaczenie = pg_connect("dbname=wydawca") or die("Nie można się połączyć");
// Zapytanie, które nie zostało wykonane
$wyn = pg_query($polaczenie, "select * from nie_istniejaca_tabela");
echo pg_last_error($polaczenie);
?>
Zobacz też:
- pg_result_error() - Zwraca błąd związany z identyfikatorem wyniku
- pg_result_error_field() - Returns an individual field of an error report.
