SunshinePHP Developer Conference 2015

pg_last_error

(PHP 4 >= 4.2.0, PHP 5)

pg_last_error特定の接続から直近のエラーメッセージ文字列を取得する

説明

string pg_last_error ([ resource $connection ] )

pg_last_error() は、指定した connection から直近のエラーメッセージを返します。

エラーメッセージは、内部的な PostgreSQL(libpq) 関数コールにより 上書きされる可能性があります。PostgreSQL モジュール関数の中で複数の エラーが発生した場合には、この関数は適切なエラーメッセージを返さない 可能性があります。

エラー処理を改善するために pg_result_error()pg_result_error_field()pg_result_status() および pg_connection_status() を使用ください。

注意:

この関数は、以前は pg_errormessage() と呼ばれていました。

パラメータ

connection

PostgreSQL データベース接続リソース。connection が指定されていない場合はデフォルトの接続が使用されます。 デフォルトの接続は、直近の pg_connect() あるいは pg_pconnect() によって作成されたものです。

返り値

指定した connection の直近のエラーメッセージを 含む文字列を返します。エラー時には FALSE を返します。

例1 pg_last_error() の例

<?php
  $dbconn 
pg_connect("dbname=publisher") or die("接続できませんでした");

  
// 失敗するクエリ
  
$res pg_query($dbconn"select * from doesnotexist");
  
  echo 
pg_last_error($dbconn);
?>

参考

add a note add a note

User Contributed Notes 1 note

up
0
Tamas Bolner
4 years ago
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
To Top