1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-05 21:58:10 +02:00

modified SVN properties

This commit is contained in:
David Grudl
2008-07-17 03:51:29 +00:00
parent 7f0fa2e75e
commit c0bd3761de
45 changed files with 8225 additions and 8227 deletions

View File

@@ -1 +1 @@
- event, log, profiler - event, log, profiler

View File

@@ -1,41 +1,40 @@
<?php <?php
/** /**
* Nette Framework * Nette Framework
* *
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "Nette license" that is bundled * This source file is subject to the "Nette license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://nettephp.com/ * For more information please see http://nettephp.com
* *
* @copyright Copyright (c) 2004, 2008 David Grudl * @copyright Copyright (c) 2004, 2008 David Grudl
* @license http://nettephp.com/license Nette license * @license http://nettephp.com/license Nette license
* @link http://nettephp.com/ * @link http://nettephp.com
* @category Nette * @category Nette
* @package Nette * @package Nette
*/ */
/*namespace Nette;*/ /*namespace Nette;*/
/** /**
* Custom output for Nette::Debug. * Custom output for Nette::Debug.
* *
* @author David Grudl * @author David Grudl
* @copyright Copyright (c) 2004, 2008 David Grudl * @copyright Copyright (c) 2004, 2008 David Grudl
* @package Nette * @package Nette
* @version $Revision$ $Date$ */
*/ interface IDebuggable
interface IDebuggable {
{
/**
/** * Returns custom panels.
* Returns custom panels. * @return array
* @return array */
*/ function getPanels();
function getPanels();
}
}

View File

