1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-08 07:06:52 +02:00

code formatting: 4 spaces -> tabs

This commit is contained in:
David Grudl
2008-05-12 00:30:59 +00:00
parent fd22c55639
commit 7bb5684d71
37 changed files with 5309 additions and 5309 deletions

View File

@@ -27,10 +27,10 @@
interface IDebuggable interface IDebuggable
{ {
/** /**
* Returns custom panels. * Returns custom panels.
* @return array * @return array
*/ */
function getPanels(); function getPanels();
} }

View File

@@ -64,213 +64,213 @@
abstract class Object abstract class Object
{ {
/** /**
* Returns the name of the class of this object. * Returns the name of the class of this object.
* *
* @return string * @return string
*/ */
final public function getClass() final public function getClass()
{ {
return get_class($this); return get_class($this);
} }
/** /**
* Access to reflection. * Access to reflection.
* *
* @return ReflectionObject * @return ReflectionObject
*/ */
final public function getReflection() final public function getReflection()
{ {
return new ReflectionObject($this); return new ReflectionObject($this);
} }
/** /**
* Call to undefined method. * Call to undefined method.
* *
* @param string method name * @param string method name
* @param array arguments * @param array arguments
* @return mixed * @return mixed
* @throws ::MemberAccessException * @throws ::MemberAccessException
*/ */
protected function __call($name, $args) protected function __call($name, $args)
{ {
if ($name === '') { if ($name === '') {
throw new /*::*/MemberAccessException("Call to method without name."); throw new /*::*/MemberAccessException("Call to method without name.");
} }
$class = get_class($this); $class = get_class($this);
// event functionality // event functionality
if (self::hasEvent($class, $name)) { if (self::hasEvent($class, $name)) {
$list = $this->$name; $list = $this->$name;
if (is_array($list) || $list instanceof Traversable) { if (is_array($list) || $list instanceof Traversable) {
foreach ($list as $handler) { foreach ($list as $handler) {
call_user_func_array($handler, $args); call_user_func_array($handler, $args);
} }
} }
return; return;
} }
// object prototypes support Class__method() // object prototypes support Class__method()
// (or use class Class__method { static function ... } with autoloading?) // (or use class Class__method { static function ... } with autoloading?)
$cl = $class; $cl = $class;
do { do {
if (function_exists($nm = $cl . '_prototype_' . $name)) { if (function_exists($nm = $cl . '_prototype_' . $name)) {
array_unshift($args, $this); array_unshift($args, $this);
return call_user_func_array($nm, $args); return call_user_func_array($nm, $args);
} }
} while ($cl = get_parent_class($cl)); } 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. * Call to undefined static method.
* *
* @param string method name (in lower case!) * @param string method name (in lower case!)
* @param array arguments * @param array arguments
* @return mixed * @return mixed
* @throws ::MemberAccessException * @throws ::MemberAccessException
*/ */
protected static function __callStatic($name, $args) protected static function __callStatic($name, $args)
{ {
$class = get_called_class(); $class = get_called_class();
throw new /*::*/MemberAccessException("Call to undefined static method $class::$name()."); throw new /*::*/MemberAccessException("Call to undefined static method $class::$name().");
} }
/** /**
* Returns property value. Do not call directly. * Returns property value. Do not call directly.
* *
* @param string property name * @param string property name
* @return mixed property value * @return mixed property value
* @throws ::MemberAccessException if the property is not defined. * @throws ::MemberAccessException if the property is not defined.
*/ */
protected function &__get($name) protected function &__get($name)
{ {
if ($name === '') { if ($name === '') {
throw new /*::*/MemberAccessException("Cannot read an property without name."); throw new /*::*/MemberAccessException("Cannot read an property without name.");
} }
// property getter support // property getter support
$class = get_class($this); $class = get_class($this);
$m = 'get' . $name; $m = 'get' . $name;
if (self::hasAccessor($class, $m)) { if (self::hasAccessor($class, $m)) {
// ampersands: // ampersands:
// - using &__get() because declaration should be forward compatible (e.g. with Nette::Web::Html) // - 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'; // - not using &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
$val = $this->$m(); $val = $this->$m();
return $val; return $val;
} else { } else {
throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name."); throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name.");
} }
} }
/** /**
* Sets value of a property. Do not call directly. * Sets value of a property. Do not call directly.
* *
* @param string property name * @param string property name
* @param mixed property value * @param mixed property value
* @return void * @return void
* @throws ::MemberAccessException if the property is not defined or is read-only * @throws ::MemberAccessException if the property is not defined or is read-only
*/ */
protected function __set($name, $value) protected function __set($name, $value)
{ {
if ($name === '') { if ($name === '') {
throw new /*::*/MemberAccessException('Cannot assign to an property without name.'); throw new /*::*/MemberAccessException('Cannot assign to an property without name.');
} }
// property setter support // property setter support
$class = get_class($this); $class = get_class($this);
if (self::hasAccessor($class, 'get' . $name)) { if (self::hasAccessor($class, 'get' . $name)) {
$m = 'set' . $name; $m = 'set' . $name;
if (self::hasAccessor($class, $m)) { if (self::hasAccessor($class, $m)) {
$this->$m($value); $this->$m($value);
} else { } else {
throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name."); throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
} }
} else { } else {
throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name."); throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
} }
} }
/** /**
* Is property defined? * Is property defined?
* *
* @param string property name * @param string property name
* @return bool * @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. * Access to undeclared property.
* *
* @param string property name * @param string property name
* @return void * @return void
* @throws ::MemberAccessException * @throws ::MemberAccessException
*/ */
protected function __unset($name) protected function __unset($name)
{ {
$class = get_class($this); $class = get_class($this);
throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name."); throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name.");
} }
/** /**
* Has property an accessor? * Has property an accessor?
* *
* @param string class name * @param string class name
* @param string method name * @param string method name
* @return bool * @return bool
*/ */
private static function hasAccessor($c, $m) private static function hasAccessor($c, $m)
{ {
static $cache; static $cache;
if (!isset($cache[$c])) { if (!isset($cache[$c])) {
// get_class_methods returns private, protected and public methods of Object (doesn't matter) // get_class_methods returns private, protected and public methods of Object (doesn't matter)
// and ONLY PUBLIC methods of descendants (perfect!) // and ONLY PUBLIC methods of descendants (perfect!)
// but returns static methods too (nothing doing...) // but returns static methods too (nothing doing...)
// and is much faster than reflection // and is much faster than reflection
// (works good since 5.0.4) // (works good since 5.0.4)
$cache[$c] = array_flip(get_class_methods($c)); $cache[$c] = array_flip(get_class_methods($c));
} }
// case-sensitive checking, capitalize the fourth character // case-sensitive checking, capitalize the fourth character
$m[3] = $m[3] & "\xDF"; $m[3] = $m[3] & "\xDF";
return isset($cache[$c][$m]); return isset($cache[$c][$m]);
} }
/** /**
* Is property an event? * Is property an event?
* *
* @param string class name * @param string class name
* @param string method name * @param string method name
* @return bool * @return bool
*/ */
private static function hasEvent($c, $m) private static function hasEvent($c, $m)
{ {
return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m); return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -37,299 +37,299 @@
class DibiMsSqlDriver extends /*Nette::*/Object implements IDibiDriver class DibiMsSqlDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var resource * @var resource
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var resource * @var resource
*/ */
private $resultset; private $resultset;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('mssql')) { if (!extension_loaded('mssql')) {
throw new DibiDriverException("PHP extension 'mssql' is not loaded."); throw new DibiDriverException("PHP extension 'mssql' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'username', 'user'); DibiConnection::alias($config, 'username', 'user');
DibiConnection::alias($config, 'password', 'pass'); DibiConnection::alias($config, 'password', 'pass');
DibiConnection::alias($config, 'host'); DibiConnection::alias($config, 'host');
if (empty($config['persistent'])) { if (empty($config['persistent'])) {
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); $this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE);
} else { } else {
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); $this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']);
} }
if (!is_resource($this->connection)) { if (!is_resource($this->connection)) {
throw new DibiDriverException("Can't connect to DB."); throw new DibiDriverException("Can't connect to DB.");
} }
if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) { if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) {
throw new DibiDriverException("Can't select DB '$config[database]'."); throw new DibiDriverException("Can't select DB '$config[database]'.");
} }
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
mssql_close($this->connection); mssql_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultset = @mssql_query($sql, $this->connection); $this->resultset = @mssql_query($sql, $this->connection);
if ($this->resultset === FALSE) { if ($this->resultset === FALSE) {
throw new DibiDriverException('Query error', 0, $sql); throw new DibiDriverException('Query error', 0, $sql);
} }
return is_resource($this->resultset); return is_resource($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return mssql_rows_affected($this->connection); return mssql_rows_affected($this->connection);
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
throw new NotSupportedException('MS SQL does not support autoincrementing.'); throw new NotSupportedException('MS SQL does not support autoincrementing.');
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
$this->query('BEGIN TRANSACTION'); $this->query('BEGIN TRANSACTION');
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
$this->query('COMMIT'); $this->query('COMMIT');
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
$this->query('ROLLBACK'); $this->query('ROLLBACK');
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'"; if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'";
if ($type === dibi::IDENTIFIER) 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_BOOL) return $value ? -1 : 0;
if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); 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); if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
// offset suppot is missing... // offset suppot is missing...
if ($limit >= 0) { if ($limit >= 0) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')'; $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
} }
if ($offset) { if ($offset) {
throw new NotImplementedException('Offset is not implemented.'); throw new NotImplementedException('Offset is not implemented.');
} }
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
return mssql_num_rows($this->resultset); return mssql_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return mssql_fetch_array($this->resultset, $type ? MSSQL_ASSOC : MSSQL_NUM); return mssql_fetch_array($this->resultset, $type ? MSSQL_ASSOC : MSSQL_NUM);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
return mssql_data_seek($this->resultset, $row); return mssql_data_seek($this->resultset, $row);
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
mssql_free_result($this->resultset); mssql_free_result($this->resultset);
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = mssql_num_fields($this->resultset); $count = mssql_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$info = (array) mssql_fetch_field($this->resultset, $i); $info = (array) mssql_fetch_field($this->resultset, $i);
$info['table'] = $info['column_source']; $info['table'] = $info['column_source'];
$meta[] = $info; $meta[] = $info;
} }
return $meta; return $meta;
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -43,360 +43,360 @@
class DibiMySqlDriver extends /*Nette::*/Object implements IDibiDriver class DibiMySqlDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var resource * @var resource
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var resource * @var resource
*/ */
private $resultset; private $resultset;
/** /**
* Is buffered (seekable and countable)? * Is buffered (seekable and countable)?
* @var bool * @var bool
*/ */
private $buffered; private $buffered;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('mysql')) { if (!extension_loaded('mysql')) {
throw new DibiDriverException("PHP extension 'mysql' is not loaded."); throw new DibiDriverException("PHP extension 'mysql' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'username', 'user'); DibiConnection::alias($config, 'username', 'user');
DibiConnection::alias($config, 'password', 'pass'); DibiConnection::alias($config, 'password', 'pass');
DibiConnection::alias($config, 'options'); DibiConnection::alias($config, 'options');
// default values // default values
if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user'); 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['password'])) $config['password'] = ini_get('mysql.default_password');
if (!isset($config['host'])) { if (!isset($config['host'])) {
$host = ini_get('mysql.default_host'); $host = ini_get('mysql.default_host');
if ($host) { if ($host) {
$config['host'] = $host; $config['host'] = $host;
$config['port'] = ini_get('mysql.default_port'); $config['port'] = ini_get('mysql.default_port');
} else { } else {
if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket'); if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket');
$config['host'] = NULL; $config['host'] = NULL;
} }
} }
if (empty($config['socket'])) { if (empty($config['socket'])) {
$host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']); $host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']);
} else { } else {
$host = ':' . $config['socket']; $host = ':' . $config['socket'];
} }
if (empty($config['persistent'])) { if (empty($config['persistent'])) {
$this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); $this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']);
} else { } else {
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); $this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']);
} }
if (!is_resource($this->connection)) { if (!is_resource($this->connection)) {
throw new DibiDriverException(mysql_error(), mysql_errno()); throw new DibiDriverException(mysql_error(), mysql_errno());
} }
if (isset($config['charset'])) { if (isset($config['charset'])) {
$ok = FALSE; $ok = FALSE;
if (function_exists('mysql_set_charset')) { 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) // 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); $ok = @mysql_set_charset($config['charset'], $this->connection);
} }
if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection);
if (!$ok) $this->throwException(); if (!$ok) $this->throwException();
} }
if (isset($config['database'])) { if (isset($config['database'])) {
@mysql_select_db($config['database'], $this->connection) or $this->throwException(); @mysql_select_db($config['database'], $this->connection) or $this->throwException();
} }
if (isset($config['sqlmode'])) { if (isset($config['sqlmode'])) {
if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException();
} }
$this->buffered = empty($config['unbuffered']); $this->buffered = empty($config['unbuffered']);
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
mysql_close($this->connection); mysql_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
if ($this->buffered) { if ($this->buffered) {
$this->resultset = @mysql_query($sql, $this->connection); $this->resultset = @mysql_query($sql, $this->connection);
} else { } else {
$this->resultset = @mysql_unbuffered_query($sql, $this->connection); $this->resultset = @mysql_unbuffered_query($sql, $this->connection);
} }
if (mysql_errno($this->connection)) { if (mysql_errno($this->connection)) {
$this->throwException($sql); $this->throwException($sql);
} }
return is_resource($this->resultset); return is_resource($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return mysql_affected_rows($this->connection); return mysql_affected_rows($this->connection);
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
return mysql_insert_id($this->connection); return mysql_insert_id($this->connection);
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
$this->query('START TRANSACTION'); $this->query('START TRANSACTION');
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
$this->query('COMMIT'); $this->query('COMMIT');
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
$this->query('ROLLBACK'); $this->query('ROLLBACK');
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return "'" . mysql_real_escape_string($value, $this->connection) . "'"; if ($type === dibi::FIELD_TEXT) return "'" . mysql_real_escape_string($value, $this->connection) . "'";
if ($type === dibi::IDENTIFIER) 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_BOOL) return $value ? 1 : 0;
if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); 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); if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
if ($limit < 0 && $offset < 1) return; if ($limit < 0 && $offset < 1) return;
// see http://dev.mysql.com/doc/refman/5.0/en/select.html // see http://dev.mysql.com/doc/refman/5.0/en/select.html
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
. ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
if (!$this->buffered) { if (!$this->buffered) {
throw new DibiDriverException('Row count is not available for unbuffered queries.'); throw new DibiDriverException('Row count is not available for unbuffered queries.');
} }
return mysql_num_rows($this->resultset); return mysql_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return mysql_fetch_array($this->resultset, $type ? MYSQL_ASSOC : MYSQL_NUM); return mysql_fetch_array($this->resultset, $type ? MYSQL_ASSOC : MYSQL_NUM);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
if (!$this->buffered) { if (!$this->buffered) {
throw new DibiDriverException('Cannot seek an unbuffered result set.'); throw new DibiDriverException('Cannot seek an unbuffered result set.');
} }
return mysql_data_seek($this->resultset, $row); return mysql_data_seek($this->resultset, $row);
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
mysql_free_result($this->resultset); mysql_free_result($this->resultset);
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = mysql_num_fields($this->resultset); $count = mysql_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$meta[] = (array) mysql_fetch_field($this->resultset, $i); $meta[] = (array) mysql_fetch_field($this->resultset, $i);
} }
return $meta; return $meta;
} }
/** /**
* Converts database error to DibiDriverException. * Converts database error to DibiDriverException.
* *
* @throws DibiDriverException * @throws DibiDriverException
*/ */
protected function throwException($sql = NULL) protected function throwException($sql = NULL)
{ {
throw new DibiDriverException(mysql_error($this->connection), mysql_errno($this->connection), $sql); throw new DibiDriverException(mysql_error($this->connection), mysql_errno($this->connection), $sql);
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -43,339 +43,339 @@
class DibiMySqliDriver extends /*Nette::*/Object implements IDibiDriver class DibiMySqliDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var mysqli * @var mysqli
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var mysqli_result * @var mysqli_result
*/ */
private $resultset; private $resultset;
/** /**
* Is buffered (seekable and countable)? * Is buffered (seekable and countable)?
* @var bool * @var bool
*/ */
private $buffered; private $buffered;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('mysqli')) { if (!extension_loaded('mysqli')) {
throw new DibiDriverException("PHP extension 'mysqli' is not loaded."); throw new DibiDriverException("PHP extension 'mysqli' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'username', 'user'); DibiConnection::alias($config, 'username', 'user');
DibiConnection::alias($config, 'password', 'pass'); DibiConnection::alias($config, 'password', 'pass');
DibiConnection::alias($config, 'options'); DibiConnection::alias($config, 'options');
DibiConnection::alias($config, 'database'); DibiConnection::alias($config, 'database');
// default values // default values
if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user'); 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['password'])) $config['password'] = ini_get('mysqli.default_pw');
if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket'); if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket');
if (!isset($config['host'])) { if (!isset($config['host'])) {
$config['host'] = ini_get('mysqli.default_host'); $config['host'] = ini_get('mysqli.default_host');
if (!isset($config['port'])) $config['port'] = ini_get('mysqli.default_port'); if (!isset($config['port'])) $config['port'] = ini_get('mysqli.default_port');
if (!isset($config['host'])) $config['host'] = 'localhost'; if (!isset($config['host'])) $config['host'] = 'localhost';
} }
$this->connection = mysqli_init(); $this->connection = mysqli_init();
@mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); @mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']);
if ($errno = mysqli_connect_errno()) { if ($errno = mysqli_connect_errno()) {
throw new DibiDriverException(mysqli_connect_error(), $errno); throw new DibiDriverException(mysqli_connect_error(), $errno);
} }
if (isset($config['charset'])) { if (isset($config['charset'])) {
$ok = FALSE; $ok = FALSE;
if (version_compare(PHP_VERSION , '5.1.5', '>=')) { 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) // 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']); $ok = @mysqli_set_charset($this->connection, $config['charset']);
} }
if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'");
if (!$ok) $this->throwException(); if (!$ok) $this->throwException();
} }
if (isset($config['sqlmode'])) { if (isset($config['sqlmode'])) {
if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException(); if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException();
} }
$this->buffered = empty($config['unbuffered']); $this->buffered = empty($config['unbuffered']);
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
mysqli_close($this->connection); mysqli_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultset = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); $this->resultset = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
if (mysqli_errno($this->connection)) { if (mysqli_errno($this->connection)) {
$this->throwException($sql); $this->throwException($sql);
} }
return is_object($this->resultset); return is_object($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return mysqli_affected_rows($this->connection); return mysqli_affected_rows($this->connection);
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
return mysqli_insert_id($this->connection); return mysqli_insert_id($this->connection);
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
$this->query('START TRANSACTION'); $this->query('START TRANSACTION');
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
$this->query('COMMIT'); $this->query('COMMIT');
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
$this->query('ROLLBACK'); $this->query('ROLLBACK');
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return "'" . mysqli_real_escape_string($this->connection, $value) . "'"; if ($type === dibi::FIELD_TEXT) return "'" . mysqli_real_escape_string($this->connection, $value) . "'";
if ($type === dibi::IDENTIFIER) 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_BOOL) return $value ? 1 : 0;
if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); 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); if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
if ($limit < 0 && $offset < 1) return; if ($limit < 0 && $offset < 1) return;
// see http://dev.mysql.com/doc/refman/5.0/en/select.html // see http://dev.mysql.com/doc/refman/5.0/en/select.html
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
. ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
if (!$this->buffered) { if (!$this->buffered) {
throw new DibiDriverException('Row count is not available for unbuffered queries.'); throw new DibiDriverException('Row count is not available for unbuffered queries.');
} }
return mysqli_num_rows($this->resultset); return mysqli_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return mysqli_fetch_array($this->resultset, $type ? MYSQLI_ASSOC : MYSQLI_NUM); return mysqli_fetch_array($this->resultset, $type ? MYSQLI_ASSOC : MYSQLI_NUM);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
if (!$this->buffered) { if (!$this->buffered) {
throw new DibiDriverException('Cannot seek an unbuffered result set.'); throw new DibiDriverException('Cannot seek an unbuffered result set.');
} }
return mysqli_data_seek($this->resultset, $row); return mysqli_data_seek($this->resultset, $row);
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
mysqli_free_result($this->resultset); mysqli_free_result($this->resultset);
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = mysqli_num_fields($this->resultset); $count = mysqli_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$meta[] = (array) mysqli_fetch_field_direct($this->resultset, $i); $meta[] = (array) mysqli_fetch_field_direct($this->resultset, $i);
} }
return $meta; return $meta;
} }
/** /**
* Converts database error to DibiDriverException. * Converts database error to DibiDriverException.
* *
* @throws DibiDriverException * @throws DibiDriverException
*/ */
protected function throwException($sql = NULL) protected function throwException($sql = NULL)
{ {
throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection), $sql); throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection), $sql);
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mysqli * @return mysqli
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mysqli_result * @return mysqli_result
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -36,340 +36,340 @@
class DibiOdbcDriver extends /*Nette::*/Object implements IDibiDriver class DibiOdbcDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var resource * @var resource
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var resource * @var resource
*/ */
private $resultset; private $resultset;
/** /**
* Cursor. * Cursor.
* @var int * @var int
*/ */
private $row = 0; private $row = 0;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('odbc')) { if (!extension_loaded('odbc')) {
throw new DibiDriverException("PHP extension 'odbc' is not loaded."); throw new DibiDriverException("PHP extension 'odbc' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'username', 'user'); DibiConnection::alias($config, 'username', 'user');
DibiConnection::alias($config, 'password', 'pass'); DibiConnection::alias($config, 'password', 'pass');
// default values // default values
if (!isset($config['username'])) $config['username'] = ini_get('odbc.default_user'); 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['password'])) $config['password'] = ini_get('odbc.default_pw');
if (!isset($config['dsn'])) $config['dsn'] = ini_get('odbc.default_db'); if (!isset($config['dsn'])) $config['dsn'] = ini_get('odbc.default_db');
if (empty($config['persistent'])) { if (empty($config['persistent'])) {
$this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']); $this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']);
} else { } else {
$this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); $this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']);
} }
if (!is_resource($this->connection)) { if (!is_resource($this->connection)) {
throw new DibiDriverException(odbc_errormsg() . ' ' . odbc_error()); throw new DibiDriverException(odbc_errormsg() . ' ' . odbc_error());
} }
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
odbc_close($this->connection); odbc_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultset = @odbc_exec($this->connection, $sql); $this->resultset = @odbc_exec($this->connection, $sql);
if ($this->resultset === FALSE) { if ($this->resultset === FALSE) {
$this->throwException($sql); $this->throwException($sql);
} }
return is_resource($this->resultset); return is_resource($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return odbc_num_rows($this->resultset); return odbc_num_rows($this->resultset);
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
throw new NotSupportedException('ODBC does not support autoincrementing.'); throw new NotSupportedException('ODBC does not support autoincrementing.');
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
if (!odbc_autocommit($this->connection, FALSE)) { if (!odbc_autocommit($this->connection, FALSE)) {
$this->throwException(); $this->throwException();
} }
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
if (!odbc_commit($this->connection)) { if (!odbc_commit($this->connection)) {
$this->throwException(); $this->throwException();
} }
odbc_autocommit($this->connection, TRUE); odbc_autocommit($this->connection, TRUE);
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
if (!odbc_rollback($this->connection)) { if (!odbc_rollback($this->connection)) {
$this->throwException(); $this->throwException();
} }
odbc_autocommit($this->connection, TRUE); odbc_autocommit($this->connection, TRUE);
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'"; if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'";
if ($type === dibi::IDENTIFIER) 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_BOOL) return $value ? -1 : 0;
if ($type === dibi::FIELD_DATE) return date("#m/d/Y#", $value); 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); if ($type === dibi::FIELD_DATETIME) return date("#m/d/Y H:i:s#", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
// offset suppot is missing... // offset suppot is missing...
if ($limit >= 0) { if ($limit >= 0) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')'; $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
} }
if ($offset) throw new InvalidArgumentException('Offset is not implemented in driver odbc.'); if ($offset) throw new InvalidArgumentException('Offset is not implemented in driver odbc.');
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
// will return -1 with many drivers :-( // will return -1 with many drivers :-(
return odbc_num_rows($this->resultset); return odbc_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
if ($type) { if ($type) {
return odbc_fetch_array($this->resultset, ++$this->row); return odbc_fetch_array($this->resultset, ++$this->row);
} else { } else {
$set = $this->resultset; $set = $this->resultset;
if (!odbc_fetch_row($set, ++$this->row)) return FALSE; if (!odbc_fetch_row($set, ++$this->row)) return FALSE;
$count = odbc_num_fields($set); $count = odbc_num_fields($set);
$cols = array(); $cols = array();
for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i); for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i);
return $cols; return $cols;
} }
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
$this->row = $row; $this->row = $row;
return TRUE; return TRUE;
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
odbc_free_result($this->resultset); odbc_free_result($this->resultset);
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = odbc_num_fields($this->resultset); $count = odbc_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 1; $i <= $count; $i++) { for ($i = 1; $i <= $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$meta[] = array( $meta[] = array(
'name' => odbc_field_name($this->resultset, $i), 'name' => odbc_field_name($this->resultset, $i),
'table' => NULL, 'table' => NULL,
'type' => odbc_field_type($this->resultset, $i), 'type' => odbc_field_type($this->resultset, $i),
'length' => odbc_field_len($this->resultset, $i), 'length' => odbc_field_len($this->resultset, $i),
'scale' => odbc_field_scale($this->resultset, $i), 'scale' => odbc_field_scale($this->resultset, $i),
'precision' => odbc_field_precision($this->resultset, $i), 'precision' => odbc_field_precision($this->resultset, $i),
); );
} }
return $meta; return $meta;
} }
/** /**
* Converts database error to DibiDriverException. * Converts database error to DibiDriverException.
* *
* @throws DibiDriverException * @throws DibiDriverException
*/ */
protected function throwException($sql = NULL) protected function throwException($sql = NULL)
{ {
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql); throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql);
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -36,323 +36,323 @@
class DibiOracleDriver extends /*Nette::*/Object implements IDibiDriver class DibiOracleDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var resource * @var resource
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var resource * @var resource
*/ */
private $resultset; private $resultset;
/** /**
* @var bool * @var bool
*/ */
private $autocommit = TRUE; private $autocommit = TRUE;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('oci8')) { if (!extension_loaded('oci8')) {
throw new DibiDriverException("PHP extension 'oci8' is not loaded."); throw new DibiDriverException("PHP extension 'oci8' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'username', 'user'); DibiConnection::alias($config, 'username', 'user');
DibiConnection::alias($config, 'password', 'pass'); DibiConnection::alias($config, 'password', 'pass');
DibiConnection::alias($config, 'database', 'db'); DibiConnection::alias($config, 'database', 'db');
DibiConnection::alias($config, 'charset'); DibiConnection::alias($config, 'charset');
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); $this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']);
if (!$this->connection) { if (!$this->connection) {
$err = oci_error(); $err = oci_error();
throw new DibiDriverException($err['message'], $err['code']); throw new DibiDriverException($err['message'], $err['code']);
} }
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
oci_close($this->connection); oci_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultset = oci_parse($this->connection, $sql); $this->resultset = oci_parse($this->connection, $sql);
if ($this->resultset) { if ($this->resultset) {
oci_execute($this->resultset, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); oci_execute($this->resultset, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
$err = oci_error($this->resultset); $err = oci_error($this->resultset);
if ($err) { if ($err) {
throw new DibiDriverException($err['message'], $err['code'], $sql); throw new DibiDriverException($err['message'], $err['code'], $sql);
} }
} else { } else {
$this->throwException($sql); $this->throwException($sql);
} }
return is_resource($this->resultset); return is_resource($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
throw new NotImplementedException; throw new NotImplementedException;
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
throw new NotSupportedException('Oracle does not support autoincrementing.'); throw new NotSupportedException('Oracle does not support autoincrementing.');
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
$this->autocommit = FALSE; $this->autocommit = FALSE;
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
if (!oci_commit($this->connection)) { if (!oci_commit($this->connection)) {
$this->throwException(); $this->throwException();
} }
$this->autocommit = TRUE; $this->autocommit = TRUE;
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
if (!oci_rollback($this->connection)) { if (!oci_rollback($this->connection)) {
$this->throwException(); $this->throwException();
} }
$this->autocommit = TRUE; $this->autocommit = TRUE;
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested 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::IDENTIFIER) return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested
if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0; if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0;
if ($type === dibi::FIELD_DATE) return date("U", $value); if ($type === dibi::FIELD_DATE) return date("U", $value);
if ($type === dibi::FIELD_DATETIME) return date("U", $value); if ($type === dibi::FIELD_DATETIME) return date("U", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
if ($limit < 0 && $offset < 1) return; if ($limit < 0 && $offset < 1) return;
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
return oci_num_rows($this->resultset); return oci_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return oci_fetch_array($this->resultset, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS); return oci_fetch_array($this->resultset, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
throw new NotImplementedException; throw new NotImplementedException;
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
oci_free_statement($this->resultset); oci_free_statement($this->resultset);
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = oci_num_fields($this->resultset); $count = oci_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 1; $i <= $count; $i++) { for ($i = 1; $i <= $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$meta[] = array( $meta[] = array(
'name' => oci_field_name($this->resultset, $i), 'name' => oci_field_name($this->resultset, $i),
'table' => NULL, 'table' => NULL,
'type' => oci_field_type($this->resultset, $i), 'type' => oci_field_type($this->resultset, $i),
'size' => oci_field_size($this->resultset, $i), 'size' => oci_field_size($this->resultset, $i),
'scale' => oci_field_scale($this->resultset, $i), 'scale' => oci_field_scale($this->resultset, $i),
'precision' => oci_field_precision($this->resultset, $i), 'precision' => oci_field_precision($this->resultset, $i),
); );
} }
return $meta; return $meta;
} }
/** /**
* Converts database error to DibiDriverException. * Converts database error to DibiDriverException.
* *
* @throws DibiDriverException * @throws DibiDriverException
*/ */
protected function throwException($sql = NULL) protected function throwException($sql = NULL)
{ {
$err = oci_error($this->connection); $err = oci_error($this->connection);
throw new DibiDriverException($err['message'], $err['code'], $sql); throw new DibiDriverException($err['message'], $err['code'], $sql);
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -37,339 +37,339 @@
class DibiPdoDriver extends /*Nette::*/Object implements IDibiDriver class DibiPdoDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var PDO * @var PDO
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var PDOStatement * @var PDOStatement
*/ */
private $resultset; private $resultset;
/** /**
* Affected rows. * Affected rows.
* @var int * @var int
*/ */
private $affectedRows = FALSE; private $affectedRows = FALSE;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('pdo')) { if (!extension_loaded('pdo')) {
throw new DibiDriverException("PHP extension 'pdo' is not loaded."); throw new DibiDriverException("PHP extension 'pdo' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'username', 'user'); DibiConnection::alias($config, 'username', 'user');
DibiConnection::alias($config, 'password', 'pass'); DibiConnection::alias($config, 'password', 'pass');
DibiConnection::alias($config, 'dsn'); DibiConnection::alias($config, 'dsn');
DibiConnection::alias($config, 'pdo'); DibiConnection::alias($config, 'pdo');
DibiConnection::alias($config, 'options'); DibiConnection::alias($config, 'options');
if ($config['pdo'] instanceof PDO) { if ($config['pdo'] instanceof PDO) {
$this->connection = $config['pdo']; $this->connection = $config['pdo'];
} else try { } else try {
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']); $this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
} catch (PDOException $e) { } catch (PDOException $e) {
throw new DibiDriverException($e->getMessage(), $e->getCode()); throw new DibiDriverException($e->getMessage(), $e->getCode());
} }
if (!$this->connection) { if (!$this->connection) {
throw new DibiDriverException('Connecting error.'); throw new DibiDriverException('Connecting error.');
} }
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
$this->connection = NULL; $this->connection = NULL;
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
// must detect if SQL returns resultset or num of affected rows // must detect if SQL returns resultset or num of affected rows
$cmd = strtoupper(substr(ltrim($sql), 0, 6)); $cmd = strtoupper(substr(ltrim($sql), 0, 6));
$list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1); $list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1);
if (isset($list[$cmd])) { if (isset($list[$cmd])) {
$this->resultset = NULL; $this->resultset = NULL;
$this->affectedRows = $this->connection->exec($sql); $this->affectedRows = $this->connection->exec($sql);
if ($this->affectedRows === FALSE) { if ($this->affectedRows === FALSE) {
$this->throwException($sql); $this->throwException($sql);
} }
return FALSE; return FALSE;
} else { } else {
$this->resultset = $this->connection->query($sql); $this->resultset = $this->connection->query($sql);
$this->affectedRows = FALSE; $this->affectedRows = FALSE;
if ($this->resultset === FALSE) { if ($this->resultset === FALSE) {
$this->throwException($sql); $this->throwException($sql);
} }
return TRUE; return TRUE;
} }
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return $this->affectedRows; return $this->affectedRows;
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
return $this->connection->lastInsertId(); return $this->connection->lastInsertId();
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
if (!$this->connection->beginTransaction()) { if (!$this->connection->beginTransaction()) {
$this->throwException(); $this->throwException();
} }
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
if (!$this->connection->commit()) { if (!$this->connection->commit()) {
$this->throwException(); $this->throwException();
} }
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
if (!$this->connection->rollBack()) { if (!$this->connection->rollBack()) {
$this->throwException(); $this->throwException();
} }
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return $this->connection->quote($value); 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::IDENTIFIER) return $value; // quoting is not supported by PDO
if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0; if ($type === dibi::FIELD_BOOL) return $value ? 1 : 0;
if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); 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); if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
throw new NotSupportedException('PDO does not support applying limit or offset.'); throw new NotSupportedException('PDO does not support applying limit or offset.');
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
throw new DibiDriverException('Row count is not available for unbuffered queries.'); 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. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return $this->resultset->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM); return $this->resultset->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
throw new DibiDriverException('Cannot seek an unbuffered result set.'); throw new DibiDriverException('Cannot seek an unbuffered result set.');
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
* @throws DibiException * @throws DibiException
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = $this->resultset->columnCount(); $count = $this->resultset->columnCount();
$meta = array(); $meta = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$info = @$this->resultset->getColumnsMeta($i); $info = @$this->resultset->getColumnsMeta($i);
if ($info === FALSE) { if ($info === FALSE) {
throw new DibiDriverException('Driver does not support meta data.'); throw new DibiDriverException('Driver does not support meta data.');
} }
$meta[] = $info; $meta[] = $info;
} }
return $meta; return $meta;
} }
/** /**
* Converts database error to DibiDriverException. * Converts database error to DibiDriverException.
* *
* @throws DibiDriverException * @throws DibiDriverException
*/ */
protected function throwException($sql = NULL) protected function throwException($sql = NULL)
{ {
$err = $this->connection->errorInfo(); $err = $this->connection->errorInfo();
throw new DibiDriverException("SQLSTATE[$err[0]]: $err[2]", $err[1], $sql); throw new DibiDriverException("SQLSTATE[$err[0]]: $err[2]", $err[1], $sql);
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return PDO * @return PDO
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return PDOStatement * @return PDOStatement
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -37,349 +37,349 @@
class DibiPostgreDriver extends /*Nette::*/Object implements IDibiDriver class DibiPostgreDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var resource * @var resource
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var resource * @var resource
*/ */
private $resultset; private $resultset;
/** /**
* Escape method. * Escape method.
* @var bool * @var bool
*/ */
private $escMethod = FALSE; private $escMethod = FALSE;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('pgsql')) { if (!extension_loaded('pgsql')) {
throw new DibiDriverException("PHP extension 'pgsql' is not loaded."); throw new DibiDriverException("PHP extension 'pgsql' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
if (isset($config['string'])) { if (isset($config['string'])) {
$string = $config['string']; $string = $config['string'];
} else { } else {
$string = ''; $string = '';
foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) { foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) {
if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' '; if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' ';
} }
} }
DibiDriverException::tryError(); DibiDriverException::tryError();
if (isset($config['persistent'])) { if (isset($config['persistent'])) {
$this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW); $this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW);
} else { } else {
$this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW); $this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW);
} }
if (DibiDriverException::catchError($msg)) { if (DibiDriverException::catchError($msg)) {
throw new DibiDriverException($msg, 0); throw new DibiDriverException($msg, 0);
} }
if (!is_resource($this->connection)) { if (!is_resource($this->connection)) {
throw new DibiDriverException('Connecting error.'); throw new DibiDriverException('Connecting error.');
} }
if (isset($config['charset'])) { if (isset($config['charset'])) {
DibiDriverException::tryError(); DibiDriverException::tryError();
pg_set_client_encoding($this->connection, $config['charset']); pg_set_client_encoding($this->connection, $config['charset']);
if (DibiDriverException::catchError($msg)) { if (DibiDriverException::catchError($msg)) {
throw new DibiDriverException($msg, 0); throw new DibiDriverException($msg, 0);
} }
} }
if (isset($config['schema'])) { if (isset($config['schema'])) {
$this->query('SET search_path TO ' . $config['schema']); $this->query('SET search_path TO ' . $config['schema']);
} }
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>='); $this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
pg_close($this->connection); pg_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @param bool update affected rows? * @param bool update affected rows?
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultset = @pg_query($this->connection, $sql); $this->resultset = @pg_query($this->connection, $sql);
if ($this->resultset === FALSE) { if ($this->resultset === FALSE) {
throw new DibiDriverException(pg_last_error($this->connection), 0, $sql); throw new DibiDriverException(pg_last_error($this->connection), 0, $sql);
} }
return is_resource($this->resultset); return is_resource($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return pg_affected_rows($this->resultset); return pg_affected_rows($this->resultset);
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
if ($sequence === NULL) { if ($sequence === NULL) {
// PostgreSQL 8.1 is needed // PostgreSQL 8.1 is needed
$has = $this->query("SELECT LASTVAL()"); $has = $this->query("SELECT LASTVAL()");
} else { } else {
$has = $this->query("SELECT CURRVAL('$sequence')"); $has = $this->query("SELECT CURRVAL('$sequence')");
} }
if (!$has) return FALSE; if (!$has) return FALSE;
$row = $this->fetch(FALSE); $row = $this->fetch(FALSE);
$this->free(); $this->free();
return is_array($row) ? $row[0] : FALSE; return is_array($row) ? $row[0] : FALSE;
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
$this->query('START TRANSACTION'); $this->query('START TRANSACTION');
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
$this->query('COMMIT'); $this->query('COMMIT');
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
$this->query('ROLLBACK'); $this->query('ROLLBACK');
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) { if ($type === dibi::FIELD_TEXT) {
if ($this->escMethod) return "'" . pg_escape_string($this->connection, $value) . "'"; if ($this->escMethod) return "'" . pg_escape_string($this->connection, $value) . "'";
return "'" . pg_escape_string($value) . "'"; return "'" . pg_escape_string($value) . "'";
} }
if ($type === dibi::IDENTIFIER) { if ($type === dibi::IDENTIFIER) {
$a = strrpos($value, '.'); $a = strrpos($value, '.');
if ($a === FALSE) return '"' . str_replace('"', '""', $value) . '"'; if ($a === FALSE) return '"' . str_replace('"', '""', $value) . '"';
// table.col delimite as table."col" // table.col delimite as table."col"
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"'; return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
} }
if ($type === dibi::FIELD_BOOL) return $value ? 'TRUE' : 'FALSE'; if ($type === dibi::FIELD_BOOL) return $value ? 'TRUE' : 'FALSE';
if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value); 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); if ($type === dibi::FIELD_DATETIME) return date("'Y-m-d H:i:s'", $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
if ($limit >= 0) if ($limit >= 0)
$sql .= ' LIMIT ' . (int) $limit; $sql .= ' LIMIT ' . (int) $limit;
if ($offset > 0) if ($offset > 0)
$sql .= ' OFFSET ' . (int) $offset; $sql .= ' OFFSET ' . (int) $offset;
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
return pg_num_rows($this->resultset); return pg_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return pg_fetch_array($this->resultset, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM); return pg_fetch_array($this->resultset, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
return pg_result_seek($this->resultset, $row); return pg_result_seek($this->resultset, $row);
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
pg_free_result($this->resultset); pg_free_result($this->resultset);
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>='); $hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
$count = pg_num_fields($this->resultset); $count = pg_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$meta[] = array( $meta[] = array(
'name' => pg_field_name($this->resultset, $i), 'name' => pg_field_name($this->resultset, $i),
'table' => $hasTable ? pg_field_table($this->resultset, $i) : NULL, 'table' => $hasTable ? pg_field_table($this->resultset, $i) : NULL,
'type' => pg_field_type($this->resultset, $i), 'type' => pg_field_type($this->resultset, $i),
'size' => pg_field_size($this->resultset, $i), 'size' => pg_field_size($this->resultset, $i),
'prtlen' => pg_field_prtlen($this->resultset, $i), 'prtlen' => pg_field_prtlen($this->resultset, $i),
); );
} }
return $meta; return $meta;
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -37,316 +37,316 @@
class DibiSqliteDriver extends /*Nette::*/Object implements IDibiDriver class DibiSqliteDriver extends /*Nette::*/Object implements IDibiDriver
{ {
/** /**
* Connection resource. * Connection resource.
* @var resource * @var resource
*/ */
private $connection; private $connection;
/** /**
* Resultset resource. * Resultset resource.
* @var resource * @var resource
*/ */
private $resultset; private $resultset;
/** /**
* Is buffered (seekable and countable)? * Is buffered (seekable and countable)?
* @var bool * @var bool
*/ */
private $buffered; private $buffered;
/** /**
* Date and datetime format. * Date and datetime format.
* @var string * @var string
*/ */
private $fmtDate, $fmtDateTime; private $fmtDate, $fmtDateTime;
/** /**
* @throws DibiException * @throws DibiException
*/ */
public function __construct() public function __construct()
{ {
if (!extension_loaded('sqlite')) { if (!extension_loaded('sqlite')) {
throw new DibiDriverException("PHP extension 'sqlite' is not loaded."); throw new DibiDriverException("PHP extension 'sqlite' is not loaded.");
} }
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
public function connect(array &$config) public function connect(array &$config)
{ {
DibiConnection::alias($config, 'database', 'file'); DibiConnection::alias($config, 'database', 'file');
$this->fmtDate = isset($config['format:date']) ? $config['format:date'] : 'U'; $this->fmtDate = isset($config['format:date']) ? $config['format:date'] : 'U';
$this->fmtDateTime = isset($config['format:datetime']) ? $config['format:datetime'] : 'U'; $this->fmtDateTime = isset($config['format:datetime']) ? $config['format:datetime'] : 'U';
$errorMsg = ''; $errorMsg = '';
if (empty($config['persistent'])) { if (empty($config['persistent'])) {
$this->connection = @sqlite_open($config['database'], 0666, $errorMsg); $this->connection = @sqlite_open($config['database'], 0666, $errorMsg);
} else { } else {
$this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); $this->connection = @sqlite_popen($config['database'], 0666, $errorMsg);
} }
if (!$this->connection) { if (!$this->connection) {
throw new DibiDriverException($errorMsg); throw new DibiDriverException($errorMsg);
} }
$this->buffered = empty($config['unbuffered']); $this->buffered = empty($config['unbuffered']);
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect()
{ {
sqlite_close($this->connection); sqlite_close($this->connection);
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
DibiDriverException::tryError(); DibiDriverException::tryError();
if ($this->buffered) { if ($this->buffered) {
$this->resultset = sqlite_query($this->connection, $sql); $this->resultset = sqlite_query($this->connection, $sql);
} else { } else {
$this->resultset = sqlite_unbuffered_query($this->connection, $sql); $this->resultset = sqlite_unbuffered_query($this->connection, $sql);
} }
if (DibiDriverException::catchError($msg)) { if (DibiDriverException::catchError($msg)) {
throw new DibiDriverException($msg, sqlite_last_error($this->connection), $sql); throw new DibiDriverException($msg, sqlite_last_error($this->connection), $sql);
} }
return is_resource($this->resultset); return is_resource($this->resultset);
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
public function affectedRows() public function affectedRows()
{ {
return sqlite_changes($this->connection); return sqlite_changes($this->connection);
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
public function insertId($sequence) public function insertId($sequence)
{ {
return sqlite_last_insert_rowid($this->connection); return sqlite_last_insert_rowid($this->connection);
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function begin() public function begin()
{ {
$this->query('BEGIN'); $this->query('BEGIN');
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function commit() public function commit()
{ {
$this->query('COMMIT'); $this->query('COMMIT');
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function rollback() public function rollback()
{ {
$this->query('ROLLBACK'); $this->query('ROLLBACK');
} }
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function format($value, $type) public function format($value, $type)
{ {
if ($type === dibi::FIELD_TEXT) return "'" . sqlite_escape_string($value) . "'"; if ($type === dibi::FIELD_TEXT) return "'" . sqlite_escape_string($value) . "'";
if ($type === dibi::IDENTIFIER) 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_BOOL) return $value ? 1 : 0;
if ($type === dibi::FIELD_DATE) return date($this->fmtDate, $value); if ($type === dibi::FIELD_DATE) return date($this->fmtDate, $value);
if ($type === dibi::FIELD_DATETIME) return date($this->fmtDateTime, $value); if ($type === dibi::FIELD_DATETIME) return date($this->fmtDateTime, $value);
throw new InvalidArgumentException('Unsupported formatting type.'); throw new InvalidArgumentException('Unsupported formatting type.');
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
if ($limit < 0 && $offset < 1) return; if ($limit < 0 && $offset < 1) return;
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
} }
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
public function rowCount() public function rowCount()
{ {
if (!$this->buffered) { if (!$this->buffered) {
throw new DibiDriverException('Row count is not available for unbuffered queries.'); throw new DibiDriverException('Row count is not available for unbuffered queries.');
} }
return sqlite_num_rows($this->resultset); return sqlite_num_rows($this->resultset);
} }
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
public function fetch($type) public function fetch($type)
{ {
return sqlite_fetch_array($this->resultset, $type ? SQLITE_ASSOC : SQLITE_NUM); return sqlite_fetch_array($this->resultset, $type ? SQLITE_ASSOC : SQLITE_NUM);
} }
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
public function seek($row) public function seek($row)
{ {
if (!$this->buffered) { if (!$this->buffered) {
throw new DibiDriverException('Cannot seek an unbuffered result set.'); throw new DibiDriverException('Cannot seek an unbuffered result set.');
} }
return sqlite_seek($this->resultset, $row); return sqlite_seek($this->resultset, $row);
} }
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function free() public function free()
{ {
$this->resultset = NULL; $this->resultset = NULL;
} }
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = sqlite_num_fields($this->resultset); $count = sqlite_num_fields($this->resultset);
$meta = array(); $meta = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required // items 'name' and 'table' are required
$meta[] = array( $meta[] = array(
'name' => sqlite_field_name($this->resultset, $i), 'name' => sqlite_field_name($this->resultset, $i),
'table' => NULL, 'table' => NULL,
); );
} }
return $meta; return $meta;
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
public function getResource() public function getResource()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
public function getResultResource() public function getResultResource()
{ {
return $this->resultset; return $this->resultset;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection() function getDibiReflection()
{} {}
} }

View File

@@ -29,434 +29,434 @@
*/ */
class DibiConnection extends /*Nette::*/Object class DibiConnection extends /*Nette::*/Object
{ {
/** /**
* Current connection configuration. * Current connection configuration.
* @var array * @var array
*/ */
private $config; private $config;
/** /**
* IDibiDriver. * IDibiDriver.
* @var array * @var array
*/ */
private $driver; private $driver;
/** /**
* Is connected? * Is connected?
* @var bool * @var bool
*/ */
private $connected = FALSE; private $connected = FALSE;
/** /**
* Is in transaction? * Is in transaction?
* @var bool * @var bool
*/ */
private $inTxn = FALSE; private $inTxn = FALSE;
/** /**
* Creates object and (optionally) connects to a database. * Creates object and (optionally) connects to a database.
* *
* @param array|string|Nette::Collections::IMap connection parameters * @param array|string|Nette::Collections::IMap connection parameters
* @param string connection name * @param string connection name
* @throws DibiException * @throws DibiException
*/ */
public function __construct($config, $name = NULL) public function __construct($config, $name = NULL)
{ {
// DSN string // DSN string
if (is_string($config)) { if (is_string($config)) {
parse_str($config, $config); parse_str($config, $config);
} elseif ($config instanceof /*Nette::Collections::*/IMap) { } elseif ($config instanceof /*Nette::Collections::*/IMap) {
$config = $config->toArray(); $config = $config->toArray();
} elseif (!is_array($config)) { } elseif (!is_array($config)) {
throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::IMap.'); throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::IMap.');
} }
if (!isset($config['driver'])) { if (!isset($config['driver'])) {
$config['driver'] = dibi::$defaultDriver; $config['driver'] = dibi::$defaultDriver;
} }
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']); $driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
$class = "Dibi" . $driver . "Driver"; $class = "Dibi" . $driver . "Driver";
if (!class_exists($class, FALSE)) { if (!class_exists($class, FALSE)) {
include_once __FILE__ . "/../../drivers/$driver.php"; include_once __FILE__ . "/../../drivers/$driver.php";
if (!class_exists($class, FALSE)) { if (!class_exists($class, FALSE)) {
throw new DibiException("Unable to create instance of dibi driver class '$class'."); throw new DibiException("Unable to create instance of dibi driver class '$class'.");
} }
} }
$config['name'] = $name; $config['name'] = $name;
$this->config = $config; $this->config = $config;
$this->driver = new $class; $this->driver = new $class;
if (empty($config['lazy'])) { if (empty($config['lazy'])) {
$this->connect(); $this->connect();
} }
} }
/** /**
* Automatically frees the resources allocated for this result set. * Automatically frees the resources allocated for this result set.
* *
* @return void * @return void
*/ */
public function __destruct() public function __destruct()
{ {
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback! // disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
$this->disconnect(); $this->disconnect();
} }
/** /**
* Connects to a database. * Connects to a database.
* *
* @return void * @return void
*/ */
final protected function connect() final protected function connect()
{ {
if (!$this->connected) { if (!$this->connected) {
$this->driver->connect($this->config); $this->driver->connect($this->config);
$this->connected = TRUE; $this->connected = TRUE;
dibi::notify($this, 'connected'); dibi::notify($this, 'connected');
} }
} }
/** /**
* Disconnects from a database. * Disconnects from a database.
* *
* @return void * @return void
*/ */
final public function disconnect() final public function disconnect()
{ {
if ($this->connected) { if ($this->connected) {
if ($this->inTxn) { if ($this->inTxn) {
$this->rollback(); $this->rollback();
} }
$this->driver->disconnect(); $this->driver->disconnect();
$this->connected = FALSE; $this->connected = FALSE;
dibi::notify($this, 'disconnected'); dibi::notify($this, 'disconnected');
} }
} }
/** /**
* Returns configuration variable. If no $key is passed, returns the entire array. * Returns configuration variable. If no $key is passed, returns the entire array.
* *
* @see self::__construct * @see self::__construct
* @param string * @param string
* @param mixed default value to use if key not found * @param mixed default value to use if key not found
* @return mixed * @return mixed
*/ */
final public function getConfig($key = NULL, $default = NULL) final public function getConfig($key = NULL, $default = NULL)
{ {
if ($key === NULL) { if ($key === NULL) {
return $this->config; return $this->config;
} elseif (isset($this->config[$key])) { } elseif (isset($this->config[$key])) {
return $this->config[$key]; return $this->config[$key];
} else { } else {
return $default; return $default;
} }
} }
/** /**
* Apply configuration alias or default values. * Apply configuration alias or default values.
* *
* @param array connect configuration * @param array connect configuration
* @param string key * @param string key
* @param string alias key * @param string alias key
* @return void * @return void
*/ */
public static function alias(&$config, $key, $alias=NULL) public static function alias(&$config, $key, $alias=NULL)
{ {
if (isset($config[$key])) return; if (isset($config[$key])) return;
if ($alias !== NULL && isset($config[$alias])) { if ($alias !== NULL && isset($config[$alias])) {
$config[$key] = $config[$alias]; $config[$key] = $config[$alias];
unset($config[$alias]); unset($config[$alias]);
} else { } else {
$config[$key] = NULL; $config[$key] = NULL;
} }
} }
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return resource * @return resource
*/ */
final public function getResource() final public function getResource()
{ {
return $this->driver->getResource(); return $this->driver->getResource();
} }
/** /**
* Generates (translates) and executes SQL query. * Generates (translates) and executes SQL query.
* *
* @param array|mixed one or more arguments * @param array|mixed one or more arguments
* @return DibiResult Result set object (if any) * @return DibiResult Result set object (if any)
* @throws DibiException * @throws DibiException
*/ */
final public function query($args) final public function query($args)
{ {
$args = func_get_args(); $args = func_get_args();
$this->connect(); $this->connect();
$trans = new DibiTranslator($this->driver); $trans = new DibiTranslator($this->driver);
if ($trans->translate($args)) { if ($trans->translate($args)) {
return $this->nativeQuery($trans->sql); return $this->nativeQuery($trans->sql);
} else { } else {
throw new DibiException('SQL translate error: ' . $trans->sql); throw new DibiException('SQL translate error: ' . $trans->sql);
} }
} }
/** /**
* Generates and prints SQL query. * Generates and prints SQL query.
* *
* @param array|mixed one or more arguments * @param array|mixed one or more arguments
* @return bool * @return bool
*/ */
final public function test($args) final public function test($args)
{ {
$args = func_get_args(); $args = func_get_args();
$this->connect(); $this->connect();
$trans = new DibiTranslator($this->driver); $trans = new DibiTranslator($this->driver);
$ok = $trans->translate($args); $ok = $trans->translate($args);
dibi::dump($trans->sql); dibi::dump($trans->sql);
return $ok; return $ok;
} }
/** /**
* Executes the SQL query. * Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return DibiResult Result set object (if any) * @return DibiResult Result set object (if any)
* @throws DibiException * @throws DibiException
*/ */
final public function nativeQuery($sql) final public function nativeQuery($sql)
{ {
$this->connect(); $this->connect();
dibi::$numOfQueries++; dibi::$numOfQueries++;
dibi::$sql = $sql; dibi::$sql = $sql;
dibi::$elapsedTime = FALSE; dibi::$elapsedTime = FALSE;
$time = -microtime(TRUE); $time = -microtime(TRUE);
dibi::notify($this, 'beforeQuery', $sql); 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 $res = $this->driver->query($sql) ? new DibiResult(clone $this->driver, $this->config) : TRUE; // backward compatibility - will be changed to NULL
$time += microtime(TRUE); $time += microtime(TRUE);
dibi::$elapsedTime = $time; dibi::$elapsedTime = $time;
dibi::$totalTime += $time; dibi::$totalTime += $time;
dibi::notify($this, 'afterQuery', $res); dibi::notify($this, 'afterQuery', $res);
return $res; return $res;
} }
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int number of rows * @return int number of rows
* @throws DibiException * @throws DibiException
*/ */
public function affectedRows() public function affectedRows()
{ {
$rows = $this->driver->affectedRows(); $rows = $this->driver->affectedRows();
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.'); if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
return $rows; return $rows;
} }
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @param string optional sequence name * @param string optional sequence name
* @return int * @return int
* @throws DibiException * @throws DibiException
*/ */
public function insertId($sequence = NULL) public function insertId($sequence = NULL)
{ {
$id = $this->driver->insertId($sequence); $id = $this->driver->insertId($sequence);
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.'); if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
return (int) $id; return (int) $id;
} }
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
*/ */
public function begin() public function begin()
{ {
$this->connect(); $this->connect();
if ($this->inTxn) { if ($this->inTxn) {
throw new DibiException('There is already an active transaction.'); throw new DibiException('There is already an active transaction.');
} }
$this->driver->begin(); $this->driver->begin();
$this->inTxn = TRUE; $this->inTxn = TRUE;
dibi::notify($this, 'begin'); dibi::notify($this, 'begin');
} }
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
*/ */
public function commit() public function commit()
{ {
if (!$this->inTxn) { if (!$this->inTxn) {
throw new DibiException('There is no active transaction.'); throw new DibiException('There is no active transaction.');
} }
$this->driver->commit(); $this->driver->commit();
$this->inTxn = FALSE; $this->inTxn = FALSE;
dibi::notify($this, 'commit'); dibi::notify($this, 'commit');
} }
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
*/ */
public function rollback() public function rollback()
{ {
if (!$this->inTxn) { if (!$this->inTxn) {
throw new DibiException('There is no active transaction.'); throw new DibiException('There is no active transaction.');
} }
$this->driver->rollback(); $this->driver->rollback();
$this->inTxn = FALSE; $this->inTxn = FALSE;
dibi::notify($this, 'rollback'); dibi::notify($this, 'rollback');
} }
/** /**
* Escapes the string. * Escapes the string.
* *
* @param string unescaped string * @param string unescaped string
* @return string escaped and optionally quoted string * @return string escaped and optionally quoted string
*/ */
public function escape($value) public function escape($value)
{ {
$this->connect(); // MySQL & PDO require connection $this->connect(); // MySQL & PDO require connection
return $this->driver->format($value, dibi::FIELD_TEXT); return $this->driver->format($value, dibi::FIELD_TEXT);
} }
/** /**
* Delimites identifier (table's or column's name, etc.). * Delimites identifier (table's or column's name, etc.).
* *
* @param string identifier * @param string identifier
* @return string delimited identifier * @return string delimited identifier
*/ */
public function delimite($value) public function delimite($value)
{ {
return $this->driver->format($value, dibi::IDENTIFIER); return $this->driver->format($value, dibi::IDENTIFIER);
} }
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
public function applyLimit(&$sql, $limit, $offset) public function applyLimit(&$sql, $limit, $offset)
{ {
$this->driver->applyLimit($sql, $limit, $offset); $this->driver->applyLimit($sql, $limit, $offset);
} }
/** /**
* Import SQL dump from file - extreme fast! * Import SQL dump from file - extreme fast!
* *
* @param string filename * @param string filename
* @return int count of sql commands * @return int count of sql commands
*/ */
public function loadFile($file) public function loadFile($file)
{ {
$this->connect(); $this->connect();
@set_time_limit(0); @set_time_limit(0);
$handle = @fopen($file, 'r'); $handle = @fopen($file, 'r');
if (!$handle) { if (!$handle) {
throw new FileNotFoundException("Cannot open file '$file'."); throw new FileNotFoundException("Cannot open file '$file'.");
} }
$count = 0; $count = 0;
$sql = ''; $sql = '';
while (!feof($handle)) { while (!feof($handle)) {
$s = fgets($handle); $s = fgets($handle);
$sql .= $s; $sql .= $s;
if (substr(rtrim($s), -1) === ';') { if (substr(rtrim($s), -1) === ';') {
$this->driver->query($sql); $this->driver->query($sql);
$sql = ''; $sql = '';
$count++; $count++;
} }
} }
fclose($handle); fclose($handle);
return $count; return $count;
} }
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
public function getDibiReflection() public function getDibiReflection()
{ {
throw new NotImplementedException; throw new NotImplementedException;
} }
/** /**
* Prevents unserialization. * Prevents unserialization.
*/ */
public function __wakeup() public function __wakeup()
{ {
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
} }
/** /**
* Prevents serialization. * Prevents serialization.
*/ */
public function __sleep() public function __sleep()
{ {
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
} }
} }

View File

@@ -29,64 +29,64 @@
*/ */
class DibiDataSource extends /*Nette::*/Object implements IDataSource class DibiDataSource extends /*Nette::*/Object implements IDataSource
{ {
/** @var DibiConnection */ /** @var DibiConnection */
private $connection; private $connection;
/** @var string */ /** @var string */
private $sql; private $sql;
/** @var int */ /** @var int */
private $count; private $count;
/** /**
* @param string SQL command or table name, as data source * @param string SQL command or table name, as data source
* @param DibiConnection connection * @param DibiConnection connection
*/ */
public function __construct($sql, DibiConnection $connection = NULL) public function __construct($sql, DibiConnection $connection = NULL)
{ {
if (strpos($sql, ' ') === FALSE) { if (strpos($sql, ' ') === FALSE) {
// table name // table name
$this->sql = $sql; $this->sql = $sql;
} else { } else {
// SQL command // SQL command
$this->sql = '(' . $sql . ') AS [source]'; $this->sql = '(' . $sql . ') AS [source]';
} }
$this->connection = $connection === NULL ? dibi::getConnection() : $connection; $this->connection = $connection === NULL ? dibi::getConnection() : $connection;
} }
/** /**
* @param int offset * @param int offset
* @param int limit * @param int limit
* @param array columns * @param array columns
* @return ArrayIterator * @return ArrayIterator
*/ */
public function getIterator($offset = NULL, $limit = NULL, $cols = NULL) public function getIterator($offset = NULL, $limit = NULL, $cols = NULL)
{ {
return $this->connection->query(' return $this->connection->query('
SELECT * SELECT *
FROM', $this->sql, ' FROM', $this->sql, '
%ofs %lmt', $offset, $limit %ofs %lmt', $offset, $limit
); );
} }
/** /**
* @return int * @return int
*/ */
public function count() public function count()
{ {
if ($this->count === NULL) { if ($this->count === NULL) {
$this->count = $this->connection->query(' $this->count = $this->connection->query('
SELECT COUNT(*) FROM', $this->sql SELECT COUNT(*) FROM', $this->sql
)->fetchSingle(); )->fetchSingle();
} }
return $this->count; return $this->count;
} }
} }

View File

@@ -44,116 +44,116 @@ class DibiException extends Exception
*/ */
class DibiDriverException extends DibiException implements /*Nette::*/IDebuggable class DibiDriverException extends DibiException implements /*Nette::*/IDebuggable
{ {
/** @var string */ /** @var string */
private static $errorMsg; private static $errorMsg;
/** @var string */ /** @var string */
private $sql; private $sql;
/** /**
* Construct an dibi driver exception. * Construct an dibi driver exception.
* *
* @param string Message describing the exception * @param string Message describing the exception
* @param int Some code * @param int Some code
* @param string SQL command * @param string SQL command
*/ */
public function __construct($message = NULL, $code = 0, $sql = NULL) public function __construct($message = NULL, $code = 0, $sql = NULL)
{ {
parent::__construct($message, (int) $code); parent::__construct($message, (int) $code);
$this->sql = $sql; $this->sql = $sql;
dibi::notify(NULL, 'exception', $this); 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() final public function getSql()
{ {
return $this->sql; return $this->sql;
} }
/** /**
* @return string string represenation of exception with SQL command * @return string string represenation of exception with SQL command
*/ */
public function __toString() public function __toString()
{ {
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : ''); return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
} }
/********************* interface Nette::IDebuggable ****************d*g**/ /********************* interface Nette::IDebuggable ****************d*g**/
/** /**
* Returns custom panels. * Returns custom panels.
* @return array * @return array
*/ */
public function getPanels() public function getPanels()
{ {
$panels = array(); $panels = array();
if ($this->sql !== NULL) { if ($this->sql !== NULL) {
$panels['SQL'] = array( $panels['SQL'] = array(
'expanded' => TRUE, 'expanded' => TRUE,
'content' => dibi::dump($this->sql, TRUE), 'content' => dibi::dump($this->sql, TRUE),
); );
} }
return $panels; return $panels;
} }
/********************* error catching ****************d*g**/ /********************* error catching ****************d*g**/
/** /**
* Starts catching potential errors/warnings * Starts catching potential errors/warnings
* *
* @return void * @return void
*/ */
public static function tryError() public static function tryError()
{ {
set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL); set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
self::$errorMsg = NULL; self::$errorMsg = NULL;
} }
/** /**
* Returns catched error/warning message. * Returns catched error/warning message.
* *
* @param string catched message * @param string catched message
* @return bool * @return bool
*/ */
public static function catchError(& $message) public static function catchError(& $message)
{ {
restore_error_handler(); restore_error_handler();
$message = self::$errorMsg; $message = self::$errorMsg;
self::$errorMsg = NULL; self::$errorMsg = NULL;
return $message !== NULL; return $message !== NULL;
} }
/** /**
* Internal error handler. Do not call directly. * Internal error handler. Do not call directly.
*/ */
public static function _errorHandler($code, $message) public static function _errorHandler($code, $message)
{ {
restore_error_handler(); restore_error_handler();
if (ini_get('html_errors')) { if (ini_get('html_errors')) {
$message = strip_tags($message); $message = strip_tags($message);
$message = html_entity_decode($message); $message = html_entity_decode($message);
} }
self::$errorMsg = $message; self::$errorMsg = $message;
} }
} }

View File

@@ -29,78 +29,78 @@
*/ */
final class DibiLogger extends /*Nette::*/Object final class DibiLogger extends /*Nette::*/Object
{ {
/** @var string Name of the file where SQL errors should be logged */ /** @var string Name of the file where SQL errors should be logged */
private $file; private $file;
/** @var bool */ /** @var bool */
public $logErrors = TRUE; public $logErrors = TRUE;
/** @var bool */ /** @var bool */
public $logQueries = TRUE; public $logQueries = TRUE;
/** /**
* @param string filename * @param string filename
*/ */
public function __construct($file) public function __construct($file)
{ {
$this->file = $file; $this->file = $file;
} }
/** /**
* Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback). * Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback).
* *
* @param DibiConnection * @param DibiConnection
* @param string event name * @param string event name
* @param mixed * @param mixed
* @return void * @return void
*/ */
public function handler($connection, $event, $arg) public function handler($connection, $event, $arg)
{ {
if ($event === 'afterQuery' && $this->logQueries) { if ($event === 'afterQuery' && $this->logQueries) {
$this->write( $this->write(
"OK: " . dibi::$sql "OK: " . dibi::$sql
. ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '') . ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '')
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms' . "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
. "\n-- driver: " . $connection->getConfig('driver') . "\n-- driver: " . $connection->getConfig('driver')
. "\n-- " . date('Y-m-d H:i:s') . "\n-- " . date('Y-m-d H:i:s')
. "\n\n" . "\n\n"
); );
return; return;
} }
if ($event === 'exception' && $this->logErrors) { if ($event === 'exception' && $this->logErrors) {
// $arg is DibiDriverException // $arg is DibiDriverException
$message = $arg->getMessage(); $message = $arg->getMessage();
$code = $arg->getCode(); $code = $arg->getCode();
if ($code) { if ($code) {
$message = "[$code] $message"; $message = "[$code] $message";
} }
$this->write( $this->write(
"ERROR: $message" "ERROR: $message"
. "\n-- SQL: " . dibi::$sql . "\n-- SQL: " . dibi::$sql
. "\n-- driver: " //. $connection->getConfig('driver') . "\n-- driver: " //. $connection->getConfig('driver')
. ";\n-- " . date('Y-m-d H:i:s') . ";\n-- " . date('Y-m-d H:i:s')
. "\n\n" . "\n\n"
); );
return; return;
} }
} }
private function write($message) private function write($message)
{ {
$handle = fopen($this->file, 'a'); $handle = fopen($this->file, 'a');
if (!$handle) return; // or throw exception? if (!$handle) return; // or throw exception?
flock($handle, LOCK_EX); flock($handle, LOCK_EX);
fwrite($handle, $message); fwrite($handle, $message);
fclose($handle); fclose($handle);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -45,92 +45,92 @@
*/ */
final class DibiResultIterator implements Iterator final class DibiResultIterator implements Iterator
{ {
/** @var DibiResult */ /** @var DibiResult */
private $result; private $result;
/** @var int */ /** @var int */
private $offset; private $offset;
/** @var int */ /** @var int */
private $limit; private $limit;
/** @var int */ /** @var int */
private $row; private $row;
/** @var int */ /** @var int */
private $pointer; private $pointer;
/** /**
* Required by the Iterator interface. * Required by the Iterator interface.
* @param int offset * @param int offset
* @param int limit * @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
*/ */
public function rewind() public function __construct(DibiResult $result, $offset, $limit)
{ {
$this->pointer = 0; $this->result = $result;
$this->result->seek($this->offset); $this->offset = (int) $offset;
$this->row = $this->result->fetch(); $this->limit = $limit === NULL ? -1 : (int) $limit;
} }
/** /**
* Returns the key of the current element. * Rewinds the Iterator to the first element.
* @return mixed * @return void
*/ */
public function key() public function rewind()
{ {
return $this->pointer; $this->pointer = 0;
} $this->result->seek($this->offset);
$this->row = $this->result->fetch();
}
/** /**
* Returns the current element. * Returns the key of the current element.
* @return mixed * @return mixed
*/ */
public function current() public function key()
{ {
return $this->row; return $this->pointer;
} }
/** /**
* Moves forward to next element. * Returns the current element.
* @return void * @return mixed
*/ */
public function next() public function current()
{ {
//$this->result->seek($this->offset + $this->pointer + 1); return $this->row;
$this->row = $this->result->fetch(); }
$this->pointer++;
}
/** /**
* Checks if there is a current element after calls to rewind() or next(). * Moves forward to next element.
* @return bool * @return void
*/ */
public function valid() public function next()
{ {
return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit); //$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);
}
} }

View File

@@ -28,264 +28,264 @@
*/ */
abstract class DibiTable extends /*Nette::*/Object abstract class DibiTable extends /*Nette::*/Object
{ {
/** @var string primary key mask */ /** @var string primary key mask */
public static $primaryMask = 'id'; public static $primaryMask = 'id';
/** @var bool */ /** @var bool */
public static $lowerCase = TRUE; public static $lowerCase = TRUE;
/** @var DibiConnection */ /** @var DibiConnection */
private $connection; private $connection;
/** @var array */ /** @var array */
private $options; private $options;
/** @var string table name */ /** @var string table name */
protected $name; protected $name;
/** @var string primary key name */ /** @var string primary key name */
protected $primary; protected $primary;
/** @var string primary key type */ /** @var string primary key type */
protected $primaryModifier = '%i'; protected $primaryModifier = '%i';
/** @var array */ /** @var array */
protected $blankRow = array(); protected $blankRow = array();
/** /**
* Table constructor. * Table constructor.
* @param array * @param array
* @return void * @return void
*/ */
public function __construct(array $options = array()) public function __construct(array $options = array())
{ {
$this->options = $options; $this->options = $options;
$this->setup(); $this->setup();
if ($this->connection === NULL) { if ($this->connection === NULL) {
$this->connection = dibi::getConnection(); $this->connection = dibi::getConnection();
} }
} }
/** /**
* Returns the table name. * Returns the table name.
* @return string * @return string
*/ */
public function getName() public function getName()
{ {
return $this->name; return $this->name;
} }
/** /**
* Returns the primary key name. * Returns the primary key name.
* @return string * @return string
*/ */
public function getPrimary() public function getPrimary()
{ {
return $this->primary; return $this->primary;
} }
/** /**
* Returns the dibi connection. * Returns the dibi connection.
* @return DibiConnection * @return DibiConnection
*/ */
public function getConnection() public function getConnection()
{ {
return $this->connection; return $this->connection;
} }
/** /**
* Setup object. * Setup object.
* @return void * @return void
*/ */
protected function setup() protected function setup()
{ {
// autodetect table name // autodetect table name
if ($this->name === NULL) { if ($this->name === NULL) {
$name = $this->getClass(); $name = $this->getClass();
if (FALSE !== ($pos = strrpos($name, ':'))) { if (FALSE !== ($pos = strrpos($name, ':'))) {
$name = substr($name, $pos + 1); $name = substr($name, $pos + 1);
} }
if (self::$lowerCase) { if (self::$lowerCase) {
$name = strtolower($name); $name = strtolower($name);
} }
$this->name = $name; $this->name = $name;
} }
// autodetect primary key name // autodetect primary key name
if ($this->primary === NULL) { if ($this->primary === NULL) {
$this->primary = str_replace( $this->primary = str_replace(
array('%p', '%s'), array('%p', '%s'),
array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-)) array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-))
self::$primaryMask self::$primaryMask
); );
} }
} }
/** /**
* Inserts row into a table. * Inserts row into a table.
* @param array|object * @param array|object
* @return int new primary key * @return int new primary key
*/ */
public function insert($data) public function insert($data)
{ {
$this->connection->query( $this->connection->query(
'INSERT INTO %n', $this->name, '%v', $this->prepare($data) 'INSERT INTO %n', $this->name, '%v', $this->prepare($data)
); );
return $this->connection->insertId(); return $this->connection->insertId();
} }
/** /**
* Updates rows in a table. * Updates rows in a table.
* @param mixed primary key value(s) * @param mixed primary key value(s)
* @param array|object * @param array|object
* @return int number of updated rows * @return int number of updated rows
*/ */
public function update($where, $data) public function update($where, $data)
{ {
$this->connection->query( $this->connection->query(
'UPDATE %n', $this->name, 'UPDATE %n', $this->name,
'SET %a', $this->prepare($data), 'SET %a', $this->prepare($data),
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
); );
return $this->connection->affectedRows(); return $this->connection->affectedRows();
} }
/** /**
* Deletes rows from a table by primary key. * Deletes rows from a table by primary key.
* @param mixed primary key value(s) * @param mixed primary key value(s)
* @return int number of deleted rows * @return int number of deleted rows
*/ */
public function delete($where) public function delete($where)
{ {
$this->connection->query( $this->connection->query(
'DELETE FROM %n', $this->name, 'DELETE FROM %n', $this->name,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')' 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
); );
return $this->connection->affectedRows(); return $this->connection->affectedRows();
} }
/** /**
* Finds rows by primary key. * Finds rows by primary key.
* @param mixed primary key value(s) * @param mixed primary key value(s)
* @return DibiResult * @return DibiResult
*/ */
public function find($what) public function find($what)
{ {
if (!is_array($what)) { if (!is_array($what)) {
$what = func_get_args(); $what = func_get_args();
} }
return $this->complete($this->connection->query( return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name, 'SELECT * FROM %n', $this->name,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')' 'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')'
)); ));
} }
/** /**
* Selects all rows. * Selects all rows.
* @param string column to order by * @param string column to order by
* @return DibiResult * @return DibiResult
*/ */
public function findAll($order = NULL) public function findAll($order = NULL)
{ {
if ($order === NULL) { if ($order === NULL) {
return $this->complete($this->connection->query( return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name 'SELECT * FROM %n', $this->name
)); ));
} else { } else {
$order = func_get_args(); $order = func_get_args();
return $this->complete($this->connection->query( return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name, 'SELECT * FROM %n', $this->name,
'ORDER BY %n', $order 'ORDER BY %n', $order
)); ));
} }
} }
/** /**
* Fetches single row. * Fetches single row.
* @param scalar|array primary key value * @param scalar|array primary key value
* @return array|object row * @return array|object row
*/ */
public function fetch($conditions) public function fetch($conditions)
{ {
if (is_array($conditions)) { if (is_array($conditions)) {
return $this->complete($this->connection->query( return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name, 'SELECT * FROM %n', $this->name,
'WHERE %and', $conditions 'WHERE %and', $conditions
))->fetch(); ))->fetch();
} }
return $this->complete($this->connection->query( return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name, 'SELECT * FROM %n', $this->name,
'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions 'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions
))->fetch(); ))->fetch();
} }
/** /**
* Returns a blank row (not fetched from database). * Returns a blank row (not fetched from database).
* @return array|object * @return array|object
*/ */
public function createBlank() public function createBlank()
{ {
$row = $this->blankRow; $row = $this->blankRow;
$row[$this->primary] = NULL; $row[$this->primary] = NULL;
if ($this->connection->getConfig('result:objects')) { if ($this->connection->getConfig('result:objects')) {
$row = (object) $row; $row = (object) $row;
} }
return $row; return $row;
} }
/** /**
* User data pre-processing. * User data pre-processing.
* @param array|object * @param array|object
* @return array * @return array
*/ */
protected function prepare($data) protected function prepare($data)
{ {
if (is_object($data)) { if (is_object($data)) {
return (array) $data; return (array) $data;
} elseif (is_array($data)) { } elseif (is_array($data)) {
return $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. * User DibiResult post-processing.
* @param DibiResult * @param DibiResult
* @return DibiResult * @return DibiResult
*/ */
protected function complete($res) protected function complete($res)
{ {
return $res; return $res;
} }
} }

View File

@@ -29,432 +29,432 @@
*/ */
final class DibiTranslator extends /*Nette::*/Object final class DibiTranslator extends /*Nette::*/Object
{ {
/** @var string */ /** @var string */
public $sql; public $sql;
/** @var IDibiDriver */ /** @var IDibiDriver */
private $driver; private $driver;
/** @var int */ /** @var int */
private $cursor; private $cursor;
/** @var array */ /** @var array */
private $args; private $args;
/** @var bool */ /** @var bool */
private $hasError; private $hasError;
/** @var bool */ /** @var bool */
private $comment; private $comment;
/** @var int */ /** @var int */
private $ifLevel; private $ifLevel;
/** @var int */ /** @var int */
private $ifLevelStart; private $ifLevelStart;
/** @var int */ /** @var int */
private $limit; private $limit;
/** @var int */ /** @var int */
private $offset; private $offset;
public function __construct(IDibiDriver $driver) public function __construct(IDibiDriver $driver)
{ {
$this->driver = $driver; $this->driver = $driver;
} }
/** /**
* return IDibiDriver. * return IDibiDriver.
*/ */
public function getDriver() public function getDriver()
{ {
return $this->driver; return $this->driver;
} }
/** /**
* Generates SQL. * Generates SQL.
* *
* @param array * @param array
* @return bool * @return bool
*/ */
public function translate(array $args) public function translate(array $args)
{ {
$this->limit = -1; $this->limit = -1;
$this->offset = 0; $this->offset = 0;
$this->hasError = FALSE; $this->hasError = FALSE;
$commandIns = NULL; $commandIns = NULL;
$lastArr = NULL; $lastArr = NULL;
// shortcuts // shortcuts
$cursor = & $this->cursor; $cursor = & $this->cursor;
$cursor = 0; $cursor = 0;
$this->args = array_values($args); $this->args = array_values($args);
$args = & $this->args; $args = & $this->args;
// conditional sql // conditional sql
$this->ifLevel = $this->ifLevelStart = 0; $this->ifLevel = $this->ifLevelStart = 0;
$comment = & $this->comment; $comment = & $this->comment;
$comment = FALSE; $comment = FALSE;
// iterate // iterate
$sql = array(); $sql = array();
while ($cursor < count($args)) while ($cursor < count($args))
{ {
$arg = $args[$cursor]; $arg = $args[$cursor];
$cursor++; $cursor++;
// simple string means SQL // simple string means SQL
if (is_string($arg)) { if (is_string($arg)) {
// speed-up - is regexp required? // speed-up - is regexp required?
$toSkip = strcspn($arg, '`[\'"%'); $toSkip = strcspn($arg, '`[\'"%');
if (strlen($arg) === $toSkip) { // needn't be translated if (strlen($arg) === $toSkip) { // needn't be translated
$sql[] = $arg; $sql[] = $arg;
} else { } else {
$sql[] = substr($arg, 0, $toSkip) $sql[] = substr($arg, 0, $toSkip)
/* /*
. preg_replace_callback('/ . preg_replace_callback('/
(?=`|\[|\'|"|%) ## speed-up (?=`|\[|\'|"|%) ## speed-up
(?: (?:
`(.+?)`| ## 1) `identifier` `(.+?)`| ## 1) `identifier`
\[(.+?)\]| ## 2) [identifier] \[(.+?)\]| ## 2) [identifier]
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string (\')((?:\'\'|[^\'])*)\'| ## 3,4) string
(")((?:""|[^"])*)"| ## 5,6) "string" (")((?:""|[^"])*)"| ## 5,6) "string"
(\'|") ## 7) lone-quote (\'|") ## 7) lone-quote
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier %([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
)/xs', )/xs',
*/ // note: this can change $this->args & $this->cursor & ... */ // note: this can change $this->args & $this->cursor & ...
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s', . preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
array($this, 'cb'), array($this, 'cb'),
substr($arg, $toSkip) substr($arg, $toSkip)
); );
} }
continue; continue;
} }
if ($comment) { if ($comment) {
$sql[] = '...'; $sql[] = '...';
continue; continue;
} }
if (is_array($arg)) { if (is_array($arg)) {
if (is_string(key($arg))) { if (is_string(key($arg))) {
// associative array -> autoselect between SET or VALUES & LIST // associative array -> autoselect between SET or VALUES & LIST
if ($commandIns === NULL) { if ($commandIns === NULL) {
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6)); $commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC'; $commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a'); $sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
} else { } else {
if ($lastArr === $cursor - 1) $sql[] = ','; if ($lastArr === $cursor - 1) $sql[] = ',';
$sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a'); $sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a');
} }
$lastArr = $cursor; $lastArr = $cursor;
continue; continue;
} elseif ($cursor === 1) { } elseif ($cursor === 1) {
// implicit array expansion // implicit array expansion
$cursor = 0; $cursor = 0;
array_splice($args, 0, 1, $arg); array_splice($args, 0, 1, $arg);
continue; continue;
} }
} }
// default processing // default processing
$sql[] = $this->formatValue($arg, FALSE); $sql[] = $this->formatValue($arg, FALSE);
} // while } // while
if ($comment) $sql[] = "*/"; if ($comment) $sql[] = "*/";
$sql = implode(' ', $sql); $sql = implode(' ', $sql);
// apply limit // apply limit
if ($this->limit > -1 || $this->offset > 0) { if ($this->limit > -1 || $this->offset > 0) {
$this->driver->applyLimit($sql, $this->limit, $this->offset); $this->driver->applyLimit($sql, $this->limit, $this->offset);
} }
$this->sql = $sql; $this->sql = $sql;
return !$this->hasError; return !$this->hasError;
} }
/** /**
* Apply modifier to single value. * Apply modifier to single value.
* @param mixed * @param mixed
* @param string * @param string
* @return string * @return string
*/ */
public function formatValue($value, $modifier) public function formatValue($value, $modifier)
{ {
// array processing (with or without modifier) // array processing (with or without modifier)
if (is_array($value)) { if (is_array($value)) {
$vx = $kx = array(); $vx = $kx = array();
$separator = ', '; $separator = ', ';
switch ($modifier) { switch ($modifier) {
case 'and': case 'and':
case 'or': case 'or':
$separator = ' ' . strtoupper($modifier) . ' '; $separator = ' ' . strtoupper($modifier) . ' ';
if (!is_string(key($value))) { if (!is_string(key($value))) {
foreach ($value as $v) { foreach ($value as $v) {
$vx[] = $this->formatValue($v, 'sql'); $vx[] = $this->formatValue($v, 'sql');
} }
return implode($separator, $vx); return implode($separator, $vx);
} }
// break intentionally omitted // break intentionally omitted
case 'a': // SET key=val, key=val, ... case 'a': // SET key=val, key=val, ...
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier $pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->delimite($pair[0]) . '=' $vx[] = $this->delimite($pair[0]) . '='
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); . $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
} }
return implode($separator, $vx); return implode($separator, $vx);
case 'l': // LIST val, val, ... case 'l': // LIST val, val, ...
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier $pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
} }
return '(' . implode(', ', $vx) . ')'; return '(' . implode(', ', $vx) . ')';
case 'v': // (key, key, ...) VALUES (val, val, ...) case 'v': // (key, key, ...) VALUES (val, val, ...)
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier $pair = explode('%', $k, 2); // split into identifier & modifier
$kx[] = $this->delimite($pair[0]); $kx[] = $this->delimite($pair[0]);
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE); $vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
} }
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')'; return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
default: default:
foreach ($value as $v) { foreach ($value as $v) {
$vx[] = $this->formatValue($v, $modifier); $vx[] = $this->formatValue($v, $modifier);
} }
return implode(', ', $vx); return implode(', ', $vx);
} }
} }
// with modifier procession // with modifier procession
if ($modifier) { if ($modifier) {
if ($value === NULL) { if ($value === NULL) {
return 'NULL'; return 'NULL';
} }
if ($value instanceof IDibiVariable) { if ($value instanceof IDibiVariable) {
return $value->toSql($this, $modifier); return $value->toSql($this, $modifier);
} }
if (!is_scalar($value)) { // array is already processed if (!is_scalar($value)) { // array is already processed
$this->hasError = TRUE; $this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**'; return '**Unexpected type ' . gettype($value) . '**';
} }
switch ($modifier) { switch ($modifier) {
case 's': // string case 's': // string
return $this->driver->format($value, dibi::FIELD_TEXT); return $this->driver->format($value, dibi::FIELD_TEXT);
case 'sn': // string or NULL case 'sn': // string or NULL
return $value == '' ? 'NULL' : $this->driver->format($value, dibi::FIELD_TEXT); // notice two equal signs return $value == '' ? 'NULL' : $this->driver->format($value, dibi::FIELD_TEXT); // notice two equal signs
case 'b': // boolean case 'b': // boolean
return $this->driver->format($value, dibi::FIELD_BOOL); return $this->driver->format($value, dibi::FIELD_BOOL);
case 'i': // signed int case 'i': // signed int
case 'u': // unsigned int, ignored case 'u': // unsigned int, ignored
// support for numbers - keep them unchanged // support for numbers - keep them unchanged
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) { if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
return $value; return $value;
} }
return (string) (int) ($value + 0); return (string) (int) ($value + 0);
case 'f': // float case 'f': // float
// support for numbers - keep them unchanged // support for numbers - keep them unchanged
if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) { 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 $value; // something like -9E-005 is accepted by SQL, HEX values is not
} }
return (string) ($value + 0); return (string) ($value + 0);
case 'd': // date case 'd': // date
return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATE); return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATE);
case 't': // datetime case 't': // datetime
return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATETIME); return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATETIME);
case 'n': // identifier name case 'n': // identifier name
return $this->delimite($value); return $this->delimite($value);
case 'sql':// preserve as SQL case 'sql':// preserve as SQL
$value = (string) $value; $value = (string) $value;
// speed-up - is regexp required? // speed-up - is regexp required?
$toSkip = strcspn($value, '`[\'"'); $toSkip = strcspn($value, '`[\'"');
if (strlen($value) === $toSkip) { // needn't be translated if (strlen($value) === $toSkip) { // needn't be translated
return $value; return $value;
} else { } else {
return substr($value, 0, $toSkip) return substr($value, 0, $toSkip)
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s', . preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
array($this, 'cb'), array($this, 'cb'),
substr($value, $toSkip) substr($value, $toSkip)
); );
} }
case 'a': case 'a':
case 'v': case 'v':
$this->hasError = TRUE; $this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**'; return '**Unexpected type ' . gettype($value) . '**';
default: default:
$this->hasError = TRUE; $this->hasError = TRUE;
return "**Unknown or invalid modifier %$modifier**"; return "**Unknown or invalid modifier %$modifier**";
} }
} }
// without modifier procession // without modifier procession
if (is_string($value)) if (is_string($value))
return $this->driver->format($value, dibi::FIELD_TEXT); return $this->driver->format($value, dibi::FIELD_TEXT);
if (is_int($value) || is_float($value)) if (is_int($value) || is_float($value))
return (string) $value; // something like -9E-005 is accepted by SQL return (string) $value; // something like -9E-005 is accepted by SQL
if (is_bool($value)) if (is_bool($value))
return $this->driver->format($value, dibi::FIELD_BOOL); return $this->driver->format($value, dibi::FIELD_BOOL);
if ($value === NULL) if ($value === NULL)
return 'NULL'; return 'NULL';
if ($value instanceof IDibiVariable) if ($value instanceof IDibiVariable)
return $value->toSql($this, NULL); return $value->toSql($this, NULL);
$this->hasError = TRUE; $this->hasError = TRUE;
return '**Unexpected ' . gettype($value) . '**'; return '**Unexpected ' . gettype($value) . '**';
} }
/** /**
* PREG callback from translate() or formatValue(). * PREG callback from translate() or formatValue().
* @param array * @param array
* @return string * @return string
*/ */
private function cb($matches) private function cb($matches)
{ {
// [1] => `ident` // [1] => `ident`
// [2] => [ident] // [2] => [ident]
// [3] => ' // [3] => '
// [4] => string // [4] => string
// [5] => " // [5] => "
// [6] => string // [6] => string
// [7] => lone-quote // [7] => lone-quote
// [8] => modifier (when called from self::translate()) // [8] => modifier (when called from self::translate())
if (!empty($matches[8])) { // modifier if (!empty($matches[8])) { // modifier
$mod = $matches[8]; $mod = $matches[8];
$cursor = & $this->cursor; $cursor = & $this->cursor;
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') { if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
$this->hasError = TRUE; $this->hasError = TRUE;
return "**Extra modifier %$mod**"; return "**Extra modifier %$mod**";
} }
if ($mod === 'if') { if ($mod === 'if') {
$this->ifLevel++; $this->ifLevel++;
$cursor++; $cursor++;
if (!$this->comment && !$this->args[$cursor - 1]) { if (!$this->comment && !$this->args[$cursor - 1]) {
// open comment // open comment
$this->ifLevelStart = $this->ifLevel; $this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE; $this->comment = TRUE;
return "/*"; return "/*";
} }
return ''; return '';
} elseif ($mod === 'else') { } elseif ($mod === 'else') {
if ($this->ifLevelStart === $this->ifLevel) { if ($this->ifLevelStart === $this->ifLevel) {
$this->ifLevelStart = 0; $this->ifLevelStart = 0;
$this->comment = FALSE; $this->comment = FALSE;
return "*/"; return "*/";
} elseif (!$this->comment) { } elseif (!$this->comment) {
$this->ifLevelStart = $this->ifLevel; $this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE; $this->comment = TRUE;
return "/*"; return "/*";
} }
} elseif ($mod === 'end') { } elseif ($mod === 'end') {
$this->ifLevel--; $this->ifLevel--;
if ($this->ifLevelStart === $this->ifLevel + 1) { if ($this->ifLevelStart === $this->ifLevel + 1) {
// close comment // close comment
$this->ifLevelStart = 0; $this->ifLevelStart = 0;
$this->comment = FALSE; $this->comment = FALSE;
return "*/"; return "*/";
} }
return ''; return '';
} elseif ($mod === 'ex') { // array expansion } elseif ($mod === 'ex') { // array expansion
array_splice($this->args, $cursor, 1, $this->args[$cursor]); array_splice($this->args, $cursor, 1, $this->args[$cursor]);
return ''; return '';
} elseif ($mod === 'lmt') { // apply limit } elseif ($mod === 'lmt') { // apply limit
if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor]; if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor];
$cursor++; $cursor++;
return ''; return '';
} elseif ($mod === 'ofs') { // apply offset } elseif ($mod === 'ofs') { // apply offset
if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor]; if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor];
$cursor++; $cursor++;
return ''; return '';
} else { // default processing } else { // default processing
$cursor++; $cursor++;
return $this->formatValue($this->args[$cursor - 1], $mod); return $this->formatValue($this->args[$cursor - 1], $mod);
} }
} }
if ($this->comment) return '...'; if ($this->comment) return '...';
if ($matches[1]) // SQL identifiers: `ident` if ($matches[1]) // SQL identifiers: `ident`
return $this->delimite($matches[1]); return $this->delimite($matches[1]);
if ($matches[2]) // SQL identifiers: [ident] if ($matches[2]) // SQL identifiers: [ident]
return $this->delimite($matches[2]); return $this->delimite($matches[2]);
if ($matches[3]) // SQL strings: '...' if ($matches[3]) // SQL strings: '...'
return $this->driver->format( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT); return $this->driver->format( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
if ($matches[5]) // SQL strings: "..." if ($matches[5]) // SQL strings: "..."
return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT); return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
if ($matches[7]) { // string quote if ($matches[7]) { // string quote
$this->hasError = TRUE; $this->hasError = TRUE;
return '**Alone quote**'; return '**Alone quote**';
} }
die('this should be never executed'); die('this should be never executed');
} }
/** /**
* Apply substitutions to indentifier and delimites it. * Apply substitutions to indentifier and delimites it.
* *
* @param string indentifier * @param string indentifier
* @return string * @return string
*/ */
private function delimite($value) private function delimite($value)
{ {
if (strpos($value, ':') !== FALSE) { if (strpos($value, ':') !== FALSE) {
$value = strtr($value, dibi::getSubst()); $value = strtr($value, dibi::getSubst());
} }
return $this->driver->format($value, dibi::IDENTIFIER); return $this->driver->format($value, dibi::IDENTIFIER);
} }
} // class DibiTranslator } // class DibiTranslator

