From 7bb5684d71411c0a9070103aeea8150443b6b84d Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 12 May 2008 00:30:59 +0000 Subject: [PATCH] code formatting: 4 spaces -> tabs --- dibi/Nette/IDebuggable.php | 10 +- dibi/Nette/Object.php | 288 ++++---- dibi/dibi.php | 1060 ++++++++++++++--------------- dibi/drivers/mssql.php | 572 ++++++++-------- dibi/drivers/mysql.php | 710 ++++++++++---------- dibi/drivers/mysqli.php | 668 +++++++++---------- dibi/drivers/odbc.php | 656 +++++++++--------- dibi/drivers/oracle.php | 628 +++++++++--------- dibi/drivers/pdo.php | 660 +++++++++--------- dibi/drivers/postgre.php | 688 +++++++++---------- dibi/drivers/sqlite.php | 622 ++++++++--------- dibi/libs/DibiConnection.php | 858 ++++++++++++------------ dibi/libs/DibiDataSource.php | 94 +-- dibi/libs/DibiException.php | 156 ++--- dibi/libs/DibiLogger.php | 118 ++-- dibi/libs/DibiResult.php | 1068 +++++++++++++++--------------- dibi/libs/DibiResultIterator.php | 126 ++-- dibi/libs/DibiTable.php | 414 ++++++------ dibi/libs/DibiTranslator.php | 678 +++++++++---------- dibi/libs/DibiVariable.php | 26 +- dibi/libs/interfaces.php | 268 ++++---- examples/apply-limit.php | 10 +- examples/connect.php | 114 ++-- examples/datetime.demo.php | 14 +- examples/dibi.table.php | 6 +- examples/dump.php | 4 +- examples/extension.method.php | 10 +- examples/fetch.php | 16 +- examples/load-sql-dump.php | 4 +- examples/logger.php | 12 +- examples/metatypes.php | 4 +- examples/nette-debug.php | 4 +- examples/profiler.php | 6 +- examples/sql-builder.php | 22 +- examples/sql-condition.php | 14 +- examples/table-prefix.php | 4 +- examples/transaction.php | 6 +- 37 files changed, 5309 insertions(+), 5309 deletions(-) diff --git a/dibi/Nette/IDebuggable.php b/dibi/Nette/IDebuggable.php index 650c4eff..8931218a 100644 --- a/dibi/Nette/IDebuggable.php +++ b/dibi/Nette/IDebuggable.php @@ -27,10 +27,10 @@ interface IDebuggable { - /** - * Returns custom panels. - * @return array - */ - function getPanels(); + /** + * Returns custom panels. + * @return array + */ + function getPanels(); } diff --git a/dibi/Nette/Object.php b/dibi/Nette/Object.php index 6bd98b2d..75b41f33 100644 --- a/dibi/Nette/Object.php +++ b/dibi/Nette/Object.php @@ -64,213 +64,213 @@ abstract class Object { - /** - * Returns the name of the class of this object. - * - * @return string - */ - final public function getClass() - { - return get_class($this); - } + /** + * Returns the name of the class of this object. + * + * @return string + */ + final public function getClass() + { + return get_class($this); + } - /** - * Access to reflection. - * - * @return ReflectionObject - */ - final public function getReflection() - { - return new ReflectionObject($this); - } + /** + * Access to reflection. + * + * @return ReflectionObject + */ + final public function getReflection() + { + return new ReflectionObject($this); + } - /** - * Call to undefined method. - * - * @param string method name - * @param array arguments - * @return mixed - * @throws ::MemberAccessException - */ - protected function __call($name, $args) - { - if ($name === '') { - throw new /*::*/MemberAccessException("Call to method without name."); - } + /** + * Call to undefined method. + * + * @param string method name + * @param array arguments + * @return mixed + * @throws ::MemberAccessException + */ + protected function __call($name, $args) + { + if ($name === '') { + throw new /*::*/MemberAccessException("Call to method without name."); + } - $class = get_class($this); + $class = get_class($this); - // event functionality - if (self::hasEvent($class, $name)) { - $list = $this->$name; - if (is_array($list) || $list instanceof Traversable) { - foreach ($list as $handler) { - call_user_func_array($handler, $args); - } - } - return; - } + // event functionality + if (self::hasEvent($class, $name)) { + $list = $this->$name; + if (is_array($list) || $list instanceof Traversable) { + foreach ($list as $handler) { + call_user_func_array($handler, $args); + } + } + return; + } - // object prototypes support Class__method() - // (or use class Class__method { static function ... } with autoloading?) - $cl = $class; - do { - if (function_exists($nm = $cl . '_prototype_' . $name)) { - array_unshift($args, $this); - return call_user_func_array($nm, $args); - } - } while ($cl = get_parent_class($cl)); + // object prototypes support Class__method() + // (or use class Class__method { static function ... } with autoloading?) + $cl = $class; + do { + if (function_exists($nm = $cl . '_prototype_' . $name)) { + array_unshift($args, $this); + return call_user_func_array($nm, $args); + } + } while ($cl = get_parent_class($cl)); - throw new /*::*/MemberAccessException("Call to undefined method $class::$name()."); - } + throw new /*::*/MemberAccessException("Call to undefined method $class::$name()."); + } - /** - * Call to undefined static method. - * - * @param string method name (in lower case!) - * @param array arguments - * @return mixed - * @throws ::MemberAccessException - */ - protected static function __callStatic($name, $args) - { - $class = get_called_class(); - throw new /*::*/MemberAccessException("Call to undefined static method $class::$name()."); - } + /** + * Call to undefined static method. + * + * @param string method name (in lower case!) + * @param array arguments + * @return mixed + * @throws ::MemberAccessException + */ + protected static function __callStatic($name, $args) + { + $class = get_called_class(); + throw new /*::*/MemberAccessException("Call to undefined static method $class::$name()."); + } - /** + /** * Returns property value. Do not call directly. - * - * @param string property name + * + * @param string property name * @return mixed property value * @throws ::MemberAccessException if the property is not defined. */ protected function &__get($name) { - if ($name === '') { - throw new /*::*/MemberAccessException("Cannot read an property without name."); - } + if ($name === '') { + throw new /*::*/MemberAccessException("Cannot read an property without name."); + } - // property getter support - $class = get_class($this); - $m = 'get' . $name; - if (self::hasAccessor($class, $m)) { - // ampersands: - // - using &__get() because declaration should be forward compatible (e.g. with Nette::Web::Html) - // - not using &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value'; - $val = $this->$m(); - return $val; + // property getter support + $class = get_class($this); + $m = 'get' . $name; + if (self::hasAccessor($class, $m)) { + // ampersands: + // - using &__get() because declaration should be forward compatible (e.g. with Nette::Web::Html) + // - not using &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value'; + $val = $this->$m(); + return $val; - } else { - throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name."); - } + } else { + throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name."); + } } /** * Sets value of a property. Do not call directly. - * + * * @param string property name * @param mixed property value - * @return void - * @throws ::MemberAccessException if the property is not defined or is read-only + * @return void + * @throws ::MemberAccessException if the property is not defined or is read-only */ protected function __set($name, $value) { - if ($name === '') { - throw new /*::*/MemberAccessException('Cannot assign to an property without name.'); - } + if ($name === '') { + throw new /*::*/MemberAccessException('Cannot assign to an property without name.'); + } - // property setter support - $class = get_class($this); - if (self::hasAccessor($class, 'get' . $name)) { - $m = 'set' . $name; - if (self::hasAccessor($class, $m)) { - $this->$m($value); + // property setter support + $class = get_class($this); + if (self::hasAccessor($class, 'get' . $name)) { + $m = 'set' . $name; + if (self::hasAccessor($class, $m)) { + $this->$m($value); - } else { - throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name."); - } + } else { + throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name."); + } - } else { - throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name."); - } + } else { + throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name."); + } } /** * Is property defined? - * + * * @param string property name * @return bool */ - protected function __isset($name) + protected function __isset($name) { - return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name); + return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name); } - /** - * Access to undeclared property. - * - * @param string property name + /** + * Access to undeclared property. + * + * @param string property name * @return void - * @throws ::MemberAccessException - */ - protected function __unset($name) - { - $class = get_class($this); - throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name."); - } + * @throws ::MemberAccessException + */ + protected function __unset($name) + { + $class = get_class($this); + throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name."); + } - /** + /** * Has property an accessor? - * + * * @param string class name - * @param string method name + * @param string method name * @return bool */ - private static function hasAccessor($c, $m) - { - static $cache; - if (!isset($cache[$c])) { - // get_class_methods returns private, protected and public methods of Object (doesn't matter) - // and ONLY PUBLIC methods of descendants (perfect!) - // but returns static methods too (nothing doing...) - // and is much faster than reflection - // (works good since 5.0.4) - $cache[$c] = array_flip(get_class_methods($c)); - } - // case-sensitive checking, capitalize the fourth character - $m[3] = $m[3] & "\xDF"; - return isset($cache[$c][$m]); - } + private static function hasAccessor($c, $m) + { + static $cache; + if (!isset($cache[$c])) { + // get_class_methods returns private, protected and public methods of Object (doesn't matter) + // and ONLY PUBLIC methods of descendants (perfect!) + // but returns static methods too (nothing doing...) + // and is much faster than reflection + // (works good since 5.0.4) + $cache[$c] = array_flip(get_class_methods($c)); + } + // case-sensitive checking, capitalize the fourth character + $m[3] = $m[3] & "\xDF"; + return isset($cache[$c][$m]); + } - /** - * Is property an event? - * - * @param string class name - * @param string method name + /** + * Is property an event? + * + * @param string class name + * @param string method name * @return bool - */ - private static function hasEvent($c, $m) - { - return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m); - } + */ + private static function hasEvent($c, $m) + { + return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m); + } } diff --git a/dibi/dibi.php b/dibi/dibi.php index 633e59bb..d71bb01d 100644 --- a/dibi/dibi.php +++ b/dibi/dibi.php @@ -24,7 +24,7 @@ * Check PHP configuration. */ if (version_compare(PHP_VERSION, '5.1.0', '<')) { - throw new Exception('dibi needs PHP 5.1.0 or newer.'); + throw new Exception('dibi needs PHP 5.1.0 or newer.'); } @@ -64,580 +64,580 @@ require_once dirname(__FILE__) . '/libs/DibiDataSource.php'; */ class dibi { - /** - * Column type in relation to PHP native type. - */ - const - FIELD_TEXT = 's', // as 'string' - FIELD_BINARY = 'S', - FIELD_BOOL = 'b', - FIELD_INTEGER = 'i', - FIELD_FLOAT = 'f', - FIELD_DATE = 'd', - FIELD_DATETIME = 't', - FIELD_UNKNOWN = '?', - - // special - FIELD_COUNTER = 'C', // counter or autoincrement, is integer - IDENTIFIER = 'n', - - // dibi version - VERSION = '0.9 (Revision: $WCREV$, Date: $WCDATE$)'; - - - /** - * Connection registry storage for DibiConnection objects. - * @var DibiConnection[] - */ - private static $registry = array(); - - /** - * Current connection. - * @var DibiConnection - */ - private static $connection; - - /** - * Substitutions for identifiers. - * @var array - */ - private static $substs = array(); - - /** - * @see addHandler - * @var array - */ - private static $handlers = array(); - - /** - * Last SQL command @see dibi::query() - * @var string - */ - public static $sql; - - /** - * Elapsed time for last query. - * @var int - */ - public static $elapsedTime; - - /** - * Elapsed time for all queries. - * @var int - */ - public static $totalTime; - - /** - * Number or queries. - * @var int - */ - public static $numOfQueries = 0; - - /** - * Default dibi driver. - * @var string - */ - public static $defaultDriver = 'mysql'; + /** + * Column type in relation to PHP native type. + */ + const + FIELD_TEXT = 's', // as 'string' + FIELD_BINARY = 'S', + FIELD_BOOL = 'b', + FIELD_INTEGER = 'i', + FIELD_FLOAT = 'f', + FIELD_DATE = 'd', + FIELD_DATETIME = 't', + FIELD_UNKNOWN = '?', + + // special + FIELD_COUNTER = 'C', // counter or autoincrement, is integer + IDENTIFIER = 'n', + + // dibi version + VERSION = '0.9 (Revision: $WCREV$, Date: $WCDATE$)'; + + + /** + * Connection registry storage for DibiConnection objects. + * @var DibiConnection[] + */ + private static $registry = array(); + + /** + * Current connection. + * @var DibiConnection + */ + private static $connection; + + /** + * Substitutions for identifiers. + * @var array + */ + private static $substs = array(); + + /** + * @see addHandler + * @var array + */ + private static $handlers = array(); + + /** + * Last SQL command @see dibi::query() + * @var string + */ + public static $sql; + + /** + * Elapsed time for last query. + * @var int + */ + public static $elapsedTime; + + /** + * Elapsed time for all queries. + * @var int + */ + public static $totalTime; + + /** + * Number or queries. + * @var int + */ + public static $numOfQueries = 0; + + /** + * Default dibi driver. + * @var string + */ + public static $defaultDriver = 'mysql'; - /** - * Static class - cannot be instantiated. - */ - final public function __construct() - { - throw new LogicException("Cannot instantiate static class " . get_class($this)); - } - - - - /********************* connections handling ****************d*g**/ - - - - /** - * Creates a new DibiConnection object and connects it to specified database. - * - * @param array|string|Nette::Collections::IMap connection parameters - * @param string connection name - * @return DibiConnection - * @throws DibiException - */ - public static function connect($config = array(), $name = 0) - { - if (class_exists(/*Nette::*/'Debug', FALSE)) { - /*Nette::*/Debug::addColophon(array(__CLASS__, 'getColophon')); - } + /** + * Static class - cannot be instantiated. + */ + final public function __construct() + { + throw new LogicException("Cannot instantiate static class " . get_class($this)); + } + + + + /********************* connections handling ****************d*g**/ + + + + /** + * Creates a new DibiConnection object and connects it to specified database. + * + * @param array|string|Nette::Collections::IMap connection parameters + * @param string connection name + * @return DibiConnection + * @throws DibiException + */ + public static function connect($config = array(), $name = 0) + { + if (class_exists(/*Nette::*/'Debug', FALSE)) { + /*Nette::*/Debug::addColophon(array(__CLASS__, 'getColophon')); + } - return self::$connection = self::$registry[$name] = new DibiConnection($config, $name); - } + return self::$connection = self::$registry[$name] = new DibiConnection($config, $name); + } - /** - * Disconnects from database (doesn't destroy DibiConnection object). - * - * @return void - */ - public static function disconnect() - { - self::getConnection()->disconnect(); - } + /** + * Disconnects from database (doesn't destroy DibiConnection object). + * + * @return void + */ + public static function disconnect() + { + self::getConnection()->disconnect(); + } - /** - * Returns TRUE when connection was established. - * - * @return bool - */ - public static function isConnected() - { - return (bool) self::$connection; - } - + /** + * Returns TRUE when connection was established. + * + * @return bool + */ + public static function isConnected() + { + return (bool) self::$connection; + } + - /** - * Retrieve active connection. - * - * @param string connection registy name - * @return object DibiConnection object. - * @throws DibiException - */ - public static function getConnection($name = NULL) - { - if ($name === NULL) { - if (!self::$connection) { - throw new DibiException('Dibi is not connected to database.'); - } + /** + * Retrieve active connection. + * + * @param string connection registy name + * @return object DibiConnection object. + * @throws DibiException + */ + public static function getConnection($name = NULL) + { + if ($name === NULL) { + if (!self::$connection) { + throw new DibiException('Dibi is not connected to database.'); + } - return self::$connection; - } + return self::$connection; + } - if (!isset(self::$registry[$name])) { - throw new DibiException("There is no connection named '$name'."); - } + if (!isset(self::$registry[$name])) { + throw new DibiException("There is no connection named '$name'."); + } - return self::$registry[$name]; - } + return self::$registry[$name]; + } - /** - * Change active connection. - * - * @param string connection registy name - * @return void - * @throws DibiException - */ - public static function activate($name) - { - self::$connection = self::getConnection($name); - } + /** + * Change active connection. + * + * @param string connection registy name + * @return void + * @throws DibiException + */ + public static function activate($name) + { + self::$connection = self::getConnection($name); + } - /********************* monostate for active connection ****************d*g**/ - - - - /** - * Generates and executes SQL query - Monostate for DibiConnection::query(). - * - * @param array|mixed one or more arguments - * @return DibiResult Result set object (if any) - * @throws DibiException - */ - public static function query($args) - { - $args = func_get_args(); - return self::getConnection()->query($args); - } - - - - /** - * Executes the SQL query - Monostate for DibiConnection::nativeQuery(). - * - * @param string SQL statement. - * @return DibiResult Result set object (if any) - */ - public static function nativeQuery($sql) - { - return self::getConnection()->nativeQuery($sql); - } - - - - /** - * Generates and prints SQL query - Monostate for DibiConnection::test(). - * - * @param array|mixed one or more arguments - * @return bool - */ - public static function test($args) - { - $args = func_get_args(); - return self::getConnection()->test($args); - } - - - - /** - * Executes SQL query and fetch result - Monostate for DibiConnection::query() & fetch(). - * - * @param array|mixed one or more arguments - * @return array - * @throws DibiException - */ - public static function fetch($args) - { - $args = func_get_args(); - return self::getConnection()->query($args)->fetch(); - } - - - - /** - * Executes SQL query and fetch results - Monostate for DibiConnection::query() & fetchAll(). - * - * @param array|mixed one or more arguments - * @return array - * @throws DibiException - */ - public static function fetchAll($args) - { - $args = func_get_args(); - return self::getConnection()->query($args)->fetchAll(); - } - - - - /** - * Executes SQL query and fetch first column - Monostate for DibiConnection::query() & fetchSingle(). - * - * @param array|mixed one or more arguments - * @return string - * @throws DibiException - */ - public static function fetchSingle($args) - { - $args = func_get_args(); - return self::getConnection()->query($args)->fetchSingle(); - } - - - - /** - * Gets the number of affected rows. - * Monostate for DibiConnection::affectedRows() - * - * @return int number of rows - * @throws DibiException - */ - public static function affectedRows() - { - return self::getConnection()->affectedRows(); - } - - - - /** - * 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() - { - self::getConnection()->begin(); - } - - - - /** - * Commits statements in a transaction - Monostate for DibiConnection::commit(). - * @return void - * @throws DibiException - */ - public static function commit() - { - self::getConnection()->commit(); - } - - - - /** - * Rollback changes in a transaction - Monostate for DibiConnection::rollback(). - * @return void - * @throws DibiException - */ - public static function rollback() - { - self::getConnection()->rollback(); - } - - - - /** - * Import SQL dump from file - extreme fast! - * - * @param string filename - * @return int count of sql commands - */ - public static function loadFile($file) - { - return self::getConnection()->loadFile($file); - } - + /********************* monostate for active connection ****************d*g**/ + + + + /** + * Generates and executes SQL query - Monostate for DibiConnection::query(). + * + * @param array|mixed one or more arguments + * @return DibiResult Result set object (if any) + * @throws DibiException + */ + public static function query($args) + { + $args = func_get_args(); + return self::getConnection()->query($args); + } + + + + /** + * Executes the SQL query - Monostate for DibiConnection::nativeQuery(). + * + * @param string SQL statement. + * @return DibiResult Result set object (if any) + */ + public static function nativeQuery($sql) + { + return self::getConnection()->nativeQuery($sql); + } + + + + /** + * Generates and prints SQL query - Monostate for DibiConnection::test(). + * + * @param array|mixed one or more arguments + * @return bool + */ + public static function test($args) + { + $args = func_get_args(); + return self::getConnection()->test($args); + } + + + + /** + * Executes SQL query and fetch result - Monostate for DibiConnection::query() & fetch(). + * + * @param array|mixed one or more arguments + * @return array + * @throws DibiException + */ + public static function fetch($args) + { + $args = func_get_args(); + return self::getConnection()->query($args)->fetch(); + } + + + + /** + * Executes SQL query and fetch results - Monostate for DibiConnection::query() & fetchAll(). + * + * @param array|mixed one or more arguments + * @return array + * @throws DibiException + */ + public static function fetchAll($args) + { + $args = func_get_args(); + return self::getConnection()->query($args)->fetchAll(); + } + + + + /** + * Executes SQL query and fetch first column - Monostate for DibiConnection::query() & fetchSingle(). + * + * @param array|mixed one or more arguments + * @return string + * @throws DibiException + */ + public static function fetchSingle($args) + { + $args = func_get_args(); + return self::getConnection()->query($args)->fetchSingle(); + } + + + + /** + * Gets the number of affected rows. + * Monostate for DibiConnection::affectedRows() + * + * @return int number of rows + * @throws DibiException + */ + public static function affectedRows() + { + return self::getConnection()->affectedRows(); + } + + + + /** + * 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() + { + self::getConnection()->begin(); + } + + + + /** + * Commits statements in a transaction - Monostate for DibiConnection::commit(). + * @return void + * @throws DibiException + */ + public static function commit() + { + self::getConnection()->commit(); + } + + + + /** + * Rollback changes in a transaction - Monostate for DibiConnection::rollback(). + * @return void + * @throws DibiException + */ + public static function rollback() + { + self::getConnection()->rollback(); + } + + + + /** + * Import SQL dump from file - extreme fast! + * + * @param string filename + * @return int count of sql commands + */ + public static function loadFile($file) + { + return self::getConnection()->loadFile($file); + } + - /** - * Replacement for majority of dibi::methods() in future. - */ - protected static function __callStatic($name, $args) - { - return call_user_func_array(array(self::getConnection(), $name), $args); - } - - - - /********************* data types ****************d*g**/ - - - - /** - * 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); - } - + /** + * Replacement for majority of dibi::methods() in future. + */ + protected static function __callStatic($name, $args) + { + return call_user_func_array(array(self::getConnection(), $name), $args); + } + + + + /********************* data types ****************d*g**/ + + + + /** + * 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->modifier = dibi::FIELD_DATE; - return $var; - } - - - - /********************* substitutions ****************d*g**/ - - - - /** - * Create a new substitution pair for indentifiers. - * - * @param string from - * @param string to - * @return void - */ - public static function addSubst($expr, $subst) - { - self::$substs[':'.$expr.':'] = $subst; - } - - - - /** - * Remove substitution pair. - * - * @param mixed from or TRUE - * @return void - */ - public static function removeSubst($expr) - { - if ($expr === TRUE) { - self::$substs = array(); - } else { - unset(self::$substs[':'.$expr.':']); - } - } + /** + * Pseudotype for date representation. + * + * @param mixed date + * @return DibiVariable + */ + public static function date($date = NULL) + { + $var = self::datetime($date); + $var->modifier = dibi::FIELD_DATE; + return $var; + } + + + + /********************* substitutions ****************d*g**/ + + + + /** + * Create a new substitution pair for indentifiers. + * + * @param string from + * @param string to + * @return void + */ + public static function addSubst($expr, $subst) + { + self::$substs[':'.$expr.':'] = $subst; + } + + + + /** + * Remove substitution pair. + * + * @param mixed from or TRUE + * @return void + */ + public static function removeSubst($expr) + { + if ($expr === TRUE) { + self::$substs = array(); + } else { + unset(self::$substs[':'.$expr.':']); + } + } - /** - * Returns substitution pairs. - * - * @return array - */ - public static function getSubst() - { - return self::$substs; - } + /** + * Returns substitution pairs. + * + * @return array + */ + public static function getSubst() + { + return self::$substs; + } - /********************* event handling ****************d*g**/ + /********************* event handling ****************d*g**/ - /** - * Add new event handler. - * - * @param callback - * @return void - * @throws InvalidArgumentException - */ - public static function addHandler($callback) - { - if (!is_callable($callback)) { - throw new InvalidArgumentException("Invalid callback."); - } - - self::$handlers[] = $callback; - } - - + /** + * Add new event handler. + * + * @param callback + * @return void + * @throws InvalidArgumentException + */ + public static function addHandler($callback) + { + if (!is_callable($callback)) { + throw new InvalidArgumentException("Invalid callback."); + } + + self::$handlers[] = $callback; + } + + - /** - * Event notification (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback). - * - * @param DibiConnection - * @param string event name - * @param mixed - * @return void - */ - public static function notify(DibiConnection $connection = NULL, $event, $arg = NULL) - { - foreach (self::$handlers as $handler) { - call_user_func($handler, $connection, $event, $arg); - } - } - - - - /** - * Enable profiler & logger. - * - * @param string filename - * @param bool log all queries? - * @return DibiProfiler - */ - public static function startLogger($file, $logQueries = FALSE) - { - $logger = new DibiLogger($file); - $logger->logQueries = $logQueries; - self::addHandler(array($logger, 'handler')); - return $logger; - } + /** + * Event notification (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback). + * + * @param DibiConnection + * @param string event name + * @param mixed + * @return void + */ + public static function notify(DibiConnection $connection = NULL, $event, $arg = NULL) + { + foreach (self::$handlers as $handler) { + call_user_func($handler, $connection, $event, $arg); + } + } + + + + /** + * Enable profiler & logger. + * + * @param string filename + * @param bool log all queries? + * @return DibiProfiler + */ + public static function startLogger($file, $logQueries = FALSE) + { + $logger = new DibiLogger($file); + $logger->logQueries = $logQueries; + self::addHandler(array($logger, 'handler')); + return $logger; + } - /********************* misc tools ****************d*g**/ - - - - /** - * Prints out a syntax highlighted version of the SQL command or DibiResult. - * - * @param string|DibiResult - * @param bool return output instead of printing it? - * @return string - */ - public static function dump($sql = NULL, $return = FALSE) - { - ob_start(); - if ($sql instanceof DibiResult) { - $sql->dump(); - - } else { - if ($sql === NULL) $sql = self::$sql; - - static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE'; - static $keywords1 = 'SELECT|UPDATE|INSERT(?:\s+INTO)|REPLACE(?:\s+INTO)|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN'; - - // insert new lines - $sql = ' ' . $sql; - $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql); + /********************* misc tools ****************d*g**/ + + + + /** + * Prints out a syntax highlighted version of the SQL command or DibiResult. + * + * @param string|DibiResult + * @param bool return output instead of printing it? + * @return string + */ + public static function dump($sql = NULL, $return = FALSE) + { + ob_start(); + if ($sql instanceof DibiResult) { + $sql->dump(); + + } else { + if ($sql === NULL) $sql = self::$sql; + + static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE'; + static $keywords1 = 'SELECT|UPDATE|INSERT(?:\s+INTO)|REPLACE(?:\s+INTO)|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN'; + + // insert new lines + $sql = ' ' . $sql; + $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql); - // reduce spaces - $sql = preg_replace('# {2,}#', ' ', $sql); + // reduce spaces + $sql = preg_replace('#[ \t]{2,}#', " ", $sql); - $sql = wordwrap($sql, 100); - $sql = htmlSpecialChars($sql); - $sql = preg_replace("#\n{2,}#", "\n", $sql); - - // syntax highlight - $sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", array('dibi', 'highlightCallback'), $sql); - $sql = trim($sql); - echo '
', $sql, "
\n"; - } + $sql = wordwrap($sql, 100); + $sql = htmlSpecialChars($sql); + $sql = preg_replace("#\n{2,}#", "\n", $sql); + + // syntax highlight + $sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", array('dibi', 'highlightCallback'), $sql); + $sql = trim($sql); + echo '
', $sql, "
\n"; + } - if ($return) { - return ob_get_clean(); - } else { - ob_end_flush(); - } - } - - - - private static function highlightCallback($matches) - { - if (!empty($matches[1])) // comment - return '' . $matches[1] . ''; - - if (!empty($matches[2])) // error - return '' . $matches[2] . ''; - - if (!empty($matches[3])) // most important keywords - return '' . $matches[3] . ''; + if ($return) { + return ob_get_clean(); + } else { + ob_end_flush(); + } + } + + + + private static function highlightCallback($matches) + { + if (!empty($matches[1])) // comment + return '' . $matches[1] . ''; + + if (!empty($matches[2])) // error + return '' . $matches[2] . ''; + + if (!empty($matches[3])) // most important keywords + return '' . $matches[3] . ''; - if (!empty($matches[4])) // other keywords - return '' . $matches[4] . ''; - } + if (!empty($matches[4])) // other keywords + return '' . $matches[4] . ''; + } - - - /** - * Returns brief descriptions. - * @return array - */ - public static function getColophon() - { - return array( - 'dibi version: ' . dibi::VERSION, - 'Number or queries: ' . dibi::$numOfQueries . (dibi::$totalTime === NULL ? '' : ' (elapsed time: ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms)'), - ); - } + + + /** + * Returns brief descriptions. + * @return array + */ + public static function getColophon() + { + return array( + 'dibi version: ' . dibi::VERSION, + 'Number or queries: ' . dibi::$numOfQueries . (dibi::$totalTime === NULL ? '' : ' (elapsed time: ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms)'), + ); + } } diff --git a/dibi/drivers/mssql.php b/dibi/drivers/mssql.php index 435c0058..314a317b 100644 --- a/dibi/drivers/mssql.php +++ b/dibi/drivers/mssql.php @@ -37,299 +37,299 @@ class DibiMsSqlDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var resource - */ - private $connection; - - - /** - * Resultset resource. - * @var resource - */ - private $resultset; + /** + * Connection resource. + * @var resource + */ + private $connection; + + + /** + * Resultset resource. + * @var resource + */ + private $resultset; - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('mssql')) { - throw new DibiDriverException("PHP extension 'mssql' is not loaded."); - } - } + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('mssql')) { + throw new DibiDriverException("PHP extension 'mssql' is not loaded."); + } + } - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - DibiConnection::alias($config, 'username', 'user'); - DibiConnection::alias($config, 'password', 'pass'); - DibiConnection::alias($config, 'host'); + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + DibiConnection::alias($config, 'username', 'user'); + DibiConnection::alias($config, 'password', 'pass'); + DibiConnection::alias($config, 'host'); - if (empty($config['persistent'])) { - $this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); - } else { - $this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); - } - - if (!is_resource($this->connection)) { - throw new DibiDriverException("Can't connect to DB."); - } + if (empty($config['persistent'])) { + $this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); + } else { + $this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); + } + + if (!is_resource($this->connection)) { + throw new DibiDriverException("Can't connect to DB."); + } - if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) { - throw new DibiDriverException("Can't select DB '$config[database]'."); - } - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - mssql_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - $this->resultset = @mssql_query($sql, $this->connection); - - if ($this->resultset === FALSE) { - throw new DibiDriverException('Query error', 0, $sql); - } - - return is_resource($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return mssql_rows_affected($this->connection); - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - throw new NotSupportedException('MS SQL does not support autoincrementing.'); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - $this->query('BEGIN TRANSACTION'); - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - $this->query('COMMIT'); - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - $this->query('ROLLBACK'); - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $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("'Y-m-d'", $value); - if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - // offset suppot is missing... - if ($limit >= 0) { - $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')'; - } - - if ($offset) { - throw new NotImplementedException('Offset is not implemented.'); - } - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - return mssql_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return mssql_fetch_array($this->resultset, $type ? MSSQL_ASSOC : MSSQL_NUM); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - return mssql_data_seek($this->resultset, $row); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - mssql_free_result($this->resultset); - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $count = mssql_num_fields($this->resultset); - $meta = array(); - for ($i = 0; $i < $count; $i++) { - // items 'name' and 'table' are required - $info = (array) mssql_fetch_field($this->resultset, $i); - $info['table'] = $info['column_source']; - $meta[] = $info; - } - return $meta; - } - - - - /** - * Returns the connection resource. - * - * @return mixed - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) { + throw new DibiDriverException("Can't select DB '$config[database]'."); + } + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + mssql_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + $this->resultset = @mssql_query($sql, $this->connection); + + if ($this->resultset === FALSE) { + throw new DibiDriverException('Query error', 0, $sql); + } + + return is_resource($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return mssql_rows_affected($this->connection); + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + throw new NotSupportedException('MS SQL does not support autoincrementing.'); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + $this->query('BEGIN TRANSACTION'); + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + $this->query('COMMIT'); + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + $this->query('ROLLBACK'); + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $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("'Y-m-d'", $value); + if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + // offset suppot is missing... + if ($limit >= 0) { + $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')'; + } + + if ($offset) { + throw new NotImplementedException('Offset is not implemented.'); + } + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + return mssql_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return mssql_fetch_array($this->resultset, $type ? MSSQL_ASSOC : MSSQL_NUM); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + return mssql_data_seek($this->resultset, $row); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + mssql_free_result($this->resultset); + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $count = mssql_num_fields($this->resultset); + $meta = array(); + for ($i = 0; $i < $count; $i++) { + // items 'name' and 'table' are required + $info = (array) mssql_fetch_field($this->resultset, $i); + $info['table'] = $info['column_source']; + $meta[] = $info; + } + return $meta; + } + + + + /** + * Returns the connection resource. + * + * @return mixed + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/mysql.php b/dibi/drivers/mysql.php index 0dec91cf..dfdb677f 100644 --- a/dibi/drivers/mysql.php +++ b/dibi/drivers/mysql.php @@ -43,360 +43,360 @@ class DibiMySqlDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var resource - */ - private $connection; - - - /** - * Resultset resource. - * @var resource - */ - private $resultset; - - - /** - * Is buffered (seekable and countable)? - * @var bool - */ - private $buffered; - - - - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('mysql')) { - throw new DibiDriverException("PHP extension 'mysql' is not loaded."); - } - } - - - - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - DibiConnection::alias($config, 'username', 'user'); - DibiConnection::alias($config, 'password', 'pass'); - DibiConnection::alias($config, 'options'); - - // default values - if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user'); - if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password'); - if (!isset($config['host'])) { - $host = ini_get('mysql.default_host'); - if ($host) { - $config['host'] = $host; - $config['port'] = ini_get('mysql.default_port'); - } else { - if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket'); - $config['host'] = NULL; - } - } - - if (empty($config['socket'])) { - $host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']); - } else { - $host = ':' . $config['socket']; - } - - if (empty($config['persistent'])) { - $this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); - } else { - $this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); - } - - if (!is_resource($this->connection)) { - throw new DibiDriverException(mysql_error(), mysql_errno()); - } - - if (isset($config['charset'])) { - $ok = FALSE; - if (function_exists('mysql_set_charset')) { - // affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.2.3) - $ok = @mysql_set_charset($config['charset'], $this->connection); - } - if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); - if (!$ok) $this->throwException(); - } - - if (isset($config['database'])) { - @mysql_select_db($config['database'], $this->connection) or $this->throwException(); - } - - if (isset($config['sqlmode'])) { - if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); - } - - $this->buffered = empty($config['unbuffered']); - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - mysql_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - if ($this->buffered) { - $this->resultset = @mysql_query($sql, $this->connection); - } else { - $this->resultset = @mysql_unbuffered_query($sql, $this->connection); - } - - if (mysql_errno($this->connection)) { - $this->throwException($sql); - } - - return is_resource($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return mysql_affected_rows($this->connection); - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - return mysql_insert_id($this->connection); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - $this->query('START TRANSACTION'); - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - $this->query('COMMIT'); - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - $this->query('ROLLBACK'); - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) return "'" . mysql_real_escape_string($value, $this->connection) . "'"; - if ($type === dibi::IDENTIFIER) return '`' . str_replace('.', '`.`', $value) . '`'; - if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0; - if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); - if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - if ($limit < 0 && $offset < 1) return; - - // see http://dev.mysql.com/doc/refman/5.0/en/select.html - $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) - . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - if (!$this->buffered) { - throw new DibiDriverException('Row count is not available for unbuffered queries.'); - } - return mysql_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return mysql_fetch_array($this->resultset, $type ? MYSQL_ASSOC : MYSQL_NUM); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - if (!$this->buffered) { - throw new DibiDriverException('Cannot seek an unbuffered result set.'); - } - - return mysql_data_seek($this->resultset, $row); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - mysql_free_result($this->resultset); - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $count = mysql_num_fields($this->resultset); - $meta = array(); - for ($i = 0; $i < $count; $i++) { - // items 'name' and 'table' are required - $meta[] = (array) mysql_fetch_field($this->resultset, $i); - } - return $meta; - } - - - - /** - * 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. - * - * @return mixed - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + /** + * Connection resource. + * @var resource + */ + private $connection; + + + /** + * Resultset resource. + * @var resource + */ + private $resultset; + + + /** + * Is buffered (seekable and countable)? + * @var bool + */ + private $buffered; + + + + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('mysql')) { + throw new DibiDriverException("PHP extension 'mysql' is not loaded."); + } + } + + + + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + DibiConnection::alias($config, 'username', 'user'); + DibiConnection::alias($config, 'password', 'pass'); + DibiConnection::alias($config, 'options'); + + // default values + if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user'); + if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password'); + if (!isset($config['host'])) { + $host = ini_get('mysql.default_host'); + if ($host) { + $config['host'] = $host; + $config['port'] = ini_get('mysql.default_port'); + } else { + if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket'); + $config['host'] = NULL; + } + } + + if (empty($config['socket'])) { + $host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']); + } else { + $host = ':' . $config['socket']; + } + + if (empty($config['persistent'])) { + $this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); + } else { + $this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); + } + + if (!is_resource($this->connection)) { + throw new DibiDriverException(mysql_error(), mysql_errno()); + } + + if (isset($config['charset'])) { + $ok = FALSE; + if (function_exists('mysql_set_charset')) { + // affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.2.3) + $ok = @mysql_set_charset($config['charset'], $this->connection); + } + if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); + if (!$ok) $this->throwException(); + } + + if (isset($config['database'])) { + @mysql_select_db($config['database'], $this->connection) or $this->throwException(); + } + + if (isset($config['sqlmode'])) { + if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); + } + + $this->buffered = empty($config['unbuffered']); + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + mysql_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + if ($this->buffered) { + $this->resultset = @mysql_query($sql, $this->connection); + } else { + $this->resultset = @mysql_unbuffered_query($sql, $this->connection); + } + + if (mysql_errno($this->connection)) { + $this->throwException($sql); + } + + return is_resource($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return mysql_affected_rows($this->connection); + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + return mysql_insert_id($this->connection); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + $this->query('START TRANSACTION'); + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + $this->query('COMMIT'); + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + $this->query('ROLLBACK'); + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) return "'" . mysql_real_escape_string($value, $this->connection) . "'"; + if ($type === dibi::IDENTIFIER) return '`' . str_replace('.', '`.`', $value) . '`'; + if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0; + if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); + if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + if ($limit < 0 && $offset < 1) return; + + // see http://dev.mysql.com/doc/refman/5.0/en/select.html + $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) + . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + if (!$this->buffered) { + throw new DibiDriverException('Row count is not available for unbuffered queries.'); + } + return mysql_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return mysql_fetch_array($this->resultset, $type ? MYSQL_ASSOC : MYSQL_NUM); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + if (!$this->buffered) { + throw new DibiDriverException('Cannot seek an unbuffered result set.'); + } + + return mysql_data_seek($this->resultset, $row); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + mysql_free_result($this->resultset); + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $count = mysql_num_fields($this->resultset); + $meta = array(); + for ($i = 0; $i < $count; $i++) { + // items 'name' and 'table' are required + $meta[] = (array) mysql_fetch_field($this->resultset, $i); + } + return $meta; + } + + + + /** + * 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. + * + * @return mixed + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/mysqli.php b/dibi/drivers/mysqli.php index ad7abe4d..3cbaa342 100644 --- a/dibi/drivers/mysqli.php +++ b/dibi/drivers/mysqli.php @@ -43,339 +43,339 @@ class DibiMySqliDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var mysqli - */ - private $connection; - - - /** - * Resultset resource. - * @var mysqli_result - */ - private $resultset; - - - /** - * Is buffered (seekable and countable)? - * @var bool - */ - private $buffered; - - - - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('mysqli')) { - throw new DibiDriverException("PHP extension 'mysqli' is not loaded."); - } - } - - - - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - DibiConnection::alias($config, 'username', 'user'); - DibiConnection::alias($config, 'password', 'pass'); - DibiConnection::alias($config, 'options'); - DibiConnection::alias($config, 'database'); - - // default values - if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user'); - if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw'); - if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket'); - if (!isset($config['host'])) { - $config['host'] = ini_get('mysqli.default_host'); - if (!isset($config['port'])) $config['port'] = ini_get('mysqli.default_port'); - if (!isset($config['host'])) $config['host'] = 'localhost'; - } - - $this->connection = mysqli_init(); - @mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); - - if ($errno = mysqli_connect_errno()) { - throw new DibiDriverException(mysqli_connect_error(), $errno); - } - - if (isset($config['charset'])) { - $ok = FALSE; - if (version_compare(PHP_VERSION , '5.1.5', '>=')) { - // affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.0.5, fixed in PHP 5.1.5) - $ok = @mysqli_set_charset($this->connection, $config['charset']); - } - if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); - if (!$ok) $this->throwException(); - } - - if (isset($config['sqlmode'])) { - if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException(); - } - - $this->buffered = empty($config['unbuffered']); - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - mysqli_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - $this->resultset = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); - - if (mysqli_errno($this->connection)) { - $this->throwException($sql); - } - - return is_object($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return mysqli_affected_rows($this->connection); - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - return mysqli_insert_id($this->connection); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - $this->query('START TRANSACTION'); - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - $this->query('COMMIT'); - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - $this->query('ROLLBACK'); - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) return "'" . mysqli_real_escape_string($this->connection, $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("'Y-m-d'", $value); - if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - if ($limit < 0 && $offset < 1) return; - - // see http://dev.mysql.com/doc/refman/5.0/en/select.html - $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) - . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - if (!$this->buffered) { - throw new DibiDriverException('Row count is not available for unbuffered queries.'); - } - return mysqli_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return mysqli_fetch_array($this->resultset, $type ? MYSQLI_ASSOC : MYSQLI_NUM); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - if (!$this->buffered) { - throw new DibiDriverException('Cannot seek an unbuffered result set.'); - } - return mysqli_data_seek($this->resultset, $row); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - mysqli_free_result($this->resultset); - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $count = mysqli_num_fields($this->resultset); - $meta = array(); - for ($i = 0; $i < $count; $i++) { - // items 'name' and 'table' are required - $meta[] = (array) mysqli_fetch_field_direct($this->resultset, $i); - } - return $meta; - } - - - - /** - * 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. - * - * @return mysqli - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mysqli_result - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + /** + * Connection resource. + * @var mysqli + */ + private $connection; + + + /** + * Resultset resource. + * @var mysqli_result + */ + private $resultset; + + + /** + * Is buffered (seekable and countable)? + * @var bool + */ + private $buffered; + + + + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('mysqli')) { + throw new DibiDriverException("PHP extension 'mysqli' is not loaded."); + } + } + + + + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + DibiConnection::alias($config, 'username', 'user'); + DibiConnection::alias($config, 'password', 'pass'); + DibiConnection::alias($config, 'options'); + DibiConnection::alias($config, 'database'); + + // default values + if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user'); + if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw'); + if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket'); + if (!isset($config['host'])) { + $config['host'] = ini_get('mysqli.default_host'); + if (!isset($config['port'])) $config['port'] = ini_get('mysqli.default_port'); + if (!isset($config['host'])) $config['host'] = 'localhost'; + } + + $this->connection = mysqli_init(); + @mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); + + if ($errno = mysqli_connect_errno()) { + throw new DibiDriverException(mysqli_connect_error(), $errno); + } + + if (isset($config['charset'])) { + $ok = FALSE; + if (version_compare(PHP_VERSION , '5.1.5', '>=')) { + // affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.0.5, fixed in PHP 5.1.5) + $ok = @mysqli_set_charset($this->connection, $config['charset']); + } + if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); + if (!$ok) $this->throwException(); + } + + if (isset($config['sqlmode'])) { + if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException(); + } + + $this->buffered = empty($config['unbuffered']); + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + mysqli_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + $this->resultset = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); + + if (mysqli_errno($this->connection)) { + $this->throwException($sql); + } + + return is_object($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return mysqli_affected_rows($this->connection); + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + return mysqli_insert_id($this->connection); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + $this->query('START TRANSACTION'); + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + $this->query('COMMIT'); + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + $this->query('ROLLBACK'); + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) return "'" . mysqli_real_escape_string($this->connection, $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("'Y-m-d'", $value); + if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + if ($limit < 0 && $offset < 1) return; + + // see http://dev.mysql.com/doc/refman/5.0/en/select.html + $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) + . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + if (!$this->buffered) { + throw new DibiDriverException('Row count is not available for unbuffered queries.'); + } + return mysqli_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return mysqli_fetch_array($this->resultset, $type ? MYSQLI_ASSOC : MYSQLI_NUM); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + if (!$this->buffered) { + throw new DibiDriverException('Cannot seek an unbuffered result set.'); + } + return mysqli_data_seek($this->resultset, $row); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + mysqli_free_result($this->resultset); + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $count = mysqli_num_fields($this->resultset); + $meta = array(); + for ($i = 0; $i < $count; $i++) { + // items 'name' and 'table' are required + $meta[] = (array) mysqli_fetch_field_direct($this->resultset, $i); + } + return $meta; + } + + + + /** + * 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. + * + * @return mysqli + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mysqli_result + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/odbc.php b/dibi/drivers/odbc.php index 3d604a1e..8448f551 100644 --- a/dibi/drivers/odbc.php +++ b/dibi/drivers/odbc.php @@ -36,340 +36,340 @@ class DibiOdbcDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var resource - */ - private $connection; + /** + * Connection resource. + * @var resource + */ + private $connection; - /** - * Resultset resource. - * @var resource - */ - private $resultset; - - - /** - * Cursor. - * @var int - */ - private $row = 0; + /** + * Resultset resource. + * @var resource + */ + private $resultset; + + + /** + * Cursor. + * @var int + */ + private $row = 0; - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('odbc')) { - throw new DibiDriverException("PHP extension 'odbc' is not loaded."); - } - } - + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('odbc')) { + throw new DibiDriverException("PHP extension 'odbc' is not loaded."); + } + } + - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - DibiConnection::alias($config, 'username', 'user'); - DibiConnection::alias($config, 'password', 'pass'); - - // default values - if (!isset($config['username'])) $config['username'] = ini_get('odbc.default_user'); - if (!isset($config['password'])) $config['password'] = ini_get('odbc.default_pw'); - if (!isset($config['dsn'])) $config['dsn'] = ini_get('odbc.default_db'); - - if (empty($config['persistent'])) { - $this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']); - } else { - $this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); - } - - if (!is_resource($this->connection)) { - throw new DibiDriverException(odbc_errormsg() . ' ' . odbc_error()); - } - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - odbc_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - $this->resultset = @odbc_exec($this->connection, $sql); - - if ($this->resultset === FALSE) { - $this->throwException($sql); - } - - return is_resource($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return odbc_num_rows($this->resultset); - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - throw new NotSupportedException('ODBC does not support autoincrementing.'); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - if (!odbc_autocommit($this->connection, FALSE)) { - $this->throwException(); - } - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - if (!odbc_commit($this->connection)) { - $this->throwException(); - } - odbc_autocommit($this->connection, TRUE); - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - if (!odbc_rollback($this->connection)) { - $this->throwException(); - } - odbc_autocommit($this->connection, TRUE); - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $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("#m/d/Y#", $value); - if ($type === dibi::FIELD_DATETIME) return date("#m/d/Y H:i:s#", $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - // offset suppot is missing... - if ($limit >= 0) { - $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')'; - } - - if ($offset) throw new InvalidArgumentException('Offset is not implemented in driver odbc.'); - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - // will return -1 with many drivers :-( - return odbc_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - if ($type) { - return odbc_fetch_array($this->resultset, ++$this->row); - } else { - $set = $this->resultset; - if (!odbc_fetch_row($set, ++$this->row)) return FALSE; - $count = odbc_num_fields($set); - $cols = array(); - for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i); - return $cols; - } - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - $this->row = $row; - return TRUE; - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - odbc_free_result($this->resultset); - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $count = odbc_num_fields($this->resultset); - $meta = array(); - for ($i = 1; $i <= $count; $i++) { - // items 'name' and 'table' are required - $meta[] = array( - 'name' => odbc_field_name($this->resultset, $i), - 'table' => NULL, - 'type' => odbc_field_type($this->resultset, $i), - 'length' => odbc_field_len($this->resultset, $i), - 'scale' => odbc_field_scale($this->resultset, $i), - 'precision' => odbc_field_precision($this->resultset, $i), - ); - } - return $meta; - } - - - - /** - * 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. - * - * @return mixed - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + DibiConnection::alias($config, 'username', 'user'); + DibiConnection::alias($config, 'password', 'pass'); + + // default values + if (!isset($config['username'])) $config['username'] = ini_get('odbc.default_user'); + if (!isset($config['password'])) $config['password'] = ini_get('odbc.default_pw'); + if (!isset($config['dsn'])) $config['dsn'] = ini_get('odbc.default_db'); + + if (empty($config['persistent'])) { + $this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']); + } else { + $this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); + } + + if (!is_resource($this->connection)) { + throw new DibiDriverException(odbc_errormsg() . ' ' . odbc_error()); + } + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + odbc_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + $this->resultset = @odbc_exec($this->connection, $sql); + + if ($this->resultset === FALSE) { + $this->throwException($sql); + } + + return is_resource($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return odbc_num_rows($this->resultset); + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + throw new NotSupportedException('ODBC does not support autoincrementing.'); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + if (!odbc_autocommit($this->connection, FALSE)) { + $this->throwException(); + } + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + if (!odbc_commit($this->connection)) { + $this->throwException(); + } + odbc_autocommit($this->connection, TRUE); + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + if (!odbc_rollback($this->connection)) { + $this->throwException(); + } + odbc_autocommit($this->connection, TRUE); + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $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("#m/d/Y#", $value); + if ($type === dibi::FIELD_DATETIME) return date("#m/d/Y H:i:s#", $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + // offset suppot is missing... + if ($limit >= 0) { + $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')'; + } + + if ($offset) throw new InvalidArgumentException('Offset is not implemented in driver odbc.'); + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + // will return -1 with many drivers :-( + return odbc_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + if ($type) { + return odbc_fetch_array($this->resultset, ++$this->row); + } else { + $set = $this->resultset; + if (!odbc_fetch_row($set, ++$this->row)) return FALSE; + $count = odbc_num_fields($set); + $cols = array(); + for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i); + return $cols; + } + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + $this->row = $row; + return TRUE; + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + odbc_free_result($this->resultset); + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $count = odbc_num_fields($this->resultset); + $meta = array(); + for ($i = 1; $i <= $count; $i++) { + // items 'name' and 'table' are required + $meta[] = array( + 'name' => odbc_field_name($this->resultset, $i), + 'table' => NULL, + 'type' => odbc_field_type($this->resultset, $i), + 'length' => odbc_field_len($this->resultset, $i), + 'scale' => odbc_field_scale($this->resultset, $i), + 'precision' => odbc_field_precision($this->resultset, $i), + ); + } + return $meta; + } + + + + /** + * 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. + * + * @return mixed + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/oracle.php b/dibi/drivers/oracle.php index d54757b4..b21c3a96 100644 --- a/dibi/drivers/oracle.php +++ b/dibi/drivers/oracle.php @@ -36,323 +36,323 @@ class DibiOracleDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var resource - */ - private $connection; + /** + * Connection resource. + * @var resource + */ + private $connection; - /** - * Resultset resource. - * @var resource - */ - private $resultset; - - - /** - * @var bool - */ - private $autocommit = TRUE; + /** + * Resultset resource. + * @var resource + */ + private $resultset; + + + /** + * @var bool + */ + private $autocommit = TRUE; - - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('oci8')) { - throw new DibiDriverException("PHP extension 'oci8' is not loaded."); - } - } - - - - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - DibiConnection::alias($config, 'username', 'user'); - DibiConnection::alias($config, 'password', 'pass'); - DibiConnection::alias($config, 'database', 'db'); - DibiConnection::alias($config, 'charset'); - - $this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); - - if (!$this->connection) { - $err = oci_error(); - throw new DibiDriverException($err['message'], $err['code']); - } - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - oci_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - - $this->resultset = oci_parse($this->connection, $sql); - if ($this->resultset) { - oci_execute($this->resultset, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); - $err = oci_error($this->resultset); - if ($err) { - throw new DibiDriverException($err['message'], $err['code'], $sql); - } - } else { - $this->throwException($sql); - } - - return is_resource($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - throw new NotImplementedException; - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - throw new NotSupportedException('Oracle does not support autoincrementing.'); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - $this->autocommit = FALSE; - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - if (!oci_commit($this->connection)) { - $this->throwException(); - } - $this->autocommit = TRUE; - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - if (!oci_rollback($this->connection)) { - $this->throwException(); - } - $this->autocommit = TRUE; - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested - if ($type === dibi::IDENTIFIER) return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested - 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); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - if ($limit < 0 && $offset < 1) return; - $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - return oci_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return oci_fetch_array($this->resultset, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - throw new NotImplementedException; - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - oci_free_statement($this->resultset); - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $count = oci_num_fields($this->resultset); - $meta = array(); - for ($i = 1; $i <= $count; $i++) { - // items 'name' and 'table' are required - $meta[] = array( - 'name' => oci_field_name($this->resultset, $i), - 'table' => NULL, - 'type' => oci_field_type($this->resultset, $i), - 'size' => oci_field_size($this->resultset, $i), - 'scale' => oci_field_scale($this->resultset, $i), - 'precision' => oci_field_precision($this->resultset, $i), - ); - } - return $meta; - } - - - - /** - * 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. - * - * @return mixed - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('oci8')) { + throw new DibiDriverException("PHP extension 'oci8' is not loaded."); + } + } + + + + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + DibiConnection::alias($config, 'username', 'user'); + DibiConnection::alias($config, 'password', 'pass'); + DibiConnection::alias($config, 'database', 'db'); + DibiConnection::alias($config, 'charset'); + + $this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); + + if (!$this->connection) { + $err = oci_error(); + throw new DibiDriverException($err['message'], $err['code']); + } + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + oci_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + + $this->resultset = oci_parse($this->connection, $sql); + if ($this->resultset) { + oci_execute($this->resultset, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); + $err = oci_error($this->resultset); + if ($err) { + throw new DibiDriverException($err['message'], $err['code'], $sql); + } + } else { + $this->throwException($sql); + } + + return is_resource($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + throw new NotImplementedException; + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + throw new NotSupportedException('Oracle does not support autoincrementing.'); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + $this->autocommit = FALSE; + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + if (!oci_commit($this->connection)) { + $this->throwException(); + } + $this->autocommit = TRUE; + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + if (!oci_rollback($this->connection)) { + $this->throwException(); + } + $this->autocommit = TRUE; + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested + if ($type === dibi::IDENTIFIER) return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested + 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); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + if ($limit < 0 && $offset < 1) return; + $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + return oci_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return oci_fetch_array($this->resultset, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + throw new NotImplementedException; + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + oci_free_statement($this->resultset); + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $count = oci_num_fields($this->resultset); + $meta = array(); + for ($i = 1; $i <= $count; $i++) { + // items 'name' and 'table' are required + $meta[] = array( + 'name' => oci_field_name($this->resultset, $i), + 'table' => NULL, + 'type' => oci_field_type($this->resultset, $i), + 'size' => oci_field_size($this->resultset, $i), + 'scale' => oci_field_scale($this->resultset, $i), + 'precision' => oci_field_precision($this->resultset, $i), + ); + } + return $meta; + } + + + + /** + * 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. + * + * @return mixed + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/pdo.php b/dibi/drivers/pdo.php index 1595cb1e..7a7f7f61 100644 --- a/dibi/drivers/pdo.php +++ b/dibi/drivers/pdo.php @@ -37,339 +37,339 @@ class DibiPdoDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var PDO - */ - private $connection; - - - /** - * Resultset resource. - * @var PDOStatement - */ - private $resultset; + /** + * Connection resource. + * @var PDO + */ + private $connection; + + + /** + * Resultset resource. + * @var PDOStatement + */ + private $resultset; - /** - * Affected rows. - * @var int - */ - private $affectedRows = FALSE; - - - - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('pdo')) { - throw new DibiDriverException("PHP extension 'pdo' is not loaded."); - } - } - - - - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - DibiConnection::alias($config, 'username', 'user'); - DibiConnection::alias($config, 'password', 'pass'); - DibiConnection::alias($config, 'dsn'); - DibiConnection::alias($config, 'pdo'); - DibiConnection::alias($config, 'options'); - - if ($config['pdo'] instanceof PDO) { - $this->connection = $config['pdo']; + /** + * Affected rows. + * @var int + */ + private $affectedRows = FALSE; + + + + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('pdo')) { + throw new DibiDriverException("PHP extension 'pdo' is not loaded."); + } + } + + + + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + DibiConnection::alias($config, 'username', 'user'); + DibiConnection::alias($config, 'password', 'pass'); + DibiConnection::alias($config, 'dsn'); + DibiConnection::alias($config, 'pdo'); + DibiConnection::alias($config, 'options'); + + if ($config['pdo'] instanceof PDO) { + $this->connection = $config['pdo']; - } else try { - $this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']); + } else try { + $this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']); - } catch (PDOException $e) { - throw new DibiDriverException($e->getMessage(), $e->getCode()); - } - - if (!$this->connection) { - throw new DibiDriverException('Connecting error.'); - } - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - $this->connection = NULL; - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - // must detect if SQL returns resultset or num of affected rows - $cmd = strtoupper(substr(ltrim($sql), 0, 6)); - $list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1); - - if (isset($list[$cmd])) { - $this->resultset = NULL; - $this->affectedRows = $this->connection->exec($sql); - - if ($this->affectedRows === FALSE) { - $this->throwException($sql); - } - - return FALSE; - - } else { - $this->resultset = $this->connection->query($sql); - $this->affectedRows = FALSE; - - if ($this->resultset === FALSE) { - $this->throwException($sql); - } - - return TRUE; - } - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return $this->affectedRows; - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - return $this->connection->lastInsertId(); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - if (!$this->connection->beginTransaction()) { - $this->throwException(); - } - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - if (!$this->connection->commit()) { - $this->throwException(); - } - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - if (!$this->connection->rollBack()) { - $this->throwException(); - } - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) return $this->connection->quote($value); - if ($type === dibi::IDENTIFIER) return $value; // quoting is not supported by PDO - if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0; - if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); - if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - throw new NotSupportedException('PDO does not support applying limit or offset.'); - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - throw new DibiDriverException('Row count is not available for unbuffered queries.'); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return $this->resultset->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - throw new DibiDriverException('Cannot seek an unbuffered result set.'); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - * @throws DibiException - */ - public function getColumnsMeta() - { - $count = $this->resultset->columnCount(); - $meta = array(); - for ($i = 0; $i < $count; $i++) { - // items 'name' and 'table' are required - $info = @$this->resultset->getColumnsMeta($i); - if ($info === FALSE) { - throw new DibiDriverException('Driver does not support meta data.'); - } - $meta[] = $info; - } - return $meta; - } - - - - /** - * 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. - * - * @return PDO - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return PDOStatement - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + } catch (PDOException $e) { + throw new DibiDriverException($e->getMessage(), $e->getCode()); + } + + if (!$this->connection) { + throw new DibiDriverException('Connecting error.'); + } + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + $this->connection = NULL; + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + // must detect if SQL returns resultset or num of affected rows + $cmd = strtoupper(substr(ltrim($sql), 0, 6)); + $list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1); + + if (isset($list[$cmd])) { + $this->resultset = NULL; + $this->affectedRows = $this->connection->exec($sql); + + if ($this->affectedRows === FALSE) { + $this->throwException($sql); + } + + return FALSE; + + } else { + $this->resultset = $this->connection->query($sql); + $this->affectedRows = FALSE; + + if ($this->resultset === FALSE) { + $this->throwException($sql); + } + + return TRUE; + } + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return $this->affectedRows; + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + return $this->connection->lastInsertId(); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + if (!$this->connection->beginTransaction()) { + $this->throwException(); + } + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + if (!$this->connection->commit()) { + $this->throwException(); + } + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + if (!$this->connection->rollBack()) { + $this->throwException(); + } + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) return $this->connection->quote($value); + if ($type === dibi::IDENTIFIER) return $value; // quoting is not supported by PDO + if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0; + if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); + if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + throw new NotSupportedException('PDO does not support applying limit or offset.'); + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + throw new DibiDriverException('Row count is not available for unbuffered queries.'); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return $this->resultset->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + throw new DibiDriverException('Cannot seek an unbuffered result set.'); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + * @throws DibiException + */ + public function getColumnsMeta() + { + $count = $this->resultset->columnCount(); + $meta = array(); + for ($i = 0; $i < $count; $i++) { + // items 'name' and 'table' are required + $info = @$this->resultset->getColumnsMeta($i); + if ($info === FALSE) { + throw new DibiDriverException('Driver does not support meta data.'); + } + $meta[] = $info; + } + return $meta; + } + + + + /** + * 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. + * + * @return PDO + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return PDOStatement + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/postgre.php b/dibi/drivers/postgre.php index 12a39c6d..be4f0ed1 100644 --- a/dibi/drivers/postgre.php +++ b/dibi/drivers/postgre.php @@ -37,349 +37,349 @@ class DibiPostgreDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var resource - */ - private $connection; - - - /** - * Resultset resource. - * @var resource - */ - private $resultset; - - - /** - * Escape method. - * @var bool - */ - private $escMethod = FALSE; - - - - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('pgsql')) { - throw new DibiDriverException("PHP extension 'pgsql' is not loaded."); - } - } - - - - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - public function connect(array &$config) - { - if (isset($config['string'])) { - $string = $config['string']; - } else { - $string = ''; - foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) { - if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' '; - } - } - - DibiDriverException::tryError(); - if (isset($config['persistent'])) { - $this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW); - } else { - $this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW); - } - if (DibiDriverException::catchError($msg)) { - throw new DibiDriverException($msg, 0); - } - - if (!is_resource($this->connection)) { - throw new DibiDriverException('Connecting error.'); - } - - if (isset($config['charset'])) { - DibiDriverException::tryError(); - pg_set_client_encoding($this->connection, $config['charset']); - if (DibiDriverException::catchError($msg)) { - throw new DibiDriverException($msg, 0); - } - } - - if (isset($config['schema'])) { - $this->query('SET search_path TO ' . $config['schema']); - } - - $this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>='); - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - pg_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @param bool update affected rows? - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - $this->resultset = @pg_query($this->connection, $sql); - - if ($this->resultset === FALSE) { - throw new DibiDriverException(pg_last_error($this->connection), 0, $sql); - } - - return is_resource($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return pg_affected_rows($this->resultset); - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - if ($sequence === NULL) { - // PostgreSQL 8.1 is needed - $has = $this->query("SELECT LASTVAL()"); - } else { - $has = $this->query("SELECT CURRVAL('$sequence')"); - } - - if (!$has) return FALSE; - - $row = $this->fetch(FALSE); - $this->free(); - return is_array($row) ? $row[0] : FALSE; - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - $this->query('START TRANSACTION'); - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - $this->query('COMMIT'); - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - $this->query('ROLLBACK'); - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - if ($type === dibi::FIELD_TEXT) { - if ($this->escMethod) return "'" . pg_escape_string($this->connection, $value) . "'"; - return "'" . pg_escape_string($value) . "'"; - } - - if ($type === dibi::IDENTIFIER) { - $a = strrpos($value, '.'); - if ($a === FALSE) return '"' . str_replace('"', '""', $value) . '"'; - // table.col delimite as table."col" - return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"'; - } - - if ($type === dibi::FIELD_BOOL) return $value ? 'TRUE' : 'FALSE'; - if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); - if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - if ($limit >= 0) - $sql .= ' LIMIT ' . (int) $limit; - - if ($offset > 0) - $sql .= ' OFFSET ' . (int) $offset; - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - return pg_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return pg_fetch_array($this->resultset, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - return pg_result_seek($this->resultset, $row); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - pg_free_result($this->resultset); - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $hasTable = version_compare(PHP_VERSION , '5.2.0', '>='); - $count = pg_num_fields($this->resultset); - $meta = array(); - for ($i = 0; $i < $count; $i++) { - // items 'name' and 'table' are required - $meta[] = array( - 'name' => pg_field_name($this->resultset, $i), - 'table' => $hasTable ? pg_field_table($this->resultset, $i) : NULL, - 'type' => pg_field_type($this->resultset, $i), - 'size' => pg_field_size($this->resultset, $i), - 'prtlen' => pg_field_prtlen($this->resultset, $i), - ); - } - return $meta; - } - - - - /** - * Returns the connection resource. - * - * @return mixed - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + /** + * Connection resource. + * @var resource + */ + private $connection; + + + /** + * Resultset resource. + * @var resource + */ + private $resultset; + + + /** + * Escape method. + * @var bool + */ + private $escMethod = FALSE; + + + + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('pgsql')) { + throw new DibiDriverException("PHP extension 'pgsql' is not loaded."); + } + } + + + + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + public function connect(array &$config) + { + if (isset($config['string'])) { + $string = $config['string']; + } else { + $string = ''; + foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) { + if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' '; + } + } + + DibiDriverException::tryError(); + if (isset($config['persistent'])) { + $this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW); + } else { + $this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW); + } + if (DibiDriverException::catchError($msg)) { + throw new DibiDriverException($msg, 0); + } + + if (!is_resource($this->connection)) { + throw new DibiDriverException('Connecting error.'); + } + + if (isset($config['charset'])) { + DibiDriverException::tryError(); + pg_set_client_encoding($this->connection, $config['charset']); + if (DibiDriverException::catchError($msg)) { + throw new DibiDriverException($msg, 0); + } + } + + if (isset($config['schema'])) { + $this->query('SET search_path TO ' . $config['schema']); + } + + $this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>='); + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + pg_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @param bool update affected rows? + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + $this->resultset = @pg_query($this->connection, $sql); + + if ($this->resultset === FALSE) { + throw new DibiDriverException(pg_last_error($this->connection), 0, $sql); + } + + return is_resource($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return pg_affected_rows($this->resultset); + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + if ($sequence === NULL) { + // PostgreSQL 8.1 is needed + $has = $this->query("SELECT LASTVAL()"); + } else { + $has = $this->query("SELECT CURRVAL('$sequence')"); + } + + if (!$has) return FALSE; + + $row = $this->fetch(FALSE); + $this->free(); + return is_array($row) ? $row[0] : FALSE; + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + $this->query('START TRANSACTION'); + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + $this->query('COMMIT'); + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + $this->query('ROLLBACK'); + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + if ($type === dibi::FIELD_TEXT) { + if ($this->escMethod) return "'" . pg_escape_string($this->connection, $value) . "'"; + return "'" . pg_escape_string($value) . "'"; + } + + if ($type === dibi::IDENTIFIER) { + $a = strrpos($value, '.'); + if ($a === FALSE) return '"' . str_replace('"', '""', $value) . '"'; + // table.col delimite as table."col" + return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"'; + } + + if ($type === dibi::FIELD_BOOL) return $value ? 'TRUE' : 'FALSE'; + if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); + if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + if ($limit >= 0) + $sql .= ' LIMIT ' . (int) $limit; + + if ($offset > 0) + $sql .= ' OFFSET ' . (int) $offset; + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + return pg_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return pg_fetch_array($this->resultset, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + return pg_result_seek($this->resultset, $row); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + pg_free_result($this->resultset); + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $hasTable = version_compare(PHP_VERSION , '5.2.0', '>='); + $count = pg_num_fields($this->resultset); + $meta = array(); + for ($i = 0; $i < $count; $i++) { + // items 'name' and 'table' are required + $meta[] = array( + 'name' => pg_field_name($this->resultset, $i), + 'table' => $hasTable ? pg_field_table($this->resultset, $i) : NULL, + 'type' => pg_field_type($this->resultset, $i), + 'size' => pg_field_size($this->resultset, $i), + 'prtlen' => pg_field_prtlen($this->resultset, $i), + ); + } + return $meta; + } + + + + /** + * Returns the connection resource. + * + * @return mixed + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/drivers/sqlite.php b/dibi/drivers/sqlite.php index 8818a33e..75ce4132 100644 --- a/dibi/drivers/sqlite.php +++ b/dibi/drivers/sqlite.php @@ -37,316 +37,316 @@ class DibiSqliteDriver extends /*Nette::*/Object implements IDibiDriver { - /** - * Connection resource. - * @var resource - */ - private $connection; - - - /** - * Resultset resource. - * @var resource - */ - private $resultset; - - - /** - * Is buffered (seekable and countable)? - * @var bool - */ - private $buffered; - - - /** - * Date and datetime format. - * @var string - */ - private $fmtDate, $fmtDateTime; - - - - /** - * @throws DibiException - */ - public function __construct() - { - if (!extension_loaded('sqlite')) { - throw new DibiDriverException("PHP extension 'sqlite' is not loaded."); - } - } - - - - /** - * Connects to a database. - * - * @return void - * @throws DibiException - */ - 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'; - - $errorMsg = ''; - if (empty($config['persistent'])) { - $this->connection = @sqlite_open($config['database'], 0666, $errorMsg); - } else { - $this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); - } - - if (!$this->connection) { - throw new DibiDriverException($errorMsg); - } - - $this->buffered = empty($config['unbuffered']); - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - public function disconnect() - { - sqlite_close($this->connection); - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - public function query($sql) - { - DibiDriverException::tryError(); - if ($this->buffered) { - $this->resultset = sqlite_query($this->connection, $sql); - } else { - $this->resultset = sqlite_unbuffered_query($this->connection, $sql); - } - if (DibiDriverException::catchError($msg)) { - throw new DibiDriverException($msg, sqlite_last_error($this->connection), $sql); - } - - return is_resource($this->resultset); - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - public function affectedRows() - { - return sqlite_changes($this->connection); - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - public function insertId($sequence) - { - return sqlite_last_insert_rowid($this->connection); - } - - - - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - public function begin() - { - $this->query('BEGIN'); - } - - - - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - public function commit() - { - $this->query('COMMIT'); - } - - - - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - public function rollback() - { - $this->query('ROLLBACK'); - } - - - - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - * @throws InvalidArgumentException - */ - public function format($value, $type) - { - 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($this->fmtDate, $value); - if ($type === dibi::FIELD_DATETIME) return date($this->fmtDateTime, $value); - throw new InvalidArgumentException('Unsupported formatting type.'); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - if ($limit < 0 && $offset < 1) return; - $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - public function rowCount() - { - if (!$this->buffered) { - throw new DibiDriverException('Row count is not available for unbuffered queries.'); - } - return sqlite_num_rows($this->resultset); - } - - - - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - public function fetch($type) - { - return sqlite_fetch_array($this->resultset, $type ? SQLITE_ASSOC : SQLITE_NUM); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - public function seek($row) - { - if (!$this->buffered) { - throw new DibiDriverException('Cannot seek an unbuffered result set.'); - } - return sqlite_seek($this->resultset, $row); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - public function free() - { - $this->resultset = NULL; - } - - - - /** - * Returns metadata for all columns in a result set. - * - * @return array - */ - public function getColumnsMeta() - { - $count = sqlite_num_fields($this->resultset); - $meta = array(); - for ($i = 0; $i < $count; $i++) { - // items 'name' and 'table' are required - $meta[] = array( - 'name' => sqlite_field_name($this->resultset, $i), - 'table' => NULL, - ); - } - return $meta; - } - - - - /** - * Returns the connection resource. - * - * @return mixed - */ - public function getResource() - { - return $this->connection; - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - public function getResultResource() - { - return $this->resultset; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection() - {} + /** + * Connection resource. + * @var resource + */ + private $connection; + + + /** + * Resultset resource. + * @var resource + */ + private $resultset; + + + /** + * Is buffered (seekable and countable)? + * @var bool + */ + private $buffered; + + + /** + * Date and datetime format. + * @var string + */ + private $fmtDate, $fmtDateTime; + + + + /** + * @throws DibiException + */ + public function __construct() + { + if (!extension_loaded('sqlite')) { + throw new DibiDriverException("PHP extension 'sqlite' is not loaded."); + } + } + + + + /** + * Connects to a database. + * + * @return void + * @throws DibiException + */ + 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'; + + $errorMsg = ''; + if (empty($config['persistent'])) { + $this->connection = @sqlite_open($config['database'], 0666, $errorMsg); + } else { + $this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); + } + + if (!$this->connection) { + throw new DibiDriverException($errorMsg); + } + + $this->buffered = empty($config['unbuffered']); + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + public function disconnect() + { + sqlite_close($this->connection); + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + public function query($sql) + { + DibiDriverException::tryError(); + if ($this->buffered) { + $this->resultset = sqlite_query($this->connection, $sql); + } else { + $this->resultset = sqlite_unbuffered_query($this->connection, $sql); + } + if (DibiDriverException::catchError($msg)) { + throw new DibiDriverException($msg, sqlite_last_error($this->connection), $sql); + } + + return is_resource($this->resultset); + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + public function affectedRows() + { + return sqlite_changes($this->connection); + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + public function insertId($sequence) + { + return sqlite_last_insert_rowid($this->connection); + } + + + + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + public function begin() + { + $this->query('BEGIN'); + } + + + + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + public function commit() + { + $this->query('COMMIT'); + } + + + + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + public function rollback() + { + $this->query('ROLLBACK'); + } + + + + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + * @throws InvalidArgumentException + */ + public function format($value, $type) + { + 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($this->fmtDate, $value); + if ($type === dibi::FIELD_DATETIME) return date($this->fmtDateTime, $value); + throw new InvalidArgumentException('Unsupported formatting type.'); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + if ($limit < 0 && $offset < 1) return; + $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + public function rowCount() + { + if (!$this->buffered) { + throw new DibiDriverException('Row count is not available for unbuffered queries.'); + } + return sqlite_num_rows($this->resultset); + } + + + + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + public function fetch($type) + { + return sqlite_fetch_array($this->resultset, $type ? SQLITE_ASSOC : SQLITE_NUM); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + public function seek($row) + { + if (!$this->buffered) { + throw new DibiDriverException('Cannot seek an unbuffered result set.'); + } + return sqlite_seek($this->resultset, $row); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + public function free() + { + $this->resultset = NULL; + } + + + + /** + * Returns metadata for all columns in a result set. + * + * @return array + */ + public function getColumnsMeta() + { + $count = sqlite_num_fields($this->resultset); + $meta = array(); + for ($i = 0; $i < $count; $i++) { + // items 'name' and 'table' are required + $meta[] = array( + 'name' => sqlite_field_name($this->resultset, $i), + 'table' => NULL, + ); + } + return $meta; + } + + + + /** + * Returns the connection resource. + * + * @return mixed + */ + public function getResource() + { + return $this->connection; + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + public function getResultResource() + { + return $this->resultset; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection() + {} } diff --git a/dibi/libs/DibiConnection.php b/dibi/libs/DibiConnection.php index 69af7fcf..3df20f55 100644 --- a/dibi/libs/DibiConnection.php +++ b/dibi/libs/DibiConnection.php @@ -29,434 +29,434 @@ */ class DibiConnection extends /*Nette::*/Object { - /** - * Current connection configuration. - * @var array - */ - private $config; - - /** - * IDibiDriver. - * @var array - */ - private $driver; - - /** - * Is connected? - * @var bool - */ - private $connected = FALSE; - - /** - * Is in transaction? - * @var bool - */ - private $inTxn = FALSE; - - - - /** - * Creates object and (optionally) connects to a database. - * - * @param array|string|Nette::Collections::IMap connection parameters - * @param string connection name - * @throws DibiException - */ - public function __construct($config, $name = NULL) - { - // DSN string - if (is_string($config)) { - parse_str($config, $config); - - } elseif ($config instanceof /*Nette::Collections::*/IMap) { - $config = $config->toArray(); - - } elseif (!is_array($config)) { - throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::IMap.'); - } - - if (!isset($config['driver'])) { - $config['driver'] = dibi::$defaultDriver; - } - - $driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']); - $class = "Dibi" . $driver . "Driver"; - if (!class_exists($class, FALSE)) { - include_once __FILE__ . "/../../drivers/$driver.php"; - - if (!class_exists($class, FALSE)) { - throw new DibiException("Unable to create instance of dibi driver class '$class'."); - } - } - - $config['name'] = $name; - $this->config = $config; - $this->driver = new $class; - - if (empty($config['lazy'])) { - $this->connect(); - } - } - - - - /** - * Automatically frees the resources allocated for this result set. - * - * @return void - */ - public function __destruct() - { - // disconnects and rolls back transaction - do not rely on auto-disconnect and rollback! - $this->disconnect(); - } - - - - /** - * Connects to a database. - * - * @return void - */ - final protected function connect() - { - if (!$this->connected) { - $this->driver->connect($this->config); - $this->connected = TRUE; - dibi::notify($this, 'connected'); - } - } - - - - /** - * Disconnects from a database. - * - * @return void - */ - final public function disconnect() - { - if ($this->connected) { - if ($this->inTxn) { - $this->rollback(); - } - $this->driver->disconnect(); - $this->connected = FALSE; - dibi::notify($this, 'disconnected'); - } - } - - - - /** - * Returns configuration variable. If no $key is passed, returns the entire array. - * - * @see self::__construct - * @param string - * @param mixed default value to use if key not found - * @return mixed - */ - final public function getConfig($key = NULL, $default = NULL) - { - if ($key === NULL) { - return $this->config; - - } elseif (isset($this->config[$key])) { - return $this->config[$key]; - - } else { - return $default; - } - } - - - - /** - * Apply configuration alias or default values. - * - * @param array connect configuration - * @param string key - * @param string alias key - * @return void - */ - public static function alias(&$config, $key, $alias=NULL) - { - if (isset($config[$key])) return; - - if ($alias !== NULL && isset($config[$alias])) { - $config[$key] = $config[$alias]; - unset($config[$alias]); - } else { - $config[$key] = NULL; - } - } - - - - /** - * Returns the connection resource. - * - * @return resource - */ - final public function getResource() - { - return $this->driver->getResource(); - } - - - - /** - * Generates (translates) and executes SQL query. - * - * @param array|mixed one or more arguments - * @return DibiResult Result set object (if any) - * @throws DibiException - */ - final public function query($args) - { - $args = func_get_args(); - $this->connect(); - $trans = new DibiTranslator($this->driver); - if ($trans->translate($args)) { - return $this->nativeQuery($trans->sql); - } else { - throw new DibiException('SQL translate error: ' . $trans->sql); - } - } - - - - /** - * Generates and prints SQL query. - * - * @param array|mixed one or more arguments - * @return bool - */ - final public function test($args) - { - $args = func_get_args(); - $this->connect(); - $trans = new DibiTranslator($this->driver); - $ok = $trans->translate($args); - dibi::dump($trans->sql); - return $ok; - } - - - - /** - * Executes the SQL query. - * - * @param string SQL statement. - * @return DibiResult Result set object (if any) - * @throws DibiException - */ - final public function nativeQuery($sql) - { - $this->connect(); - - dibi::$numOfQueries++; - dibi::$sql = $sql; - dibi::$elapsedTime = FALSE; - $time = -microtime(TRUE); - dibi::notify($this, 'beforeQuery', $sql); - - $res = $this->driver->query($sql) ? new DibiResult(clone $this->driver, $this->config) : TRUE; // backward compatibility - will be changed to NULL - - $time += microtime(TRUE); - dibi::$elapsedTime = $time; - dibi::$totalTime += $time; - dibi::notify($this, 'afterQuery', $res); - - return $res; - } - - - - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int number of rows - * @throws DibiException - */ - public function affectedRows() - { - $rows = $this->driver->affectedRows(); - if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.'); - return $rows; - } - - - - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @param string optional sequence name - * @return int - * @throws DibiException - */ - public function insertId($sequence = NULL) - { - $id = $this->driver->insertId($sequence); - if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.'); - return (int) $id; - } - - - - /** - * Begins a transaction (if supported). - * @return void - */ - 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'); - } - - - - /** - * Commits statements in a transaction. - * @return void - */ - public function commit() - { - if (!$this->inTxn) { - throw new DibiException('There is no active transaction.'); - } - $this->driver->commit(); - $this->inTxn = FALSE; - dibi::notify($this, 'commit'); - } - - - - /** - * Rollback changes in a transaction. - * @return void - */ - public function rollback() - { - if (!$this->inTxn) { - throw new DibiException('There is no active transaction.'); - } - $this->driver->rollback(); - $this->inTxn = FALSE; - dibi::notify($this, 'rollback'); - } - - - - /** - * Escapes the string. - * - * @param string unescaped string - * @return string escaped and optionally quoted string - */ - public function escape($value) - { - $this->connect(); // MySQL & PDO require connection - return $this->driver->format($value, dibi::FIELD_TEXT); - } - - - - /** - * Delimites identifier (table's or column's name, etc.). - * - * @param string identifier - * @return string delimited identifier - */ - public function delimite($value) - { - return $this->driver->format($value, dibi::IDENTIFIER); - } - - - - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - public function applyLimit(&$sql, $limit, $offset) - { - $this->driver->applyLimit($sql, $limit, $offset); - } - - - - /** - * Import SQL dump from file - extreme fast! - * - * @param string filename - * @return int count of sql commands - */ - public function loadFile($file) - { - $this->connect(); - - @set_time_limit(0); - - $handle = @fopen($file, 'r'); - if (!$handle) { - throw new FileNotFoundException("Cannot open file '$file'."); - } - - $count = 0; - $sql = ''; - while (!feof($handle)) { - $s = fgets($handle); - $sql .= $s; - if (substr(rtrim($s), -1) === ';') { - $this->driver->query($sql); - $sql = ''; - $count++; - } - } - fclose($handle); - return $count; - } - - - - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - public function getDibiReflection() - { - throw new NotImplementedException; - } - - - - /** - * Prevents unserialization. - */ - public function __wakeup() - { - throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); - } - - - - /** - * Prevents serialization. - */ - public function __sleep() - { - throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); - } + /** + * Current connection configuration. + * @var array + */ + private $config; + + /** + * IDibiDriver. + * @var array + */ + private $driver; + + /** + * Is connected? + * @var bool + */ + private $connected = FALSE; + + /** + * Is in transaction? + * @var bool + */ + private $inTxn = FALSE; + + + + /** + * Creates object and (optionally) connects to a database. + * + * @param array|string|Nette::Collections::IMap connection parameters + * @param string connection name + * @throws DibiException + */ + public function __construct($config, $name = NULL) + { + // DSN string + if (is_string($config)) { + parse_str($config, $config); + + } elseif ($config instanceof /*Nette::Collections::*/IMap) { + $config = $config->toArray(); + + } elseif (!is_array($config)) { + throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::IMap.'); + } + + if (!isset($config['driver'])) { + $config['driver'] = dibi::$defaultDriver; + } + + $driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']); + $class = "Dibi" . $driver . "Driver"; + if (!class_exists($class, FALSE)) { + include_once __FILE__ . "/../../drivers/$driver.php"; + + if (!class_exists($class, FALSE)) { + throw new DibiException("Unable to create instance of dibi driver class '$class'."); + } + } + + $config['name'] = $name; + $this->config = $config; + $this->driver = new $class; + + if (empty($config['lazy'])) { + $this->connect(); + } + } + + + + /** + * Automatically frees the resources allocated for this result set. + * + * @return void + */ + public function __destruct() + { + // disconnects and rolls back transaction - do not rely on auto-disconnect and rollback! + $this->disconnect(); + } + + + + /** + * Connects to a database. + * + * @return void + */ + final protected function connect() + { + if (!$this->connected) { + $this->driver->connect($this->config); + $this->connected = TRUE; + dibi::notify($this, 'connected'); + } + } + + + + /** + * Disconnects from a database. + * + * @return void + */ + final public function disconnect() + { + if ($this->connected) { + if ($this->inTxn) { + $this->rollback(); + } + $this->driver->disconnect(); + $this->connected = FALSE; + dibi::notify($this, 'disconnected'); + } + } + + + + /** + * Returns configuration variable. If no $key is passed, returns the entire array. + * + * @see self::__construct + * @param string + * @param mixed default value to use if key not found + * @return mixed + */ + final public function getConfig($key = NULL, $default = NULL) + { + if ($key === NULL) { + return $this->config; + + } elseif (isset($this->config[$key])) { + return $this->config[$key]; + + } else { + return $default; + } + } + + + + /** + * Apply configuration alias or default values. + * + * @param array connect configuration + * @param string key + * @param string alias key + * @return void + */ + public static function alias(&$config, $key, $alias=NULL) + { + if (isset($config[$key])) return; + + if ($alias !== NULL && isset($config[$alias])) { + $config[$key] = $config[$alias]; + unset($config[$alias]); + } else { + $config[$key] = NULL; + } + } + + + + /** + * Returns the connection resource. + * + * @return resource + */ + final public function getResource() + { + return $this->driver->getResource(); + } + + + + /** + * Generates (translates) and executes SQL query. + * + * @param array|mixed one or more arguments + * @return DibiResult Result set object (if any) + * @throws DibiException + */ + final public function query($args) + { + $args = func_get_args(); + $this->connect(); + $trans = new DibiTranslator($this->driver); + if ($trans->translate($args)) { + return $this->nativeQuery($trans->sql); + } else { + throw new DibiException('SQL translate error: ' . $trans->sql); + } + } + + + + /** + * Generates and prints SQL query. + * + * @param array|mixed one or more arguments + * @return bool + */ + final public function test($args) + { + $args = func_get_args(); + $this->connect(); + $trans = new DibiTranslator($this->driver); + $ok = $trans->translate($args); + dibi::dump($trans->sql); + return $ok; + } + + + + /** + * Executes the SQL query. + * + * @param string SQL statement. + * @return DibiResult Result set object (if any) + * @throws DibiException + */ + final public function nativeQuery($sql) + { + $this->connect(); + + dibi::$numOfQueries++; + dibi::$sql = $sql; + dibi::$elapsedTime = FALSE; + $time = -microtime(TRUE); + dibi::notify($this, 'beforeQuery', $sql); + + $res = $this->driver->query($sql) ? new DibiResult(clone $this->driver, $this->config) : TRUE; // backward compatibility - will be changed to NULL + + $time += microtime(TRUE); + dibi::$elapsedTime = $time; + dibi::$totalTime += $time; + dibi::notify($this, 'afterQuery', $res); + + return $res; + } + + + + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int number of rows + * @throws DibiException + */ + public function affectedRows() + { + $rows = $this->driver->affectedRows(); + if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.'); + return $rows; + } + + + + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @param string optional sequence name + * @return int + * @throws DibiException + */ + public function insertId($sequence = NULL) + { + $id = $this->driver->insertId($sequence); + if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.'); + return (int) $id; + } + + + + /** + * Begins a transaction (if supported). + * @return void + */ + 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'); + } + + + + /** + * Commits statements in a transaction. + * @return void + */ + public function commit() + { + if (!$this->inTxn) { + throw new DibiException('There is no active transaction.'); + } + $this->driver->commit(); + $this->inTxn = FALSE; + dibi::notify($this, 'commit'); + } + + + + /** + * Rollback changes in a transaction. + * @return void + */ + public function rollback() + { + if (!$this->inTxn) { + throw new DibiException('There is no active transaction.'); + } + $this->driver->rollback(); + $this->inTxn = FALSE; + dibi::notify($this, 'rollback'); + } + + + + /** + * Escapes the string. + * + * @param string unescaped string + * @return string escaped and optionally quoted string + */ + public function escape($value) + { + $this->connect(); // MySQL & PDO require connection + return $this->driver->format($value, dibi::FIELD_TEXT); + } + + + + /** + * Delimites identifier (table's or column's name, etc.). + * + * @param string identifier + * @return string delimited identifier + */ + public function delimite($value) + { + return $this->driver->format($value, dibi::IDENTIFIER); + } + + + + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + public function applyLimit(&$sql, $limit, $offset) + { + $this->driver->applyLimit($sql, $limit, $offset); + } + + + + /** + * Import SQL dump from file - extreme fast! + * + * @param string filename + * @return int count of sql commands + */ + public function loadFile($file) + { + $this->connect(); + + @set_time_limit(0); + + $handle = @fopen($file, 'r'); + if (!$handle) { + throw new FileNotFoundException("Cannot open file '$file'."); + } + + $count = 0; + $sql = ''; + while (!feof($handle)) { + $s = fgets($handle); + $sql .= $s; + if (substr(rtrim($s), -1) === ';') { + $this->driver->query($sql); + $sql = ''; + $count++; + } + } + fclose($handle); + return $count; + } + + + + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + public function getDibiReflection() + { + throw new NotImplementedException; + } + + + + /** + * Prevents unserialization. + */ + public function __wakeup() + { + throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); + } + + + + /** + * Prevents serialization. + */ + public function __sleep() + { + throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); + } } diff --git a/dibi/libs/DibiDataSource.php b/dibi/libs/DibiDataSource.php index c5a8ac1d..70f385a5 100644 --- a/dibi/libs/DibiDataSource.php +++ b/dibi/libs/DibiDataSource.php @@ -29,64 +29,64 @@ */ class DibiDataSource extends /*Nette::*/Object implements IDataSource { - /** @var DibiConnection */ - private $connection; + /** @var DibiConnection */ + private $connection; - /** @var string */ - private $sql; + /** @var string */ + private $sql; - /** @var int */ - private $count; + /** @var int */ + private $count; - /** - * @param string SQL command or table name, as data source - * @param DibiConnection connection - */ - public function __construct($sql, DibiConnection $connection = NULL) - { - if (strpos($sql, ' ') === FALSE) { - // table name - $this->sql = $sql; - } else { - // SQL command - $this->sql = '(' . $sql . ') AS [source]'; - } + /** + * @param string SQL command or table name, as data source + * @param DibiConnection connection + */ + public function __construct($sql, DibiConnection $connection = NULL) + { + if (strpos($sql, ' ') === FALSE) { + // table name + $this->sql = $sql; + } else { + // SQL command + $this->sql = '(' . $sql . ') AS [source]'; + } - $this->connection = $connection === NULL ? dibi::getConnection() : $connection; - } + $this->connection = $connection === NULL ? dibi::getConnection() : $connection; + } - /** - * @param int offset - * @param int limit - * @param array columns - * @return ArrayIterator - */ - public function getIterator($offset = NULL, $limit = NULL, $cols = NULL) - { - return $this->connection->query(' - SELECT * - FROM', $this->sql, ' - %ofs %lmt', $offset, $limit - ); - } + /** + * @param int offset + * @param int limit + * @param array columns + * @return ArrayIterator + */ + public function getIterator($offset = NULL, $limit = NULL, $cols = NULL) + { + return $this->connection->query(' + SELECT * + FROM', $this->sql, ' + %ofs %lmt', $offset, $limit + ); + } - /** - * @return int - */ - public function count() - { - if ($this->count === NULL) { - $this->count = $this->connection->query(' - SELECT COUNT(*) FROM', $this->sql - )->fetchSingle(); - } - return $this->count; - } + /** + * @return int + */ + public function count() + { + if ($this->count === NULL) { + $this->count = $this->connection->query(' + SELECT COUNT(*) FROM', $this->sql + )->fetchSingle(); + } + return $this->count; + } } diff --git a/dibi/libs/DibiException.php b/dibi/libs/DibiException.php index 8fe55a8d..18b077c8 100644 --- a/dibi/libs/DibiException.php +++ b/dibi/libs/DibiException.php @@ -44,116 +44,116 @@ class DibiException extends Exception */ class DibiDriverException extends DibiException implements /*Nette::*/IDebuggable { - /** @var string */ - private static $errorMsg; + /** @var string */ + private static $errorMsg; - /** @var string */ - private $sql; + /** @var string */ + private $sql; - /** - * Construct an dibi driver exception. + /** + * Construct an dibi driver exception. * * @param string Message describing the exception * @param int Some code - * @param string SQL command + * @param string SQL command */ - public function __construct($message = NULL, $code = 0, $sql = NULL) - { - parent::__construct($message, (int) $code); - $this->sql = $sql; - dibi::notify(NULL, 'exception', $this); - } + public function __construct($message = NULL, $code = 0, $sql = NULL) + { + parent::__construct($message, (int) $code); + $this->sql = $sql; + dibi::notify(NULL, 'exception', $this); + } - /** - * @return string The SQL passed to the constructor + /** + * @return string The SQL passed to the constructor */ - final public function getSql() - { - return $this->sql; - } + final public function getSql() + { + return $this->sql; + } - /** - * @return string string represenation of exception with SQL command - */ - public function __toString() - { - return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : ''); - } + /** + * @return string string represenation of exception with SQL command + */ + public function __toString() + { + return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : ''); + } - /********************* interface Nette::IDebuggable ****************d*g**/ + /********************* interface Nette::IDebuggable ****************d*g**/ - /** - * Returns custom panels. - * @return array - */ - public function getPanels() - { - $panels = array(); - if ($this->sql !== NULL) { - $panels['SQL'] = array( - 'expanded' => TRUE, - 'content' => dibi::dump($this->sql, TRUE), - ); - } - return $panels; - } + /** + * Returns custom panels. + * @return array + */ + public function getPanels() + { + $panels = array(); + if ($this->sql !== NULL) { + $panels['SQL'] = array( + 'expanded' => TRUE, + 'content' => dibi::dump($this->sql, TRUE), + ); + } + return $panels; + } - /********************* error catching ****************d*g**/ + /********************* error catching ****************d*g**/ - /** - * Starts catching potential errors/warnings - * - * @return void - */ - public static function tryError() - { - set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL); - self::$errorMsg = NULL; - } + /** + * Starts catching potential errors/warnings + * + * @return void + */ + public static function tryError() + { + set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL); + self::$errorMsg = NULL; + } - /** - * Returns catched error/warning message. - * - * @param string catched message - * @return bool - */ - public static function catchError(& $message) - { - restore_error_handler(); - $message = self::$errorMsg; - self::$errorMsg = NULL; - return $message !== NULL; - } + /** + * Returns catched error/warning message. + * + * @param string catched message + * @return bool + */ + public static function catchError(& $message) + { + restore_error_handler(); + $message = self::$errorMsg; + self::$errorMsg = NULL; + return $message !== NULL; + } - /** - * Internal error handler. Do not call directly. - */ - public static function _errorHandler($code, $message) - { - restore_error_handler(); + /** + * Internal error handler. Do not call directly. + */ + public static function _errorHandler($code, $message) + { + restore_error_handler(); - if (ini_get('html_errors')) { - $message = strip_tags($message); - $message = html_entity_decode($message); - } + if (ini_get('html_errors')) { + $message = strip_tags($message); + $message = html_entity_decode($message); + } - self::$errorMsg = $message; - } + self::$errorMsg = $message; + } } \ No newline at end of file diff --git a/dibi/libs/DibiLogger.php b/dibi/libs/DibiLogger.php index 48d5e906..c864cb92 100644 --- a/dibi/libs/DibiLogger.php +++ b/dibi/libs/DibiLogger.php @@ -29,78 +29,78 @@ */ final class DibiLogger extends /*Nette::*/Object { - /** @var string Name of the file where SQL errors should be logged */ - private $file; + /** @var string Name of the file where SQL errors should be logged */ + private $file; - /** @var bool */ - public $logErrors = TRUE; + /** @var bool */ + public $logErrors = TRUE; - /** @var bool */ - public $logQueries = TRUE; + /** @var bool */ + public $logQueries = TRUE; - /** - * @param string filename - */ - public function __construct($file) - { - $this->file = $file; - } + /** + * @param string filename + */ + public function __construct($file) + { + $this->file = $file; + } - /** - * Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback). - * - * @param DibiConnection - * @param string event name - * @param mixed - * @return void - */ - public function handler($connection, $event, $arg) - { - if ($event === 'afterQuery' && $this->logQueries) { - $this->write( - "OK: " . dibi::$sql - . ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '') - . "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms' - . "\n-- driver: " . $connection->getConfig('driver') - . "\n-- " . date('Y-m-d H:i:s') - . "\n\n" - ); - return; - } + /** + * Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback). + * + * @param DibiConnection + * @param string event name + * @param mixed + * @return void + */ + public function handler($connection, $event, $arg) + { + if ($event === 'afterQuery' && $this->logQueries) { + $this->write( + "OK: " . dibi::$sql + . ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '') + . "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms' + . "\n-- driver: " . $connection->getConfig('driver') + . "\n-- " . date('Y-m-d H:i:s') + . "\n\n" + ); + return; + } - if ($event === 'exception' && $this->logErrors) { - // $arg is DibiDriverException - $message = $arg->getMessage(); - $code = $arg->getCode(); - if ($code) { - $message = "[$code] $message"; - } + if ($event === 'exception' && $this->logErrors) { + // $arg is DibiDriverException + $message = $arg->getMessage(); + $code = $arg->getCode(); + if ($code) { + $message = "[$code] $message"; + } - $this->write( - "ERROR: $message" - . "\n-- SQL: " . dibi::$sql - . "\n-- driver: " //. $connection->getConfig('driver') - . ";\n-- " . date('Y-m-d H:i:s') - . "\n\n" - ); - return; - } - } + $this->write( + "ERROR: $message" + . "\n-- SQL: " . dibi::$sql + . "\n-- driver: " //. $connection->getConfig('driver') + . ";\n-- " . date('Y-m-d H:i:s') + . "\n\n" + ); + return; + } + } - private function write($message) - { - $handle = fopen($this->file, 'a'); - if (!$handle) return; // or throw exception? + private function write($message) + { + $handle = fopen($this->file, 'a'); + if (!$handle) return; // or throw exception? - flock($handle, LOCK_EX); - fwrite($handle, $message); - fclose($handle); - } + flock($handle, LOCK_EX); + fwrite($handle, $message); + fclose($handle); + } } diff --git a/dibi/libs/DibiResult.php b/dibi/libs/DibiResult.php index 37e042e2..2c74228b 100644 --- a/dibi/libs/DibiResult.php +++ b/dibi/libs/DibiResult.php @@ -43,545 +43,545 @@ */ class DibiResult extends /*Nette::*/Object implements IDataSource { - /** - * IDibiDriver. - * @var array - */ - private $driver; - - /** - * Translate table. - * @var array - */ - private $xlat; - - /** - * Cache for $driver->getColumnsMeta(). - * @var array - */ - private $metaCache; - - /** - * Already fetched? Used for allowance for first seek(0). - * @var bool - */ - private $fetched = FALSE; - - /** - * Qualifiy each column name with the table name? - * @var array|FALSE - */ - private $withTables = FALSE; - - /** - * Fetch as object? - * @var bool - */ - public $asObjects = FALSE; - - - - private static $types = array( - dibi::FIELD_TEXT => 'string', - dibi::FIELD_BINARY => 'string', - dibi::FIELD_INTEGER => 'int', - dibi::FIELD_FLOAT => 'float', - dibi::FIELD_COUNTER => 'int', - ); - - - - /** - * @param IDibiDriver - * @param array - */ - public function __construct($driver, $config) - { - $this->driver = $driver; - $this->setWithTables(!empty($config['result:withtables'])); - $this->asObjects = !empty($config['result:objects']); - } - - - - /** - * Automatically frees the resources allocated for this result set. - * - * @return void - */ - public function __destruct() - { - @$this->free(); - } - - - - /** - * Returns the resultset resource. - * - * @return mixed - */ - final public function getResource() - { - return $this->getDriver()->getResultResource(); - } - - - - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - final public function seek($row) - { - return ($row !== 0 || $this->fetched) ? (bool) $this->getDriver()->seek($row) : TRUE; - } - - - - /** - * Returns the number of rows in a result set. - * - * @return int - */ - final public function rowCount() - { - return $this->getDriver()->rowCount(); - } - - - - /** - * Frees the resources allocated for this result set. - * - * @return void - */ - final public function free() - { - if ($this->driver !== NULL) { - $this->driver->free(); - $this->driver = NULL; - } - } - - - - /** - * Qualifiy each column name with the table name? - * - * @param bool - * @return void - * @throws DibiException - */ - final public function setWithTables($val) - { - if ($val) { - if ($this->metaCache === NULL) { - $this->metaCache = $this->getDriver()->getColumnsMeta(); - } - - $cols = array(); - foreach ($this->metaCache as $col) { - // intentional == - $name = $col['table'] == '' ? $col['name'] : ($col['table'] . '.' . $col['name']); - if (isset($cols[$name])) { - $fix = 1; - while (isset($cols[$name . '#' . $fix])) $fix++; - $name .= '#' . $fix; - } - $cols[$name] = TRUE; - } - $this->withTables = array_keys($cols); - - } else { - $this->withTables = FALSE; - } - } - - - - /** - * Qualifiy each key with the table name? - * - * @return bool - */ - final public function getWithTables() - { - return (bool) $this->withTables; - } - - - - /** - * Fetches the row at current position, process optional type conversion. - * and moves the internal cursor to the next position - * - * @param bool fetch as object? Overrides $this->asObjects - * @return array|FALSE array on success, FALSE if no next record - */ - final public function fetch($asObject = NULL) - { - if ($this->withTables === FALSE) { - $row = $this->getDriver()->fetch(TRUE); - if (!is_array($row)) return FALSE; - - } else { - $row = $this->getDriver()->fetch(FALSE); - if (!is_array($row)) return FALSE; - $row = array_combine($this->withTables, $row); - } - - $this->fetched = TRUE; - - // types-converting? - if ($this->xlat !== NULL) { - foreach ($this->xlat as $col => $type) { - if (isset($row[$col])) { - $row[$col] = $this->convert($row[$col], $type[0], $type[1]); - } - } - } - - if ($asObject || ($asObject === NULL && $this->asObjects)) { - $row = (object) $row; - } - - return $row; - } - - - - /** - * Like fetch(), but returns only first field. - * - * @return mixed value on success, FALSE if no next record - */ - final function fetchSingle() - { - $row = $this->getDriver()->fetch(TRUE); - if (!is_array($row)) return FALSE; - $this->fetched = TRUE; - $value = reset($row); - - // types-converting? - $key = key($row); - if (isset($this->xlat[$key])) { - $type = $this->xlat[$key]; - return $this->convert($value, $type[0], $type[1]); - } - - return $value; - } - - - - /** - * Fetches all records from table. - * - * @return array - */ - final function fetchAll() - { - $this->seek(0); - $row = $this->fetch(FALSE); - if (!$row) return array(); // empty resultset - - $data = array(); - if (count($row) === 1) { - $key = key($row); - do { - $data[] = $row[$key]; - } while ($row = $this->fetch(FALSE)); - - } else { - if ($this->asObjects) $row = (object) $row; - do { - $data[] = $row; - } while ($row = $this->fetch()); - } - - return $data; - } - - - - /** - * Fetches all records from table and returns associative tree. - * Associative descriptor: assoc1,#,assoc2,=,assoc3,@ - * builds a tree: $data[assoc1][index][assoc2]['assoc3']->value = {record} - * - * @param string associative descriptor - * @return array - * @throws InvalidArgumentException - */ - final function fetchAssoc($assoc) - { - $this->seek(0); - $row = $this->fetch(FALSE); - if (!$row) return array(); // empty resultset - - $data = NULL; - $assoc = explode(',', $assoc); - - // check columns - foreach ($assoc as $as) { - if ($as !== '#' && $as !== '=' && $as !== '@' && !array_key_exists($as, $row)) { - throw new InvalidArgumentException("Unknown column '$as' in associative descriptor."); - } - } - - // strip leading = and @ - $assoc[] = '='; // gap - $last = count($assoc) - 1; - while ($assoc[$last] === '=' || $assoc[$last] === '@') { - $leaf = $assoc[$last]; - unset($assoc[$last]); - $last--; - - if ($last < 0) { - $assoc[] = '#'; - break; - } - } - - // make associative tree - do { - $x = & $data; - - // iterative deepening - foreach ($assoc as $i => $as) { - if ($as === '#') { // indexed-array node - $x = & $x[]; - - } elseif ($as === '=') { // "record" node - if ($x === NULL) { - $x = $row; - $x = & $x[ $assoc[$i+1] ]; - $x = NULL; // prepare child node - } else { - $x = & $x[ $assoc[$i+1] ]; - } - - } elseif ($as === '@') { // "object" node - if ($x === NULL) { - $x = (object) $row; - $x = & $x->{$assoc[$i+1]}; - $x = NULL; // prepare child node - } else { - $x = & $x->{$assoc[$i+1]}; - } - - - } else { // associative-array node - $x = & $x[ $row[ $as ] ]; - } - } - - if ($x === NULL) { // build leaf - if ($leaf === '=') $x = $row; else $x = (object) $row; - } - - } while ($row = $this->fetch(FALSE)); - - unset($x); - return $data; - } - - - - /** - * Fetches all records from table like $key => $value pairs. - * - * @param string associative key - * @param string value - * @return array - * @throws InvalidArgumentException - */ - final function fetchPairs($key = NULL, $value = NULL) - { - $this->seek(0); - $row = $this->fetch(FALSE); - if (!$row) return array(); // empty resultset - - $data = array(); - - if ($value === NULL) { - if ($key !== NULL) { - throw new InvalidArgumentException("Either none or both columns must be specified."); - } - - if (count($row) < 2) { - throw new UnexpectedValueException("Result must have at least two columns."); - } - - // autodetect - $tmp = array_keys($row); - $key = $tmp[0]; - $value = $tmp[1]; - - } else { - if (!array_key_exists($value, $row)) { - throw new InvalidArgumentException("Unknown value column '$value'."); - } - - if ($key === NULL) { // indexed-array - do { - $data[] = $row[$value]; - } while ($row = $this->fetch(FALSE)); - return $data; - } - - if (!array_key_exists($key, $row)) { - throw new InvalidArgumentException("Unknown key column '$key'."); - } - } - - do { - $data[ $row[$key] ] = $row[$value]; - } while ($row = $this->fetch(FALSE)); - - return $data; - } - - - - final public function setType($col, $type = NULL, $format = NULL) - { - $this->xlat[$col] = array($type, $format); - } - - - - final public function getType($col) - { - return isset($this->xlat[$col]) ? $this->xlat[$col] : NULL; - } - - - - final public function convert($value, $type, $format = NULL) - { - if ($value === NULL || $value === FALSE) { - return $value; - } + /** + * IDibiDriver. + * @var array + */ + private $driver; + + /** + * Translate table. + * @var array + */ + private $xlat; + + /** + * Cache for $driver->getColumnsMeta(). + * @var array + */ + private $metaCache; + + /** + * Already fetched? Used for allowance for first seek(0). + * @var bool + */ + private $fetched = FALSE; + + /** + * Qualifiy each column name with the table name? + * @var array|FALSE + */ + private $withTables = FALSE; + + /** + * Fetch as object? + * @var bool + */ + public $asObjects = FALSE; + + + + private static $types = array( + dibi::FIELD_TEXT => 'string', + dibi::FIELD_BINARY => 'string', + dibi::FIELD_INTEGER => 'int', + dibi::FIELD_FLOAT => 'float', + dibi::FIELD_COUNTER => 'int', + ); + + + + /** + * @param IDibiDriver + * @param array + */ + public function __construct($driver, $config) + { + $this->driver = $driver; + $this->setWithTables(!empty($config['result:withtables'])); + $this->asObjects = !empty($config['result:objects']); + } + + + + /** + * Automatically frees the resources allocated for this result set. + * + * @return void + */ + public function __destruct() + { + @$this->free(); + } + + + + /** + * Returns the resultset resource. + * + * @return mixed + */ + final public function getResource() + { + return $this->getDriver()->getResultResource(); + } + + + + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + final public function seek($row) + { + return ($row !== 0 || $this->fetched) ? (bool) $this->getDriver()->seek($row) : TRUE; + } + + + + /** + * Returns the number of rows in a result set. + * + * @return int + */ + final public function rowCount() + { + return $this->getDriver()->rowCount(); + } + + + + /** + * Frees the resources allocated for this result set. + * + * @return void + */ + final public function free() + { + if ($this->driver !== NULL) { + $this->driver->free(); + $this->driver = NULL; + } + } + + + + /** + * Qualifiy each column name with the table name? + * + * @param bool + * @return void + * @throws DibiException + */ + final public function setWithTables($val) + { + if ($val) { + if ($this->metaCache === NULL) { + $this->metaCache = $this->getDriver()->getColumnsMeta(); + } + + $cols = array(); + foreach ($this->metaCache as $col) { + // intentional == + $name = $col['table'] == '' ? $col['name'] : ($col['table'] . '.' . $col['name']); + if (isset($cols[$name])) { + $fix = 1; + while (isset($cols[$name . '#' . $fix])) $fix++; + $name .= '#' . $fix; + } + $cols[$name] = TRUE; + } + $this->withTables = array_keys($cols); + + } else { + $this->withTables = FALSE; + } + } + + + + /** + * Qualifiy each key with the table name? + * + * @return bool + */ + final public function getWithTables() + { + return (bool) $this->withTables; + } + + + + /** + * Fetches the row at current position, process optional type conversion. + * and moves the internal cursor to the next position + * + * @param bool fetch as object? Overrides $this->asObjects + * @return array|FALSE array on success, FALSE if no next record + */ + final public function fetch($asObject = NULL) + { + if ($this->withTables === FALSE) { + $row = $this->getDriver()->fetch(TRUE); + if (!is_array($row)) return FALSE; + + } else { + $row = $this->getDriver()->fetch(FALSE); + if (!is_array($row)) return FALSE; + $row = array_combine($this->withTables, $row); + } + + $this->fetched = TRUE; + + // types-converting? + if ($this->xlat !== NULL) { + foreach ($this->xlat as $col => $type) { + if (isset($row[$col])) { + $row[$col] = $this->convert($row[$col], $type[0], $type[1]); + } + } + } + + if ($asObject || ($asObject === NULL && $this->asObjects)) { + $row = (object) $row; + } + + return $row; + } + + + + /** + * Like fetch(), but returns only first field. + * + * @return mixed value on success, FALSE if no next record + */ + final function fetchSingle() + { + $row = $this->getDriver()->fetch(TRUE); + if (!is_array($row)) return FALSE; + $this->fetched = TRUE; + $value = reset($row); + + // types-converting? + $key = key($row); + if (isset($this->xlat[$key])) { + $type = $this->xlat[$key]; + return $this->convert($value, $type[0], $type[1]); + } + + return $value; + } + + + + /** + * Fetches all records from table. + * + * @return array + */ + final function fetchAll() + { + $this->seek(0); + $row = $this->fetch(FALSE); + if (!$row) return array(); // empty resultset + + $data = array(); + if (count($row) === 1) { + $key = key($row); + do { + $data[] = $row[$key]; + } while ($row = $this->fetch(FALSE)); + + } else { + if ($this->asObjects) $row = (object) $row; + do { + $data[] = $row; + } while ($row = $this->fetch()); + } + + return $data; + } + + + + /** + * Fetches all records from table and returns associative tree. + * Associative descriptor: assoc1,#,assoc2,=,assoc3,@ + * builds a tree: $data[assoc1][index][assoc2]['assoc3']->value = {record} + * + * @param string associative descriptor + * @return array + * @throws InvalidArgumentException + */ + final function fetchAssoc($assoc) + { + $this->seek(0); + $row = $this->fetch(FALSE); + if (!$row) return array(); // empty resultset + + $data = NULL; + $assoc = explode(',', $assoc); + + // check columns + foreach ($assoc as $as) { + if ($as !== '#' && $as !== '=' && $as !== '@' && !array_key_exists($as, $row)) { + throw new InvalidArgumentException("Unknown column '$as' in associative descriptor."); + } + } + + // strip leading = and @ + $assoc[] = '='; // gap + $last = count($assoc) - 1; + while ($assoc[$last] === '=' || $assoc[$last] === '@') { + $leaf = $assoc[$last]; + unset($assoc[$last]); + $last--; + + if ($last < 0) { + $assoc[] = '#'; + break; + } + } + + // make associative tree + do { + $x = & $data; + + // iterative deepening + foreach ($assoc as $i => $as) { + if ($as === '#') { // indexed-array node + $x = & $x[]; + + } elseif ($as === '=') { // "record" node + if ($x === NULL) { + $x = $row; + $x = & $x[ $assoc[$i+1] ]; + $x = NULL; // prepare child node + } else { + $x = & $x[ $assoc[$i+1] ]; + } + + } elseif ($as === '@') { // "object" node + if ($x === NULL) { + $x = (object) $row; + $x = & $x->{$assoc[$i+1]}; + $x = NULL; // prepare child node + } else { + $x = & $x->{$assoc[$i+1]}; + } + + + } else { // associative-array node + $x = & $x[ $row[ $as ] ]; + } + } + + if ($x === NULL) { // build leaf + if ($leaf === '=') $x = $row; else $x = (object) $row; + } + + } while ($row = $this->fetch(FALSE)); + + unset($x); + return $data; + } + + + + /** + * Fetches all records from table like $key => $value pairs. + * + * @param string associative key + * @param string value + * @return array + * @throws InvalidArgumentException + */ + final function fetchPairs($key = NULL, $value = NULL) + { + $this->seek(0); + $row = $this->fetch(FALSE); + if (!$row) return array(); // empty resultset + + $data = array(); + + if ($value === NULL) { + if ($key !== NULL) { + throw new InvalidArgumentException("Either none or both columns must be specified."); + } + + if (count($row) < 2) { + throw new UnexpectedValueException("Result must have at least two columns."); + } + + // autodetect + $tmp = array_keys($row); + $key = $tmp[0]; + $value = $tmp[1]; + + } else { + if (!array_key_exists($value, $row)) { + throw new InvalidArgumentException("Unknown value column '$value'."); + } + + if ($key === NULL) { // indexed-array + do { + $data[] = $row[$value]; + } while ($row = $this->fetch(FALSE)); + return $data; + } + + if (!array_key_exists($key, $row)) { + throw new InvalidArgumentException("Unknown key column '$key'."); + } + } + + do { + $data[ $row[$key] ] = $row[$value]; + } while ($row = $this->fetch(FALSE)); + + return $data; + } + + + + final public function setType($col, $type = NULL, $format = NULL) + { + $this->xlat[$col] = array($type, $format); + } + + + + final public function getType($col) + { + return isset($this->xlat[$col]) ? $this->xlat[$col] : NULL; + } + + + + final public function convert($value, $type, $format = NULL) + { + if ($value === NULL || $value === FALSE) { + return $value; + } - if (isset(self::$types[$type])) { - settype($value, self::$types[$type]); - return $value; - } + if (isset(self::$types[$type])) { + settype($value, self::$types[$type]); + return $value; + } - if ($type === dibi::FIELD_DATE || $type === dibi::FIELD_DATETIME) { - return $format === NULL ? strtotime($value) : date($format, strtotime($value)); - } - - if ($type === dibi::FIELD_BOOL) { - return ((bool) $value) && $value !== 'f' && $value !== 'F'; - } - - return $value; - } - - - - /** - * Gets an array of meta informations about column. - * - * @return array - */ - final public function getColumnsMeta() - { - if ($this->metaCache === NULL) { - $this->metaCache = $this->getDriver()->getColumnsMeta(); - } - - $cols = array(); - foreach ($this->metaCache as $col) { - $name = (!$this->withTables || $col['table'] === NULL) ? $col['name'] : ($col['table'] . '.' . $col['name']); - $cols[$name] = $col; - } - return $cols; - } - - - - /** - * Displays complete result-set as HTML table for debug purposes. - * - * @return void - */ - final public function dump() - { - $none = TRUE; - foreach ($this as $i => $row) { - if ($none) { - echo "\n\n\n\t\n\t\t\n"; - - foreach ($row as $col => $foo) { - echo "\t\t\n"; - } - - echo "\t\n\n\n"; - $none = FALSE; - } - - echo "\t\n\t\t\n"; - foreach ($row as $col) { - //if (is_object($col)) $col = $col->__toString(); - echo "\t\t\n"; - } - echo "\t\n"; - } - - if ($none) { - echo '

empty resultset

'; - } else { - echo "\n
#row" . htmlSpecialChars($col) . "
", $i, "", htmlSpecialChars($col), "
\n"; - } - } + if ($type === dibi::FIELD_DATE || $type === dibi::FIELD_DATETIME) { + return $format === NULL ? strtotime($value) : date($format, strtotime($value)); + } + + if ($type === dibi::FIELD_BOOL) { + return ((bool) $value) && $value !== 'f' && $value !== 'F'; + } + + return $value; + } + + + + /** + * Gets an array of meta informations about column. + * + * @return array + */ + final public function getColumnsMeta() + { + if ($this->metaCache === NULL) { + $this->metaCache = $this->getDriver()->getColumnsMeta(); + } + + $cols = array(); + foreach ($this->metaCache as $col) { + $name = (!$this->withTables || $col['table'] === NULL) ? $col['name'] : ($col['table'] . '.' . $col['name']); + $cols[$name] = $col; + } + return $cols; + } + + + + /** + * Displays complete result-set as HTML table for debug purposes. + * + * @return void + */ + final public function dump() + { + $none = TRUE; + foreach ($this as $i => $row) { + if ($none) { + echo "\n\n\n\t\n\t\t\n"; + + foreach ($row as $col => $foo) { + echo "\t\t\n"; + } + + echo "\t\n\n\n"; + $none = FALSE; + } + + echo "\t\n\t\t\n"; + foreach ($row as $col) { + //if (is_object($col)) $col = $col->__toString(); + echo "\t\t\n"; + } + echo "\t\n"; + } + + if ($none) { + echo '

empty resultset

'; + } else { + echo "\n
#row" . htmlSpecialChars($col) . "
", $i, "", htmlSpecialChars($col), "
\n"; + } + } - /** - * Required by the IteratorAggregate interface. - * @param int offset - * @param int limit - * @return ArrayIterator - */ - final public function getIterator($offset = NULL, $limit = NULL) - { - return new DibiResultIterator($this, $offset, $limit); - } - - - - /** - * Required by the Countable interface. - * @return int - */ - final public function count() - { - return $this->rowCount(); - } - - - - /** - * Safe access to property $driver. - * - * @return IDibiDriver - * @throws InvalidStateException - */ - private function getDriver() - { - if ($this->driver === NULL) { - throw new InvalidStateException('Resultset was released from memory.'); - } - - return $this->driver; - } + /** + * Required by the IteratorAggregate interface. + * @param int offset + * @param int limit + * @return ArrayIterator + */ + final public function getIterator($offset = NULL, $limit = NULL) + { + return new DibiResultIterator($this, $offset, $limit); + } + + + + /** + * Required by the Countable interface. + * @return int + */ + final public function count() + { + return $this->rowCount(); + } + + + + /** + * Safe access to property $driver. + * + * @return IDibiDriver + * @throws InvalidStateException + */ + private function getDriver() + { + if ($this->driver === NULL) { + throw new InvalidStateException('Resultset was released from memory.'); + } + + return $this->driver; + } } diff --git a/dibi/libs/DibiResultIterator.php b/dibi/libs/DibiResultIterator.php index 7c34bec0..a3a1a8df 100644 --- a/dibi/libs/DibiResultIterator.php +++ b/dibi/libs/DibiResultIterator.php @@ -45,92 +45,92 @@ */ final class DibiResultIterator implements Iterator { - /** @var DibiResult */ - private $result; + /** @var DibiResult */ + private $result; - /** @var int */ - private $offset; + /** @var int */ + private $offset; - /** @var int */ - private $limit; + /** @var int */ + private $limit; - /** @var int */ - private $row; + /** @var int */ + private $row; - /** @var int */ - private $pointer; + /** @var int */ + private $pointer; - /** - * Required by the Iterator interface. - * @param int offset - * @param int limit - */ - public function __construct(DibiResult $result, $offset, $limit) - { - $this->result = $result; - $this->offset = (int) $offset; - $this->limit = $limit === NULL ? -1 : (int) $limit; - } - - - - /** - * Rewinds the Iterator to the first element. - * @return void + /** + * Required by the Iterator interface. + * @param int offset + * @param int limit */ - public function rewind() - { - $this->pointer = 0; - $this->result->seek($this->offset); - $this->row = $this->result->fetch(); - } + public function __construct(DibiResult $result, $offset, $limit) + { + $this->result = $result; + $this->offset = (int) $offset; + $this->limit = $limit === NULL ? -1 : (int) $limit; + } - /** - * Returns the key of the current element. - * @return mixed + /** + * Rewinds the Iterator to the first element. + * @return void */ - public function key() - { - return $this->pointer; - } + public function rewind() + { + $this->pointer = 0; + $this->result->seek($this->offset); + $this->row = $this->result->fetch(); + } - /** - * Returns the current element. - * @return mixed + /** + * Returns the key of the current element. + * @return mixed */ - public function current() - { - return $this->row; - } + public function key() + { + return $this->pointer; + } - /** - * Moves forward to next element. - * @return void + /** + * Returns the current element. + * @return mixed */ - public function next() - { - //$this->result->seek($this->offset + $this->pointer + 1); - $this->row = $this->result->fetch(); - $this->pointer++; - } + public function current() + { + return $this->row; + } - /** - * Checks if there is a current element after calls to rewind() or next(). - * @return bool + /** + * Moves forward to next element. + * @return void */ - public function valid() - { - return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit); - } + public function next() + { + //$this->result->seek($this->offset + $this->pointer + 1); + $this->row = $this->result->fetch(); + $this->pointer++; + } + + + + /** + * Checks if there is a current element after calls to rewind() or next(). + * @return bool + */ + public function valid() + { + return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit); + } } diff --git a/dibi/libs/DibiTable.php b/dibi/libs/DibiTable.php index 17af7ad1..16674bdf 100644 --- a/dibi/libs/DibiTable.php +++ b/dibi/libs/DibiTable.php @@ -28,264 +28,264 @@ */ abstract class DibiTable extends /*Nette::*/Object { - /** @var string primary key mask */ - public static $primaryMask = 'id'; + /** @var string primary key mask */ + public static $primaryMask = 'id'; - /** @var bool */ - public static $lowerCase = TRUE; + /** @var bool */ + public static $lowerCase = TRUE; - /** @var DibiConnection */ - private $connection; + /** @var DibiConnection */ + private $connection; - /** @var array */ - private $options; + /** @var array */ + private $options; - /** @var string table name */ - protected $name; + /** @var string table name */ + protected $name; - /** @var string primary key name */ - protected $primary; + /** @var string primary key name */ + protected $primary; - /** @var string primary key type */ - protected $primaryModifier = '%i'; + /** @var string primary key type */ + protected $primaryModifier = '%i'; - /** @var array */ - protected $blankRow = array(); + /** @var array */ + protected $blankRow = array(); - /** - * Table constructor. - * @param array - * @return void - */ - public function __construct(array $options = array()) - { - $this->options = $options; + /** + * Table constructor. + * @param array + * @return void + */ + public function __construct(array $options = array()) + { + $this->options = $options; - $this->setup(); + $this->setup(); - if ($this->connection === NULL) { - $this->connection = dibi::getConnection(); - } - } + if ($this->connection === NULL) { + $this->connection = dibi::getConnection(); + } + } - /** - * Returns the table name. - * @return string - */ - public function getName() - { - return $this->name; - } + /** + * Returns the table name. + * @return string + */ + public function getName() + { + return $this->name; + } - /** - * Returns the primary key name. - * @return string - */ - public function getPrimary() - { - return $this->primary; - } + /** + * Returns the primary key name. + * @return string + */ + public function getPrimary() + { + return $this->primary; + } - /** - * Returns the dibi connection. - * @return DibiConnection - */ - public function getConnection() - { - return $this->connection; - } + /** + * Returns the dibi connection. + * @return DibiConnection + */ + public function getConnection() + { + return $this->connection; + } - /** - * Setup object. - * @return void - */ - protected function setup() - { - // autodetect table name - if ($this->name === NULL) { - $name = $this->getClass(); - if (FALSE !== ($pos = strrpos($name, ':'))) { - $name = substr($name, $pos + 1); - } - if (self::$lowerCase) { - $name = strtolower($name); - } - $this->name = $name; - } + /** + * Setup object. + * @return void + */ + protected function setup() + { + // autodetect table name + if ($this->name === NULL) { + $name = $this->getClass(); + if (FALSE !== ($pos = strrpos($name, ':'))) { + $name = substr($name, $pos + 1); + } + if (self::$lowerCase) { + $name = strtolower($name); + } + $this->name = $name; + } - // autodetect primary key name - if ($this->primary === NULL) { - $this->primary = str_replace( - array('%p', '%s'), - array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-)) - self::$primaryMask - ); - } - } + // autodetect primary key name + if ($this->primary === NULL) { + $this->primary = str_replace( + array('%p', '%s'), + array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-)) + self::$primaryMask + ); + } + } - /** - * Inserts row into a table. - * @param array|object - * @return int new primary key - */ - public function insert($data) - { - $this->connection->query( - 'INSERT INTO %n', $this->name, '%v', $this->prepare($data) - ); - return $this->connection->insertId(); - } + /** + * Inserts row into a table. + * @param array|object + * @return int new primary key + */ + public function insert($data) + { + $this->connection->query( + 'INSERT INTO %n', $this->name, '%v', $this->prepare($data) + ); + return $this->connection->insertId(); + } - /** - * Updates rows in a table. - * @param mixed primary key value(s) - * @param array|object - * @return int number of updated rows - */ - public function update($where, $data) - { - $this->connection->query( - 'UPDATE %n', $this->name, - 'SET %a', $this->prepare($data), - 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' - ); - return $this->connection->affectedRows(); - } + /** + * Updates rows in a table. + * @param mixed primary key value(s) + * @param array|object + * @return int number of updated rows + */ + public function update($where, $data) + { + $this->connection->query( + 'UPDATE %n', $this->name, + 'SET %a', $this->prepare($data), + 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' + ); + return $this->connection->affectedRows(); + } - /** - * Deletes rows from a table by primary key. - * @param mixed primary key value(s) - * @return int number of deleted rows - */ - public function delete($where) - { - $this->connection->query( - 'DELETE FROM %n', $this->name, - 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' - ); - return $this->connection->affectedRows(); - } + /** + * Deletes rows from a table by primary key. + * @param mixed primary key value(s) + * @return int number of deleted rows + */ + public function delete($where) + { + $this->connection->query( + 'DELETE FROM %n', $this->name, + 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' + ); + return $this->connection->affectedRows(); + } - /** - * Finds rows by primary key. - * @param mixed primary key value(s) - * @return DibiResult - */ - public function find($what) - { - if (!is_array($what)) { - $what = func_get_args(); - } - return $this->complete($this->connection->query( - 'SELECT * FROM %n', $this->name, - 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')' - )); - } + /** + * Finds rows by primary key. + * @param mixed primary key value(s) + * @return DibiResult + */ + public function find($what) + { + if (!is_array($what)) { + $what = func_get_args(); + } + return $this->complete($this->connection->query( + 'SELECT * FROM %n', $this->name, + 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')' + )); + } - /** - * Selects all rows. - * @param string column to order by - * @return DibiResult - */ - public function findAll($order = NULL) - { - if ($order === NULL) { - return $this->complete($this->connection->query( - 'SELECT * FROM %n', $this->name - )); - } else { - $order = func_get_args(); - return $this->complete($this->connection->query( - 'SELECT * FROM %n', $this->name, - 'ORDER BY %n', $order - )); - } - } + /** + * Selects all rows. + * @param string column to order by + * @return DibiResult + */ + public function findAll($order = NULL) + { + if ($order === NULL) { + return $this->complete($this->connection->query( + 'SELECT * FROM %n', $this->name + )); + } else { + $order = func_get_args(); + return $this->complete($this->connection->query( + 'SELECT * FROM %n', $this->name, + 'ORDER BY %n', $order + )); + } + } - /** - * Fetches single row. - * @param scalar|array primary key value - * @return array|object row - */ - public function fetch($conditions) - { - if (is_array($conditions)) { - return $this->complete($this->connection->query( - 'SELECT * FROM %n', $this->name, - 'WHERE %and', $conditions - ))->fetch(); - } - return $this->complete($this->connection->query( - 'SELECT * FROM %n', $this->name, - 'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions - ))->fetch(); - } + /** + * Fetches single row. + * @param scalar|array primary key value + * @return array|object row + */ + public function fetch($conditions) + { + if (is_array($conditions)) { + return $this->complete($this->connection->query( + 'SELECT * FROM %n', $this->name, + 'WHERE %and', $conditions + ))->fetch(); + } + return $this->complete($this->connection->query( + 'SELECT * FROM %n', $this->name, + 'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions + ))->fetch(); + } - /** - * Returns a blank row (not fetched from database). - * @return array|object - */ - public function createBlank() - { - $row = $this->blankRow; - $row[$this->primary] = NULL; - if ($this->connection->getConfig('result:objects')) { - $row = (object) $row; - } - return $row; - } + /** + * Returns a blank row (not fetched from database). + * @return array|object + */ + public function createBlank() + { + $row = $this->blankRow; + $row[$this->primary] = NULL; + if ($this->connection->getConfig('result:objects')) { + $row = (object) $row; + } + return $row; + } - /** - * User data pre-processing. - * @param array|object - * @return array - */ - protected function prepare($data) - { - if (is_object($data)) { - return (array) $data; - } elseif (is_array($data)) { - return $data; - } + /** + * User data pre-processing. + * @param array|object + * @return array + */ + protected function prepare($data) + { + if (is_object($data)) { + return (array) $data; + } elseif (is_array($data)) { + return $data; + } - throw new InvalidArgumentException('Dataset must be array or anonymous object.'); - } + throw new InvalidArgumentException('Dataset must be array or anonymous object.'); + } - /** - * User DibiResult post-processing. - * @param DibiResult - * @return DibiResult - */ - protected function complete($res) - { - return $res; - } + /** + * User DibiResult post-processing. + * @param DibiResult + * @return DibiResult + */ + protected function complete($res) + { + return $res; + } } diff --git a/dibi/libs/DibiTranslator.php b/dibi/libs/DibiTranslator.php index f642a31d..aa86dc6a 100644 --- a/dibi/libs/DibiTranslator.php +++ b/dibi/libs/DibiTranslator.php @@ -29,432 +29,432 @@ */ final class DibiTranslator extends /*Nette::*/Object { - /** @var string */ - public $sql; + /** @var string */ + public $sql; - /** @var IDibiDriver */ - private $driver; + /** @var IDibiDriver */ + private $driver; - /** @var int */ - private $cursor; + /** @var int */ + private $cursor; - /** @var array */ - private $args; + /** @var array */ + private $args; - /** @var bool */ - private $hasError; + /** @var bool */ + private $hasError; - /** @var bool */ - private $comment; + /** @var bool */ + private $comment; - /** @var int */ - private $ifLevel; + /** @var int */ + private $ifLevel; - /** @var int */ - private $ifLevelStart; + /** @var int */ + private $ifLevelStart; - /** @var int */ - private $limit; + /** @var int */ + private $limit; - /** @var int */ - private $offset; + /** @var int */ + private $offset; - public function __construct(IDibiDriver $driver) - { - $this->driver = $driver; - } + public function __construct(IDibiDriver $driver) + { + $this->driver = $driver; + } - /** - * return IDibiDriver. - */ - public function getDriver() - { - return $this->driver; - } + /** + * return IDibiDriver. + */ + public function getDriver() + { + return $this->driver; + } - /** - * Generates SQL. - * - * @param array - * @return bool - */ - public function translate(array $args) - { - $this->limit = -1; - $this->offset = 0; - $this->hasError = FALSE; - $commandIns = NULL; - $lastArr = NULL; - // shortcuts - $cursor = & $this->cursor; - $cursor = 0; - $this->args = array_values($args); - $args = & $this->args; + /** + * Generates SQL. + * + * @param array + * @return bool + */ + public function translate(array $args) + { + $this->limit = -1; + $this->offset = 0; + $this->hasError = FALSE; + $commandIns = NULL; + $lastArr = NULL; + // shortcuts + $cursor = & $this->cursor; + $cursor = 0; + $this->args = array_values($args); + $args = & $this->args; - // conditional sql - $this->ifLevel = $this->ifLevelStart = 0; - $comment = & $this->comment; - $comment = FALSE; + // conditional sql + $this->ifLevel = $this->ifLevelStart = 0; + $comment = & $this->comment; + $comment = FALSE; - // iterate - $sql = array(); - while ($cursor < count($args)) - { - $arg = $args[$cursor]; - $cursor++; + // iterate + $sql = array(); + while ($cursor < count($args)) + { + $arg = $args[$cursor]; + $cursor++; - // simple string means SQL - if (is_string($arg)) { - // speed-up - is regexp required? - $toSkip = strcspn($arg, '`[\'"%'); + // simple string means SQL + if (is_string($arg)) { + // speed-up - is regexp required? + $toSkip = strcspn($arg, '`[\'"%'); - if (strlen($arg) === $toSkip) { // needn't be translated - $sql[] = $arg; - } else { - $sql[] = substr($arg, 0, $toSkip) + if (strlen($arg) === $toSkip) { // needn't be translated + $sql[] = $arg; + } else { + $sql[] = substr($arg, 0, $toSkip) /* - . preg_replace_callback('/ - (?=`|\[|\'|"|%) ## speed-up - (?: - `(.+?)`| ## 1) `identifier` - \[(.+?)\]| ## 2) [identifier] - (\')((?:\'\'|[^\'])*)\'| ## 3,4) string - (")((?:""|[^"])*)"| ## 5,6) "string" - (\'|") ## 7) lone-quote - %([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier - )/xs', + . preg_replace_callback('/ + (?=`|\[|\'|"|%) ## speed-up + (?: + `(.+?)`| ## 1) `identifier` + \[(.+?)\]| ## 2) [identifier] + (\')((?:\'\'|[^\'])*)\'| ## 3,4) string + (")((?:""|[^"])*)"| ## 5,6) "string" + (\'|") ## 7) lone-quote + %([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier + )/xs', */ // note: this can change $this->args & $this->cursor & ... - . preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s', - array($this, 'cb'), - substr($arg, $toSkip) - ); + . preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s', + array($this, 'cb'), + substr($arg, $toSkip) + ); - } - continue; - } + } + continue; + } - if ($comment) { - $sql[] = '...'; - continue; - } + if ($comment) { + $sql[] = '...'; + continue; + } - if (is_array($arg)) { - if (is_string(key($arg))) { - // associative array -> autoselect between SET or VALUES & LIST - if ($commandIns === NULL) { - $commandIns = strtoupper(substr(ltrim($args[0]), 0, 6)); - $commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC'; - $sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a'); - } else { - if ($lastArr === $cursor - 1) $sql[] = ','; - $sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a'); - } - $lastArr = $cursor; - continue; + if (is_array($arg)) { + if (is_string(key($arg))) { + // associative array -> autoselect between SET or VALUES & LIST + if ($commandIns === NULL) { + $commandIns = strtoupper(substr(ltrim($args[0]), 0, 6)); + $commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC'; + $sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a'); + } else { + if ($lastArr === $cursor - 1) $sql[] = ','; + $sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a'); + } + $lastArr = $cursor; + continue; - } elseif ($cursor === 1) { - // implicit array expansion - $cursor = 0; - array_splice($args, 0, 1, $arg); - continue; - } - } + } elseif ($cursor === 1) { + // implicit array expansion + $cursor = 0; + array_splice($args, 0, 1, $arg); + continue; + } + } - // default processing - $sql[] = $this->formatValue($arg, FALSE); - } // while + // default processing + $sql[] = $this->formatValue($arg, FALSE); + } // while - if ($comment) $sql[] = "*/"; + if ($comment) $sql[] = "*/"; - $sql = implode(' ', $sql); + $sql = implode(' ', $sql); - // apply limit - if ($this->limit > -1 || $this->offset > 0) { - $this->driver->applyLimit($sql, $this->limit, $this->offset); - } + // apply limit + if ($this->limit > -1 || $this->offset > 0) { + $this->driver->applyLimit($sql, $this->limit, $this->offset); + } - $this->sql = $sql; - return !$this->hasError; - } + $this->sql = $sql; + return !$this->hasError; + } - /** - * Apply modifier to single value. - * @param mixed - * @param string - * @return string - */ - public function formatValue($value, $modifier) - { - // array processing (with or without modifier) - if (is_array($value)) { + /** + * Apply modifier to single value. + * @param mixed + * @param string + * @return string + */ + public function formatValue($value, $modifier) + { + // array processing (with or without modifier) + if (is_array($value)) { - $vx = $kx = array(); - $separator = ', '; - switch ($modifier) { - case 'and': - case 'or': - $separator = ' ' . strtoupper($modifier) . ' '; - if (!is_string(key($value))) { - foreach ($value as $v) { - $vx[] = $this->formatValue($v, 'sql'); - } - return implode($separator, $vx); - } - // break intentionally omitted - case 'a': // SET key=val, key=val, ... - foreach ($value as $k => $v) { - $pair = explode('%', $k, 2); // split into identifier & modifier - $vx[] = $this->delimite($pair[0]) . '=' - . $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); - } - return implode($separator, $vx); + $vx = $kx = array(); + $separator = ', '; + switch ($modifier) { + case 'and': + case 'or': + $separator = ' ' . strtoupper($modifier) . ' '; + if (!is_string(key($value))) { + foreach ($value as $v) { + $vx[] = $this->formatValue($v, 'sql'); + } + return implode($separator, $vx); + } + // break intentionally omitted + case 'a': // SET key=val, key=val, ... + foreach ($value as $k => $v) { + $pair = explode('%', $k, 2); // split into identifier & modifier + $vx[] = $this->delimite($pair[0]) . '=' + . $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); + } + return implode($separator, $vx); - case 'l': // LIST val, val, ... - foreach ($value as $k => $v) { - $pair = explode('%', $k, 2); // split into identifier & modifier - $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); - } - return '(' . implode(', ', $vx) . ')'; + case 'l': // LIST val, val, ... + foreach ($value as $k => $v) { + $pair = explode('%', $k, 2); // split into identifier & modifier + $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); + } + return '(' . implode(', ', $vx) . ')'; - case 'v': // (key, key, ...) VALUES (val, val, ...) - foreach ($value as $k => $v) { - $pair = explode('%', $k, 2); // split into identifier & modifier - $kx[] = $this->delimite($pair[0]); - $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); - } - return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')'; + case 'v': // (key, key, ...) VALUES (val, val, ...) + foreach ($value as $k => $v) { + $pair = explode('%', $k, 2); // split into identifier & modifier + $kx[] = $this->delimite($pair[0]); + $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); + } + return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')'; - default: - foreach ($value as $v) { - $vx[] = $this->formatValue($v, $modifier); - } - return implode(', ', $vx); - } - } + default: + foreach ($value as $v) { + $vx[] = $this->formatValue($v, $modifier); + } + return implode(', ', $vx); + } + } - // with modifier procession - if ($modifier) { - if ($value === NULL) { - return 'NULL'; - } + // with modifier procession + if ($modifier) { + if ($value === NULL) { + return 'NULL'; + } - if ($value instanceof IDibiVariable) { - return $value->toSql($this, $modifier); - } + if ($value instanceof IDibiVariable) { + return $value->toSql($this, $modifier); + } - if (!is_scalar($value)) { // array is already processed - $this->hasError = TRUE; - return '**Unexpected type ' . gettype($value) . '**'; - } + if (!is_scalar($value)) { // array is already processed + $this->hasError = TRUE; + return '**Unexpected type ' . gettype($value) . '**'; + } - switch ($modifier) { - case 's': // string - return $this->driver->format($value, dibi::FIELD_TEXT); + switch ($modifier) { + case 's': // string + return $this->driver->format($value, dibi::FIELD_TEXT); - case 'sn': // string or NULL - return $value == '' ? 'NULL' : $this->driver->format($value, dibi::FIELD_TEXT); // notice two equal signs + case 'sn': // string or NULL + return $value == '' ? 'NULL' : $this->driver->format($value, dibi::FIELD_TEXT); // notice two equal signs - case 'b': // boolean - return $this->driver->format($value, dibi::FIELD_BOOL); + case 'b': // boolean + return $this->driver->format($value, dibi::FIELD_BOOL); - case 'i': // signed int - case 'u': // unsigned int, ignored - // support for numbers - keep them unchanged - if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) { - return $value; - } - return (string) (int) ($value + 0); + case 'i': // signed int + case 'u': // unsigned int, ignored + // support for numbers - keep them unchanged + if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) { + return $value; + } + return (string) (int) ($value + 0); - case 'f': // float - // support for numbers - keep them unchanged - if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) { - return $value; // something like -9E-005 is accepted by SQL, HEX values is not - } - return (string) ($value + 0); + case 'f': // float + // support for numbers - keep them unchanged + if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) { + return $value; // something like -9E-005 is accepted by SQL, HEX values is not + } + return (string) ($value + 0); - case 'd': // date - return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATE); + case 'd': // date + return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATE); - case 't': // datetime - return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATETIME); + case 't': // datetime + return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATETIME); - case 'n': // identifier name - return $this->delimite($value); + case 'n': // identifier name + return $this->delimite($value); - case 'sql':// preserve as SQL - $value = (string) $value; - // speed-up - is regexp required? - $toSkip = strcspn($value, '`[\'"'); - if (strlen($value) === $toSkip) { // needn't be translated - return $value; - } else { - return substr($value, 0, $toSkip) - . preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s', - array($this, 'cb'), - substr($value, $toSkip) - ); - } + case 'sql':// preserve as SQL + $value = (string) $value; + // speed-up - is regexp required? + $toSkip = strcspn($value, '`[\'"'); + if (strlen($value) === $toSkip) { // needn't be translated + return $value; + } else { + return substr($value, 0, $toSkip) + . preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s', + array($this, 'cb'), + substr($value, $toSkip) + ); + } - case 'a': - case 'v': - $this->hasError = TRUE; - return '**Unexpected type ' . gettype($value) . '**'; + case 'a': + case 'v': + $this->hasError = TRUE; + return '**Unexpected type ' . gettype($value) . '**'; - default: - $this->hasError = TRUE; - return "**Unknown or invalid modifier %$modifier**"; - } - } + default: + $this->hasError = TRUE; + return "**Unknown or invalid modifier %$modifier**"; + } + } - // without modifier procession - if (is_string($value)) - return $this->driver->format($value, dibi::FIELD_TEXT); + // without modifier procession + if (is_string($value)) + return $this->driver->format($value, dibi::FIELD_TEXT); - if (is_int($value) || is_float($value)) - return (string) $value; // something like -9E-005 is accepted by SQL + if (is_int($value) || is_float($value)) + return (string) $value; // something like -9E-005 is accepted by SQL - if (is_bool($value)) - return $this->driver->format($value, dibi::FIELD_BOOL); + if (is_bool($value)) + return $this->driver->format($value, dibi::FIELD_BOOL); - if ($value === NULL) - return 'NULL'; + if ($value === NULL) + return 'NULL'; - if ($value instanceof IDibiVariable) - return $value->toSql($this, NULL); + if ($value instanceof IDibiVariable) + return $value->toSql($this, NULL); - $this->hasError = TRUE; - return '**Unexpected ' . gettype($value) . '**'; - } + $this->hasError = TRUE; + return '**Unexpected ' . gettype($value) . '**'; + } - /** - * PREG callback from translate() or formatValue(). - * @param array - * @return string - */ - private function cb($matches) - { - // [1] => `ident` - // [2] => [ident] - // [3] => ' - // [4] => string - // [5] => " - // [6] => string - // [7] => lone-quote - // [8] => modifier (when called from self::translate()) + /** + * PREG callback from translate() or formatValue(). + * @param array + * @return string + */ + private function cb($matches) + { + // [1] => `ident` + // [2] => [ident] + // [3] => ' + // [4] => string + // [5] => " + // [6] => string + // [7] => lone-quote + // [8] => modifier (when called from self::translate()) - if (!empty($matches[8])) { // modifier - $mod = $matches[8]; - $cursor = & $this->cursor; + if (!empty($matches[8])) { // modifier + $mod = $matches[8]; + $cursor = & $this->cursor; - if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') { - $this->hasError = TRUE; - return "**Extra modifier %$mod**"; - } + if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') { + $this->hasError = TRUE; + return "**Extra modifier %$mod**"; + } - if ($mod === 'if') { - $this->ifLevel++; - $cursor++; - if (!$this->comment && !$this->args[$cursor - 1]) { - // open comment - $this->ifLevelStart = $this->ifLevel; - $this->comment = TRUE; - return "/*"; - } - return ''; + if ($mod === 'if') { + $this->ifLevel++; + $cursor++; + if (!$this->comment && !$this->args[$cursor - 1]) { + // open comment + $this->ifLevelStart = $this->ifLevel; + $this->comment = TRUE; + return "/*"; + } + return ''; - } elseif ($mod === 'else') { - if ($this->ifLevelStart === $this->ifLevel) { - $this->ifLevelStart = 0; - $this->comment = FALSE; - return "*/"; - } elseif (!$this->comment) { - $this->ifLevelStart = $this->ifLevel; - $this->comment = TRUE; - return "/*"; - } + } elseif ($mod === 'else') { + if ($this->ifLevelStart === $this->ifLevel) { + $this->ifLevelStart = 0; + $this->comment = FALSE; + return "*/"; + } elseif (!$this->comment) { + $this->ifLevelStart = $this->ifLevel; + $this->comment = TRUE; + return "/*"; + } - } elseif ($mod === 'end') { - $this->ifLevel--; - if ($this->ifLevelStart === $this->ifLevel + 1) { - // close comment - $this->ifLevelStart = 0; - $this->comment = FALSE; - return "*/"; - } - return ''; + } elseif ($mod === 'end') { + $this->ifLevel--; + if ($this->ifLevelStart === $this->ifLevel + 1) { + // close comment + $this->ifLevelStart = 0; + $this->comment = FALSE; + return "*/"; + } + return ''; - } elseif ($mod === 'ex') { // array expansion - array_splice($this->args, $cursor, 1, $this->args[$cursor]); - return ''; + } elseif ($mod === 'ex') { // array expansion + array_splice($this->args, $cursor, 1, $this->args[$cursor]); + return ''; - } elseif ($mod === 'lmt') { // apply limit - if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor]; - $cursor++; - return ''; + } elseif ($mod === 'lmt') { // apply limit + if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor]; + $cursor++; + return ''; - } elseif ($mod === 'ofs') { // apply offset - if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor]; - $cursor++; - return ''; + } elseif ($mod === 'ofs') { // apply offset + if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor]; + $cursor++; + return ''; - } else { // default processing - $cursor++; - return $this->formatValue($this->args[$cursor - 1], $mod); - } - } + } else { // default processing + $cursor++; + return $this->formatValue($this->args[$cursor - 1], $mod); + } + } - if ($this->comment) return '...'; + if ($this->comment) return '...'; - if ($matches[1]) // SQL identifiers: `ident` - return $this->delimite($matches[1]); + if ($matches[1]) // SQL identifiers: `ident` + return $this->delimite($matches[1]); - if ($matches[2]) // SQL identifiers: [ident] - return $this->delimite($matches[2]); + if ($matches[2]) // SQL identifiers: [ident] + return $this->delimite($matches[2]); - if ($matches[3]) // SQL strings: '...' - return $this->driver->format( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT); + if ($matches[3]) // SQL strings: '...' + return $this->driver->format( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT); - if ($matches[5]) // SQL strings: "..." - return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT); + if ($matches[5]) // SQL strings: "..." + return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT); - if ($matches[7]) { // string quote - $this->hasError = TRUE; - return '**Alone quote**'; - } + if ($matches[7]) { // string quote + $this->hasError = TRUE; + return '**Alone quote**'; + } - die('this should be never executed'); - } + die('this should be never executed'); + } - /** - * Apply substitutions to indentifier and delimites it. - * - * @param string indentifier - * @return string - */ - private function delimite($value) - { - if (strpos($value, ':') !== FALSE) { - $value = strtr($value, dibi::getSubst()); - } - return $this->driver->format($value, dibi::IDENTIFIER); - } + /** + * Apply substitutions to indentifier and delimites it. + * + * @param string indentifier + * @return string + */ + private function delimite($value) + { + if (strpos($value, ':') !== FALSE) { + $value = strtr($value, dibi::getSubst()); + } + return $this->driver->format($value, dibi::IDENTIFIER); + } } // class DibiTranslator diff --git a/dibi/libs/DibiVariable.php b/dibi/libs/DibiVariable.php index 77871a71..0620e693 100644 --- a/dibi/libs/DibiVariable.php +++ b/dibi/libs/DibiVariable.php @@ -25,24 +25,24 @@ */ class DibiVariable extends /*Nette::*/Object implements IDibiVariable { - /** @var mixed */ - public $value; + /** @var mixed */ + public $value; - /** @var string */ - public $modifier; + /** @var string */ + public $modifier; - public function __construct($value, $modifier) - { - $this->value = $value; - $this->modifier = $modifier; - } + public function __construct($value, $modifier) + { + $this->value = $value; + $this->modifier = $modifier; + } - public function toSql(DibiTranslator $translator, $modifier) - { - return $translator->formatValue($this->value, $this->modifier); - } + public function toSql(DibiTranslator $translator, $modifier) + { + return $translator->formatValue($this->value, $this->modifier); + } } \ No newline at end of file diff --git a/dibi/libs/interfaces.php b/dibi/libs/interfaces.php index d9166870..f737c801 100644 --- a/dibi/libs/interfaces.php +++ b/dibi/libs/interfaces.php @@ -25,14 +25,14 @@ */ interface IDibiVariable { - /** - * Format for SQL. - * - * @param object DibiTranslator - * @param string optional modifier - * @return string SQL code - */ - public function toSql(DibiTranslator $translator, $modifier); + /** + * Format for SQL. + * + * @param object DibiTranslator + * @param string optional modifier + * @return string SQL code + */ + public function toSql(DibiTranslator $translator, $modifier); } @@ -45,8 +45,8 @@ interface IDibiVariable */ interface IDataSource extends Countable, IteratorAggregate { - //function IteratorAggregate::getIterator(); - //function Countable::count(); + //function IteratorAggregate::getIterator(); + //function Countable::count(); } @@ -64,179 +64,179 @@ interface IDataSource extends Countable, IteratorAggregate interface IDibiDriver { - /** - * Internal: Connects to a database. - * - * @param array - * @return void - * @throws DibiException - */ - function connect(array &$config); + /** + * Internal: Connects to a database. + * + * @param array + * @return void + * @throws DibiException + */ + function connect(array &$config); - /** - * Internal: Disconnects from a database. - * - * @return void - * @throws DibiException - */ - function disconnect(); + /** + * Internal: Disconnects from a database. + * + * @return void + * @throws DibiException + */ + function disconnect(); - /** - * Internal: Executes the SQL query. - * - * @param string SQL statement. - * @return bool have resultset? - * @throws DibiDriverException - */ - function query($sql); + /** + * Internal: Executes the SQL query. + * + * @param string SQL statement. + * @return bool have resultset? + * @throws DibiDriverException + */ + function query($sql); - /** - * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. - * - * @return int|FALSE number of rows or FALSE on error - */ - function affectedRows(); + /** + * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. + * + * @return int|FALSE number of rows or FALSE on error + */ + function affectedRows(); - /** - * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. - * - * @return int|FALSE int on success or FALSE on failure - */ - function insertId($sequence); + /** + * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. + * + * @return int|FALSE int on success or FALSE on failure + */ + function insertId($sequence); - /** - * Begins a transaction (if supported). - * @return void - * @throws DibiDriverException - */ - function begin(); + /** + * Begins a transaction (if supported). + * @return void + * @throws DibiDriverException + */ + function begin(); - /** - * Commits statements in a transaction. - * @return void - * @throws DibiDriverException - */ - function commit(); + /** + * Commits statements in a transaction. + * @return void + * @throws DibiDriverException + */ + function commit(); - /** - * Rollback changes in a transaction. - * @return void - * @throws DibiDriverException - */ - function rollback(); + /** + * Rollback changes in a transaction. + * @return void + * @throws DibiDriverException + */ + function rollback(); - /** - * Format to SQL command. - * - * @param string value - * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) - * @return string formatted value - */ - function format($value, $type); + /** + * Format to SQL command. + * + * @param string value + * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) + * @return string formatted value + */ + function format($value, $type); - /** - * Injects LIMIT/OFFSET to the SQL query. - * - * @param string &$sql The SQL query that will be modified. - * @param int $limit - * @param int $offset - * @return void - */ - function applyLimit(&$sql, $limit, $offset); + /** + * Injects LIMIT/OFFSET to the SQL query. + * + * @param string &$sql The SQL query that will be modified. + * @param int $limit + * @param int $offset + * @return void + */ + function applyLimit(&$sql, $limit, $offset); - /** - * Returns the number of rows in a result set. - * - * @return int - */ - function rowCount(); + /** + * Returns the number of rows in a result set. + * + * @return int + */ + function rowCount(); - /** - * Moves cursor position without fetching row. - * - * @param int the 0-based cursor pos to seek to - * @return boolean TRUE on success, FALSE if unable to seek to specified record - * @throws DibiException - */ - function seek($row); + /** + * Moves cursor position without fetching row. + * + * @param int the 0-based cursor pos to seek to + * @return boolean TRUE on success, FALSE if unable to seek to specified record + * @throws DibiException + */ + function seek($row); - /** - * Fetches the row at current position and moves the internal cursor to the next position. - * internal usage only - * - * @param bool TRUE for associative array, FALSE for numeric - * @return array array on success, nonarray if no next record - */ - function fetch($type); + /** + * Fetches the row at current position and moves the internal cursor to the next position. + * internal usage only + * + * @param bool TRUE for associative array, FALSE for numeric + * @return array array on success, nonarray if no next record + */ + function fetch($type); - /** - * Frees the resources allocated for this result set. - * - * @param resource resultset resource - * @return void - */ - function free(); + /** + * Frees the resources allocated for this result set. + * + * @param resource resultset resource + * @return void + */ + function free(); - /** - * Returns metadata for all columns in a result set. - * - * @return array - * @throws DibiException - */ - function getColumnsMeta(); + /** + * Returns metadata for all columns in a result set. + * + * @return array + * @throws DibiException + */ + function getColumnsMeta(); - /** - * Returns the connection resource. - * - * @return mixed - */ - function getResource(); + /** + * Returns the connection resource. + * + * @return mixed + */ + function getResource(); - /** - * Returns the resultset resource. - * - * @return mixed - */ - function getResultResource(); + /** + * Returns the resultset resource. + * + * @return mixed + */ + function getResultResource(); - /** - * Gets a information of the current database. - * - * @return DibiReflection - */ - function getDibiReflection(); + /** + * Gets a information of the current database. + * + * @return DibiReflection + */ + function getDibiReflection(); } diff --git a/examples/apply-limit.php b/examples/apply-limit.php index 739f6520..feac6e7d 100644 --- a/examples/apply-limit.php +++ b/examples/apply-limit.php @@ -6,15 +6,15 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); // no limit $res = dibi::query('SELECT * FROM [products]'); foreach ($res as $n => $row) { - print_r($row); + print_r($row); } echo '
'; @@ -22,7 +22,7 @@ echo '
'; // with limit = 2 $res = dibi::query('SELECT * FROM [products] %lmt', 2); foreach ($res as $n => $row) { - print_r($row); + print_r($row); } echo '
'; @@ -30,5 +30,5 @@ echo '
'; // with limit = 2, offset = 1 $res = dibi::query('SELECT * FROM [products] %lmt %ofs', 2, 1); foreach ($res as $n => $row) { - print_r($row); + print_r($row); } diff --git a/examples/connect.php b/examples/connect.php index 3b758bcc..88279e12 100644 --- a/examples/connect.php +++ b/examples/connect.php @@ -7,15 +7,15 @@ require_once '../dibi/dibi.php'; // connects to SQlite echo '

Connecting to Sqlite: '; try { - dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', - 'result:objects' => TRUE, // fetch rows as objects - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'sqlite', + 'database' => 'sample.sdb', + 'result:objects' => TRUE, // fetch rows as objects + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -25,11 +25,11 @@ echo "

\n"; // connects to MySQL using DSN echo '

Connecting to MySQL: '; try { - dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=utf8'); - echo 'OK'; + dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=utf8'); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -39,18 +39,18 @@ echo "

\n"; // connects to MySQLi using array echo '

Connecting to MySQL: '; try { - dibi::connect(array( - 'driver' => 'mysqli', - 'host' => 'localhost', - 'username' => 'root', - 'password' => 'xxx', - 'database' => 'dibi', - 'charset' => 'utf8', - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'mysqli', + 'host' => 'localhost', + 'username' => 'root', + 'password' => 'xxx', + 'database' => 'dibi', + 'charset' => 'utf8', + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -60,16 +60,16 @@ echo "

\n"; // connects to ODBC echo '

Connecting to ODBC: '; try { - dibi::connect(array( - 'driver' => 'odbc', - 'username' => 'root', - 'password' => '***', - 'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/sample.mdb', - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'odbc', + 'username' => 'root', + 'password' => '***', + 'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/sample.mdb', + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -79,15 +79,15 @@ echo "

\n"; // connects to PostgreSql echo '

Connecting to PostgreSql: '; try { - dibi::connect(array( - 'driver' => 'postgre', - 'string' => 'host=localhost port=5432 dbname=mary', - 'persistent' => TRUE, - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'postgre', + 'string' => 'host=localhost port=5432 dbname=mary', + 'persistent' => TRUE, + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -97,14 +97,14 @@ echo "

\n"; // connects to PDO echo '

Connecting to Sqlite via PDO: '; try { - dibi::connect(array( - 'driver' => 'pdo', - 'dsn' => 'sqlite2::memory:', - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'pdo', + 'dsn' => 'sqlite2::memory:', + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -113,16 +113,16 @@ echo "

\n"; // connects to MS SQL echo '

Connecting to MS SQL: '; try { - dibi::connect(array( - 'driver' => 'mssql', - 'host' => 'localhost', - 'username' => 'root', - 'password' => 'xxx', - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'mssql', + 'host' => 'localhost', + 'username' => 'root', + 'password' => 'xxx', + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; @@ -131,15 +131,15 @@ echo "

\n"; // connects to Oracle echo '

Connecting to Oracle: '; try { - dibi::connect(array( - 'driver' => 'oracle', - 'username' => 'root', - 'password' => 'xxx', - 'database' => 'db', - )); - echo 'OK'; + dibi::connect(array( + 'driver' => 'oracle', + 'username' => 'root', + 'password' => 'xxx', + 'database' => 'db', + )); + echo 'OK'; } catch (DibiException $e) { - echo get_class($e), ': ', $e->getMessage(), "\n"; + echo get_class($e), ': ', $e->getMessage(), "\n"; } echo "

\n"; \ No newline at end of file diff --git a/examples/datetime.demo.php b/examples/datetime.demo.php index 9adaf583..9b1535cd 100644 --- a/examples/datetime.demo.php +++ b/examples/datetime.demo.php @@ -11,10 +11,10 @@ date_default_timezone_set('Europe/Prague'); // CHANGE TO REAL PARAMETERS! dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', - 'format:date' => "'Y-m-d'", - 'format:datetime' => "'Y-m-d H-i-s'", + 'driver' => 'sqlite', + 'database' => 'sample.sdb', + 'format:date' => "'Y-m-d'", + 'format:datetime' => "'Y-m-d H-i-s'", )); @@ -22,7 +22,7 @@ dibi::connect(array( // 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'), + 'id' => 123, + 'date' => dibi::date('12.3.2007'), + 'stamp' => dibi::dateTime('23.1.2007 10:23'), )); diff --git a/examples/dibi.table.php b/examples/dibi.table.php index e08d0a43..5752a1b4 100644 --- a/examples/dibi.table.php +++ b/examples/dibi.table.php @@ -6,8 +6,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); dibi::begin(); @@ -39,7 +39,7 @@ echo "Primary key: $products->primary\n"; // Finds rows by primary key foreach ($products->find(1, 3) as $row) { - print_r($row); + print_r($row); } diff --git a/examples/dump.php b/examples/dump.php index 33c41fef..b3f2648e 100644 --- a/examples/dump.php +++ b/examples/dump.php @@ -5,8 +5,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); diff --git a/examples/extension.method.php b/examples/extension.method.php index dd0fb7c3..964a7d0a 100644 --- a/examples/extension.method.php +++ b/examples/extension.method.php @@ -6,8 +6,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); @@ -15,9 +15,9 @@ dibi::connect(array( // using the "prototype" to add custom method to class DibiResult function DibiResult_prototype_fetchShuffle(DibiResult $obj) { - $all = $obj->fetchAll(); - shuffle($all); - return $all; + $all = $obj->fetchAll(); + shuffle($all); + return $all; } diff --git a/examples/fetch.php b/examples/fetch.php index ea7bfc79..ce098aba 100644 --- a/examples/fetch.php +++ b/examples/fetch.php @@ -6,8 +6,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); @@ -16,9 +16,9 @@ TABLE products product_id | title -----------+---------- - 1 | Chair - 2 | Table - 3 | Computer + 1 | Chair + 2 | Table + 3 | Computer */ @@ -56,19 +56,19 @@ echo '
'; // fetch row by row foreach ($res as $n => $row) { - print_r($row); + print_r($row); } echo '
'; // fetch row by row with defined offset foreach ($res->getIterator(2) as $n => $row) { - print_r($row); + print_r($row); } // fetch row by row with defined offset and limit foreach ($res->getIterator(2, 1) as $n => $row) { - print_r($row); + print_r($row); } diff --git a/examples/load-sql-dump.php b/examples/load-sql-dump.php index 21555faa..5eedc6b5 100644 --- a/examples/load-sql-dump.php +++ b/examples/load-sql-dump.php @@ -6,8 +6,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); diff --git a/examples/logger.php b/examples/logger.php index dec3eb81..0a291865 100644 --- a/examples/logger.php +++ b/examples/logger.php @@ -9,21 +9,21 @@ dibi::startLogger('log.sql', TRUE); dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); try { - $res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] = %i', 1); + $res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] = %i', 1); - $res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', 5); + $res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', 5); - $res = dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38); + $res = dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38); } catch (DibiException $e) { - echo '