@@ -1,278 +1,277 @@
<?php <?php
/** /**
* Nette Framework * Nette Framework
* *
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "Nette license" that is bundled * This source file is subject to the "Nette license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://nettephp.com/ * For more information please see http://nettephp.com
* *
* @copyright Copyright (c) 2004, 2008 David Grudl * @copyright Copyright (c) 2004, 2008 David Grudl
* @license http://nettephp.com/license Nette license * @license http://nettephp.com/license Nette license
* @link http://nettephp.com/ * @link http://nettephp.com
* @category Nette * @category Nette
* @package Nette * @package Nette
*/ */
/*namespace Nette;*/ /*namespace Nette;*/
/** /**
* Nette::Object is the ultimate ancestor of all instantiable classes. * Nette::Object is the ultimate ancestor of all instantiable classes.
* *
* It defines some handful methods and enhances object core of PHP: * It defines some handful methods and enhances object core of PHP:
* - access to undeclared members throws exceptions * - access to undeclared members throws exceptions
* - support for conventional properties with getters and setters * - support for conventional properties with getters and setters
* - support for event raising functionality * - support for event raising functionality
* - ability to add new methods to class (extension methods) * - ability to add new methods to class (extension methods)
* *
* Properties is a syntactic sugar which allows access public getter and setter * Properties is a syntactic sugar which allows access public getter and setter
* methods as normal object variables. A property is defined by a getter method * methods as normal object variables. A property is defined by a getter method
* and optional setter method (no setter method means read-only property). * and optional setter method (no setter method means read-only property).
* <code> * <code>
* $val = $obj->label; // equivalent to $val = $obj->getLabel(); * $val = $obj->label; // equivalent to $val = $obj->getLabel();
* $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette'); * $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette');
* </code> * </code>
* Property names are case-sensitive, and they are written in the camelCaps * Property names are case-sensitive, and they are written in the camelCaps
* or PascalCaps. * or PascalCaps.
* *
* Event functionality is provided by declaration of property named 'on{Something}' * Event functionality is provided by declaration of property named 'on{Something}'
* Multiple handlers are allowed. * Multiple handlers are allowed.
* <code> * <code>
* public $onClick; // declaration in class * public $onClick; // declaration in class
* $this->onClick[] = 'callback'; // attaching event handler * $this->onClick[] = 'callback'; // attaching event handler
* if (!empty($this->onClick)) ... // are there any handlers? * if (!empty($this->onClick)) ... // are there any handlers?
* $this->onClick($sender, $arg); // raises the event with arguments * $this->onClick($sender, $arg); // raises the event with arguments
* </code> * </code>
* *
* Adding method to class (i.e. to all instances) works similar to JavaScript * Adding method to class (i.e. to all instances) works similar to JavaScript
* prototype property. The syntax for adding a new method is: * prototype property. The syntax for adding a new method is:
* <code> * <code>
* function MyClass_prototype_newMethod(MyClass $obj, $arg, ...) { ... } * function MyClass_prototype_newMethod(MyClass $obj, $arg, ...) { ... }
* $obj = new MyClass; * $obj = new MyClass;
* $obj->newMethod($x); // equivalent to MyClass_prototype_newMethod($obj, $x); * $obj->newMethod($x); // equivalent to MyClass_prototype_newMethod($obj, $x);
* </code> * </code>
* *
* @author David Grudl * @author David Grudl
* @copyright Copyright (c) 2004, 2008 David Grudl * @copyright Copyright (c) 2004, 2008 David Grudl
* @package Nette * @package Nette
* @version $Revision$ $Date$ */
*/ 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) {
{ $class = get_class($this);
$class = get_class($this);
if ($name === '') {
if ($name === '') { throw new /*::*/MemberAccessException("Call to class '$class' method without name.");
throw new /*::*/MemberAccessException("Call to class '$class' method without name."); }
}
// 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) {
{ $class = get_class($this);
$class = get_class($this);
if ($name === '') {
if ($name === '') { throw new /*::*/MemberAccessException("Cannot read an class '$class' property without name.");
throw new /*::*/MemberAccessException("Cannot read an class '$class' property without name."); }
}
// property getter support
// property getter support $m = 'get' . $name;
$m = 'get' . $name; if (self::hasAccessor($class, $m)) {
if (self::hasAccessor($class, $m)) { // ampersands:
// ampersands: // - uses &__get() because declaration should be forward compatible (e.g. with Nette::Web::Html)
// - uses &__get() because declaration should be forward compatible (e.g. with Nette::Web::Html) // - doesn't call &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
// - doesn't call &$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) {
{ $class = get_class($this);
$class = get_class($this);
if ($name === '') {
if ($name === '') { throw new /*::*/MemberAccessException("Cannot assign to an class '$class' property without name.");
throw new /*::*/MemberAccessException("Cannot assign to an class '$class' property without name."); }
}
// property setter support
// property setter support 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

@@ -1,364 +1,364 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for MS SQL database. /**
* * The dibi driver for MS SQL database.
* Connection options: *
* - 'host' - the MS SQL server host name. It can also include a port number (hostname:port) * Connection options:
* - 'username' (or 'user') * - 'host' - the MS SQL server host name. It can also include a port number (hostname:port)
* - 'password' (or 'pass') * - 'username' (or 'user')
* - 'persistent' - try to find a persistent link? * - 'password' (or 'pass')
* - 'database' - the database name to select * - 'persistent' - try to find a persistent link?
* - 'lazy' - if TRUE, connection will be established only when required * - 'database' - the database name to select
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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', 'hostname'); DibiConnection::alias($config, 'host', 'hostname');
if (empty($config['persistent'])) { if (empty($config['persistent'])) {
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @ $this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @
} else { } else {
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @ $this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @
} }
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)) { // intentionally @ if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) { // intentionally @
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultSet = @mssql_query($sql, $this->connection); // intentionally @ $this->resultSet = @mssql_query($sql, $this->connection); // intentionally @
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) ? clone $this : NULL; return is_resource($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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');
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return "'" . str_replace("'", "''", $value) . "'"; return "'" . str_replace("'", "''", $value) . "'";
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
return '[' . str_replace('.', '].[', $value) . ']'; return '[' . str_replace('.', '].[', $value) . ']';
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? -1 : 0; return $value ? -1 : 0;
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("'Y-m-d'", $value); return date("'Y-m-d'", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("'Y-m-d H:i:s'", $value); return date("'Y-m-d H:i:s'", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,432 +1,432 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for MySQL database. /**
* * The dibi driver for MySQL database.
* Connection options: *
* - 'host' - the MySQL server host name * Connection options:
* - 'port' - the port number to attempt to connect to the MySQL server * - 'host' - the MySQL server host name
* - 'socket' - the socket or named pipe * - 'port' - the port number to attempt to connect to the MySQL server
* - 'username' (or 'user') * - 'socket' - the socket or named pipe
* - 'password' (or 'pass') * - 'username' (or 'user')
* - 'persistent' - try to find a persistent link? * - 'password' (or 'pass')
* - 'database' - the database name to select * - 'persistent' - try to find a persistent link?
* - 'charset' - character encoding to set * - 'database' - the database name to select
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically? * - 'charset' - character encoding to set
* - 'options' - driver specific constants (MYSQL_*) * - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
* - 'sqlmode' - see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html * - 'options' - driver specific constants (MYSQL_*)
* - 'lazy' - if TRUE, connection will be established only when required * - 'sqlmode' - see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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, 'host', 'hostname'); DibiConnection::alias($config, 'host', 'hostname');
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']); // intentionally @ $this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); // intentionally @
} else { } else {
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); // intentionally @ $this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); // intentionally @
} }
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); // intentionally @ $ok = @mysql_set_charset($config['charset'], $this->connection); // intentionally @
} }
if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); // intentionally @ if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); // intentionally @
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(); // intentionally @ @mysql_select_db($config['database'], $this->connection) or $this->throwException(); // intentionally @
} }
if (isset($config['sqlmode'])) { if (isset($config['sqlmode'])) {
if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); // intentionally @ if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); // intentionally @
} }
$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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @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); // intentionally @ $this->resultSet = @mysql_query($sql, $this->connection); // intentionally @
} else { } else {
$this->resultSet = @mysql_unbuffered_query($sql, $this->connection); // intentionally @ $this->resultSet = @mysql_unbuffered_query($sql, $this->connection); // intentionally @
} }
if (mysql_errno($this->connection)) { if (mysql_errno($this->connection)) {
$this->throwException($sql); $this->throwException($sql);
} }
return is_resource($this->resultSet) ? clone $this : NULL; return is_resource($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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');
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return "'" . mysql_real_escape_string($value, $this->connection) . "'"; return "'" . mysql_real_escape_string($value, $this->connection) . "'";
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
return '`' . str_replace('.', '`.`', $value) . '`'; return '`' . str_replace('.', '`.`', $value) . '`';
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("'Y-m-d'", $value); return date("'Y-m-d'", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("'Y-m-d H:i:s'", $value); return date("'Y-m-d H:i:s'", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,411 +1,411 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for MySQL database via improved extension. /**
* * The dibi driver for MySQL database via improved extension.
* Connection options: *
* - 'host' - the MySQL server host name * Connection options:
* - 'port' - the port number to attempt to connect to the MySQL server * - 'host' - the MySQL server host name
* - 'socket' - the socket or named pipe * - 'port' - the port number to attempt to connect to the MySQL server
* - 'username' (or 'user') * - 'socket' - the socket or named pipe
* - 'password' (or 'pass') * - 'username' (or 'user')
* - 'persistent' - try to find a persistent link? * - 'password' (or 'pass')
* - 'database' - the database name to select * - 'persistent' - try to find a persistent link?
* - 'charset' - character encoding to set * - 'database' - the database name to select
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically? * - 'charset' - character encoding to set
* - 'options' - driver specific constants (MYSQLI_*) * - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
* - 'sqlmode' - see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html * - 'options' - driver specific constants (MYSQLI_*)
* - 'lazy' - if TRUE, connection will be established only when required * - 'sqlmode' - see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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, 'host', 'hostname'); DibiConnection::alias($config, 'host', 'hostname');
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']); // intentionally @ @mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); // intentionally @
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']); // intentionally @ $ok = @mysqli_set_charset($this->connection, $config['charset']); // intentionally @
} }
if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); // intentionally @ if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); // intentionally @
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(); // intentionally @ if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException(); // intentionally @
} }
$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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @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); // intentionally @ $this->resultSet = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); // intentionally @
if (mysqli_errno($this->connection)) { if (mysqli_errno($this->connection)) {
$this->throwException($sql); $this->throwException($sql);
} }
return is_object($this->resultSet) ? clone $this : NULL; return is_object($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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');
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return "'" . mysqli_real_escape_string($this->connection, $value) . "'"; return "'" . mysqli_real_escape_string($this->connection, $value) . "'";
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
return '`' . str_replace('.', '`.`', $value) . '`'; return '`' . str_replace('.', '`.`', $value) . '`';
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("'Y-m-d'", $value); return date("'Y-m-d'", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("'Y-m-d H:i:s'", $value); return date("'Y-m-d H:i:s'", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,404 +1,404 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver interacting with databases via ODBC connections. /**
* * The dibi driver interacting with databases via ODBC connections.
* Connection options: *
* - 'dsn' - driver specific DSN * Connection options:
* - 'username' (or 'user') * - 'dsn' - driver specific DSN
* - 'password' (or 'pass') * - 'username' (or 'user')
* - 'persistent' - try to find a persistent link? * - 'password' (or 'pass')
* - 'lazy' - if TRUE, connection will be established only when required * - 'persistent' - try to find a persistent link?
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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']); // intentionally @ $this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']); // intentionally @
} else { } else {
$this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); // intentionally @ $this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); // intentionally @
} }
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultSet = @odbc_exec($this->connection, $sql); // intentionally @ $this->resultSet = @odbc_exec($this->connection, $sql); // intentionally @
if ($this->resultSet === FALSE) { if ($this->resultSet === FALSE) {
$this->throwException($sql); $this->throwException($sql);
} }
return is_resource($this->resultSet) ? clone $this : NULL; return is_resource($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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);
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return "'" . str_replace("'", "''", $value) . "'"; return "'" . str_replace("'", "''", $value) . "'";
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
return '[' . str_replace('.', '].[', $value) . ']'; return '[' . str_replace('.', '].[', $value) . ']';
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? -1 : 0; return $value ? -1 : 0;
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("#m/d/Y#", $value); return date("#m/d/Y#", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("#m/d/Y H:i:s#", $value); return date("#m/d/Y H:i:s#", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,387 +1,387 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for Oracle database. /**
* * The dibi driver for Oracle database.
* Connection options: *
* - 'database' (or 'db') - the name of the local Oracle instance or the name of the entry in tnsnames.ora * Connection options:
* - 'username' (or 'user') * - 'database' (or 'db') - the name of the local Oracle instance or the name of the entry in tnsnames.ora
* - 'password' (or 'pass') * - 'username' (or 'user')
* - 'charset' - character encoding to set * - 'password' (or 'pass')
* - 'lazy' - if TRUE, connection will be established only when required * - 'charset' - character encoding to set
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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']); // intentionally @ $this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @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) ? clone $this : NULL; return is_resource($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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;
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("U", $value); return date("U", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("U", $value); return date("U", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,427 +1,427 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for PDO. /**
* * The dibi driver for PDO.
* Connection options: *
* - 'dsn' - driver specific DSN * Connection options:
* - 'username' (or 'user') * - 'dsn' - driver specific DSN
* - 'password' (or 'pass') * - 'username' (or 'user')
* - 'options' - driver specific options array * - 'password' (or 'pass')
* - 'pdo' - PDO object (optional) * - 'options' - driver specific options array
* - 'lazy' - if TRUE, connection will be established only when required * - 'pdo' - PDO object (optional)
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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|FALSE * @var int|FALSE
*/ */
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
// must detect if SQL returns result set or num of affected rows // must detect if SQL returns result set 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 NULL; return NULL;
} 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 clone $this; return clone $this;
} }
} }
/** /**
* 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();
} }
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
return $this->connection->quote($value, PDO::PARAM_STR); return $this->connection->quote($value, PDO::PARAM_STR);
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return $this->connection->quote($value, PDO::PARAM_LOB); return $this->connection->quote($value, PDO::PARAM_LOB);
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
switch ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)) { switch ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)) {
case 'mysql': case 'mysql':
return '`' . str_replace('.', '`.`', $value) . '`'; return '`' . str_replace('.', '`.`', $value) . '`';
case 'pgsql': case 'pgsql':
$a = strrpos($value, '.'); $a = strrpos($value, '.');
if ($a === FALSE) { if ($a === FALSE) {
return '"' . str_replace('"', '""', $value) . '"'; return '"' . str_replace('"', '""', $value) . '"';
} else { } else {
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"'; return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
} }
case 'sqlite': case 'sqlite':
case 'sqlite2': case 'sqlite2':
case 'odbc': case 'odbc':
case 'oci': // TODO: not tested case 'oci': // TODO: not tested
case 'mssql': case 'mssql':
return '[' . str_replace('.', '].[', $value) . ']'; return '[' . str_replace('.', '].[', $value) . ']';
default: default:
return $value; return $value;
} }
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $this->connection->quote($value, PDO::PARAM_BOOL); return $this->connection->quote($value, PDO::PARAM_BOOL);
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("'Y-m-d'", $value); return date("'Y-m-d'", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("'Y-m-d H:i:s'", $value); return date("'Y-m-d H:i:s'", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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); // intentionally @ $info = @$this->resultSet->getColumnsMeta($i); // intentionally @
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 result set resource. * Returns the result set 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

@@ -1,426 +1,426 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for PostgreSQL database. /**
* * The dibi driver for PostgreSQL database.
* Connection options: *
* - 'host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service' - see PostgreSQL API * Connection options:
* - 'string' - or use connection string * - 'host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service' - see PostgreSQL API
* - 'persistent' - try to find a persistent link? * - 'string' - or use connection string
* - 'charset' - character encoding to set * - 'persistent' - try to find a persistent link?
* - 'schema' - the schema search path * - 'charset' - character encoding to set
* - 'lazy' - if TRUE, connection will be established only when required * - 'schema' - the schema search path
* * - 'lazy' - if TRUE, connection will be established only when required
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @throws DibiDriverException * @throws DibiDriverException
*/ */
public function query($sql) public function query($sql)
{ {
$this->resultSet = @pg_query($this->connection, $sql); // intentionally @ $this->resultSet = @pg_query($this->connection, $sql); // intentionally @
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) && pg_num_fields($this->resultSet) ? clone $this : NULL; return is_resource($this->resultSet) && pg_num_fields($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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');
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
if ($this->escMethod) { if ($this->escMethod) {
return "'" . pg_escape_string($this->connection, $value) . "'"; return "'" . pg_escape_string($this->connection, $value) . "'";
} else { } else {
return "'" . pg_escape_string($value) . "'"; return "'" . pg_escape_string($value) . "'";
} }
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
if ($this->escMethod) { if ($this->escMethod) {
return "'" . pg_escape_bytea($this->connection, $value) . "'"; return "'" . pg_escape_bytea($this->connection, $value) . "'";
} else { } else {
return "'" . pg_escape_bytea($value) . "'"; return "'" . pg_escape_bytea($value) . "'";
} }
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
$a = strrpos($value, '.'); $a = strrpos($value, '.');
if ($a === FALSE) { if ($a === FALSE) {
return '"' . str_replace('"', '""', $value) . '"'; return '"' . str_replace('"', '""', $value) . '"';
} else { } else {
// 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)) . '"';
} }
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? 'TRUE' : 'FALSE'; return $value ? 'TRUE' : 'FALSE';
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date("'Y-m-d'", $value); return date("'Y-m-d'", $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date("'Y-m-d H:i:s'", $value); return date("'Y-m-d H:i:s'", $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return pg_unescape_bytea($value); return pg_unescape_bytea($value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,381 +1,381 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* The dibi driver for SQLite database. /**
* * The dibi driver for SQLite database.
* Connection options: *
* - 'database' (or 'file') - the filename of the SQLite database * Connection options:
* - 'persistent' - try to find a persistent link? * - 'database' (or 'file') - the filename of the SQLite database
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically? * - 'persistent' - try to find a persistent link?
* - 'lazy' - if TRUE, connection will be established only when required * - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
* - 'format:date' - how to format date in SQL (@see date) * - 'lazy' - if TRUE, connection will be established only when required
* - 'format:datetime' - how to format datetime in SQL (@see date) * - 'format:date' - how to format date in SQL (@see date)
* * - 'format:datetime' - how to format datetime in SQL (@see date)
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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); // intentionally @ $this->connection = @sqlite_open($config['database'], 0666, $errorMsg); // intentionally @
} else { } else {
$this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); // intentionally @ $this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); // intentionally @
} }
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @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) ? clone $this : NULL; return is_resource($this->resultSet) ? clone $this : NULL;
} }
/** /**
* 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');
} }
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function escape($value, $type) public function escape($value, $type)
{ {
switch ($type) { switch ($type) {
case dibi::FIELD_TEXT: case dibi::FIELD_TEXT:
case dibi::FIELD_BINARY: case dibi::FIELD_BINARY:
return "'" . sqlite_escape_string($value) . "'"; return "'" . sqlite_escape_string($value) . "'";
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
return '[' . str_replace('.', '].[', $value) . ']'; return '[' . str_replace('.', '].[', $value) . ']';
case dibi::FIELD_BOOL: case dibi::FIELD_BOOL:
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::FIELD_DATE: case dibi::FIELD_DATE:
return date($this->fmtDate, $value); return date($this->fmtDate, $value);
case dibi::FIELD_DATETIME: case dibi::FIELD_DATETIME:
return date($this->fmtDateTime, $value); return date($this->fmtDateTime, $value);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
} }
} }
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function unescape($value, $type) public function unescape($value, $type)
{ {
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported 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 result set resource. * Returns the result set 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

@@ -1,497 +1,501 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* dibi connection. /**
* * dibi connection.
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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::Hashtable connection parameters * @param array|string|Nette::Collections::Hashtable 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 if (class_exists(/*Nette::*/'Debug', FALSE)) {
if (is_string($config)) { /*Nette::*/Debug::addColophon(array('dibi', 'getColophon'));
parse_str($config, $config); }
} elseif ($config instanceof /*Nette::Collections::*/Hashtable) { // DSN string
$config = (array) $config; if (is_string($config)) {
parse_str($config, $config);
} elseif (!is_array($config)) {
throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::Hashtable.'); } elseif ($config instanceof /*Nette::Collections::*/Hashtable) {
} $config = (array) $config;
if (!isset($config['driver'])) { } elseif (!is_array($config)) {
$config['driver'] = dibi::$defaultDriver; throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::Hashtable.');
} }
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']); if (!isset($config['driver'])) {
$class = "Dibi" . $driver . "Driver"; $config['driver'] = dibi::$defaultDriver;
if (!class_exists($class, FALSE)) { }
include_once __FILE__ . "/../../drivers/$driver.php";
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
if (!class_exists($class, FALSE)) { $class = "Dibi" . $driver . "Driver";
throw new DibiException("Unable to create instance of dibi driver class '$class'."); if (!class_exists($class, FALSE)) {
} include_once __FILE__ . "/../../drivers/$driver.php";
}
if (!class_exists($class, FALSE)) {
if (isset($config['result:objects'])) { throw new DibiException("Unable to create instance of dibi driver class '$class'.");
// normalize }
$val = $config['result:objects']; }
$config['result:objects'] = is_string($val) && !is_numeric($val) ? $val : (bool) $val;
} if (isset($config['result:objects'])) {
// normalize
$config['name'] = $name; $val = $config['result:objects'];
$this->config = $config; $config['result:objects'] = is_string($val) && !is_numeric($val) ? $val : (bool) $val;
$this->driver = new $class; }
if (empty($config['lazy'])) { $config['name'] = $name;
$this->connect(); $this->config = $config;
} $this->driver = new $class;
}
if (empty($config['lazy'])) {
$this->connect();
}
/** }
* Automatically frees the resources allocated for this result set.
*
* @return void
*/ /**
public function __destruct() * Automatically frees the resources allocated for this result set.
{ *
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback! * @return void
$this->disconnect(); */
} public function __destruct()
{
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
$this->disconnect();
/** }
* Connects to a database.
*
* @return void
*/ /**
final protected function connect() * Connects to a database.
{ *
if (!$this->connected) { * @return void
$this->driver->connect($this->config); */
$this->connected = TRUE; final protected function connect()
dibi::notify($this, 'connected'); {
} if (!$this->connected) {
} $this->driver->connect($this->config);
$this->connected = TRUE;
dibi::notify($this, 'connected');
}
/** }
* Disconnects from a database.
*
* @return void
*/ /**
final public function disconnect() * Disconnects from a database.
{ *
if ($this->connected) { * @return void
if ($this->inTxn) { */
$this->rollback(); final public function disconnect()
} {
$this->driver->disconnect(); if ($this->connected) {
$this->connected = FALSE; if ($this->inTxn) {
dibi::notify($this, 'disconnected'); $this->rollback();
} }
} $this->driver->disconnect();
$this->connected = FALSE;
dibi::notify($this, 'disconnected');
}
/** }
* Returns TRUE when connection was established.
*
* @return bool
*/ /**
final public function isConnected() * Returns TRUE when connection was established.
{ *
return $this->connected; * @return bool
} */
final public function isConnected()
{
return $this->connected;
/** }
* Returns configuration variable. If no $key is passed, returns the entire array.
*
* @see self::__construct
* @param string /**
* @param mixed default value to use if key not found * Returns configuration variable. If no $key is passed, returns the entire array.
* @return mixed *
*/ * @see self::__construct
final public function getConfig($key = NULL, $default = NULL) * @param string
{ * @param mixed default value to use if key not found
if ($key === NULL) { * @return mixed
return $this->config; */
final public function getConfig($key = NULL, $default = NULL)
} elseif (isset($this->config[$key])) { {
return $this->config[$key]; if ($key === NULL) {
return $this->config;
} else {
return $default; } elseif (isset($this->config[$key])) {
} return $this->config[$key];
}
} else {
return $default;
}
/** }
* Apply configuration alias or default values.
*
* @param array connect configuration
* @param string key /**
* @param string alias key * Apply configuration alias or default values.
* @return void *
*/ * @param array connect configuration
public static function alias(&$config, $key, $alias=NULL) * @param string key
{ * @param string alias key
if (isset($config[$key])) return; * @return void
*/
if ($alias !== NULL && isset($config[$alias])) { public static function alias(&$config, $key, $alias=NULL)
$config[$key] = $config[$alias]; {
unset($config[$alias]); if (isset($config[$key])) return;
} else {
$config[$key] = NULL; if ($alias !== NULL && isset($config[$alias])) {
} $config[$key] = $config[$alias];
} unset($config[$alias]);
} else {
$config[$key] = NULL;
}
/** }
* Returns the connection resource.
*
* @return resource
*/ /**
final public function getResource() * Returns the connection resource.
{ *
return $this->driver->getResource(); * @return resource
} */
final public function getResource()
{
return $this->driver->getResource();
/** }
* Generates (translates) and executes SQL query.
*
* @param array|mixed one or more arguments
* @return DibiResult|NULL result set object (if any) /**
* @throws DibiException * Generates (translates) and executes SQL query.
*/ *
final public function query($args) * @param array|mixed one or more arguments
{ * @return DibiResult|NULL result set object (if any)
$args = func_get_args(); * @throws DibiException
$this->connect(); */
$trans = new DibiTranslator($this->driver); final public function query($args)
if ($trans->translate($args)) { {
return $this->nativeQuery($trans->sql); $args = func_get_args();
} else { $this->connect();
throw new DibiException('SQL translate error: ' . $trans->sql); $trans = new DibiTranslator($this->driver);
} if ($trans->translate($args)) {
} return $this->nativeQuery($trans->sql);
} else {
throw new DibiException('SQL translate error: ' . $trans->sql);
}
/** }
* Generates and prints SQL query.
*
* @param array|mixed one or more arguments
* @return bool /**
*/ * Generates and prints SQL query.
final public function test($args) *
{ * @param array|mixed one or more arguments
$args = func_get_args(); * @return bool
$this->connect(); */
$trans = new DibiTranslator($this->driver); final public function test($args)
$ok = $trans->translate($args); {
dibi::dump($trans->sql); $args = func_get_args();
return $ok; $this->connect();
} $trans = new DibiTranslator($this->driver);
$ok = $trans->translate($args);
dibi::dump($trans->sql);
return $ok;
/** }
* Executes the SQL query.
*
* @param string SQL statement.
* @return DibiResult|NULL result set object (if any) /**
* @throws DibiException * Executes the SQL query.
*/ *
final public function nativeQuery($sql) * @param string SQL statement.
{ * @return DibiResult|NULL result set object (if any)
$this->connect(); * @throws DibiException
*/
dibi::$numOfQueries++; final public function nativeQuery($sql)
dibi::$sql = $sql; {
dibi::$elapsedTime = FALSE; $this->connect();
$time = -microtime(TRUE);
dibi::notify($this, 'beforeQuery', $sql); dibi::$numOfQueries++;
dibi::$sql = $sql;
if ($res = $this->driver->query($sql)) { // intentionally = dibi::$elapsedTime = FALSE;
$res = new DibiResult($res, $this->config); $time = -microtime(TRUE);
} dibi::notify($this, 'beforeQuery', $sql);
$time += microtime(TRUE); if ($res = $this->driver->query($sql)) { // intentionally =
dibi::$elapsedTime = $time; $res = new DibiResult($res, $this->config);
dibi::$totalTime += $time; }
dibi::notify($this, 'afterQuery', $res);
$time += microtime(TRUE);
return $res; dibi::$elapsedTime = $time;
} dibi::$totalTime += $time;
dibi::notify($this, 'afterQuery', $res);
return $res;
/** }
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
*
* @return int number of rows
* @throws DibiException /**
*/ * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
public function affectedRows() *
{ * @return int number of rows
$rows = $this->driver->affectedRows(); * @throws DibiException
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.'); */
return $rows; public function affectedRows()
} {
$rows = $this->driver->affectedRows();
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
return $rows;
/** }
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
*
* @param string optional sequence name
* @return int /**
* @throws DibiException * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
*/ *
public function insertId($sequence = NULL) * @param string optional sequence name
{ * @return int
$id = $this->driver->insertId($sequence); * @throws DibiException
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.'); */
return (int) $id; public function insertId($sequence = NULL)
} {
$id = $this->driver->insertId($sequence);
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
return (int) $id;
/** }
* Begins a transaction (if supported).
* @return void
*/
public function begin() /**
{ * Begins a transaction (if supported).
$this->connect(); * @return void
if ($this->inTxn) { */
throw new DibiException('There is already an active transaction.'); public function begin()
} {
$this->driver->begin(); $this->connect();
$this->inTxn = TRUE; if ($this->inTxn) {
dibi::notify($this, 'begin'); throw new DibiException('There is already an active transaction.');
} }
$this->driver->begin();
$this->inTxn = TRUE;
dibi::notify($this, 'begin');
/** }
* Commits statements in a transaction.
* @return void
*/
public function commit() /**
{ * Commits statements in a transaction.
if (!$this->inTxn) { * @return void
throw new DibiException('There is no active transaction.'); */
} public function commit()
$this->driver->commit(); {
$this->inTxn = FALSE; if (!$this->inTxn) {
dibi::notify($this, 'commit'); throw new DibiException('There is no active transaction.');
} }
$this->driver->commit();
$this->inTxn = FALSE;
dibi::notify($this, 'commit');
/** }
* Rollback changes in a transaction.
* @return void
*/
public function rollback() /**
{ * Rollback changes in a transaction.
if (!$this->inTxn) { * @return void
throw new DibiException('There is no active transaction.'); */
} public function rollback()
$this->driver->rollback(); {
$this->inTxn = FALSE; if (!$this->inTxn) {
dibi::notify($this, 'rollback'); throw new DibiException('There is no active transaction.');
} }
$this->driver->rollback();
$this->inTxn = FALSE;
dibi::notify($this, 'rollback');
/** }
* Encodes data for use in an SQL statement.
*
* @param string unescaped string
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) /**
* @return string escaped and quoted string * Encodes data for use in an SQL statement.
*/ *
public function escape($value, $type = dibi::FIELD_TEXT) * @param string unescaped string
{ * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
$this->connect(); // MySQL & PDO require connection * @return string escaped and quoted string
return $this->driver->escape($value, $type); */
} public function escape($value, $type = dibi::FIELD_TEXT)
{
$this->connect(); // MySQL & PDO require connection
return $this->driver->escape($value, $type);
/** }
* Decodes data from result set.
*
* @param string value
* @param string type (dibi::FIELD_BINARY) /**
* @return string decoded value * Decodes data from result set.
*/ *
public function unescape($value, $type = dibi::FIELD_BINARY) * @param string value
{ * @param string type (dibi::FIELD_BINARY)
return $this->driver->unescape($value, $type); * @return string decoded value
} */
public function unescape($value, $type = dibi::FIELD_BINARY)
{
return $this->driver->unescape($value, $type);
/** }
* Delimites identifier (table's or column's name, etc.).
*
* @param string identifier
* @return string delimited identifier /**
*/ * Delimites identifier (table's or column's name, etc.).
public function delimite($value) *
{ * @param string identifier
return $this->driver->escape($value, dibi::IDENTIFIER); * @return string delimited identifier
} */
public function delimite($value)
{
return $this->driver->escape($value, dibi::IDENTIFIER);
/** }
* Injects LIMIT/OFFSET to the SQL query.
*
* @param string &$sql The SQL query that will be modified.
* @param int $limit /**
* @param int $offset * Injects LIMIT/OFFSET to the SQL query.
* @return void *
*/ * @param string &$sql The SQL query that will be modified.
public function applyLimit(&$sql, $limit, $offset) * @param int $limit
{ * @param int $offset
$this->driver->applyLimit($sql, $limit, $offset); * @return void
} */
public function applyLimit(&$sql, $limit, $offset)
{
$this->driver->applyLimit($sql, $limit, $offset);
/** }
* Import SQL dump from file - extreme fast!
*
* @param string filename
* @return int count of sql commands /**
*/ * Import SQL dump from file - extreme fast!
public function loadFile($file) *
{ * @param string filename
$this->connect(); * @return int count of sql commands
*/
@set_time_limit(0); // intentionally @ public function loadFile($file)
{
$handle = @fopen($file, 'r'); // intentionally @ $this->connect();
if (!$handle) {
throw new FileNotFoundException("Cannot open file '$file'."); @set_time_limit(0); // intentionally @
}
$handle = @fopen($file, 'r'); // intentionally @
$count = 0; if (!$handle) {
$sql = ''; throw new FileNotFoundException("Cannot open file '$file'.");
while (!feof($handle)) { }
$s = fgets($handle);
$sql .= $s; $count = 0;
if (substr(rtrim($s), -1) === ';') { $sql = '';
$this->driver->query($sql); while (!feof($handle)) {
$sql = ''; $s = fgets($handle);
$count++; $sql .= $s;
} if (substr(rtrim($s), -1) === ';') {
} $this->driver->query($sql);
fclose($handle); $sql = '';
return $count; $count++;
} }
}
fclose($handle);
return $count;
/** }
* Gets a information of the current database.
*
* @return DibiReflection
*/ /**
public function getDibiReflection() * Gets a information of the current database.
{ *
throw new NotImplementedException; * @return DibiReflection
} */
public function getDibiReflection()
{
throw new NotImplementedException;
/** }
* Prevents unserialization.
*/
public function __wakeup()
{ /**
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); * Prevents unserialization.
} */
public function __wakeup()
{
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
/** }
* Prevents serialization.
*/
public function __sleep()
{ /**
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.'); * Prevents serialization.
} */
public function __sleep()
} {
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
}
}

View File

@@ -1,92 +1,92 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* Default implementation of IDataSource for dibi. /**
* * Default implementation of IDataSource for dibi.
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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

@@ -1,159 +1,158 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* dibi common exception. /**
* * dibi common exception.
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
class DibiException extends Exception class DibiException extends Exception
{ {
} }
/** /**
* database server exception. * database server exception.
* *
* @author David Grudl * @author David Grudl
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @package dibi * @package dibi
* @version $Revision$ $Date$ */
*/ 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

@@ -1,329 +1,329 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* dibi SQL builder via fluent interfaces. EXPERIMENTAL! /**
* * dibi SQL builder via fluent interfaces. EXPERIMENTAL!
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
class DibiFluent extends /*Nette::*/Object class DibiFluent extends /*Nette::*/Object
{ {
/** @var array */ /** @var array */
public static $masks = array( public static $masks = array(
'SELECT' => array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY', 'SELECT' => array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY',
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', '%end'), 'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', '%end'),
'UPDATE' => array('UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT', '%end'), 'UPDATE' => array('UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
'INSERT' => array('INSERT', 'INTO', 'VALUES', 'SELECT', '%end'), 'INSERT' => array('INSERT', 'INTO', 'VALUES', 'SELECT', '%end'),
'DELETE' => array('DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT', '%end'), 'DELETE' => array('DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
); );
/** @var array */ /** @var array */
public static $separators = array( public static $separators = array(
'SELECT' => ',', 'SELECT' => ',',
'FROM' => FALSE, 'FROM' => FALSE,
'WHERE' => 'AND', 'WHERE' => 'AND',
'GROUP BY' => ',', 'GROUP BY' => ',',
'HAVING' => 'AND', 'HAVING' => 'AND',
'ORDER BY' => ',', 'ORDER BY' => ',',
'LIMIT' => FALSE, 'LIMIT' => FALSE,
'OFFSET' => FALSE, 'OFFSET' => FALSE,
'SET' => ',', 'SET' => ',',
'VALUES' => ',', 'VALUES' => ',',
'INTO' => FALSE, 'INTO' => FALSE,
); );
/** @var DibiConnection */ /** @var DibiConnection */
private $connection; private $connection;
/** @var string */ /** @var string */
private $command; private $command;
/** @var array */ /** @var array */
private $clauses = array(); private $clauses = array();
/** @var array */ /** @var array */
private $flags = array(); private $flags = array();
/** @var array */ /** @var array */
private $cursor; private $cursor;
/** /**
* @param DibiConnection * @param DibiConnection
*/ */
public function __construct(DibiConnection $connection) public function __construct(DibiConnection $connection)
{ {
$this->connection = $connection; $this->connection = $connection;
} }
/** /**
* Appends new argument to the clause. * Appends new argument to the clause.
* @param string clause name * @param string clause name
* @param array arguments * @param array arguments
* @return DibiFluent provides a fluent interface * @return DibiFluent provides a fluent interface
*/ */
public function __call($clause, $args) public function __call($clause, $args)
{ {
$clause = self::_clause($clause); $clause = self::_clause($clause);
// lazy initialization // lazy initialization
if ($this->command === NULL) { if ($this->command === NULL) {
if (isset(self::$masks[$clause])) { if (isset(self::$masks[$clause])) {
$this->clauses = array_fill_keys(self::$masks[$clause], NULL); $this->clauses = array_fill_keys(self::$masks[$clause], NULL);
} }
$this->cursor = & $this->clauses[$clause]; $this->cursor = & $this->clauses[$clause];
$this->cursor = array(); $this->cursor = array();
$this->command = $clause; $this->command = $clause;
} }
// special types or argument // special types or argument
if (count($args) === 1) { if (count($args) === 1) {
$arg = $args[0]; $arg = $args[0];
// TODO: really ignore TRUE? // TODO: really ignore TRUE?
if ($arg === TRUE) { if ($arg === TRUE) {
$args = array(); $args = array();
} elseif (is_string($arg) && preg_match('#^[a-z][a-z0-9_.]*$#i', $arg)) { } elseif (is_string($arg) && preg_match('#^[a-z][a-z0-9_.]*$#i', $arg)) {
$args = array('%n', $arg); $args = array('%n', $arg);
} }
} }
if (array_key_exists($clause, $this->clauses)) { if (array_key_exists($clause, $this->clauses)) {
// append to clause // append to clause
$this->cursor = & $this->clauses[$clause]; $this->cursor = & $this->clauses[$clause];
// TODO: really delete? // TODO: really delete?
if ($args === array(FALSE)) { if ($args === array(FALSE)) {
$this->cursor = NULL; $this->cursor = NULL;
return $this; return $this;
} }
if (isset(self::$separators[$clause])) { if (isset(self::$separators[$clause])) {
$sep = self::$separators[$clause]; $sep = self::$separators[$clause];
if ($sep === FALSE) { if ($sep === FALSE) {
$this->cursor = array(); $this->cursor = array();
} elseif (!empty($this->cursor)) { } elseif (!empty($this->cursor)) {
$this->cursor[] = $sep; $this->cursor[] = $sep;
} }
} }
} else { } else {
// append to currect flow // append to currect flow
if ($args === array(FALSE)) { if ($args === array(FALSE)) {
return $this; return $this;
} }
$this->cursor[] = $clause; $this->cursor[] = $clause;
} }
if ($this->cursor === NULL) { if ($this->cursor === NULL) {
$this->cursor = array(); $this->cursor = array();
} }
array_splice($this->cursor, count($this->cursor), 0, $args); array_splice($this->cursor, count($this->cursor), 0, $args);
return $this; return $this;
} }
/** /**
* Switch to a clause. * Switch to a clause.
* @param string clause name * @param string clause name
* @return DibiFluent provides a fluent interface * @return DibiFluent provides a fluent interface
*/ */
public function clause($clause, $remove = FALSE) public function clause($clause, $remove = FALSE)
{ {
$this->cursor = & $this->clauses[self::_clause($clause)]; $this->cursor = & $this->clauses[self::_clause($clause)];
if ($remove) { if ($remove) {
$this->cursor = NULL; $this->cursor = NULL;
} elseif ($this->cursor === NULL) { } elseif ($this->cursor === NULL) {
$this->cursor = array(); $this->cursor = array();
} }
return $this; return $this;
} }
/** /**
* Change a SQL flag. * Change a SQL flag.
* @param string flag name * @param string flag name
* @param bool value * @param bool value
* @return DibiFluent provides a fluent interface * @return DibiFluent provides a fluent interface
*/ */
public function setFlag($flag, $value = TRUE) public function setFlag($flag, $value = TRUE)
{ {
$flag = strtoupper($flag); $flag = strtoupper($flag);
if ($value) { if ($value) {
$this->flags[$flag] = TRUE; $this->flags[$flag] = TRUE;
} else { } else {
unset($this->flags[$flag]); unset($this->flags[$flag]);
} }
return $this; return $this;
} }
/** /**
* Is a flag set? * Is a flag set?
* @param string flag name * @param string flag name
* @return bool * @return bool
*/ */
final public function getFlag($flag, $value = TRUE) final public function getFlag($flag, $value = TRUE)
{ {
return isset($this->flags[strtoupper($flag)]); return isset($this->flags[strtoupper($flag)]);
} }
/** /**
* Returns SQL command. * Returns SQL command.
* @return string * @return string
*/ */
final public function getCommand() final public function getCommand()
{ {
return $this->command; return $this->command;
} }
/** /**
* Generates and executes SQL query. * Generates and executes SQL query.
* @return DibiResult|NULL result set object (if any) * @return DibiResult|NULL result set object (if any)
* @throws DibiException * @throws DibiException
*/ */
public function execute() public function execute()
{ {
return $this->connection->query($this->_export()); return $this->connection->query($this->_export());
} }
/** /**
* Generates, executes SQL query and fetches the single row. * Generates, executes SQL query and fetches the single row.
* @return array|FALSE array on success, FALSE if no next record * @return array|FALSE array on success, FALSE if no next record
* @throws DibiException * @throws DibiException
*/ */
public function fetch() public function fetch()
{ {
if ($this->command === 'SELECT') { if ($this->command === 'SELECT') {
$this->clauses['LIMIT'] = array(1); $this->clauses['LIMIT'] = array(1);
} }
return $this->connection->query($this->_export())->fetch(); return $this->connection->query($this->_export())->fetch();
} }
/** /**
* Generates and prints SQL query or it's part. * Generates and prints SQL query or it's part.
* @param string clause name * @param string clause name
* @return bool * @return bool
*/ */
public function test($clause = NULL) public function test($clause = NULL)
{ {
return $this->connection->test($this->_export($clause)); return $this->connection->test($this->_export($clause));
} }
/** /**
* Generates parameters for DibiTranslator. * Generates parameters for DibiTranslator.
* @param string clause name * @param string clause name
* @return array * @return array
*/ */
protected function _export($clause = NULL) protected function _export($clause = NULL)
{ {
if ($clause === NULL) { if ($clause === NULL) {
$data = $this->clauses; $data = $this->clauses;
} else { } else {
$clause = self::_clause($clause); $clause = self::_clause($clause);
if (array_key_exists($clause, $this->clauses)) { if (array_key_exists($clause, $this->clauses)) {
$data = array($clause => $this->clauses[$clause]); $data = array($clause => $this->clauses[$clause]);
} else { } else {
return array(); return array();
} }
} }
$args = array(); $args = array();
foreach ($data as $clause => $statement) { foreach ($data as $clause => $statement) {
if ($statement !== NULL) { if ($statement !== NULL) {
if ($clause[0] !== '%') { if ($clause[0] !== '%') {
$args[] = $clause; $args[] = $clause;
if ($clause === $this->command) { if ($clause === $this->command) {
$args[] = implode(' ', array_keys($this->flags)); $args[] = implode(' ', array_keys($this->flags));
} }
} }
array_splice($args, count($args), 0, $statement); array_splice($args, count($args), 0, $statement);
} }
} }
return $args; return $args;
} }
/** /**
* Format camelCase clause name to UPPER CASE. * Format camelCase clause name to UPPER CASE.
* @param string * @param string
* @return string * @return string
*/ */
private static function _clause($s) private static function _clause($s)
{ {
if ($s === 'order' || $s === 'group') { if ($s === 'order' || $s === 'group') {
$s .= 'By'; $s .= 'By';
trigger_error("Did you mean '$s'?", E_USER_NOTICE); trigger_error("Did you mean '$s'?", E_USER_NOTICE);
} }
return strtoupper(preg_replace('#[A-Z]#', ' $0', $s)); return strtoupper(preg_replace('#[A-Z]#', ' $0', $s));
} }
/** /**
* Returns (highlighted) SQL query. * Returns (highlighted) SQL query.
* @return string * @return string
*/ */
final public function __toString() final public function __toString()
{ {
ob_start(); ob_start();
$this->test(); $this->test();
return ob_get_clean(); return ob_get_clean();
} }
} }
// PHP < 5.2 compatibility // PHP < 5.2 compatibility
if (!function_exists('array_fill_keys')) { if (!function_exists('array_fill_keys')) {
function array_fill_keys($keys, $value) function array_fill_keys($keys, $value)
{ {
return array_combine($keys, array_fill(0, count($keys), $value)); return array_combine($keys, array_fill(0, count($keys), $value));
} }
} }

View File

@@ -1,106 +1,106 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* dibi basic logger & profiler (experimental). /**
* * dibi basic logger & profiler (experimental).
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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

@@ -1,290 +1,290 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* Experimental object-oriented interface to database tables. /**
* * Experimental object-oriented interface to database tables.
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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 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 DibiConnection * @param DibiConnection
* @return void * @return void
*/ */
public function __construct(DibiConnection $connection = NULL) public function __construct(DibiConnection $connection = NULL)
{ {
$this->connection = $connection === NULL ? dibi::getConnection() : $connection; $this->connection = $connection === NULL ? dibi::getConnection() : $connection;
$this->setup(); $this->setup();
} }
/** /**
* 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 ($class = $this->connection->getConfig('result:objects')) { if ($class = $this->connection->getConfig('result:objects')) {
if ($class === TRUE) { if ($class === TRUE) {
$row = (object) $row; $row = (object) $row;
} else { } else {
$row = new $class($row); $row = new $class($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

@@ -1,457 +1,457 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* dibi SQL translator. /**
* * dibi SQL translator.
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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
case 'bin':// binary case 'bin':// binary
case 'b': // boolean case 'b': // boolean
return $this->driver->escape($value, $modifier); return $this->driver->escape($value, $modifier);
case 'sn': // string or NULL case 'sn': // string or NULL
return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::FIELD_TEXT); // notice two equal signs return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::FIELD_TEXT); // notice two equal signs
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
case 't': // datetime case 't': // datetime
return $this->driver->escape(is_string($value) ? strtotime($value) : $value, $modifier); return $this->driver->escape(is_string($value) ? strtotime($value) : $value, $modifier);
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 'and': case 'and':
case 'or': case 'or':
case 'a': case 'a':
case 'l': case 'l':
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->escape($value, dibi::FIELD_TEXT); return $this->driver->escape($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->escape($value, dibi::FIELD_BOOL); return $this->driver->escape($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->escape( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT); return $this->driver->escape( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
if ($matches[5]) // SQL strings: "..." if ($matches[5]) // SQL strings: "..."
return $this->driver->escape( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT); return $this->driver->escape( 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)
{ {
return $this->driver->escape(dibi::substitute($value), dibi::IDENTIFIER); return $this->driver->escape(dibi::substitute($value), dibi::IDENTIFIER);
} }
} // class DibiTranslator } // class DibiTranslator

View File

@@ -1,48 +1,49 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* Default implemenation of IDibiVariable. /**
* @package dibi * Default implemenation of IDibiVariable.
*/ * @package dibi
class DibiVariable extends /*Nette::*/Object implements IDibiVariable */
{ class DibiVariable extends /*Nette::*/Object implements IDibiVariable
/** @var mixed */ {
public $value; /** @var mixed */
public $value;
/** @var string */
public $modifier; /** @var string */
public $modifier;
public function __construct($value, $modifier)
{ public function __construct($value, $modifier)
$this->value = $value; {
$this->modifier = $modifier; $this->value = $value;
} $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

@@ -1,256 +1,256 @@
<?php <?php
/** /**
* dibi - tiny'n'smart database abstraction layer * dibi - tiny'n'smart database abstraction layer
* ---------------------------------------------- * ----------------------------------------------
* *
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
* *
* This source file is subject to the "dibi license" that is bundled * This source file is subject to the "dibi license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* For more information please see http://dibiphp.com/ * For more information please see http://dibiphp.com
* *
* @copyright Copyright (c) 2005, 2008 David Grudl * @copyright Copyright (c) 2005, 2008 David Grudl
* @license http://dibiphp.com/license dibi license * @license http://dibiphp.com/license dibi license
* @link http://dibiphp.com/ * @link http://dibiphp.com
* @package dibi * @package dibi
*/ * @version $Id$
*/
/**
* Interface for user variable, used for generating SQL. /**
* @package dibi * Interface for user variable, used for generating SQL.
*/ * @package dibi
interface IDibiVariable */
{ interface IDibiVariable
/** {
* Format for SQL. /**
* * Format for SQL.
* @param object DibiTranslator *
* @param string optional modifier * @param object DibiTranslator
* @return string SQL code * @param string optional modifier
*/ * @return string SQL code
function toSql(DibiTranslator $translator, $modifier); */
} function toSql(DibiTranslator $translator, $modifier);
}
/**
* Provides an interface between a dataset and data-aware components. /**
* @package dibi * Provides an interface between a dataset and data-aware components.
*/ * @package dibi
interface IDataSource extends Countable, IteratorAggregate */
{ interface IDataSource extends Countable, IteratorAggregate
//function IteratorAggregate::getIterator(); {
//function Countable::count(); //function IteratorAggregate::getIterator();
} //function Countable::count();
}
/**
* dibi driver interface. /**
* * dibi driver interface.
* @author David Grudl *
* @copyright Copyright (c) 2005, 2008 David Grudl * @author David Grudl
* @package dibi * @copyright Copyright (c) 2005, 2008 David Grudl
* @version $Revision$ $Date$ * @package dibi
*/ */
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 IDibiDriver|NULL * @return IDibiDriver|NULL
* @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();
/** /**
* Encodes data for use in an SQL statement. * Encodes data for use in an SQL statement.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...) * @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
* @return string encoded value * @return string encoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
function escape($value, $type); function escape($value, $type);
/** /**
* Decodes data from result set. * Decodes data from result set.
* *
* @param string value * @param string value
* @param string type (dibi::FIELD_BINARY) * @param string type (dibi::FIELD_BINARY)
* @return string decoded value * @return string decoded value
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
function unescape($value, $type); function unescape($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 result set resource * @param resource result set 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 result set resource. * Returns the result set 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

@@ -1,2 +1,2 @@
Disallow: /drivers Disallow: /drivers
Disallow: /Nette Disallow: /Nette

View File

@@ -1,34 +1,34 @@
<h1>dibi apply limit/offset example</h1> <h1>dibi apply limit/offset example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; 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>';
// 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>';
// 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

@@ -1,145 +1,145 @@
<h1>dibi::connect() example</h1> <h1>dibi::connect() example</h1>
<?php <?php
require_once '../dibi/dibi.php'; 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";
// 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";
// 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";
// 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";
// 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";
// 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";
// 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";
// 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

@@ -1,28 +1,28 @@
<h1>IDibiVariable example</h1> <h1>IDibiVariable example</h1>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
// required since PHP 5.1.0 // required since PHP 5.1.0
date_default_timezone_set('Europe/Prague'); 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'",
)); ));
// 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

@@ -1,88 +1,88 @@
<h1>DibiTable demo</h1> <h1>DibiTable demo</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; 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();
// autodetection: primary keys are customer_id, order_id, ... // autodetection: primary keys are customer_id, order_id, ...
DibiTable::$primaryMask = '%s_id'; DibiTable::$primaryMask = '%s_id';
// table products // table products
class Products extends DibiTable class Products extends DibiTable
{ {
// rely on autodetection... // rely on autodetection...
// protected $name = 'products'; // protected $name = 'products';
// protected $primary = 'product_id'; // protected $primary = 'product_id';
} }
// create table object // create table object
$products = new Products(); $products = new Products();
echo "Table name: $products->name\n"; echo "Table name: $products->name\n";
echo "Primary key: $products->primary\n"; 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);
} }
// select all // select all
$products->findAll()->dump(); $products->findAll()->dump();
// select all, order by title, product_id // select all, order by title, product_id
$products->findAll('title', $products->primary)->dump(); $products->findAll('title', $products->primary)->dump();
// fetches single row with id 3 // fetches single row with id 3
$row = $products->fetch(3); $row = $products->fetch(3);
// deletes row from a table // deletes row from a table
$count = $products->delete(1); $count = $products->delete(1);
// deletes multiple rows // deletes multiple rows
$count = $products->delete(array(1, 2, 3)); $count = $products->delete(array(1, 2, 3));
var_dump($count); // number of deleted rows var_dump($count); // number of deleted rows
// update row #2 in a table // update row #2 in a table
$data = (object) NULL; $data = (object) NULL;
$data->title = 'New title'; $data->title = 'New title';
$count = $products->update(2, $data); $count = $products->update(2, $data);
var_dump($count); // number of updated rows var_dump($count); // number of updated rows
// update multiple rows in a table // update multiple rows in a table
$count = $products->update(array(3, 5), $data); $count = $products->update(array(3, 5), $data);
var_dump($count); // number of updated rows var_dump($count); // number of updated rows
// inserts row into a table // inserts row into a table
$data = array(); $data = array();
$data['title'] = 'New product'; $data['title'] = 'New product';
$id = $products->insert($data); $id = $products->insert($data);
var_dump($id); // generated id var_dump($id); // generated id
// is absolutely SQL injection safe // is absolutely SQL injection safe
$key = '3 OR 1=1'; $key = '3 OR 1=1';
$products->delete($key); $products->delete($key);
// --> DELETE FROM [products] WHERE [product_id] IN ( 3 ) // --> DELETE FROM [products] WHERE [product_id] IN ( 3 )

View File

@@ -1,30 +1,30 @@
<h1>dibi dump example</h1> <h1>dibi dump example</h1>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
$res = dibi::query(' $res = dibi::query('
SELECT * FROM [products] SELECT * FROM [products]
INNER JOIN [orders] USING ([product_id]) INNER JOIN [orders] USING ([product_id])
INNER JOIN [customers] USING ([customer_id]) INNER JOIN [customers] USING ([customer_id])
'); ');
echo '<h2>dibi::dump()</h2>'; echo '<h2>dibi::dump()</h2>';
// dump last query (dibi::$sql) // dump last query (dibi::$sql)
dibi::dump(); dibi::dump();
// dump result table // dump result table
echo '<h2>DibiResult::dump()</h2>'; echo '<h2>DibiResult::dump()</h2>';
$res->dump(); $res->dump();

View File

@@ -1,27 +1,27 @@
<h1>dibi extension method example</h1> <h1>dibi extension method example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
// 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;
} }
// fetch complete result set shuffled // fetch complete result set shuffled
$res = dibi::query('SELECT * FROM [customers]'); $res = dibi::query('SELECT * FROM [customers]');
$all = $res->fetchShuffle(); $all = $res->fetchShuffle();
print_r($all); print_r($all);

View File

@@ -1,93 +1,93 @@
<h1>dibi fetch example</h1> <h1>dibi fetch example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
/* /*
TABLE products TABLE products
product_id | title product_id | title
-----------+---------- -----------+----------
1 | Chair 1 | Chair
2 | Table 2 | Table
3 | Computer 3 | Computer
*/ */
// fetch a single row // fetch a single row
$row = dibi::fetch('SELECT title FROM [products]'); $row = dibi::fetch('SELECT title FROM [products]');
print_r($row); // Chair print_r($row); // Chair
echo '<hr>'; echo '<hr>';
// fetch a single value // fetch a single value
$value = dibi::fetchSingle('SELECT [title] FROM [products]'); $value = dibi::fetchSingle('SELECT [title] FROM [products]');
print_r($value); // Chair print_r($value); // Chair
echo '<hr>'; echo '<hr>';
// fetch complete result set // fetch complete result set
$all = dibi::fetchAll('SELECT * FROM [products]'); $all = dibi::fetchAll('SELECT * FROM [products]');
print_r($all); print_r($all);
echo '<hr>'; echo '<hr>';
// fetch complete result set like association array // fetch complete result set like association array
$res = dibi::query('SELECT * FROM [products]'); $res = dibi::query('SELECT * FROM [products]');
$assoc = $res->fetchAssoc('title'); // key $assoc = $res->fetchAssoc('title'); // key
print_r($assoc); print_r($assoc);
echo '<hr>'; echo '<hr>';
// fetch complete result set like pairs key => value // fetch complete result set like pairs key => value
$pairs = $res->fetchPairs('product_id', 'title'); $pairs = $res->fetchPairs('product_id', 'title');
print_r($pairs); print_r($pairs);
echo '<hr>'; 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);
} }
// more complex association array // more complex association array
$res = dibi::query(' $res = dibi::query('
SELECT * SELECT *
FROM [products] FROM [products]
INNER JOIN [orders] USING ([product_id]) INNER JOIN [orders] USING ([product_id])
INNER JOIN [customers] USING ([customer_id]) INNER JOIN [customers] USING ([customer_id])
'); ');
$assoc = $res->fetchAssoc('customers.name,products.title'); // key $assoc = $res->fetchAssoc('customers.name,products.title'); // key
print_r($assoc); print_r($assoc);
echo '<hr>'; echo '<hr>';
$assoc = $res->fetchAssoc('customers.name,#,products.title'); // key $assoc = $res->fetchAssoc('customers.name,#,products.title'); // key
print_r($assoc); print_r($assoc);
echo '<hr>'; echo '<hr>';
$assoc = $res->fetchAssoc('customers.name,=,products.title'); // key $assoc = $res->fetchAssoc('customers.name,=,products.title'); // key
print_r($assoc); print_r($assoc);
echo '<hr>'; echo '<hr>';

View File

@@ -1,63 +1,63 @@
<h1>dibi dump example</h1> <h1>dibi dump example</h1>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
$id = 10; $id = 10;
$record = array( $record = array(
'title' => 'Drtička na trávu', 'title' => 'Drtička na trávu',
'price' => 318, 'price' => 318,
'active' => TRUE, 'active' => TRUE,
); );
// SELECT ... // SELECT ...
dibi::select('product_id')->as('id') dibi::select('product_id')->as('id')
->select('title') ->select('title')
->from('products') ->from('products')
->innerJoin('orders')->using('(product_id)') ->innerJoin('orders')->using('(product_id)')
->innerJoin('customers USING (customer_id)') ->innerJoin('customers USING (customer_id)')
->orderBy('title') ->orderBy('title')
->test(); ->test();
echo "\n"; echo "\n";
// INSERT ... // INSERT ...
dibi::insert('products', $record) dibi::insert('products', $record)
->setFlag('IGNORE') ->setFlag('IGNORE')
->test(); ->test();
echo "\n"; echo "\n";
// UPDATE ... // UPDATE ...
dibi::update('products', $record) dibi::update('products', $record)
->where('product_id = %d', $id) ->where('product_id = %d', $id)
->test(); ->test();
echo "\n"; echo "\n";
// DELETE ... // DELETE ...
dibi::delete('products') dibi::delete('products')
->where('product_id = %d', $id) ->where('product_id = %d', $id)
->test(); ->test();
echo "\n"; echo "\n";
// custom commands // custom commands
dibi::command() dibi::command()
->update('products') ->update('products')
->where('product_id = %d', $id) ->where('product_id = %d', $id)
->set($record) ->set($record)
->test(); ->test();
echo "\n"; echo "\n";
dibi::command() dibi::command()
->truncate('products') ->truncate('products')
->test(); ->test();

View File

@@ -1,16 +1,16 @@
<h1>dibi import SQL dump example</h1> <h1>dibi import SQL dump example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
$count = dibi::loadFile('compress.zlib://dump.sql.gz'); $count = dibi::loadFile('compress.zlib://dump.sql.gz');
echo 'Number of SQL commands:', $count; echo 'Number of SQL commands:', $count;

View File

@@ -1,32 +1,32 @@
<h1>dibi logger example</h1> <h1>dibi logger example</h1>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
// enable log to this file, TRUE means "log all queries" // enable log to this file, TRUE means "log all queries"
dibi::startLogger('log.sql', TRUE); 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>';
} }
echo "<h2>File log.sql:</h2>"; echo "<h2>File log.sql:</h2>";
echo '<pre>', file_get_contents('log.sql'), '</pre>'; echo '<pre>', file_get_contents('log.sql'), '</pre>';

View File

@@ -1,21 +1,21 @@
<h1>dibi metatypes example</h1> <h1>dibi metatypes example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
$res = dibi::query('SELECT * FROM [customers]'); $res = dibi::query('SELECT * FROM [customers]');
// auto-convert this column to integer // auto-convert this column to integer
$res->setType('customer_id', Dibi::FIELD_INTEGER); $res->setType('customer_id', Dibi::FIELD_INTEGER);
$res->setType('added', Dibi::FIELD_DATETIME, 'H:i j.n.Y'); $res->setType('added', Dibi::FIELD_DATETIME, 'H:i j.n.Y');
$row = $res->fetch(); $row = $res->fetch();
var_dump($row); var_dump($row);

View File

@@ -1,19 +1,19 @@
<h1>Nette::Debug && dibi example</h1> <h1>Nette::Debug && dibi example</h1>
<?php <?php
require_once 'Nette/Debug.php'; require_once 'Nette/Debug.php';
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
Debug::enable(); Debug::enable();
Debug::enableProfiler(); Debug::enableProfiler();
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
// throws error // throws error
dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38); dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38);

View File

@@ -1,25 +1,25 @@
<h1>Dibi profiler example</h1> <h1>Dibi profiler example</h1>
<?php <?php
require_once '../dibi/dibi.php'; 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);
} }
?> ?>
<p>Last query: <strong><?php echo dibi::$sql; ?></strong></p> <p>Last query: <strong><?php echo dibi::$sql; ?></strong></p>
<p>Number of queries: <strong><?php echo dibi::$numOfQueries; ?></strong></p> <p>Number of queries: <strong><?php echo dibi::$numOfQueries; ?></strong></p>
<p>Elapsed time for last query: <strong><?php echo sprintf('%0.3f', dibi::$elapsedTime * 1000); ?> ms</strong></p> <p>Elapsed time for last query: <strong><?php echo sprintf('%0.3f', dibi::$elapsedTime * 1000); ?> ms</strong></p>
<p>Total elapsed time: <strong><?php echo sprintf('%0.3f', dibi::$totalTime * 1000); ?> ms</strong></p> <p>Total elapsed time: <strong><?php echo sprintf('%0.3f', dibi::$totalTime * 1000); ?> ms</strong></p>

View File

@@ -1,66 +1,66 @@
<style> <style>
pre.dibi { padding-bottom: 10px; } pre.dibi { padding-bottom: 10px; }
</style> </style>
<h1>dibi SQL builder example</h1> <h1>dibi SQL builder example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
// required since PHP 5.1.0 // required since PHP 5.1.0
date_default_timezone_set('Europe/Prague'); 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);
// 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);
// SELECT // SELECT
$ipMask = '192.168.%'; $ipMask = '192.168.%';
$timestamp = mktime(0, 0, 0, 10, 13, 1997); $timestamp = mktime(0, 0, 0, 10, 13, 1997);
dibi::test(' dibi::test('
SELECT COUNT(*) as [count] SELECT COUNT(*) as [count]
FROM [comments] FROM [comments]
WHERE [ip] LIKE %s', $ipMask, ' WHERE [ip] LIKE %s', $ipMask, '
AND [date] > ', dibi::date($timestamp) AND [date] > ', dibi::date($timestamp)
); );
// IN array // IN array
$array = array(1, 2, 3); $array = array(1, 2, 3);
dibi::test(" dibi::test("
SELECT * SELECT *
FROM [people] FROM [people]
WHERE [id] IN (", $array, ") WHERE [id] IN (", $array, ")
"); ");

View File

@@ -1,51 +1,51 @@
<style> <style>
pre.dibi { padding-bottom: 10px; } pre.dibi { padding-bottom: 10px; }
</style> </style>
<h1>dibi conditional SQL example</h1> <h1>dibi conditional SQL example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
$cond1 = rand(0,2) < 1; $cond1 = rand(0,2) < 1;
$cond2 = rand(0,2) < 1; $cond2 = rand(0,2) < 1;
$foo = -1; $foo = -1;
$bar = 2; $bar = 2;
$name = $cond1 ? 'K%' : NULL; $name = $cond1 ? 'K%' : NULL;
// if & end // if & end
dibi::test(' dibi::test('
SELECT * SELECT *
FROM [customers] FROM [customers]
%if', isset($name), 'WHERE [name] LIKE %s', $name, '%end' %if', isset($name), 'WHERE [name] LIKE %s', $name, '%end'
); );
// if & else & (optional) end // if & else & (optional) end
dibi::test(" 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, "
"); ");
// nested condition // nested condition
dibi::test(' 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

@@ -1,44 +1,44 @@
<h1>dibi prefix & substitute example</h1> <h1>dibi prefix & substitute example</h1>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
// create new substitution :blog: ==> wp_ // create new substitution :blog: ==> wp_
dibi::addSubst('blog', 'wp_'); dibi::addSubst('blog', 'wp_');
// generate and dump SQL // generate and dump SQL
dibi::test("UPDATE [:blog:items] SET [text]='Hello World'"); dibi::test("UPDATE [:blog:items] SET [text]='Hello World'");
// create new substitution :: (empty) ==> my_ // create new substitution :: (empty) ==> my_
dibi::addSubst('', 'my_'); dibi::addSubst('', 'my_');
// generate and dump SQL // generate and dump SQL
dibi::test("UPDATE [database.::table] SET [text]='Hello World'"); dibi::test("UPDATE [database.::table] SET [text]='Hello World'");
function substFallBack($expr) function substFallBack($expr)
{ {
return 'the_' . $expr; return 'the_' . $expr;
} }
// create substitution fallback // create substitution fallback
dibi::setSubstFallBack('substFallBack'); dibi::setSubstFallBack('substFallBack');
// generate and dump SQL // generate and dump SQL
dibi::test("UPDATE [:account:user] SET [name]='John Doe'"); dibi::test("UPDATE [:account:user] SET [name]='John Doe'");

View File

@@ -1,28 +1,28 @@
<h1>dibi transaction example</h1> <h1>dibi transaction example</h1>
<pre> <pre>
<?php <?php
require_once '../dibi/dibi.php'; require_once '../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => 'sample.sdb', 'database' => 'sample.sdb',
)); ));
echo "<h2>Before:</h2>\n"; echo "<h2>Before:</h2>\n";
dibi::query('SELECT * FROM [products]')->dump(); 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();
echo "<h2>After:</h2>\n"; echo "<h2>After:</h2>\n";
dibi::query('SELECT * FROM [products]')->dump(); dibi::query('SELECT * FROM [products]')->dump();