View File

@@ -25,24 +25,24 @@
*/ */
class DibiVariable extends /*Nette::*/Object implements IDibiVariable class DibiVariable extends /*Nette::*/Object implements IDibiVariable
{ {
/** @var mixed */ /** @var mixed */
public $value; public $value;
/** @var string */ /** @var string */
public $modifier; public $modifier;
public function __construct($value, $modifier) public function __construct($value, $modifier)
{ {
$this->value = $value; $this->value = $value;
$this->modifier = $modifier; $this->modifier = $modifier;
} }
public function toSql(DibiTranslator $translator, $modifier) public function toSql(DibiTranslator $translator, $modifier)
{ {
return $translator->formatValue($this->value, $this->modifier); return $translator->formatValue($this->value, $this->modifier);
} }
} }

View File

@@ -25,14 +25,14 @@
*/ */
interface IDibiVariable interface IDibiVariable
{ {
/** /**
* Format for SQL. * Format for SQL.
* *
* @param object DibiTranslator * @param object DibiTranslator
* @param string optional modifier * @param string optional modifier
* @return string SQL code * @return string SQL code
*/ */
public function toSql(DibiTranslator $translator, $modifier); public function toSql(DibiTranslator $translator, $modifier);
} }
@@ -45,8 +45,8 @@ interface IDibiVariable
*/ */
interface IDataSource extends Countable, IteratorAggregate interface IDataSource extends Countable, IteratorAggregate
{ {
//function IteratorAggregate::getIterator(); //function IteratorAggregate::getIterator();
//function Countable::count(); //function Countable::count();
} }
@@ -64,179 +64,179 @@ interface IDataSource extends Countable, IteratorAggregate
interface IDibiDriver interface IDibiDriver
{ {
/** /**
* Internal: Connects to a database. * Internal: Connects to a database.
* *
* @param array * @param array
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
function connect(array &$config); function connect(array &$config);
/** /**
* Internal: Disconnects from a database. * Internal: Disconnects from a database.
* *
* @return void * @return void
* @throws DibiException * @throws DibiException
*/ */
function disconnect(); function disconnect();
/** /**
* Internal: Executes the SQL query. * Internal: Executes the SQL query.
* *
* @param string SQL statement. * @param string SQL statement.
* @return bool have resultset? * @return bool have resultset?
* @throws DibiDriverException * @throws DibiDriverException
*/ */
function query($sql); function query($sql);
/** /**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query. * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* *
* @return int|FALSE number of rows or FALSE on error * @return int|FALSE number of rows or FALSE on error
*/ */
function affectedRows(); function affectedRows();
/** /**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* *
* @return int|FALSE int on success or FALSE on failure * @return int|FALSE int on success or FALSE on failure
*/ */
function insertId($sequence); function insertId($sequence);
/** /**
* Begins a transaction (if supported). * Begins a transaction (if supported).
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
function begin(); function begin();
/** /**
* Commits statements in a transaction. * Commits statements in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
function commit(); function commit();
/** /**
* Rollback changes in a transaction. * Rollback changes in a transaction.
* @return void * @return void
* @throws DibiDriverException * @throws DibiDriverException
*/ */
function rollback(); function rollback();
/** /**
* Format to SQL command. * Format to SQL command.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value * @return string formatted value
*/ */
function format($value, $type); function format($value, $type);
/** /**
* Injects LIMIT/OFFSET to the SQL query. * Injects LIMIT/OFFSET to the SQL query.
* *
* @param string &$sql The SQL query that will be modified. * @param string &$sql The SQL query that will be modified.
* @param int $limit * @param int $limit
* @param int $offset * @param int $offset
* @return void * @return void
*/ */
function applyLimit(&$sql, $limit, $offset); function applyLimit(&$sql, $limit, $offset);
/** /**
* Returns the number of rows in a result set. * Returns the number of rows in a result set.
* *
* @return int * @return int
*/ */
function rowCount(); function rowCount();
/** /**
* Moves cursor position without fetching row. * Moves cursor position without fetching row.
* *
* @param int the 0-based cursor pos to seek to * @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record * @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException * @throws DibiException
*/ */
function seek($row); function seek($row);
/** /**
* Fetches the row at current position and moves the internal cursor to the next position. * Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only * internal usage only
* *
* @param bool TRUE for associative array, FALSE for numeric * @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record * @return array array on success, nonarray if no next record
*/ */
function fetch($type); function fetch($type);
/** /**
* Frees the resources allocated for this result set. * Frees the resources allocated for this result set.
* *
* @param resource resultset resource * @param resource resultset resource
* @return void * @return void
*/ */
function free(); function free();
/** /**
* Returns metadata for all columns in a result set. * Returns metadata for all columns in a result set.
* *
* @return array * @return array
* @throws DibiException * @throws DibiException
*/ */
function getColumnsMeta(); function getColumnsMeta();
/** /**
* Returns the connection resource. * Returns the connection resource.
* *
* @return mixed * @return mixed
*/ */
function getResource(); function getResource();
/** /**
* Returns the resultset resource. * Returns the resultset resource.
* *
* @return mixed * @return mixed
*/ */
function getResultResource(); function getResultResource();
/** /**
* Gets a information of the current database. * Gets a information of the current database.
* *
* @return DibiReflection * @return DibiReflection
*/ */
function getDibiReflection(); function getDibiReflection();
} }