', get_class($e), ': ', $e->getMessage(), '

'; + echo '

', get_class($e), ': ', $e->getMessage(), '

'; } diff --git a/examples/metatypes.php b/examples/metatypes.php index 878db729..d77f5b42 100644 --- a/examples/metatypes.php +++ b/examples/metatypes.php @@ -6,8 +6,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); diff --git a/examples/nette-debug.php b/examples/nette-debug.php index 3c998ff7..5489b783 100644 --- a/examples/nette-debug.php +++ b/examples/nette-debug.php @@ -9,8 +9,8 @@ Debug::enable(); dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); diff --git a/examples/profiler.php b/examples/profiler.php index ff8842b1..fede2305 100644 --- a/examples/profiler.php +++ b/examples/profiler.php @@ -5,13 +5,13 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); for ($i=0; $i<20; $i++) { - $res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', $i); + $res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', $i); } ?> diff --git a/examples/sql-builder.php b/examples/sql-builder.php index d28dd4a8..e9fcb777 100644 --- a/examples/sql-builder.php +++ b/examples/sql-builder.php @@ -12,26 +12,26 @@ date_default_timezone_set('Europe/Prague'); dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); // dibi detects INSERT or REPLACE command dibi::test(' REPLACE INTO [products]', array( - 'title' => 'Drtička na trávu', - 'price' => 318, - 'active' => TRUE, + 'title' => 'Drtička na trávu', + 'price' => 318, + 'active' => TRUE, )); // multiple INSERT command $array = array( - 'title' => 'Super Product', - 'price' => 12, - 'brand' => NULL, - 'created' => dibi::datetime(), + 'title' => 'Super Product', + 'price' => 12, + 'brand' => NULL, + 'created' => dibi::datetime(), ); dibi::test("INSERT INTO [products]", $array, $array, $array); @@ -39,8 +39,8 @@ dibi::test("INSERT INTO [products]", $array, $array, $array); // dibi detects UPDATE command dibi::test(" UPDATE [colors] SET", array( - 'color' => 'blue', - 'order' => 12, + 'color' => 'blue', + 'order' => 12, ), " WHERE [id]=%i", 123); diff --git a/examples/sql-condition.php b/examples/sql-condition.php index 9c934459..4c373c8a 100644 --- a/examples/sql-condition.php +++ b/examples/sql-condition.php @@ -9,8 +9,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); @@ -35,8 +35,8 @@ dibi::test(" SELECT * FROM [people] WHERE [id] > 0 - %if", ($foo > 0), "AND [foo]=%i", $foo, " - %else %if", ($bar > 0), "AND [bar]=%i", $bar, " + %if", ($foo > 0), "AND [foo]=%i", $foo, " + %else %if", ($bar > 0), "AND [bar]=%i", $bar, " "); @@ -45,7 +45,7 @@ dibi::test(' SELECT * FROM [customers] WHERE - %if', isset($name), '[name] LIKE %s', $name, ' - %if', $cond2, 'AND [admin]=1 %end - %else 1 LIMIT 10 %end' + %if', isset($name), '[name] LIKE %s', $name, ' + %if', $cond2, 'AND [admin]=1 %end + %else 1 LIMIT 10 %end' ); diff --git a/examples/table-prefix.php b/examples/table-prefix.php index db6a0202..00f42e2a 100644 --- a/examples/table-prefix.php +++ b/examples/table-prefix.php @@ -5,8 +5,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); diff --git a/examples/transaction.php b/examples/transaction.php index 4d5cd61b..7b316e8b 100644 --- a/examples/transaction.php +++ b/examples/transaction.php @@ -6,8 +6,8 @@ require_once '../dibi/dibi.php'; dibi::connect(array( - 'driver' => 'sqlite', - 'database' => 'sample.sdb', + 'driver' => 'sqlite', + 'database' => 'sample.sdb', )); @@ -18,7 +18,7 @@ dibi::query('SELECT * FROM [products]')->dump(); dibi::begin(); dibi::query('INSERT INTO [products]', array( - 'title' => 'Test product', + 'title' => 'Test product', )); dibi::rollback(); // or dibi::commit();