View File

@@ -1,2 +1,2 @@
<a href="http://dibiphp.com" title="dibi - tiny 'n' smart database abstraction layer" <a href="http://dibiphp.com" title="dibi - tiny 'n' smart database abstraction layer"
><img src="dibi-powered.gif" width="80" height="15" alt="dibi powered" /></a> ><img src="dibi-powered.gif" width="80" height="15" alt="dibi powered" /></a>

View File

@@ -1,69 +1,69 @@
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
Tento text je NEOFICI<43>LN<4C>M p<>ekladem "Dibi license". Nevyjad<61>uje pr<70>vn<76> podstatu Tento text je NEOFICI<43>LN<4C>M p<>ekladem "Dibi license". Nevyjad<61>uje pr<70>vn<76> podstatu
podm<EFBFBD>nek pro <20><><EFBFBD>en<65> tohoto softwaru - k tomuto <20><>elu slou<6F><75> v<>hradn<64> p<>vodn<64> podm<EFBFBD>nek pro <20><><EFBFBD>en<65> tohoto softwaru - k tomuto <20><>elu slou<6F><75> v<>hradn<64> p<>vodn<64>
anglick<EFBFBD> verze licence. anglick<EFBFBD> verze licence.
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
Dibi Licence, verze 1 Dibi Licence, verze 1
====================== ======================
Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
V<EFBFBD>echna pr<70>va vyhrazena. V<EFBFBD>echna pr<70>va vyhrazena.
Tato licence je pr<70>vn<76> ujedn<64>n<EFBFBD> mezi v<>mi a Davidem Grudlem (d<>le Author) Tato licence je pr<70>vn<76> ujedn<64>n<EFBFBD> mezi v<>mi a Davidem Grudlem (d<>le Author)
pro pot<6F>eby pou<6F>it<69> "dibi" (d<>le "Software"). Z<>sk<73>n<EFBFBD>m, pou<6F>it<69>m pro pot<6F>eby pou<6F>it<69> "dibi" (d<>le "Software"). Z<>sk<73>n<EFBFBD>m, pou<6F>it<69>m
a/nebo zkop<6F>rov<6F>n<EFBFBD>m Software projevujete souhlas s t<>m, <20>e jste p<>e<EFBFBD>etli, a/nebo zkop<6F>rov<6F>n<EFBFBD>m Software projevujete souhlas s t<>m, <20>e jste p<>e<EFBFBD>etli,
porozum<EFBFBD>li a budete jednat v souladu s podm<64>nkami t<>to licence. porozum<EFBFBD>li a budete jednat v souladu s podm<64>nkami t<>to licence.
POVOLEN<EFBFBD> POU<4F>IT<49> POVOLEN<EFBFBD> POU<4F>IT<49>
---------------- ----------------
Je povoleno pou<6F><75>vat, kop<6F>rovat, modifikovat a distribuovat Software Je povoleno pou<6F><75>vat, kop<6F>rovat, modifikovat a distribuovat Software
a jeho dokumentaci, v p<>vodn<64>m i upravovan<61>m tvaru, pro jak<61>koliv <20><>el, a jeho dokumentaci, v p<>vodn<64>m i upravovan<61>m tvaru, pro jak<61>koliv <20><>el,
za p<>edpokladu, <20>e jsou spln<6C>ny tyto podm<64>nky: za p<>edpokladu, <20>e jsou spln<6C>ny tyto podm<64>nky:
1. Kopie t<>to licen<65>n<EFBFBD> smlouvy mus<75> b<>t sou<6F><75>st<73> distribuce. 1. Kopie t<>to licen<65>n<EFBFBD> smlouvy mus<75> b<>t sou<6F><75>st<73> distribuce.
2. <20><><EFBFBD>en<65> zdrojov<6F> k<>d mus<75> zachovat v<><76>e uvedenou informaci o autorsk<73>ch 2. <20><><EFBFBD>en<65> zdrojov<6F> k<>d mus<75> zachovat v<><76>e uvedenou informaci o autorsk<73>ch
pr<70>vech ve v<>ech souborech zdrojov<6F>ho k<>du. pr<70>vech ve v<>ech souborech zdrojov<6F>ho k<>du.
3. <20><><EFBFBD>en<65> bin<69>rn<72> tvar mus<75> reprodukovat v<><76>e uvedenou informaci o autorsk<73>ch 3. <20><><EFBFBD>en<65> bin<69>rn<72> tvar mus<75> reprodukovat v<><76>e uvedenou informaci o autorsk<73>ch
pr<70>vech v dokumentaci a/nebo jin<69>ch materi<72>lech poskytovan<61>ch s distribuc<75>. pr<70>vech v dokumentaci a/nebo jin<69>ch materi<72>lech poskytovan<61>ch s distribuc<75>.
4. Produkty odvozen<65> od Software mus<75> obsahovat potvrzen<65>, <20>e jsou odvozen<65> 4. Produkty odvozen<65> od Software mus<75> obsahovat potvrzen<65>, <20>e jsou odvozen<65>
od "dibi", ve sv<73> dokumentaci a/nebo jin<69>ch materi<72>lech od "dibi", ve sv<73> dokumentaci a/nebo jin<69>ch materi<72>lech
poskytovan<61>ch s distribuc<75>. poskytovan<61>ch s distribuc<75>.
5. N<>zev "dibi" nesm<73> b<>t pou<6F>it p<>i podpo<70>e nebo propagaci produkt<6B> 5. N<>zev "dibi" nesm<73> b<>t pou<6F>it p<>i podpo<70>e nebo propagaci produkt<6B>
odvozen<65>mi ze Software bez p<>edchoz<6F>ho p<>semn<6D>ho souhlasu Autora. odvozen<65>mi ze Software bez p<>edchoz<6F>ho p<>semn<6D>ho souhlasu Autora.
6. Produkty odvozen<65> od Software nesm<73> b<>t nazv<7A>ny "dibi", 6. Produkty odvozen<65> od Software nesm<73> b<>t nazv<7A>ny "dibi",
ani se nesm<73> "dibi" objevit v jejich n<>zvu bez p<>edchoz<6F>ho ani se nesm<73> "dibi" objevit v jejich n<>zvu bez p<>edchoz<6F>ho
p<>semn<6D>ho souhlasu Autora. p<>semn<6D>ho souhlasu Autora.
ZBAVEN<EFBFBD> ZODPOV<4F>DNOSTI ZBAVEN<EFBFBD> ZODPOV<4F>DNOSTI
--------------------- ---------------------
Souhlas<EFBFBD>te se zbaven<65>m zodpov<6F>dnosti a kryt<79>m Autora a p<>isp<73>vatel<65> v<><76>i Souhlas<EFBFBD>te se zbaven<65>m zodpov<6F>dnosti a kryt<79>m Autora a p<>isp<73>vatel<65> v<><76>i
jak<EFBFBD>mkoliv p<><70>m<EFBFBD>m, nep<65><70>m<EFBFBD>m, n<>hodn<64>m nebo n<>sledn<64>m odjinud poch<63>zej<65>c<EFBFBD>m <20>kod<6F>m, jak<EFBFBD>mkoliv p<><70>m<EFBFBD>m, nep<65><70>m<EFBFBD>m, n<>hodn<64>m nebo n<>sledn<64>m odjinud poch<63>zej<65>c<EFBFBD>m <20>kod<6F>m,
<EFBFBD>alob<EFBFBD>m nebo spor<6F>m, jako<6B> i p<>ed v<>emi souvisej<65>c<EFBFBD>mi n<>klady, z<>vazky, <EFBFBD>alob<EFBFBD>m nebo spor<6F>m, jako<6B> i p<>ed v<>emi souvisej<65>c<EFBFBD>mi n<>klady, z<>vazky,
od<EFBFBD>kodn<EFBFBD>n<EFBFBD>mi, <20>hradami nebo poplatky vypl<70>vaj<61>c<EFBFBD>ch z pou<6F><75>v<EFBFBD>n<EFBFBD> nebo od<EFBFBD>kodn<EFBFBD>n<EFBFBD>mi, <20>hradami nebo poplatky vypl<70>vaj<61>c<EFBFBD>ch z pou<6F><75>v<EFBFBD>n<EFBFBD> nebo
nespr<EFBFBD>vn<EFBFBD>ho u<>it<69> Software, nebo z poru<72>en<65> podm<64>nek t<>to licence. nespr<EFBFBD>vn<EFBFBD>ho u<>it<69> Software, nebo z poru<72>en<65> podm<64>nek t<>to licence.
Z<EFBFBD>RUKA SE NEPOSKYTUJE Z<EFBFBD>RUKA SE NEPOSKYTUJE
--------------------- ---------------------
TENTO SOFTWARE JE POSKYTOV<4F>N DR<44>ITELEM LICENCE A JEHO P<>ISP<53>VATELI "JAK STOJ<4F> A LE<4C><45>" TENTO SOFTWARE JE POSKYTOV<4F>N DR<44>ITELEM LICENCE A JEHO P<>ISP<53>VATELI "JAK STOJ<4F> A LE<4C><45>"
A JAK<41>KOLIV V<>SLOVN<56> NEBO P<>EDPOKL<4B>DAN<41> Z<>RUKY V<>ETN<54>, ALE NEJEN, P<>EDPOKL<4B>DAN<41>CH A JAK<41>KOLIV V<>SLOVN<56> NEBO P<>EDPOKL<4B>DAN<41> Z<>RUKY V<>ETN<54>, ALE NEJEN, P<>EDPOKL<4B>DAN<41>CH
OBCHODN<EFBFBD>CH Z<>RUK A Z<>RUKY VHODNOSTI PRO JAK<41>KOLIV <20><>EL JSOU POP<4F>ENY. OBCHODN<EFBFBD>CH Z<>RUK A Z<>RUKY VHODNOSTI PRO JAK<41>KOLIV <20><>EL JSOU POP<4F>ENY.
DR<EFBFBD>ITEL, ANI P<>ISP<53>VATEL<45> NEBUDOU V <20><>DN<44>M P<><50>PAD<41> ODPOV<4F>DNI ZA JAK<41>KOLIV P<><50>M<EFBFBD>, DR<EFBFBD>ITEL, ANI P<>ISP<53>VATEL<45> NEBUDOU V <20><>DN<44>M P<><50>PAD<41> ODPOV<4F>DNI ZA JAK<41>KOLIV P<><50>M<EFBFBD>,
NEP<EFBFBD><EFBFBD>M<EFBFBD>, N<>HODN<44>, ZVL<56><4C>TN<54>, P<><50>KLADN<44> NEBO VYPL<50>VAJ<41>C<EFBFBD> <20>KODY (V<>ETN<54>, ALE NEJEN, NEP<EFBFBD><EFBFBD>M<EFBFBD>, N<>HODN<44>, ZVL<56><4C>TN<54>, P<><50>KLADN<44> NEBO VYPL<50>VAJ<41>C<EFBFBD> <20>KODY (V<>ETN<54>, ALE NEJEN,
<EFBFBD>KOD VZNIKL<4B>CH NARU<52>EN<45>M DOD<4F>VEK ZBO<42><4F> NEBO SLU<4C>EB; ZTR<54>TOU POU<4F>ITELNOSTI, <EFBFBD>KOD VZNIKL<4B>CH NARU<52>EN<45>M DOD<4F>VEK ZBO<42><4F> NEBO SLU<4C>EB; ZTR<54>TOU POU<4F>ITELNOSTI,
DAT NEBO ZISK<53>; NEBO P<>ERU<52>EN<45>M OBCHODN<44> <20>INNOSTI) JAKKOLIV ZP<5A>SOBEN<45> NA Z<>KLAD<41> DAT NEBO ZISK<53>; NEBO P<>ERU<52>EN<45>M OBCHODN<44> <20>INNOSTI) JAKKOLIV ZP<5A>SOBEN<45> NA Z<>KLAD<41>
JAK<EFBFBD>KOLIV TEORIE O ZODPOV<4F>DNOSTI, A<> U<> PLYNOUC<55> Z JIN<49>HO SMLUVN<56>HO VZTAHU, JAK<EFBFBD>KOLIV TEORIE O ZODPOV<4F>DNOSTI, A<> U<> PLYNOUC<55> Z JIN<49>HO SMLUVN<56>HO VZTAHU,
UR<EFBFBD>IT<EFBFBD> ZODPOV<4F>DNOSTI NEBO P<>E<EFBFBD>INU (V<>ETN<54> NEDBALOSTI) NA JAK<41>MKOLIV ZP<5A>SOBU POU<4F>IT<49> UR<EFBFBD>IT<EFBFBD> ZODPOV<4F>DNOSTI NEBO P<>E<EFBFBD>INU (V<>ETN<54> NEDBALOSTI) NA JAK<41>MKOLIV ZP<5A>SOBU POU<4F>IT<49>
TOHOTO SOFTWARE, I V P<><50>PAD<41>, <20>E DR<44>ITEL PR<50>V BYL UPOZORN<52>N NA MO<4D>NOST TAKOV<4F>CH <20>KOD. TOHOTO SOFTWARE, I V P<><50>PAD<41>, <20>E DR<44>ITEL PR<50>V BYL UPOZORN<52>N NA MO<4D>NOST TAKOV<4F>CH <20>KOD.