View File

@@ -6,15 +6,15 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
// no limit // no limit
$res = dibi::query('SELECT * FROM [products]'); $res = dibi::query('SELECT * FROM [products]');
foreach ($res as $n => $row) { foreach ($res as $n => $row) {
print_r($row); print_r($row);
} }
echo '<hr>'; echo '<hr>';
@@ -22,7 +22,7 @@ echo '<hr>';
// with limit = 2 // with limit = 2
$res = dibi::query('SELECT * FROM [products] %lmt', 2); $res = dibi::query('SELECT * FROM [products] %lmt', 2);
foreach ($res as $n => $row) { foreach ($res as $n => $row) {
print_r($row); print_r($row);
} }
echo '<hr>'; echo '<hr>';
@@ -30,5 +30,5 @@ echo '<hr>';
// with limit = 2, offset = 1 // with limit = 2, offset = 1
$res = dibi::query('SELECT * FROM [products] %lmt %ofs', 2, 1); $res = dibi::query('SELECT * FROM [products] %lmt %ofs', 2, 1);
foreach ($res as $n => $row) { foreach ($res as $n => $row) {
print_r($row); print_r($row);
} }

View File

@@ -7,15 +7,15 @@ require_once '../dibi/dibi.php';
// connects to SQlite // connects to SQlite
echo '<p>Connecting to Sqlite: '; echo '<p>Connecting to Sqlite: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
'result:objects' => TRUE, // fetch rows as objects 'result:objects' => TRUE, // fetch rows as objects
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -25,11 +25,11 @@ echo "</p>\n";
// connects to MySQL using DSN // connects to MySQL using DSN
echo '<p>Connecting to MySQL: '; echo '<p>Connecting to MySQL: ';
try { try {
dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=utf8'); dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=utf8');
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -39,18 +39,18 @@ echo "</p>\n";
// connects to MySQLi using array // connects to MySQLi using array
echo '<p>Connecting to MySQL: '; echo '<p>Connecting to MySQL: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'mysqli', 'driver' => 'mysqli',
'host' => 'localhost', 'host' => 'localhost',
'username' => 'root', 'username' => 'root',
'password' => 'xxx', 'password' => 'xxx',
'database' => 'dibi', 'database' => 'dibi',
'charset' => 'utf8', 'charset' => 'utf8',
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -60,16 +60,16 @@ echo "</p>\n";
// connects to ODBC // connects to ODBC
echo '<p>Connecting to ODBC: '; echo '<p>Connecting to ODBC: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'odbc', 'driver' => 'odbc',
'username' => 'root', 'username' => 'root',
'password' => '***', 'password' => '***',
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/sample.mdb', 'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/sample.mdb',
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -79,15 +79,15 @@ echo "</p>\n";
// connects to PostgreSql // connects to PostgreSql
echo '<p>Connecting to PostgreSql: '; echo '<p>Connecting to PostgreSql: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'postgre', 'driver' => 'postgre',
'string' => 'host=localhost port=5432 dbname=mary', 'string' => 'host=localhost port=5432 dbname=mary',
'persistent' => TRUE, 'persistent' => TRUE,
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -97,14 +97,14 @@ echo "</p>\n";
// connects to PDO // connects to PDO
echo '<p>Connecting to Sqlite via PDO: '; echo '<p>Connecting to Sqlite via PDO: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'pdo', 'driver' => 'pdo',
'dsn' => 'sqlite2::memory:', 'dsn' => 'sqlite2::memory:',
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -113,16 +113,16 @@ echo "</p>\n";
// connects to MS SQL // connects to MS SQL
echo '<p>Connecting to MS SQL: '; echo '<p>Connecting to MS SQL: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'mssql', 'driver' => 'mssql',
'host' => 'localhost', 'host' => 'localhost',
'username' => 'root', 'username' => 'root',
'password' => 'xxx', 'password' => 'xxx',
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";
@@ -131,15 +131,15 @@ echo "</p>\n";
// connects to Oracle // connects to Oracle
echo '<p>Connecting to Oracle: '; echo '<p>Connecting to Oracle: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'oracle', 'driver' => 'oracle',
'username' => 'root', 'username' => 'root',
'password' => 'xxx', 'password' => 'xxx',
'database' => 'db', 'database' => 'db',
)); ));
echo 'OK'; echo 'OK';
} catch (DibiException $e) { } catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n"; echo get_class($e), ': ', $e->getMessage(), "\n";
} }
echo "</p>\n"; echo "</p>\n";

