Index: skeleton/rdbms/sybase/SybaseConnection.class.php =================================================================== --- skeleton/rdbms/sybase/SybaseConnection.class.php (revision 12052) +++ skeleton/rdbms/sybase/SybaseConnection.class.php (working copy) @@ -22,7 +22,6 @@ * @purpose Database connection */ class SybaseConnection extends DBConnection { - private $formatter= NULL; @@ -62,7 +61,7 @@ } if (!is_resource($this->handle)) { - throw(new SQLConnectException(trim(sybase_get_last_message()), $this->dsn)); + throw new SQLConnectException(trim(sybase_get_last_message()), $this->dsn); } $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $reconnect)); @@ -91,11 +90,11 @@ */ public function selectdb($db) { if (!sybase_select_db($db, $this->handle)) { - throw(new SQLStatementFailedException( + throw new SQLStatementFailedException( 'Cannot select database: '.trim(sybase_get_last_message()), 'use '.$db, current(sybase_fetch_row(sybase_query('select @@error', $this->handle))) - )); + ); } return TRUE; } @@ -209,11 +208,11 @@ $sql= call_user_func_array(array($this, 'prepare'), $args); if (!is_resource($this->handle)) { - if (!($this->flags & DB_AUTOCONNECT)) throw(new SQLStateException('Not connected')); + if (!($this->flags & DB_AUTOCONNECT)) throw new SQLStateException('Not connected'); $c= $this->connect(); // Check for subsequent connection errors - if (FALSE === $c) throw(new SQLStateException('Previously failed to connect')); + if (FALSE === $c) throw new SQLStateException('Previously failed to connect'); } $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $sql)); @@ -233,17 +232,19 @@ // Sybase: Client message: Read from SQL server failed. (severity 78) // // but that seems a bit errorprone. - throw(new SQLConnectionClosedException( + throw new SQLConnectionClosedException( 'Statement failed: '.trim(sybase_get_last_message()), $sql - )); + ); } - - throw(new SQLStatementFailedException( - 'Statement failed: '.trim(sybase_get_last_message()), - $sql, - current(sybase_fetch_row($error)) - )); + + $code= current(sybase_fetch_row($error)); + $message= trim(sybase_get_last_message()); + if (1205 == $code) { + throw new SQLDeadlockException($message, $sql); + } else { + throw new SQLStatementFailedException('Statement failed: '.$message, $sql, $code); + } } if (TRUE === $result) { Index: skeleton/rdbms/sybase/SybaseResultSet.class.php =================================================================== --- skeleton/rdbms/sybase/SybaseResultSet.class.php (revision 12052) +++ skeleton/rdbms/sybase/SybaseResultSet.class.php (working copy) @@ -39,7 +39,7 @@ */ public function seek($offset) { if (!sybase_data_seek($this->handle, $offset)) { - throw(new SQLException('Cannot seek to offset '.$offset)); + throw new SQLException('Cannot seek to offset '.$offset); } return TRUE; } Index: skeleton/rdbms/SQLDeadlockException.class.php =================================================================== --- skeleton/rdbms/SQLDeadlockException.class.php (revision 0) +++ skeleton/rdbms/SQLDeadlockException.class.php (revision 0) @@ -0,0 +1,54 @@ +sql= $sql; + } + + /** + * Get SQL + * + * @return string + */ + public function getSql() { + return $this->sql; + } + + /** + * Return compound message of this exception. + * + * @return string + */ + public function compoundMessage() { + return sprintf( + "Exception %s (deadlock: %s) {\n". + " %s\n". + "}\n", + $this->getClassName(), + $this->message, + $this->sql + ); + } + } +?> Property changes on: skeleton/rdbms/SQLDeadlockException.class.php ___________________________________________________________________ Name: svn:keywords + Id Index: skeleton/rdbms/DBConnection.class.php =================================================================== --- skeleton/rdbms/DBConnection.class.php (revision 12052) +++ skeleton/rdbms/DBConnection.class.php (working copy) @@ -8,6 +8,7 @@ 'rdbms.SQLException', 'rdbms.SQLConnectException', 'rdbms.SQLStateException', + 'rdbms.SQLDeadlockException', 'rdbms.SQLStatementFailedException', 'rdbms.SQLConnectionClosedException', 'rdbms.DBEvent', Index: skeleton/rdbms/pgsql/PostgreSQLResultSet.class.php =================================================================== --- skeleton/rdbms/pgsql/PostgreSQLResultSet.class.php (revision 12052) +++ skeleton/rdbms/pgsql/PostgreSQLResultSet.class.php (working copy) @@ -38,7 +38,7 @@ */ public function seek($offset) { if (!pg_data_seek($this->handle, $offset)) { - throw(new SQLException('Cannot seek to offset '.$offset)); + throw new SQLException('Cannot seek to offset '.$offset); } return TRUE; } Index: skeleton/rdbms/pgsql/PostgreSQLConnection.class.php =================================================================== --- skeleton/rdbms/pgsql/PostgreSQLConnection.class.php (revision 12052) +++ skeleton/rdbms/pgsql/PostgreSQLConnection.class.php (working copy) @@ -21,7 +21,6 @@ * @purpose Database connection */ class PostgreSQLConnection extends DBConnection { - private $formatter= NULL; @@ -46,12 +45,14 @@ if ($this->flags & DB_PERSISTENT) { $this->handle= pg_pconnect($cs); + } else if ($this->flags & DB_NEWLINK) { + $this->handle= pg_connect($cs, PGSQL_CONNECT_FORCE_NEW); } else { $this->handle= pg_connect($cs); } if (!is_resource($this->handle)) { - throw(new SQLConnectException(rtrim(pg_last_error()), $this->dsn)); + throw new SQLConnectException(rtrim(pg_last_error()), $this->dsn); } $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $reconnect)); @@ -80,9 +81,9 @@ * @throws rdbms.SQLStatementFailedException */ public function selectdb($db) { - throw(new SQLStatementFailedException( + throw new SQLStatementFailedException( 'Cannot select database, not implemented in PostgreSQL' - )); + ); } /** @@ -190,33 +191,54 @@ $sql= call_user_func_array(array($this, 'prepare'), $args); if (!is_resource($this->handle)) { - if (!($this->flags & DB_AUTOCONNECT)) throw(new SQLStateException('Not connected')); + if (!($this->flags & DB_AUTOCONNECT)) throw new SQLStateException('Not connected'); $c= $this->connect(); // Check for subsequent connection errors - if (FALSE === $c) throw(new SQLStateException('Previously failed to connect.')); + if (FALSE === $c) throw new SQLStateException('Previously failed to connect.'); } $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $sql)); - $result= pg_query($this->handle, $sql); - - if (empty($result)) { - throw(new SQLStatementFailedException( - 'Statement failed: '.rtrim(pg_last_error($this->handle)), - $sql - )); + $success= pg_send_query($this->handle, $sql); + if (!$success) { + if (PGSQL_CONNECTION_OK !== pg_connection_status($this->handle)) { + throw new SQLConnectionClosedException( + 'Statement failed: '.rtrim(pg_last_error($this->handle)), + $sql + ); + } else { + throw new SQLStatementFailedException( + 'Statement failed: '.rtrim(pg_last_error($this->handle)), + $sql + ); + } } - if (TRUE === $result) { - $this->_obs && $this->notifyObservers(new DBEvent('queryend', TRUE)); - return TRUE; + $result= pg_get_result($this->handle); + switch ($status= pg_result_status($result, PGSQL_STATUS_LONG)) { + case PGSQL_FATAL_ERROR: case PGSQL_BAD_RESPONSE: { + $code= pg_result_error_field($result, PGSQL_DIAG_SQLSTATE); + $message= pg_result_error_field($result, PGSQL_DIAG_MESSAGE_PRIMARY); + if ('40P01' == $code) { + throw new SQLDeadlockException($message, $sql); + } else { + throw new SQLStatementFailedException('Statement failed: '.$message, $sql, $code); + } + } + + case PGSQL_COMMAND_OK: { + $this->_obs && $this->notifyObservers(new DBEvent('queryend', TRUE)); + return TRUE; + } + + default: { + $resultset= new PostgreSQLResultSet($result); + $this->_obs && $this->notifyObservers(new DBEvent('queryend', $resultset)); + + return $resultset; + } } - - $resultset= new PostgreSQLResultSet($result); - $this->_obs && $this->notifyObservers(new DBEvent('queryend', $resultset)); - - return $resultset; } /** Index: skeleton/rdbms/sqlite/SQLiteResultSet.class.php =================================================================== --- skeleton/rdbms/sqlite/SQLiteResultSet.class.php (revision 12052) +++ skeleton/rdbms/sqlite/SQLiteResultSet.class.php (working copy) @@ -38,7 +38,7 @@ */ public function seek($offset) { if (!sqlite_seek($this->handle, $offset)) { - throw(new SQLException('Cannot seek to offset '.$offset)); + throw new SQLException('Cannot seek to offset '.$offset); } return TRUE; } Index: skeleton/rdbms/sqlite/SQLiteConnection.class.php =================================================================== --- skeleton/rdbms/sqlite/SQLiteConnection.class.php (revision 12052) +++ skeleton/rdbms/sqlite/SQLiteConnection.class.php (working copy) @@ -50,9 +50,8 @@ * @purpose Database connection */ class SQLiteConnection extends DBConnection { - - private - $formatter= NULL; + private + $formatter= NULL; /** * Connect @@ -80,7 +79,7 @@ } if (!is_resource($this->handle)) { - throw(new SQLConnectException($err, $this->dsn)); + throw new SQLConnectException($err, $this->dsn); } $this->getFormatter()->dialect->registerCallbackFunctions($this->handle); @@ -110,9 +109,9 @@ * @throws rdbms.SQLStatementFailedException */ public function selectdb($db) { - throw(new SQLStatementFailedException( + throw new SQLStatementFailedException( 'Cannot select database, not implemented in SQLite' - )); + ); } /** @@ -220,11 +219,11 @@ $sql= call_user_func_array(array($this, 'prepare'), $args); if (!is_resource($this->handle)) { - if (!($this->flags & DB_AUTOCONNECT)) throw(new SQLStateException('Not connected')); + if (!($this->flags & DB_AUTOCONNECT)) throw new SQLStateException('Not connected'); $c= $this->connect(); // Check for subsequent connection errors - if (FALSE === $c) throw(new SQLStateException('Previously failed to connect.')); + if (FALSE === $c) throw new SQLStateException('Previously failed to connect.'); } $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $sql)); @@ -237,11 +236,11 @@ if (FALSE === $result) { $e= sqlite_last_error($this->handle); - throw(new SQLStatementFailedException( + throw new SQLStatementFailedException( 'Statement failed: '.sqlite_error_string($e), $sql, $e - )); + ); } if (TRUE === $result) { Index: skeleton/rdbms/mysql/MySQLConnection.class.php =================================================================== --- skeleton/rdbms/mysql/MySQLConnection.class.php (revision 12052) +++ skeleton/rdbms/mysql/MySQLConnection.class.php (working copy) @@ -22,7 +22,7 @@ * @purpose Database connection */ class MySQLConnection extends DBConnection { - public + private $formatter= NULL; /** @@ -120,11 +120,11 @@ */ public function selectdb($db) { if (!mysql_select_db($db, $this->handle)) { - throw(new SQLStatementFailedException( + throw new SQLStatementFailedException( 'Cannot select database: '.mysql_error($this->handle), 'use '.$db, mysql_errno($this->handle) - )); + ); } return TRUE; } @@ -235,11 +235,11 @@ $sql= call_user_func_array(array($this, 'prepare'), $args); if (!is_resource($this->handle)) { - if (!($this->flags & DB_AUTOCONNECT)) throw(new SQLStateException('Not connected')); + if (!($this->flags & DB_AUTOCONNECT)) throw new SQLStateException('Not connected'); $c= $this->connect(); // Check for subsequent connection errors - if (FALSE === $c) throw(new SQLStateException('Previously failed to connect.')); + if (FALSE === $c) throw new SQLStateException('Previously failed to connect.'); } $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $sql)); @@ -254,19 +254,21 @@ switch ($e= mysql_errno($this->handle)) { case 2006: // MySQL server has gone away case 2013: // Lost connection to MySQL server during query - throw(new SQLConnectionClosedException( + throw new SQLConnectionClosedException( 'Statement failed: '.mysql_error($this->handle), $sql, $e - )); - break; + ); + case 1213: // Deadlock + throw new SQLDeadlockException(mysql_error($this->handle), $sql); + default: - throw(new SQLStatementFailedException( + throw new SQLStatementFailedException( 'Statement failed: '.mysql_error($this->handle), $sql, $e - )); + ); } } Index: skeleton/rdbms/mysql/MySQLResultSet.class.php =================================================================== --- skeleton/rdbms/mysql/MySQLResultSet.class.php (revision 12052) +++ skeleton/rdbms/mysql/MySQLResultSet.class.php (working copy) @@ -39,7 +39,7 @@ */ public function seek($offset) { if (!mysql_data_seek($this->handle, $offset)) { - throw(new SQLException('Cannot seek to offset '.$offset)); + throw new SQLException('Cannot seek to offset '.$offset); } return TRUE; }