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