From 7c6947a01979c9f491af963fe0727ba0f7f438d7 Mon Sep 17 00:00:00 2001
From: David Grudl
Date: Fri, 23 Nov 2007 23:27:14 +0000
Subject: [PATCH] * added dibi::date & dibi::datetime *
DibiConnection::insertId && affectedRows throws exception on failure * added
protected throwException() to drivers * DibiPostgreDriver - can build
connection string * DibiSqliteDriver - support for parameters 'format:date' &
'format:datetime' * fixed query errors in DibiSqliteDriver * DibiConnection
prevents serialization and multiple transactions
---
TODO.txt | 7 +++
dibi/dibi.php | 73 ++++++++++++++++++++++++-------
dibi/drivers/mssql.php | 18 +++++++-
dibi/drivers/mysql.php | 26 ++++++++---
dibi/drivers/mysqli.php | 28 +++++++++---
dibi/drivers/odbc.php | 26 ++++++++---
dibi/drivers/oracle.php | 30 +++++++++----
dibi/drivers/pdo.php | 48 ++++++++++++--------
dibi/drivers/postgre.php | 58 ++++++++++++++++--------
dibi/drivers/sqlite.php | 43 +++++++++++++++---
dibi/libs/DibiConnection.php | 60 +++++++++++++++++++++----
dibi/libs/DibiDriverInterface.php | 6 ++-
dibi/libs/DibiException.php | 23 ++++++++++
dibi/libs/NException.php | 2 +-
examples/connect.php | 16 +++----
examples/date.type.demo.php | 73 -------------------------------
examples/datetime.demo.php | 30 +++++++++++++
examples/transaction.php | 28 ++++++++++++
18 files changed, 419 insertions(+), 176 deletions(-)
create mode 100644 TODO.txt
delete mode 100644 examples/date.type.demo.php
create mode 100644 examples/datetime.demo.php
create mode 100644 examples/transaction.php
diff --git a/TODO.txt b/TODO.txt
new file mode 100644
index 00000000..e55397e5
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,7 @@
+- dibi::insertOrUpdate...
+- sjednotit DibiVariable, modifier a type u DibiDriverInterface::format()
+- odstranit podporu pro modifikátory v kličích pole?
+- odstranit podporu pro conditional query?
+- odstranit podporu pro meta types?
+- event, log, profiler
+
diff --git a/dibi/dibi.php b/dibi/dibi.php
index 92b8da8d..f1c4eb60 100644
--- a/dibi/dibi.php
+++ b/dibi/dibi.php
@@ -317,25 +317,12 @@ class dibi extends NClass
- /**
- * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query
- * Monostate for DibiConnection::insertId()
- *
- * @param string optional sequence name for DibiPostgreDriver
- * @return int|FALSE int on success or FALSE on failure
- */
- public static function insertId($sequence=NULL)
- {
- return self::getConnection()->insertId($sequence);
- }
-
-
-
/**
* Gets the number of affected rows
* Monostate for DibiConnection::affectedRows()
*
- * @return int number of rows or FALSE on error
+ * @return int number of rows
+ * @throws DibiException
*/
public static function affectedRows()
{
@@ -344,8 +331,25 @@ class dibi extends NClass
+ /**
+ * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query
+ * Monostate for DibiConnection::insertId()
+ *
+ * @param string optional sequence name
+ * @return int
+ * @throws DibiException
+ */
+ public static function insertId($sequence=NULL)
+ {
+ return self::getConnection()->insertId($sequence);
+ }
+
+
+
/**
* Begins a transaction - Monostate for DibiConnection::begin()
+ * @return void
+ * @throws DibiException
*/
public static function begin()
{
@@ -356,6 +360,8 @@ class dibi extends NClass
/**
* Commits statements in a transaction - Monostate for DibiConnection::commit()
+ * @return void
+ * @throws DibiException
*/
public static function commit()
{
@@ -366,6 +372,8 @@ class dibi extends NClass
/**
* Rollback changes in a transaction - Monostate for DibiConnection::rollback()
+ * @return void
+ * @throws DibiException
*/
public static function rollback()
{
@@ -384,6 +392,41 @@ class dibi extends NClass
+ /**
+ * Pseudotype for timestamp representation
+ *
+ * @param mixed datetime
+ * @return DibiVariable
+ */
+ public static function datetime($time = NULL)
+ {
+ if ($time === NULL) {
+ $time = time(); // current time
+ } elseif (is_string($time)) {
+ $time = strtotime($time); // try convert to timestamp
+ } else {
+ $time = (int) $time;
+ }
+ return new DibiVariable($time, dibi::FIELD_DATETIME);
+ }
+
+
+
+ /**
+ * Pseudotype for date representation
+ *
+ * @param mixed date
+ * @return DibiVariable
+ */
+ public static function date($date = NULL)
+ {
+ $var = self::datetime($date);
+ $var->type = dibi::FIELD_DATE;
+ return $var;
+ }
+
+
+
/**
* Create a new substitution pair for indentifiers
*
diff --git a/dibi/drivers/mssql.php b/dibi/drivers/mssql.php
index af7cc1e3..aa5ed0e1 100644
--- a/dibi/drivers/mssql.php
+++ b/dibi/drivers/mssql.php
@@ -121,7 +121,7 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -145,6 +145,7 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
@@ -156,6 +157,7 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
@@ -167,6 +169,7 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
@@ -316,6 +319,19 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ throw new DibiDriverException();
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/mysql.php b/dibi/drivers/mysql.php
index 47231226..b1aedcde 100644
--- a/dibi/drivers/mysql.php
+++ b/dibi/drivers/mysql.php
@@ -29,7 +29,7 @@
* - 'password' (or 'pass')
* - 'persistent' - try to find a persistent link?
* - 'database' - the database name to select
- * - 'charset' - sets the encoding
+ * - 'charset' - character encoding to set
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
* - 'options' - driver specific constants (MYSQL_*)
* - 'lazy' - if TRUE, connection will be established only when required
@@ -115,7 +115,7 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
}
if (isset($config['database']) && !@mysql_select_db($config['database'], $this->connection)) {
- throw new DibiDriverException(mysql_error($this->connection), mysql_errno($this->connection));
+ $this->throwException();
}
$this->buffered = empty($config['unbuffered']);
@@ -150,8 +150,8 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
$this->resultset = @mysql_unbuffered_query($sql, $this->connection);
}
- if ($errno = mysql_errno($this->connection)) {
- throw new DibiDriverException(mysql_error($this->connection), $errno, $sql);
+ if (mysql_errno($this->connection)) {
+ $this->throwException($sql);
}
return is_resource($this->resultset);
@@ -162,7 +162,7 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -186,6 +186,7 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
@@ -197,6 +198,7 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
@@ -208,6 +210,7 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
@@ -378,6 +381,19 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ throw new DibiDriverException(mysql_error($this->connection), mysql_errno($this->connection), $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/mysqli.php b/dibi/drivers/mysqli.php
index c2d98bb5..b138abc5 100644
--- a/dibi/drivers/mysqli.php
+++ b/dibi/drivers/mysqli.php
@@ -29,7 +29,7 @@
* - 'password' (or 'pass')
* - 'persistent' - try to find a persistent link?
* - 'database' - the database name to select
- * - 'charset' - sets the encoding
+ * - 'charset' - character encoding to set
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
* - 'options' - driver specific constants (MYSQLI_*)
* - 'lazy' - if TRUE, connection will be established only when required
@@ -130,7 +130,7 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
$this->resultset = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
if ($errno = mysqli_errno($this->connection)) {
- throw new DibiDriverException(mysqli_error($this->connection), $errno, $sql);
+ $this->throwException($sql);
}
return is_object($this->resultset);
@@ -141,7 +141,7 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -165,11 +165,12 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
if (!mysqli_autocommit($this->connection, FALSE)) {
- throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection));
+ $this->throwException($sql);
}
}
@@ -178,11 +179,12 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
if (!mysqli_commit($this->connection)) {
- throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection));
+ $this->throwException($sql);
}
mysqli_autocommit($this->connection, TRUE);
}
@@ -192,11 +194,12 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
if (!mysqli_rollback($this->connection)) {
- throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection));
+ $this->throwException($sql);
}
mysqli_autocommit($this->connection, TRUE);
}
@@ -353,6 +356,19 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection), $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/odbc.php b/dibi/drivers/odbc.php
index d4ee8e47..90b3290e 100644
--- a/dibi/drivers/odbc.php
+++ b/dibi/drivers/odbc.php
@@ -116,7 +116,7 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
$this->resultset = @odbc_exec($this->connection, $sql);
if ($this->resultset === FALSE) {
- throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql);
+ $this->throwException($sql);
}
return is_resource($this->resultset);
@@ -127,7 +127,7 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -151,11 +151,12 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
if (!odbc_autocommit($this->connection, FALSE)) {
- throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
+ $this->throwException();
}
}
@@ -164,11 +165,12 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
if (!odbc_commit($this->connection)) {
- throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
+ $this->throwException();
}
odbc_autocommit($this->connection, TRUE);
}
@@ -178,11 +180,12 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
if (!odbc_rollback($this->connection)) {
- throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
+ $this->throwException();
}
odbc_autocommit($this->connection, TRUE);
}
@@ -330,6 +333,19 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/oracle.php b/dibi/drivers/oracle.php
index 357bd08d..10c3d066 100644
--- a/dibi/drivers/oracle.php
+++ b/dibi/drivers/oracle.php
@@ -25,7 +25,7 @@
* - 'database' (or 'db') - the name of the local Oracle instance or the name of the entry in tnsnames.ora
* - 'username' (or 'user')
* - 'password' (or 'pass')
- * - 'charset' - sets the encoding
+ * - 'charset' - character encoding to set
* - 'lazy' - if TRUE, connection will be established only when required
*
* @author David Grudl
@@ -114,8 +114,7 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
throw new DibiDriverException($err['message'], $err['code'], $sql);
}
} else {
- $err = oci_error($this->connection);
- throw new DibiDriverException($err['message'], $err['code'], $sql);
+ $this->throwException($sql);
}
return is_resource($this->resultset);
@@ -126,7 +125,7 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -150,6 +149,7 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
@@ -161,12 +161,12 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
if (!oci_commit($this->connection)) {
- $err = oci_error($this->connection);
- throw new DibiDriverException($err['message'], $err['code']);
+ $this->throwException();
}
$this->autocommit = TRUE;
}
@@ -176,12 +176,12 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
if (!oci_rollback($this->connection)) {
- $err = oci_error($this->connection);
- throw new DibiDriverException($err['message'], $err['code']);
+ $this->throwException();
}
$this->autocommit = TRUE;
}
@@ -290,6 +290,20 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ $err = oci_error($this->connection);
+ throw new DibiDriverException($err['message'], $err['code'], $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/pdo.php b/dibi/drivers/pdo.php
index 095f1239..b756aed5 100644
--- a/dibi/drivers/pdo.php
+++ b/dibi/drivers/pdo.php
@@ -77,8 +77,6 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
if (!$this->connection) {
throw new DibiDriverException('Connecting error');
}
-
- $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
@@ -103,11 +101,12 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
*/
public function query($sql)
{
- try {
- $this->resultset = $this->connection->query($sql);
- } catch (PDOException $e) {
- throw new DibiDriverException($e->getMessage(), $e->getCode(), $sql);
+ $this->resultset = $this->connection->query($sql);
+
+ if ($this->resultset === FALSE) {
+ $this->throwException($sql);
}
+
return $this->resultset instanceof PDOStatement;
}
@@ -116,7 +115,7 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -140,13 +139,12 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
- try {
- $this->connection->beginTransaction();
- } catch (PDOException $e) {
- throw new DibiDriverException($e->getMessage(), $e->getCode());
+ if (!$this->connection->beginTransaction()) {
+ $this->throwException();
}
}
@@ -155,13 +153,12 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
- try {
- $this->connection->commit();
- } catch (PDOException $e) {
- throw new DibiDriverException($e->getMessage(), $e->getCode());
+ if (!$this->connection->commit()) {
+ $this->throwException();
}
}
@@ -170,13 +167,12 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
- try {
- $this->connection->rollBack();
- } catch (PDOException $e) {
- throw new DibiDriverException($e->getMessage(), $e->getCode());
+ if (!$this->connection->rollBack()) {
+ $this->throwException();
}
}
@@ -284,6 +280,20 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ $err = $this->connection->errorInfo();
+ throw new DibiDriverException("SQLSTATE[$err[0]]: $err[2]", $err[1], $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/postgre.php b/dibi/drivers/postgre.php
index 82a06739..1b137507 100644
--- a/dibi/drivers/postgre.php
+++ b/dibi/drivers/postgre.php
@@ -22,9 +22,10 @@
* The dibi driver for PostgreSQL database
*
* Connection options:
- * - 'database' (or 'string') - connection string
+ * - 'host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service' - see PostgreSQL API
+ * - 'string' - or use connection string
* - 'persistent' - try to find a persistent link?
- * - 'charset' - sets the encoding
+ * - 'charset' - character encoding to set
* - 'lazy' - if TRUE, connection will be established only when required
*
* @author David Grudl
@@ -58,21 +59,26 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
*/
public function connect(array &$config)
{
- DibiConnection::alias($config, 'database', 'string');
- DibiConnection::alias($config, 'type');
-
if (!extension_loaded('pgsql')) {
throw new DibiException("PHP extension 'pgsql' is not loaded");
}
-
- NException::catchError('DibiDriverException');
- if (isset($config['persistent'])) {
- $this->connection = @pg_connect($config['database'], PGSQL_CONNECT_FORCE_NEW);
+ if (isset($config['string'])) {
+ $string = $config['string'];
} else {
- $this->connection = @pg_pconnect($config['database'], PGSQL_CONNECT_FORCE_NEW);
+ $string = '';
+ foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) {
+ if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' ';
+ }
}
- NException::restore();
+
+ DibiDriverException::catchError();
+ if (isset($config['persistent'])) {
+ $this->connection = @pg_connect($string, PGSQL_CONNECT_FORCE_NEW);
+ } else {
+ $this->connection = @pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW);
+ }
+ DibiDriverException::restore();
if (!is_resource($this->connection)) {
throw new DibiDriverException('Connecting error');
@@ -111,7 +117,7 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
$this->resultset = @pg_query($this->connection, $sql);
if ($this->resultset === FALSE) {
- throw new DibiDriverException(pg_last_error($this->connection), 0, $sql);
+ $this->throwException($sql);
}
return is_resource($this->resultset);
@@ -122,7 +128,7 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -145,13 +151,11 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
$has = $this->query("SELECT CURRVAL('$sequence') AS seq");
}
- if ($has) {
- $row = $this->fetch();
- $this->free();
- return $row['seq'];
- }
+ if (!$has) return FALSE;
- return FALSE;
+ $row = $this->fetch();
+ $this->free();
+ return isset($row['seq']) ? $row['seq'] : FALSE;
}
@@ -159,6 +163,7 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
@@ -170,6 +175,7 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
@@ -181,6 +187,7 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
@@ -318,6 +325,19 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ throw new DibiDriverException(pg_last_error($this->connection), 0, $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/drivers/sqlite.php b/dibi/drivers/sqlite.php
index af21b81b..b235bd4e 100644
--- a/dibi/drivers/sqlite.php
+++ b/dibi/drivers/sqlite.php
@@ -26,6 +26,8 @@
* - 'persistent' - try to find a persistent link?
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
* - 'lazy' - if TRUE, connection will be established only when required
+ * - 'format:date' - how to format date in SQL (@see date)
+ * - 'format:datetime' - how to format datetime in SQL (@see date)
*
* @author David Grudl
* @copyright Copyright (c) 2005, 2007 David Grudl
@@ -55,6 +57,12 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
*/
private $buffered;
+ /**
+ * Date and datetime format
+ * @var string
+ */
+ private $fmtDate, $fmtDateTime;
+
/**
* Connects to a database
@@ -65,6 +73,8 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
public function connect(array &$config)
{
DibiConnection::alias($config, 'database', 'file');
+ $this->fmtDate = isset($config['format:date']) ? $config['format:date'] : 'U';
+ $this->fmtDateTime = isset($config['format:datetime']) ? $config['format:datetime'] : 'U';
if (!extension_loaded('sqlite')) {
throw new DibiException("PHP extension 'sqlite' is not loaded");
@@ -108,14 +118,16 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
{
$errorMsg = NULL;
+ DibiDriverException::catchError();
if ($this->buffered) {
- $this->resultset = @sqlite_query($this->connection, $sql, SQLITE_ASSOC, $errorMsg);
+ $this->resultset = sqlite_query($this->connection, $sql, SQLITE_ASSOC);
} else {
- $this->resultset = @sqlite_unbuffered_query($this->connection, $sql, SQLITE_ASSOC, $errorMsg);
+ $this->resultset = sqlite_unbuffered_query($this->connection, $sql, SQLITE_ASSOC);
}
+ DibiDriverException::restore();
- if ($errorMsg !== NULL) {
- throw new DibiDriverException($errorMsg, sqlite_last_error($this->connection), $sql);
+ if (sqlite_last_error($this->connection)) {
+ $this->throwException();
}
return is_resource($this->resultset);
@@ -126,7 +138,7 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
public function affectedRows()
{
@@ -150,6 +162,7 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
public function begin()
{
@@ -161,6 +174,7 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function commit()
{
@@ -172,6 +186,7 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
public function rollback()
{
@@ -193,8 +208,8 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
if ($type === dibi::FIELD_TEXT) return "'" . sqlite_escape_string($value) . "'";
if ($type === dibi::IDENTIFIER) return '[' . str_replace('.', '].[', $value) . ']';
if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0;
- if ($type === dibi::FIELD_DATE) return date("U", $value);
- if ($type === dibi::FIELD_DATETIME) return date("U", $value);
+ if ($type === dibi::FIELD_DATE) return date($this->fmtDate, $value);
+ if ($type === dibi::FIELD_DATETIME) return date($this->fmtDateTime, $value);
throw new InvalidArgumentException('Unsupported formatting type');
}
@@ -287,6 +302,20 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
}
+
+ /**
+ * Converts database error to DibiDriverException
+ *
+ * @throws DibiDriverException
+ */
+ protected function throwException($sql=NULL)
+ {
+ $errno = sqlite_last_error($this->connection);
+ throw new DibiDriverException(sqlite_error_string($errno), $errno, $sql);
+ }
+
+
+
/**
* Returns the connection resource
*
diff --git a/dibi/libs/DibiConnection.php b/dibi/libs/DibiConnection.php
index fd391280..3e2c54e2 100644
--- a/dibi/libs/DibiConnection.php
+++ b/dibi/libs/DibiConnection.php
@@ -47,6 +47,12 @@ class DibiConnection extends NObject
*/
private $connected = FALSE;
+ /**
+ * Is in transaction?
+ * @var bool
+ */
+ private $inTxn = FALSE;
+
/**
@@ -122,6 +128,9 @@ class DibiConnection extends NObject
final public function disconnect()
{
if ($this->connected) {
+ if ($this->inTxn) {
+ $this->rollback();
+ }
$this->driver->disconnect();
$this->connected = FALSE;
dibi::notify($this, 'disconnected');
@@ -259,12 +268,14 @@ class DibiConnection extends NObject
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int number of rows
+ * @throws DibiException
*/
public function affectedRows()
{
$rows = $this->driver->affectedRows();
- return $rows < 0 ? FALSE : $rows;
+ if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows');
+ return $rows;
}
@@ -272,12 +283,15 @@ class DibiConnection extends NObject
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query
*
- * @return int|FALSE int on success or FALSE on failure
+ * @param string optional sequence name
+ * @return int
+ * @throws DibiException
*/
public function insertId($sequence = NULL)
{
$id = $this->driver->insertId($sequence);
- return $id < 1 ? FALSE : $id;
+ if ($id < 1) throw new DibiException('Cannot retrieve last generated ID');
+ return $id;
}
@@ -289,8 +303,14 @@ class DibiConnection extends NObject
public function begin()
{
$this->connect();
+ if ($this->inTxn) {
+ throw new DibiException('There is already an active transaction');
+ }
$this->driver->begin();
+ $this->inTxn = TRUE;
dibi::notify($this, 'begin');
+
+ return $this;
}
@@ -301,8 +321,11 @@ class DibiConnection extends NObject
*/
public function commit()
{
- $this->connect();
+ if (!$this->inTxn) {
+ throw new DibiException('There is no active transaction');
+ }
$this->driver->commit();
+ $this->inTxn = FALSE;
dibi::notify($this, 'commit');
}
@@ -314,8 +337,11 @@ class DibiConnection extends NObject
*/
public function rollback()
{
- $this->connect();
+ if (!$this->inTxn) {
+ throw new DibiException('There is no active transaction');
+ }
$this->driver->rollback();
+ $this->inTxn = FALSE;
dibi::notify($this, 'rollback');
}
@@ -375,6 +401,26 @@ class DibiConnection extends NObject
+ /**
+ * Prevents unserialization
+ */
+ public function __wakeup()
+ {
+ throw new DibiException('You cannot serialize or unserialize '.__CLASS__.' instances');
+ }
+
+
+
+ /**
+ * Prevents serialization
+ */
+ public function __sleep()
+ {
+ throw new DibiException('You cannot serialize or unserialize '.__CLASS__.' instances');
+ }
+
+
+
/**
* Returns last error
* @deprecated
@@ -384,6 +430,4 @@ class DibiConnection extends NObject
throw new BadMethodCallException(__METHOD__ . ' has been deprecated');
}
-
-
}
diff --git a/dibi/libs/DibiDriverInterface.php b/dibi/libs/DibiDriverInterface.php
index 2ef33559..67e28239 100644
--- a/dibi/libs/DibiDriverInterface.php
+++ b/dibi/libs/DibiDriverInterface.php
@@ -65,7 +65,7 @@ interface DibiDriverInterface
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query
*
- * @return int number of rows or FALSE on error
+ * @return int|FALSE number of rows or FALSE on error
*/
function affectedRows();
@@ -83,6 +83,7 @@ interface DibiDriverInterface
/**
* Begins a transaction (if supported).
* @return void
+ * @throws DibiDriverException
*/
function begin();
@@ -91,6 +92,7 @@ interface DibiDriverInterface
/**
* Commits statements in a transaction.
* @return void
+ * @throws DibiDriverException
*/
function commit();
@@ -99,6 +101,7 @@ interface DibiDriverInterface
/**
* Rollback changes in a transaction.
* @return void
+ * @throws DibiDriverException
*/
function rollback();
@@ -165,6 +168,7 @@ interface DibiDriverInterface
function free();
+
/**
* Returns the connection resource
*
diff --git a/dibi/libs/DibiException.php b/dibi/libs/DibiException.php
index 254cfa46..9aaa2c27 100644
--- a/dibi/libs/DibiException.php
+++ b/dibi/libs/DibiException.php
@@ -46,6 +46,13 @@ class DibiDriverException extends DibiException
private $sql;
+ /**
+ * Construct an dibi driver exception
+ *
+ * @param string Message describing the exception
+ * @param int Some code
+ * @param string SQL command
+ */
public function __construct($message = NULL, $code = 0, $sql = NULL)
{
parent::__construct($message, (int) $code);
@@ -55,6 +62,9 @@ class DibiDriverException extends DibiException
+ /**
+ * @return string The SQL passed to the constructor
+ */
final public function getSql()
{
return $this->sql;
@@ -62,9 +72,22 @@ class DibiDriverException extends DibiException
+ /**
+ * @return string string represenation of exception with SQL command
+ */
public function __toString()
{
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
}
+
+
+ /**
+ * @see NException::catchError (this is Late static binding fix
+ */
+ public static function catchError($class = __CLASS__)
+ {
+ parent::catchError($class);
+ }
+
}
\ No newline at end of file
diff --git a/dibi/libs/NException.php b/dibi/libs/NException.php
index c87bab25..d27b6ca5 100644
--- a/dibi/libs/NException.php
+++ b/dibi/libs/NException.php
@@ -74,7 +74,7 @@ class NException extends Exception
/**
* Returns string represenation of exception
*
- * @return void
+ * @return string
*/
public function __toString()
{
diff --git a/examples/connect.php b/examples/connect.php
index afa4a17c..efd2a329 100644
--- a/examples/connect.php
+++ b/examples/connect.php
@@ -14,7 +14,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "
\n";
@@ -28,7 +28,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
@@ -49,7 +49,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
@@ -68,7 +68,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
@@ -86,7 +86,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
@@ -103,7 +103,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
@@ -121,7 +121,7 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
@@ -139,6 +139,6 @@ try {
echo 'OK';
} catch (DibiException $e) {
- echo get_class($e), ': ', $e->getMessage();
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
echo "\n";
\ No newline at end of file
diff --git a/examples/date.type.demo.php b/examples/date.type.demo.php
deleted file mode 100644
index 2c8d5bbd..00000000
--- a/examples/date.type.demo.php
+++ /dev/null
@@ -1,73 +0,0 @@
-DibiVariableInterface example
-time = time(); // current time
-
- elseif (is_string($time))
- $this->time = strtotime($time); // try convert to timestamp
-
- else
- $this->time = (int) $time;
- }
-
-
-
- /**
- * Format for SQL
- *
- * @param object destination DibiDriver
- * @param string optional modifier
- * @return string
- */
- public function toSql(DibiDriverInterface $driver, $modifier)
- {
- return $driver->format($this->time, dibi::FIELD_DATETIME); // format according to driver's spec.
- }
-
-
-
-}
-
-
-
-// CHANGE TO REAL PARAMETERS!
-dibi::connect(array(
- 'driver' => 'sqlite',
- 'database' => 'sample.sdb',
-));
-
-
-
-// generate and dump SQL
-dibi::test("
-INSERT INTO [mytable]", array(
- 'A' => 12,
- 'B' => NULL,
- 'C' => new MyDateTime(31542), // using out class
- 'D' => 'any string',
-));
diff --git a/examples/datetime.demo.php b/examples/datetime.demo.php
new file mode 100644
index 00000000..3e7016c8
--- /dev/null
+++ b/examples/datetime.demo.php
@@ -0,0 +1,30 @@
+DibiVariableInterface example
+ 'sqlite',
+ 'database' => 'sample.sdb',
+ 'format:date' => "'Y-m-d'",
+ 'format:datetime' => "'Y-m-d H-i-s'",
+));
+
+
+
+// generate and dump SQL
+dibi::test("
+INSERT INTO [mytable]", array(
+ 'id' => 123,
+ 'date' => dibi::date('12.3.2007'),
+ 'stamp' => dibi::dateTime('23.1.2007 10:23'),
+));
diff --git a/examples/transaction.php b/examples/transaction.php
new file mode 100644
index 00000000..4d5cd61b
--- /dev/null
+++ b/examples/transaction.php
@@ -0,0 +1,28 @@
+dibi transaction example
+
+ 'sqlite',
+ 'database' => 'sample.sdb',
+));
+
+
+echo "Before:
\n";
+dibi::query('SELECT * FROM [products]')->dump();
+
+
+
+dibi::begin();
+dibi::query('INSERT INTO [products]', array(
+ 'title' => 'Test product',
+));
+dibi::rollback(); // or dibi::commit();
+
+
+
+echo "After:
\n";
+dibi::query('SELECT * FROM [products]')->dump();
\ No newline at end of file