View File

@@ -11,10 +11,10 @@ date_default_timezone_set('Europe/Prague');
// CHANGE TO REAL PARAMETERS! // CHANGE TO REAL PARAMETERS!
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
'format:date' => "'Y-m-d'", 'format:date' => "'Y-m-d'",
'format:datetime' => "'Y-m-d H-i-s'", 'format:datetime' => "'Y-m-d H-i-s'",
)); ));
@@ -22,7 +22,7 @@ dibi::connect(array(
// generate and dump SQL // generate and dump SQL
dibi::test(" dibi::test("
INSERT INTO [mytable]", array( INSERT INTO [mytable]", array(
'id' => 123, 'id' => 123,
'date' => dibi::date('12.3.2007'), 'date' => dibi::date('12.3.2007'),
'stamp' => dibi::dateTime('23.1.2007 10:23'), 'stamp' => dibi::dateTime('23.1.2007 10:23'),
)); ));

View File

@@ -6,8 +6,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
dibi::begin(); dibi::begin();
@@ -39,7 +39,7 @@ echo "Primary key: $products->primary\n";
// Finds rows by primary key // Finds rows by primary key
foreach ($products->find(1, 3) as $row) { foreach ($products->find(1, 3) as $row) {
print_r($row); print_r($row);
} }