View File

@@ -1,62 +1,62 @@
The Dibi License, Version 1 The Dibi License, Version 1
============================ ============================
Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com) Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
All rights reserved. All rights reserved.
This license is a legal agreement between you and David Grudl (the "Author") This license is a legal agreement between you and David Grudl (the "Author")
for the use of "dibi" (the "Software"). By obtaining, using and/or for the use of "dibi" (the "Software"). By obtaining, using and/or
copying the Software, you agree that you have read, understood, and will copying the Software, you agree that you have read, understood, and will
comply with the terms and conditions of this license. comply with the terms and conditions of this license.
PERMITTED USE PERMITTED USE
------------- -------------
You are permitted to use, copy, modify, and distribute the Software and its You are permitted to use, copy, modify, and distribute the Software and its
documentation, with or without modification, for any purpose, provided that documentation, with or without modification, for any purpose, provided that
the following conditions are met: the following conditions are met:
1. A copy of this license agreement must be included with the distribution. 1. A copy of this license agreement must be included with the distribution.
2. Redistributions of source code must retain the above copyright notice in 2. Redistributions of source code must retain the above copyright notice in
all source code files. all source code files.
3. Redistributions in binary form must reproduce the above copyright notice 3. Redistributions in binary form must reproduce the above copyright notice
in the documentation and/or other materials provided with the distribution. in the documentation and/or other materials provided with the distribution.
4. Products derived from the Software must include an acknowledgment that 4. Products derived from the Software must include an acknowledgment that
they are derived from "dibi" in their documentation and/or other they are derived from "dibi" in their documentation and/or other
materials provided with the distribution. materials provided with the distribution.
5. The name "dibi" must not be used to endorse or promote products 5. The name "dibi" must not be used to endorse or promote products
derived from the Software without prior written permission from Author. derived from the Software without prior written permission from Author.
6. Products derived from the Software may not be called "dibi", 6. Products derived from the Software may not be called "dibi",
nor may "dibi" appear in their name, without prior written nor may "dibi" appear in their name, without prior written
permission from Author. permission from Author.
INDEMNITY INDEMNITY
--------- ---------
You agree to indemnify and hold harmless the Author and any contributors You agree to indemnify and hold harmless the Author and any contributors
for any direct, indirect, incidental, or consequential third-party claims, for any direct, indirect, incidental, or consequential third-party claims,
actions or suits, as well as any related expenses, liabilities, damages, actions or suits, as well as any related expenses, liabilities, damages,
settlements or fees arising from your use or misuse of the Software, settlements or fees arising from your use or misuse of the Software,
or a violation of any terms of this license. or a violation of any terms of this license.
DISCLAIMER OF WARRANTY DISCLAIMER OF WARRANTY
---------------------- ----------------------
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,41 +1,41 @@
Dibi (c) David Grudl, 2005-2008 (http://davidgrudl.com) Dibi (c) David Grudl, 2005-2008 (http://davidgrudl.com)
Introduction Introduction
------------ ------------
Thank you for downloading Dibi! Thank you for downloading Dibi!
Database access functions in PHP are not standardised. This is class library Database access functions in PHP are not standardised. This is class library
to hide the differences between the different databases access. to hide the differences between the different databases access.
The files in this archive are released under the Dibi license. The files in this archive are released under the Dibi license.
See license.txt in this directory for a copy of the license. See license.txt in this directory for a copy of the license.
Documentation and Examples Documentation and Examples
-------------------------- --------------------------
Refer to the 'examples' directory for examples. Dibi documentation is Refer to the 'examples' directory for examples. Dibi documentation is
available on the homepage: available on the homepage:
http://dibiphp.com http://dibiphp.com
Dibi.compact Dibi.compact
------------ ------------
This is shrinked single-file version of whole Dibi, useful when you don't This is shrinked single-file version of whole Dibi, useful when you don't
want to modify library, but just use it. want to modify library, but just use it.
This is exactly the same as normal version, just only comments and This is exactly the same as normal version, just only comments and
whitespaces are removed. whitespaces are removed.
----- -----
For more information, visit the author's weblog (in czech language): For more information, visit the author's weblog (in czech language):
http://phpfashion.com http://phpfashion.com

View File

@@ -1,4 +1,3 @@
Dibi version 0.9 Dibi 0.9 (revision $WCREV$)
Revision: $WCREV$ Released on $WCDATE$
Date: $WCDATE$