View File

@@ -5,8 +5,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));

View File

@@ -6,8 +6,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
@@ -15,9 +15,9 @@ dibi::connect(array(
// using the "prototype" to add custom method to class DibiResult // using the "prototype" to add custom method to class DibiResult
function DibiResult_prototype_fetchShuffle(DibiResult $obj) function DibiResult_prototype_fetchShuffle(DibiResult $obj)
{ {
$all = $obj->fetchAll(); $all = $obj->fetchAll();
shuffle($all); shuffle($all);
return $all; return $all;
} }

View File

@@ -6,8 +6,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
@@ -16,9 +16,9 @@ TABLE products
product_id | title product_id | title
-----------+---------- -----------+----------
1 | Chair 1 | Chair
2 | Table 2 | Table
3 | Computer 3 | Computer
*/ */
@@ -56,19 +56,19 @@ echo '<hr>';
// fetch row by row // fetch row by row
foreach ($res as $n => $row) { foreach ($res as $n => $row) {
print_r($row); print_r($row);
} }
echo '<hr>'; echo '<hr>';
// fetch row by row with defined offset // fetch row by row with defined offset
foreach ($res->getIterator(2) as $n => $row) { foreach ($res->getIterator(2) as $n => $row) {
print_r($row); print_r($row);
} }
// fetch row by row with defined offset and limit // fetch row by row with defined offset and limit
foreach ($res->getIterator(2, 1) as $n => $row) { foreach ($res->getIterator(2, 1) as $n => $row) {
print_r($row); print_r($row);
} }

View File

@@ -6,8 +6,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));

View File

@@ -9,21 +9,21 @@ dibi::startLogger('log.sql', TRUE);
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
try { 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) { } catch (DibiException $e) {
echo '<p>', get_class($e), ': ', $e->getMessage(), '</p>'; echo '<p>', get_class($e), ': ', $e->getMessage(), '</p>';
} }

View File

@@ -6,8 +6,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));

View File

@@ -9,8 +9,8 @@ Debug::enable();
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));

View File

@@ -5,13 +5,13 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
for ($i=0; $i<20; $i++) { 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);
} }
?> ?>

View File

@@ -12,26 +12,26 @@ date_default_timezone_set('Europe/Prague');
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
// dibi detects INSERT or REPLACE command // dibi detects INSERT or REPLACE command
dibi::test(' dibi::test('
REPLACE INTO [products]', array( REPLACE INTO [products]', array(
'title' => 'Drti<74>ka na tr<74>vu', 'title' => 'Drti<74>ka na tr<74>vu',
'price' => 318, 'price' => 318,
'active' => TRUE, 'active' => TRUE,
)); ));
// multiple INSERT command // multiple INSERT command
$array = array( $array = array(
'title' => 'Super Product', 'title' => 'Super Product',
'price' => 12, 'price' => 12,
'brand' => NULL, 'brand' => NULL,
'created' => dibi::datetime(), 'created' => dibi::datetime(),
); );
dibi::test("INSERT INTO [products]", $array, $array, $array); 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 detects UPDATE command
dibi::test(" dibi::test("
UPDATE [colors] SET", array( UPDATE [colors] SET", array(
'color' => 'blue', 'color' => 'blue',
'order' => 12, 'order' => 12,
), " ), "
WHERE [id]=%i", 123); WHERE [id]=%i", 123);

View File

@@ -9,8 +9,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
@@ -35,8 +35,8 @@ dibi::test("
SELECT * SELECT *
FROM [people] FROM [people]
WHERE [id] > 0 WHERE [id] > 0
%if", ($foo > 0), "AND [foo]=%i", $foo, " %if", ($foo > 0), "AND [foo]=%i", $foo, "
%else %if", ($bar > 0), "AND [bar]=%i", $bar, " %else %if", ($bar > 0), "AND [bar]=%i", $bar, "
"); ");
@@ -45,7 +45,7 @@ dibi::test('
SELECT * SELECT *
FROM [customers] FROM [customers]
WHERE WHERE
%if', isset($name), '[name] LIKE %s', $name, ' %if', isset($name), '[name] LIKE %s', $name, '
%if', $cond2, 'AND [admin]=1 %end %if', $cond2, 'AND [admin]=1 %end
%else 1 LIMIT 10 %end' %else 1 LIMIT 10 %end'
); );

View File

@@ -5,8 +5,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));

View File

@@ -6,8 +6,8 @@ require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
@@ -18,7 +18,7 @@ dibi::query('SELECT * FROM [products]')->dump();
dibi::begin(); dibi::begin();
dibi::query('INSERT INTO [products]', array( dibi::query('INSERT INTO [products]', array(
'title' => 'Test product', 'title' => 'Test product',
)); ));
dibi::rollback(); // or dibi::commit(); dibi::rollback(); // or dibi::commit();