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:
@@ -1,41 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "Nette license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://nettephp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @category Nette
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
/*namespace Nette;*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom output for Nette::Debug.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @package Nette
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
interface IDebuggable
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns custom panels.
|
||||
* @return array
|
||||
*/
|
||||
function getPanels();
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "Nette license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://nettephp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com
|
||||
* @category Nette
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
/*namespace Nette;*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom output for Nette::Debug.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @package Nette
|
||||
*/
|
||||
interface IDebuggable
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns custom panels.
|
||||
* @return array
|
||||
*/
|
||||
function getPanels();
|
||||
|
||||
}
|
||||
|
@@ -1,278 +1,277 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "Nette license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://nettephp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com/
|
||||
* @category Nette
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
/*namespace Nette;*/
|
||||
|
||||
|
||||
/**
|
||||
* Nette::Object is the ultimate ancestor of all instantiable classes.
|
||||
*
|
||||
* It defines some handful methods and enhances object core of PHP:
|
||||
* - access to undeclared members throws exceptions
|
||||
* - support for conventional properties with getters and setters
|
||||
* - support for event raising functionality
|
||||
* - ability to add new methods to class (extension methods)
|
||||
*
|
||||
* 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
|
||||
* and optional setter method (no setter method means read-only property).
|
||||
* <code>
|
||||
* $val = $obj->label; // equivalent to $val = $obj->getLabel();
|
||||
* $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette');
|
||||
* </code>
|
||||
* Property names are case-sensitive, and they are written in the camelCaps
|
||||
* or PascalCaps.
|
||||
*
|
||||
* Event functionality is provided by declaration of property named 'on{Something}'
|
||||
* Multiple handlers are allowed.
|
||||
* <code>
|
||||
* public $onClick; // declaration in class
|
||||
* $this->onClick[] = 'callback'; // attaching event handler
|
||||
* if (!empty($this->onClick)) ... // are there any handlers?
|
||||
* $this->onClick($sender, $arg); // raises the event with arguments
|
||||
* </code>
|
||||
*
|
||||
* Adding method to class (i.e. to all instances) works similar to JavaScript
|
||||
* prototype property. The syntax for adding a new method is:
|
||||
* <code>
|
||||
* function MyClass_prototype_newMethod(MyClass $obj, $arg, ...) { ... }
|
||||
* $obj = new MyClass;
|
||||
* $obj->newMethod($x); // equivalent to MyClass_prototype_newMethod($obj, $x);
|
||||
* </code>
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @package Nette
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
abstract class Object
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the name of the class of this object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getClass()
|
||||
{
|
||||
return get_class($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access to reflection.
|
||||
*
|
||||
* @return ReflectionObject
|
||||
*/
|
||||
final public function getReflection()
|
||||
{
|
||||
return new ReflectionObject($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call to undefined method.
|
||||
*
|
||||
* @param string method name
|
||||
* @param array arguments
|
||||
* @return mixed
|
||||
* @throws ::MemberAccessException
|
||||
*/
|
||||
protected function __call($name, $args)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
if ($name === '') {
|
||||
throw new /*::*/MemberAccessException("Call to class '$class' method without name.");
|
||||
}
|
||||
|
||||
// event functionality
|
||||
if (self::hasEvent($class, $name)) {
|
||||
$list = $this->$name;
|
||||
if (is_array($list) || $list instanceof Traversable) {
|
||||
foreach ($list as $handler) {
|
||||
call_user_func_array($handler, $args);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// object prototypes support Class__method()
|
||||
// (or use class Class__method { static function ... } with autoloading?)
|
||||
$cl = $class;
|
||||
do {
|
||||
if (function_exists($nm = $cl . '_prototype_' . $name)) {
|
||||
array_unshift($args, $this);
|
||||
return call_user_func_array($nm, $args);
|
||||
}
|
||||
} while ($cl = get_parent_class($cl));
|
||||
|
||||
throw new /*::*/MemberAccessException("Call to undefined method $class::$name().");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call to undefined static method.
|
||||
*
|
||||
* @param string method name (in lower case!)
|
||||
* @param array arguments
|
||||
* @return mixed
|
||||
* @throws ::MemberAccessException
|
||||
*/
|
||||
protected static function __callStatic($name, $args)
|
||||
{
|
||||
$class = get_called_class();
|
||||
throw new /*::*/MemberAccessException("Call to undefined static method $class::$name().");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns property value. Do not call directly.
|
||||
*
|
||||
* @param string property name
|
||||
* @return mixed property value
|
||||
* @throws ::MemberAccessException if the property is not defined.
|
||||
*/
|
||||
protected function &__get($name)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
if ($name === '') {
|
||||
throw new /*::*/MemberAccessException("Cannot read an class '$class' property without name.");
|
||||
}
|
||||
|
||||
// property getter support
|
||||
$m = 'get' . $name;
|
||||
if (self::hasAccessor($class, $m)) {
|
||||
// ampersands:
|
||||
// - 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';
|
||||
$val = $this->$m();
|
||||
return $val;
|
||||
|
||||
} else {
|
||||
throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets value of a property. Do not call directly.
|
||||
*
|
||||
* @param string property name
|
||||
* @param mixed property value
|
||||
* @return void
|
||||
* @throws ::MemberAccessException if the property is not defined or is read-only
|
||||
*/
|
||||
protected function __set($name, $value)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
if ($name === '') {
|
||||
throw new /*::*/MemberAccessException("Cannot assign to an class '$class' property without name.");
|
||||
}
|
||||
|
||||
// property setter support
|
||||
if (self::hasAccessor($class, 'get' . $name)) {
|
||||
$m = 'set' . $name;
|
||||
if (self::hasAccessor($class, $m)) {
|
||||
$this->$m($value);
|
||||
|
||||
} else {
|
||||
throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is property defined?
|
||||
*
|
||||
* @param string property name
|
||||
* @return bool
|
||||
*/
|
||||
protected function __isset($name)
|
||||
{
|
||||
return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access to undeclared property.
|
||||
*
|
||||
* @param string property name
|
||||
* @return void
|
||||
* @throws ::MemberAccessException
|
||||
*/
|
||||
protected function __unset($name)
|
||||
{
|
||||
$class = get_class($this);
|
||||
throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Has property an accessor?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasAccessor($c, $m)
|
||||
{
|
||||
static $cache;
|
||||
if (!isset($cache[$c])) {
|
||||
// get_class_methods returns private, protected and public methods of Object (doesn't matter)
|
||||
// and ONLY PUBLIC methods of descendants (perfect!)
|
||||
// but returns static methods too (nothing doing...)
|
||||
// and is much faster than reflection
|
||||
// (works good since 5.0.4)
|
||||
$cache[$c] = array_flip(get_class_methods($c));
|
||||
}
|
||||
// case-sensitive checking, capitalize the fourth character
|
||||
$m[3] = $m[3] & "\xDF";
|
||||
return isset($cache[$c][$m]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is property an event?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasEvent($c, $m)
|
||||
{
|
||||
return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m);
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "Nette license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://nettephp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @license http://nettephp.com/license Nette license
|
||||
* @link http://nettephp.com
|
||||
* @category Nette
|
||||
* @package Nette
|
||||
*/
|
||||
|
||||
/*namespace Nette;*/
|
||||
|
||||
|
||||
/**
|
||||
* Nette::Object is the ultimate ancestor of all instantiable classes.
|
||||
*
|
||||
* It defines some handful methods and enhances object core of PHP:
|
||||
* - access to undeclared members throws exceptions
|
||||
* - support for conventional properties with getters and setters
|
||||
* - support for event raising functionality
|
||||
* - ability to add new methods to class (extension methods)
|
||||
*
|
||||
* 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
|
||||
* and optional setter method (no setter method means read-only property).
|
||||
* <code>
|
||||
* $val = $obj->label; // equivalent to $val = $obj->getLabel();
|
||||
* $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette');
|
||||
* </code>
|
||||
* Property names are case-sensitive, and they are written in the camelCaps
|
||||
* or PascalCaps.
|
||||
*
|
||||
* Event functionality is provided by declaration of property named 'on{Something}'
|
||||
* Multiple handlers are allowed.
|
||||
* <code>
|
||||
* public $onClick; // declaration in class
|
||||
* $this->onClick[] = 'callback'; // attaching event handler
|
||||
* if (!empty($this->onClick)) ... // are there any handlers?
|
||||
* $this->onClick($sender, $arg); // raises the event with arguments
|
||||
* </code>
|
||||
*
|
||||
* Adding method to class (i.e. to all instances) works similar to JavaScript
|
||||
* prototype property. The syntax for adding a new method is:
|
||||
* <code>
|
||||
* function MyClass_prototype_newMethod(MyClass $obj, $arg, ...) { ... }
|
||||
* $obj = new MyClass;
|
||||
* $obj->newMethod($x); // equivalent to MyClass_prototype_newMethod($obj, $x);
|
||||
* </code>
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
||||
* @package Nette
|
||||
*/
|
||||
abstract class Object
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the name of the class of this object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getClass()
|
||||
{
|
||||
return get_class($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access to reflection.
|
||||
*
|
||||
* @return ReflectionObject
|
||||
*/
|
||||
final public function getReflection()
|
||||
{
|
||||
return new ReflectionObject($this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call to undefined method.
|
||||
*
|
||||
* @param string method name
|
||||
* @param array arguments
|
||||
* @return mixed
|
||||
* @throws ::MemberAccessException
|
||||
*/
|
||||
protected function __call($name, $args)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
if ($name === '') {
|
||||
throw new /*::*/MemberAccessException("Call to class '$class' method without name.");
|
||||
}
|
||||
|
||||
// event functionality
|
||||
if (self::hasEvent($class, $name)) {
|
||||
$list = $this->$name;
|
||||
if (is_array($list) || $list instanceof Traversable) {
|
||||
foreach ($list as $handler) {
|
||||
call_user_func_array($handler, $args);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// object prototypes support Class__method()
|
||||
// (or use class Class__method { static function ... } with autoloading?)
|
||||
$cl = $class;
|
||||
do {
|
||||
if (function_exists($nm = $cl . '_prototype_' . $name)) {
|
||||
array_unshift($args, $this);
|
||||
return call_user_func_array($nm, $args);
|
||||
}
|
||||
} while ($cl = get_parent_class($cl));
|
||||
|
||||
throw new /*::*/MemberAccessException("Call to undefined method $class::$name().");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call to undefined static method.
|
||||
*
|
||||
* @param string method name (in lower case!)
|
||||
* @param array arguments
|
||||
* @return mixed
|
||||
* @throws ::MemberAccessException
|
||||
*/
|
||||
protected static function __callStatic($name, $args)
|
||||
{
|
||||
$class = get_called_class();
|
||||
throw new /*::*/MemberAccessException("Call to undefined static method $class::$name().");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns property value. Do not call directly.
|
||||
*
|
||||
* @param string property name
|
||||
* @return mixed property value
|
||||
* @throws ::MemberAccessException if the property is not defined.
|
||||
*/
|
||||
protected function &__get($name)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
if ($name === '') {
|
||||
throw new /*::*/MemberAccessException("Cannot read an class '$class' property without name.");
|
||||
}
|
||||
|
||||
// property getter support
|
||||
$m = 'get' . $name;
|
||||
if (self::hasAccessor($class, $m)) {
|
||||
// ampersands:
|
||||
// - 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';
|
||||
$val = $this->$m();
|
||||
return $val;
|
||||
|
||||
} else {
|
||||
throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets value of a property. Do not call directly.
|
||||
*
|
||||
* @param string property name
|
||||
* @param mixed property value
|
||||
* @return void
|
||||
* @throws ::MemberAccessException if the property is not defined or is read-only
|
||||
*/
|
||||
protected function __set($name, $value)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
if ($name === '') {
|
||||
throw new /*::*/MemberAccessException("Cannot assign to an class '$class' property without name.");
|
||||
}
|
||||
|
||||
// property setter support
|
||||
if (self::hasAccessor($class, 'get' . $name)) {
|
||||
$m = 'set' . $name;
|
||||
if (self::hasAccessor($class, $m)) {
|
||||
$this->$m($value);
|
||||
|
||||
} else {
|
||||
throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is property defined?
|
||||
*
|
||||
* @param string property name
|
||||
* @return bool
|
||||
*/
|
||||
protected function __isset($name)
|
||||
{
|
||||
return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Access to undeclared property.
|
||||
*
|
||||
* @param string property name
|
||||
* @return void
|
||||
* @throws ::MemberAccessException
|
||||
*/
|
||||
protected function __unset($name)
|
||||
{
|
||||
$class = get_class($this);
|
||||
throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Has property an accessor?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasAccessor($c, $m)
|
||||
{
|
||||
static $cache;
|
||||
if (!isset($cache[$c])) {
|
||||
// get_class_methods returns private, protected and public methods of Object (doesn't matter)
|
||||
// and ONLY PUBLIC methods of descendants (perfect!)
|
||||
// but returns static methods too (nothing doing...)
|
||||
// and is much faster than reflection
|
||||
// (works good since 5.0.4)
|
||||
$cache[$c] = array_flip(get_class_methods($c));
|
||||
}
|
||||
// case-sensitive checking, capitalize the fourth character
|
||||
$m[3] = $m[3] & "\xDF";
|
||||
return isset($cache[$c][$m]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is property an event?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasEvent($c, $m)
|
||||
{
|
||||
return preg_match('#^on[A-Z]#', $m) && property_exists($c, $m);
|
||||
}
|
||||
|
||||
}
|
||||
|
1589
dibi/dibi.php
1589
dibi/dibi.php
File diff suppressed because it is too large
Load Diff
@@ -1,364 +1,364 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - '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
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiMsSqlDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('mssql')) {
|
||||
throw new DibiDriverException("PHP extension 'mssql' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'host', 'hostname');
|
||||
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @
|
||||
} else {
|
||||
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException("Can't connect to DB.");
|
||||
}
|
||||
|
||||
if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) { // intentionally @
|
||||
throw new DibiDriverException("Can't select DB '$config[database]'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
mssql_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @mssql_query($sql, $this->connection); // intentionally @
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
throw new DibiDriverException('Query error', 0, $sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return mssql_rows_affected($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
throw new NotSupportedException('MS SQL does not support autoincrementing.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('BEGIN TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . str_replace("'", "''", $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? -1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
// offset suppot is missing...
|
||||
if ($limit >= 0) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
}
|
||||
|
||||
if ($offset) {
|
||||
throw new NotImplementedException('Offset is not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return mssql_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return mssql_fetch_array($this->resultSet, $type ? MSSQL_ASSOC : MSSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
return mssql_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
mssql_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = mssql_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = (array) mssql_fetch_field($this->resultSet, $i);
|
||||
$info['table'] = $info['column_source'];
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - '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
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiMsSqlDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('mssql')) {
|
||||
throw new DibiDriverException("PHP extension 'mssql' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'host', 'hostname');
|
||||
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @
|
||||
} else {
|
||||
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException("Can't connect to DB.");
|
||||
}
|
||||
|
||||
if (isset($config['database']) && !@mssql_select_db($config['database'], $this->connection)) { // intentionally @
|
||||
throw new DibiDriverException("Can't select DB '$config[database]'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
mssql_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @mssql_query($sql, $this->connection); // intentionally @
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
throw new DibiDriverException('Query error', 0, $sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return mssql_rows_affected($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
throw new NotSupportedException('MS SQL does not support autoincrementing.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('BEGIN TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . str_replace("'", "''", $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? -1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
// offset suppot is missing...
|
||||
if ($limit >= 0) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
}
|
||||
|
||||
if ($offset) {
|
||||
throw new NotImplementedException('Offset is not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return mssql_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return mssql_fetch_array($this->resultSet, $type ? MSSQL_ASSOC : MSSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
return mssql_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
mssql_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = mssql_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = (array) mssql_fetch_field($this->resultSet, $i);
|
||||
$info['table'] = $info['column_source'];
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,432 +1,432 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for MySQL database.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'host' - the MySQL server host name
|
||||
* - 'port' - the port number to attempt to connect to the MySQL server
|
||||
* - 'socket' - the socket or named pipe
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'database' - the database name to select
|
||||
* - 'charset' - character encoding to set
|
||||
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
|
||||
* - 'options' - driver specific constants (MYSQL_*)
|
||||
* - '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
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiMySqlDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Is buffered (seekable and countable)?
|
||||
* @var bool
|
||||
*/
|
||||
private $buffered;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('mysql')) {
|
||||
throw new DibiDriverException("PHP extension 'mysql' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'host', 'hostname');
|
||||
DibiConnection::alias($config, 'options');
|
||||
|
||||
// default values
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password');
|
||||
if (!isset($config['host'])) {
|
||||
$host = ini_get('mysql.default_host');
|
||||
if ($host) {
|
||||
$config['host'] = $host;
|
||||
$config['port'] = ini_get('mysql.default_port');
|
||||
} else {
|
||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket');
|
||||
$config['host'] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($config['socket'])) {
|
||||
$host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']);
|
||||
} else {
|
||||
$host = ':' . $config['socket'];
|
||||
}
|
||||
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); // intentionally @
|
||||
} else {
|
||||
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); // intentionally @
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException(mysql_error(), mysql_errno());
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
$ok = FALSE;
|
||||
if (function_exists('mysql_set_charset')) {
|
||||
// affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.2.3)
|
||||
$ok = @mysql_set_charset($config['charset'], $this->connection); // intentionally @
|
||||
}
|
||||
if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); // intentionally @
|
||||
if (!$ok) $this->throwException();
|
||||
}
|
||||
|
||||
if (isset($config['database'])) {
|
||||
@mysql_select_db($config['database'], $this->connection) or $this->throwException(); // intentionally @
|
||||
}
|
||||
|
||||
if (isset($config['sqlmode'])) {
|
||||
if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); // intentionally @
|
||||
}
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
mysql_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
if ($this->buffered) {
|
||||
$this->resultSet = @mysql_query($sql, $this->connection); // intentionally @
|
||||
} else {
|
||||
$this->resultSet = @mysql_unbuffered_query($sql, $this->connection); // intentionally @
|
||||
}
|
||||
|
||||
if (mysql_errno($this->connection)) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return mysql_affected_rows($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return mysql_insert_id($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . mysql_real_escape_string($value, $this->connection) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
|
||||
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
|
||||
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
|
||||
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return mysql_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return mysql_fetch_array($this->resultSet, $type ? MYSQL_ASSOC : MYSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
return mysql_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
mysql_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = mysql_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = (array) mysql_fetch_field($this->resultSet, $i);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
throw new DibiDriverException(mysql_error($this->connection), mysql_errno($this->connection), $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for MySQL database.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'host' - the MySQL server host name
|
||||
* - 'port' - the port number to attempt to connect to the MySQL server
|
||||
* - 'socket' - the socket or named pipe
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'database' - the database name to select
|
||||
* - 'charset' - character encoding to set
|
||||
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
|
||||
* - 'options' - driver specific constants (MYSQL_*)
|
||||
* - '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
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiMySqlDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Is buffered (seekable and countable)?
|
||||
* @var bool
|
||||
*/
|
||||
private $buffered;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('mysql')) {
|
||||
throw new DibiDriverException("PHP extension 'mysql' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'host', 'hostname');
|
||||
DibiConnection::alias($config, 'options');
|
||||
|
||||
// default values
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password');
|
||||
if (!isset($config['host'])) {
|
||||
$host = ini_get('mysql.default_host');
|
||||
if ($host) {
|
||||
$config['host'] = $host;
|
||||
$config['port'] = ini_get('mysql.default_port');
|
||||
} else {
|
||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket');
|
||||
$config['host'] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($config['socket'])) {
|
||||
$host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']);
|
||||
} else {
|
||||
$host = ':' . $config['socket'];
|
||||
}
|
||||
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); // intentionally @
|
||||
} else {
|
||||
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); // intentionally @
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException(mysql_error(), mysql_errno());
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
$ok = FALSE;
|
||||
if (function_exists('mysql_set_charset')) {
|
||||
// affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.2.3)
|
||||
$ok = @mysql_set_charset($config['charset'], $this->connection); // intentionally @
|
||||
}
|
||||
if (!$ok) $ok = @mysql_query("SET NAMES '$config[charset]'", $this->connection); // intentionally @
|
||||
if (!$ok) $this->throwException();
|
||||
}
|
||||
|
||||
if (isset($config['database'])) {
|
||||
@mysql_select_db($config['database'], $this->connection) or $this->throwException(); // intentionally @
|
||||
}
|
||||
|
||||
if (isset($config['sqlmode'])) {
|
||||
if (!@mysql_query("SET sql_mode='$config[sqlmode]'", $this->connection)) $this->throwException(); // intentionally @
|
||||
}
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
mysql_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
if ($this->buffered) {
|
||||
$this->resultSet = @mysql_query($sql, $this->connection); // intentionally @
|
||||
} else {
|
||||
$this->resultSet = @mysql_unbuffered_query($sql, $this->connection); // intentionally @
|
||||
}
|
||||
|
||||
if (mysql_errno($this->connection)) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return mysql_affected_rows($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return mysql_insert_id($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . mysql_real_escape_string($value, $this->connection) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
|
||||
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
|
||||
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
|
||||
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return mysql_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return mysql_fetch_array($this->resultSet, $type ? MYSQL_ASSOC : MYSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
return mysql_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
mysql_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = mysql_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = (array) mysql_fetch_field($this->resultSet, $i);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
throw new DibiDriverException(mysql_error($this->connection), mysql_errno($this->connection), $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,411 +1,411 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for MySQL database via improved extension.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'host' - the MySQL server host name
|
||||
* - 'port' - the port number to attempt to connect to the MySQL server
|
||||
* - 'socket' - the socket or named pipe
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'database' - the database name to select
|
||||
* - 'charset' - character encoding to set
|
||||
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
|
||||
* - 'options' - driver specific constants (MYSQLI_*)
|
||||
* - '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
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiMySqliDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var mysqli
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var mysqli_result
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Is buffered (seekable and countable)?
|
||||
* @var bool
|
||||
*/
|
||||
private $buffered;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('mysqli')) {
|
||||
throw new DibiDriverException("PHP extension 'mysqli' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'host', 'hostname');
|
||||
DibiConnection::alias($config, 'options');
|
||||
DibiConnection::alias($config, 'database');
|
||||
|
||||
// default values
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw');
|
||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket');
|
||||
if (!isset($config['host'])) {
|
||||
$config['host'] = ini_get('mysqli.default_host');
|
||||
if (!isset($config['port'])) $config['port'] = ini_get('mysqli.default_port');
|
||||
if (!isset($config['host'])) $config['host'] = 'localhost';
|
||||
}
|
||||
|
||||
$this->connection = mysqli_init();
|
||||
@mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); // intentionally @
|
||||
|
||||
if ($errno = mysqli_connect_errno()) {
|
||||
throw new DibiDriverException(mysqli_connect_error(), $errno);
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
$ok = FALSE;
|
||||
if (version_compare(PHP_VERSION , '5.1.5', '>=')) {
|
||||
// affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.0.5, fixed in PHP 5.1.5)
|
||||
$ok = @mysqli_set_charset($this->connection, $config['charset']); // intentionally @
|
||||
}
|
||||
if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); // intentionally @
|
||||
if (!$ok) $this->throwException();
|
||||
}
|
||||
|
||||
if (isset($config['sqlmode'])) {
|
||||
if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException(); // intentionally @
|
||||
}
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
mysqli_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); // intentionally @
|
||||
|
||||
if (mysqli_errno($this->connection)) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_object($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return mysqli_affected_rows($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return mysqli_insert_id($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . mysqli_real_escape_string($this->connection, $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
|
||||
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
|
||||
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
|
||||
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return mysqli_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return mysqli_fetch_array($this->resultSet, $type ? MYSQLI_ASSOC : MYSQLI_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
return mysqli_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
mysqli_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = mysqli_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = (array) mysqli_fetch_field_direct($this->resultSet, $i);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection), $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mysqli
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mysqli_result
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for MySQL database via improved extension.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'host' - the MySQL server host name
|
||||
* - 'port' - the port number to attempt to connect to the MySQL server
|
||||
* - 'socket' - the socket or named pipe
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'database' - the database name to select
|
||||
* - 'charset' - character encoding to set
|
||||
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
|
||||
* - 'options' - driver specific constants (MYSQLI_*)
|
||||
* - '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
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiMySqliDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var mysqli
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var mysqli_result
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Is buffered (seekable and countable)?
|
||||
* @var bool
|
||||
*/
|
||||
private $buffered;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('mysqli')) {
|
||||
throw new DibiDriverException("PHP extension 'mysqli' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'host', 'hostname');
|
||||
DibiConnection::alias($config, 'options');
|
||||
DibiConnection::alias($config, 'database');
|
||||
|
||||
// default values
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw');
|
||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket');
|
||||
if (!isset($config['host'])) {
|
||||
$config['host'] = ini_get('mysqli.default_host');
|
||||
if (!isset($config['port'])) $config['port'] = ini_get('mysqli.default_port');
|
||||
if (!isset($config['host'])) $config['host'] = 'localhost';
|
||||
}
|
||||
|
||||
$this->connection = mysqli_init();
|
||||
@mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); // intentionally @
|
||||
|
||||
if ($errno = mysqli_connect_errno()) {
|
||||
throw new DibiDriverException(mysqli_connect_error(), $errno);
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
$ok = FALSE;
|
||||
if (version_compare(PHP_VERSION , '5.1.5', '>=')) {
|
||||
// affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.0.5, fixed in PHP 5.1.5)
|
||||
$ok = @mysqli_set_charset($this->connection, $config['charset']); // intentionally @
|
||||
}
|
||||
if (!$ok) $ok = @mysqli_query($this->connection, "SET NAMES '$config[charset]'"); // intentionally @
|
||||
if (!$ok) $this->throwException();
|
||||
}
|
||||
|
||||
if (isset($config['sqlmode'])) {
|
||||
if (!@mysqli_query($this->connection, "SET sql_mode='$config[sqlmode]'")) $this->throwException(); // intentionally @
|
||||
}
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
mysqli_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); // intentionally @
|
||||
|
||||
if (mysqli_errno($this->connection)) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_object($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return mysqli_affected_rows($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return mysqli_insert_id($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . mysqli_real_escape_string($this->connection, $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
|
||||
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
|
||||
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
|
||||
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return mysqli_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return mysqli_fetch_array($this->resultSet, $type ? MYSQLI_ASSOC : MYSQLI_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
return mysqli_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
mysqli_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = mysqli_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = (array) mysqli_fetch_field_direct($this->resultSet, $i);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection), $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mysqli
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mysqli_result
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,404 +1,404 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver interacting with databases via ODBC connections.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'dsn' - driver specific DSN
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - '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
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiOdbcDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Cursor.
|
||||
* @var int
|
||||
*/
|
||||
private $row = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('odbc')) {
|
||||
throw new DibiDriverException("PHP extension 'odbc' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
|
||||
// default values
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('odbc.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('odbc.default_pw');
|
||||
if (!isset($config['dsn'])) $config['dsn'] = ini_get('odbc.default_db');
|
||||
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']); // intentionally @
|
||||
} else {
|
||||
$this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); // intentionally @
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException(odbc_errormsg() . ' ' . odbc_error());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
odbc_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @odbc_exec($this->connection, $sql); // intentionally @
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return odbc_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
throw new NotSupportedException('ODBC does not support autoincrementing.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
if (!odbc_autocommit($this->connection, FALSE)) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!odbc_commit($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
odbc_autocommit($this->connection, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!odbc_rollback($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
odbc_autocommit($this->connection, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . str_replace("'", "''", $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? -1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("#m/d/Y#", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("#m/d/Y H:i:s#", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
// offset suppot is missing...
|
||||
if ($limit >= 0) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
}
|
||||
|
||||
if ($offset) throw new InvalidArgumentException('Offset is not implemented in driver odbc.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
// will return -1 with many drivers :-(
|
||||
return odbc_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
if ($type) {
|
||||
return odbc_fetch_array($this->resultSet, ++$this->row);
|
||||
} else {
|
||||
$set = $this->resultSet;
|
||||
if (!odbc_fetch_row($set, ++$this->row)) return FALSE;
|
||||
$count = odbc_num_fields($set);
|
||||
$cols = array();
|
||||
for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i);
|
||||
return $cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
$this->row = $row;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
odbc_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = odbc_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => odbc_field_name($this->resultSet, $i),
|
||||
'table' => NULL,
|
||||
'type' => odbc_field_type($this->resultSet, $i),
|
||||
'length' => odbc_field_len($this->resultSet, $i),
|
||||
'scale' => odbc_field_scale($this->resultSet, $i),
|
||||
'precision' => odbc_field_precision($this->resultSet, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver interacting with databases via ODBC connections.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'dsn' - driver specific DSN
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - '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
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiOdbcDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Cursor.
|
||||
* @var int
|
||||
*/
|
||||
private $row = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('odbc')) {
|
||||
throw new DibiDriverException("PHP extension 'odbc' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
|
||||
// default values
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('odbc.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('odbc.default_pw');
|
||||
if (!isset($config['dsn'])) $config['dsn'] = ini_get('odbc.default_db');
|
||||
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @odbc_connect($config['dsn'], $config['username'], $config['password']); // intentionally @
|
||||
} else {
|
||||
$this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); // intentionally @
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException(odbc_errormsg() . ' ' . odbc_error());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
odbc_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @odbc_exec($this->connection, $sql); // intentionally @
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return odbc_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
throw new NotSupportedException('ODBC does not support autoincrementing.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
if (!odbc_autocommit($this->connection, FALSE)) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!odbc_commit($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
odbc_autocommit($this->connection, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!odbc_rollback($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
odbc_autocommit($this->connection, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . str_replace("'", "''", $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? -1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("#m/d/Y#", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("#m/d/Y H:i:s#", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
// offset suppot is missing...
|
||||
if ($limit >= 0) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
}
|
||||
|
||||
if ($offset) throw new InvalidArgumentException('Offset is not implemented in driver odbc.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
// will return -1 with many drivers :-(
|
||||
return odbc_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
if ($type) {
|
||||
return odbc_fetch_array($this->resultSet, ++$this->row);
|
||||
} else {
|
||||
$set = $this->resultSet;
|
||||
if (!odbc_fetch_row($set, ++$this->row)) return FALSE;
|
||||
$count = odbc_num_fields($set);
|
||||
$cols = array();
|
||||
for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i);
|
||||
return $cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
$this->row = $row;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
odbc_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = odbc_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => odbc_field_name($this->resultSet, $i),
|
||||
'table' => NULL,
|
||||
'type' => odbc_field_type($this->resultSet, $i),
|
||||
'length' => odbc_field_len($this->resultSet, $i),
|
||||
'scale' => odbc_field_scale($this->resultSet, $i),
|
||||
'precision' => odbc_field_precision($this->resultSet, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,387 +1,387 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - '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
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiOracleDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $autocommit = TRUE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('oci8')) {
|
||||
throw new DibiDriverException("PHP extension 'oci8' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'database', 'db');
|
||||
DibiConnection::alias($config, 'charset');
|
||||
|
||||
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
||||
|
||||
if (!$this->connection) {
|
||||
$err = oci_error();
|
||||
throw new DibiDriverException($err['message'], $err['code']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
oci_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
|
||||
$this->resultSet = oci_parse($this->connection, $sql);
|
||||
if ($this->resultSet) {
|
||||
oci_execute($this->resultSet, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
|
||||
$err = oci_error($this->resultSet);
|
||||
if ($err) {
|
||||
throw new DibiDriverException($err['message'], $err['code'], $sql);
|
||||
}
|
||||
} else {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
throw new NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
throw new NotSupportedException('Oracle does not support autoincrementing.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->autocommit = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!oci_commit($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
$this->autocommit = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!oci_rollback($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
$this->autocommit = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("U", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("U", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return oci_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return oci_fetch_array($this->resultSet, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
throw new NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
oci_free_statement($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = oci_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => oci_field_name($this->resultSet, $i),
|
||||
'table' => NULL,
|
||||
'type' => oci_field_type($this->resultSet, $i),
|
||||
'size' => oci_field_size($this->resultSet, $i),
|
||||
'scale' => oci_field_scale($this->resultSet, $i),
|
||||
'precision' => oci_field_precision($this->resultSet, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
$err = oci_error($this->connection);
|
||||
throw new DibiDriverException($err['message'], $err['code'], $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - '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
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiOracleDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $autocommit = TRUE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('oci8')) {
|
||||
throw new DibiDriverException("PHP extension 'oci8' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'database', 'db');
|
||||
DibiConnection::alias($config, 'charset');
|
||||
|
||||
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
||||
|
||||
if (!$this->connection) {
|
||||
$err = oci_error();
|
||||
throw new DibiDriverException($err['message'], $err['code']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
oci_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
|
||||
$this->resultSet = oci_parse($this->connection, $sql);
|
||||
if ($this->resultSet) {
|
||||
oci_execute($this->resultSet, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
|
||||
$err = oci_error($this->resultSet);
|
||||
if ($err) {
|
||||
throw new DibiDriverException($err['message'], $err['code'], $sql);
|
||||
}
|
||||
} else {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
throw new NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
throw new NotSupportedException('Oracle does not support autoincrementing.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->autocommit = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!oci_commit($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
$this->autocommit = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!oci_rollback($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
$this->autocommit = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']'; // TODO: not tested
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("U", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("U", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return oci_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return oci_fetch_array($this->resultSet, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
throw new NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
oci_free_statement($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = oci_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => oci_field_name($this->resultSet, $i),
|
||||
'table' => NULL,
|
||||
'type' => oci_field_type($this->resultSet, $i),
|
||||
'size' => oci_field_size($this->resultSet, $i),
|
||||
'scale' => oci_field_scale($this->resultSet, $i),
|
||||
'precision' => oci_field_precision($this->resultSet, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
$err = oci_error($this->connection);
|
||||
throw new DibiDriverException($err['message'], $err['code'], $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,427 +1,427 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for PDO.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'dsn' - driver specific DSN
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'options' - driver specific options array
|
||||
* - 'pdo' - PDO object (optional)
|
||||
* - 'lazy' - if TRUE, connection will be established only when required
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiPdoDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var PDO
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var PDOStatement
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Affected rows.
|
||||
* @var int|FALSE
|
||||
*/
|
||||
private $affectedRows = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('pdo')) {
|
||||
throw new DibiDriverException("PHP extension 'pdo' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'dsn');
|
||||
DibiConnection::alias($config, 'pdo');
|
||||
DibiConnection::alias($config, 'options');
|
||||
|
||||
if ($config['pdo'] instanceof PDO) {
|
||||
$this->connection = $config['pdo'];
|
||||
|
||||
} else try {
|
||||
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new DibiDriverException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
if (!$this->connection) {
|
||||
throw new DibiDriverException('Connecting error.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->connection = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
// must detect if SQL returns result set or num of affected rows
|
||||
$cmd = strtoupper(substr(ltrim($sql), 0, 6));
|
||||
$list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1);
|
||||
|
||||
if (isset($list[$cmd])) {
|
||||
$this->resultSet = NULL;
|
||||
$this->affectedRows = $this->connection->exec($sql);
|
||||
|
||||
if ($this->affectedRows === FALSE) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
$this->resultSet = $this->connection->query($sql);
|
||||
$this->affectedRows = FALSE;
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return clone $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return $this->affectedRows;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
if (!$this->connection->beginTransaction()) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!$this->connection->commit()) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!$this->connection->rollBack()) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
return $this->connection->quote($value, PDO::PARAM_STR);
|
||||
|
||||
case dibi::FIELD_BINARY:
|
||||
return $this->connection->quote($value, PDO::PARAM_LOB);
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
switch ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
case 'mysql':
|
||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||
|
||||
case 'pgsql':
|
||||
$a = strrpos($value, '.');
|
||||
if ($a === FALSE) {
|
||||
return '"' . str_replace('"', '""', $value) . '"';
|
||||
} else {
|
||||
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
|
||||
}
|
||||
|
||||
case 'sqlite':
|
||||
case 'sqlite2':
|
||||
case 'odbc':
|
||||
case 'oci': // TODO: not tested
|
||||
case 'mssql':
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $this->connection->quote($value, PDO::PARAM_BOOL);
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
throw new NotSupportedException('PDO does not support applying limit or offset.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return $this->resultSet->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = $this->resultSet->columnCount();
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = @$this->resultSet->getColumnsMeta($i); // intentionally @
|
||||
if ($info === FALSE) {
|
||||
throw new DibiDriverException('Driver does not support meta data.');
|
||||
}
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
$err = $this->connection->errorInfo();
|
||||
throw new DibiDriverException("SQLSTATE[$err[0]]: $err[2]", $err[1], $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return PDO
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for PDO.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'dsn' - driver specific DSN
|
||||
* - 'username' (or 'user')
|
||||
* - 'password' (or 'pass')
|
||||
* - 'options' - driver specific options array
|
||||
* - 'pdo' - PDO object (optional)
|
||||
* - 'lazy' - if TRUE, connection will be established only when required
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiPdoDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var PDO
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var PDOStatement
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Affected rows.
|
||||
* @var int|FALSE
|
||||
*/
|
||||
private $affectedRows = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('pdo')) {
|
||||
throw new DibiDriverException("PHP extension 'pdo' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'username', 'user');
|
||||
DibiConnection::alias($config, 'password', 'pass');
|
||||
DibiConnection::alias($config, 'dsn');
|
||||
DibiConnection::alias($config, 'pdo');
|
||||
DibiConnection::alias($config, 'options');
|
||||
|
||||
if ($config['pdo'] instanceof PDO) {
|
||||
$this->connection = $config['pdo'];
|
||||
|
||||
} else try {
|
||||
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new DibiDriverException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
if (!$this->connection) {
|
||||
throw new DibiDriverException('Connecting error.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->connection = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
// must detect if SQL returns result set or num of affected rows
|
||||
$cmd = strtoupper(substr(ltrim($sql), 0, 6));
|
||||
$list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1);
|
||||
|
||||
if (isset($list[$cmd])) {
|
||||
$this->resultSet = NULL;
|
||||
$this->affectedRows = $this->connection->exec($sql);
|
||||
|
||||
if ($this->affectedRows === FALSE) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
$this->resultSet = $this->connection->query($sql);
|
||||
$this->affectedRows = FALSE;
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
$this->throwException($sql);
|
||||
}
|
||||
|
||||
return clone $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return $this->affectedRows;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
if (!$this->connection->beginTransaction()) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!$this->connection->commit()) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!$this->connection->rollBack()) {
|
||||
$this->throwException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
return $this->connection->quote($value, PDO::PARAM_STR);
|
||||
|
||||
case dibi::FIELD_BINARY:
|
||||
return $this->connection->quote($value, PDO::PARAM_LOB);
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
switch ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
case 'mysql':
|
||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||
|
||||
case 'pgsql':
|
||||
$a = strrpos($value, '.');
|
||||
if ($a === FALSE) {
|
||||
return '"' . str_replace('"', '""', $value) . '"';
|
||||
} else {
|
||||
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
|
||||
}
|
||||
|
||||
case 'sqlite':
|
||||
case 'sqlite2':
|
||||
case 'odbc':
|
||||
case 'oci': // TODO: not tested
|
||||
case 'mssql':
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $this->connection->quote($value, PDO::PARAM_BOOL);
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
throw new NotSupportedException('PDO does not support applying limit or offset.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return $this->resultSet->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = $this->resultSet->columnCount();
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = @$this->resultSet->getColumnsMeta($i); // intentionally @
|
||||
if ($info === FALSE) {
|
||||
throw new DibiDriverException('Driver does not support meta data.');
|
||||
}
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts database error to DibiDriverException.
|
||||
*
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
protected function throwException($sql = NULL)
|
||||
{
|
||||
$err = $this->connection->errorInfo();
|
||||
throw new DibiDriverException("SQLSTATE[$err[0]]: $err[2]", $err[1], $sql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return PDO
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,426 +1,426 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for PostgreSQL database.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service' - see PostgreSQL API
|
||||
* - 'string' - or use connection string
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'charset' - character encoding to set
|
||||
* - '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
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiPostgreDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Escape method.
|
||||
* @var bool
|
||||
*/
|
||||
private $escMethod = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('pgsql')) {
|
||||
throw new DibiDriverException("PHP extension 'pgsql' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
if (isset($config['string'])) {
|
||||
$string = $config['string'];
|
||||
} else {
|
||||
$string = '';
|
||||
foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) {
|
||||
if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
DibiDriverException::tryError();
|
||||
if (isset($config['persistent'])) {
|
||||
$this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW);
|
||||
} else {
|
||||
$this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW);
|
||||
}
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
throw new DibiDriverException($msg, 0);
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException('Connecting error.');
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
DibiDriverException::tryError();
|
||||
pg_set_client_encoding($this->connection, $config['charset']);
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
throw new DibiDriverException($msg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['schema'])) {
|
||||
$this->query('SET search_path TO ' . $config['schema']);
|
||||
}
|
||||
|
||||
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
pg_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @param bool update affected rows?
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @pg_query($this->connection, $sql); // intentionally @
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
throw new DibiDriverException(pg_last_error($this->connection), 0, $sql);
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return pg_affected_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
if ($sequence === NULL) {
|
||||
// PostgreSQL 8.1 is needed
|
||||
$has = $this->query("SELECT LASTVAL()");
|
||||
} else {
|
||||
$has = $this->query("SELECT CURRVAL('$sequence')");
|
||||
}
|
||||
|
||||
if (!$has) return FALSE;
|
||||
|
||||
$row = $this->fetch(FALSE);
|
||||
$this->free();
|
||||
return is_array($row) ? $row[0] : FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
if ($this->escMethod) {
|
||||
return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||
} else {
|
||||
return "'" . pg_escape_string($value) . "'";
|
||||
}
|
||||
|
||||
case dibi::FIELD_BINARY:
|
||||
if ($this->escMethod) {
|
||||
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
||||
} else {
|
||||
return "'" . pg_escape_bytea($value) . "'";
|
||||
}
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
$a = strrpos($value, '.');
|
||||
if ($a === FALSE) {
|
||||
return '"' . str_replace('"', '""', $value) . '"';
|
||||
} else {
|
||||
// table.col delimite as table."col"
|
||||
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
|
||||
}
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 'TRUE' : 'FALSE';
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_BINARY:
|
||||
return pg_unescape_bytea($value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit >= 0)
|
||||
$sql .= ' LIMIT ' . (int) $limit;
|
||||
|
||||
if ($offset > 0)
|
||||
$sql .= ' OFFSET ' . (int) $offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return pg_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return pg_fetch_array($this->resultSet, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
return pg_result_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
pg_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
$count = pg_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => pg_field_name($this->resultSet, $i),
|
||||
'table' => $hasTable ? pg_field_table($this->resultSet, $i) : NULL,
|
||||
'type' => pg_field_type($this->resultSet, $i),
|
||||
'size' => pg_field_size($this->resultSet, $i),
|
||||
'prtlen' => pg_field_prtlen($this->resultSet, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for PostgreSQL database.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service' - see PostgreSQL API
|
||||
* - 'string' - or use connection string
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'charset' - character encoding to set
|
||||
* - '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
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiPostgreDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Escape method.
|
||||
* @var bool
|
||||
*/
|
||||
private $escMethod = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('pgsql')) {
|
||||
throw new DibiDriverException("PHP extension 'pgsql' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
if (isset($config['string'])) {
|
||||
$string = $config['string'];
|
||||
} else {
|
||||
$string = '';
|
||||
foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) {
|
||||
if (isset($config[$key])) $string .= $key . '=' . $config[$key] . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
DibiDriverException::tryError();
|
||||
if (isset($config['persistent'])) {
|
||||
$this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW);
|
||||
} else {
|
||||
$this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW);
|
||||
}
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
throw new DibiDriverException($msg, 0);
|
||||
}
|
||||
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiDriverException('Connecting error.');
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
DibiDriverException::tryError();
|
||||
pg_set_client_encoding($this->connection, $config['charset']);
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
throw new DibiDriverException($msg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['schema'])) {
|
||||
$this->query('SET search_path TO ' . $config['schema']);
|
||||
}
|
||||
|
||||
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
pg_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @param bool update affected rows?
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
$this->resultSet = @pg_query($this->connection, $sql); // intentionally @
|
||||
|
||||
if ($this->resultSet === FALSE) {
|
||||
throw new DibiDriverException(pg_last_error($this->connection), 0, $sql);
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return pg_affected_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
if ($sequence === NULL) {
|
||||
// PostgreSQL 8.1 is needed
|
||||
$has = $this->query("SELECT LASTVAL()");
|
||||
} else {
|
||||
$has = $this->query("SELECT CURRVAL('$sequence')");
|
||||
}
|
||||
|
||||
if (!$has) return FALSE;
|
||||
|
||||
$row = $this->fetch(FALSE);
|
||||
$this->free();
|
||||
return is_array($row) ? $row[0] : FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
if ($this->escMethod) {
|
||||
return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||
} else {
|
||||
return "'" . pg_escape_string($value) . "'";
|
||||
}
|
||||
|
||||
case dibi::FIELD_BINARY:
|
||||
if ($this->escMethod) {
|
||||
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
||||
} else {
|
||||
return "'" . pg_escape_bytea($value) . "'";
|
||||
}
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
$a = strrpos($value, '.');
|
||||
if ($a === FALSE) {
|
||||
return '"' . str_replace('"', '""', $value) . '"';
|
||||
} else {
|
||||
// table.col delimite as table."col"
|
||||
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
|
||||
}
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 'TRUE' : 'FALSE';
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date("'Y-m-d H:i:s'", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_BINARY:
|
||||
return pg_unescape_bytea($value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit >= 0)
|
||||
$sql .= ' LIMIT ' . (int) $limit;
|
||||
|
||||
if ($offset > 0)
|
||||
$sql .= ' OFFSET ' . (int) $offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return pg_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return pg_fetch_array($this->resultSet, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
return pg_result_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
pg_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
$count = pg_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => pg_field_name($this->resultSet, $i),
|
||||
'table' => $hasTable ? pg_field_table($this->resultSet, $i) : NULL,
|
||||
'type' => pg_field_type($this->resultSet, $i),
|
||||
'size' => pg_field_size($this->resultSet, $i),
|
||||
'prtlen' => pg_field_prtlen($this->resultSet, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,381 +1,381 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for SQLite database.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'database' (or 'file') - the filename of the SQLite database
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
|
||||
* - 'lazy' - if TRUE, connection will be established only when required
|
||||
* - 'format:date' - how to format date in SQL (@see date)
|
||||
* - 'format:datetime' - how to format datetime in SQL (@see date)
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiSqliteDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Is buffered (seekable and countable)?
|
||||
* @var bool
|
||||
*/
|
||||
private $buffered;
|
||||
|
||||
|
||||
/**
|
||||
* Date and datetime format.
|
||||
* @var string
|
||||
*/
|
||||
private $fmtDate, $fmtDateTime;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('sqlite')) {
|
||||
throw new DibiDriverException("PHP extension 'sqlite' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'database', 'file');
|
||||
$this->fmtDate = isset($config['format:date']) ? $config['format:date'] : 'U';
|
||||
$this->fmtDateTime = isset($config['format:datetime']) ? $config['format:datetime'] : 'U';
|
||||
|
||||
$errorMsg = '';
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @sqlite_open($config['database'], 0666, $errorMsg); // intentionally @
|
||||
} else {
|
||||
$this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); // intentionally @
|
||||
}
|
||||
|
||||
if (!$this->connection) {
|
||||
throw new DibiDriverException($errorMsg);
|
||||
}
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
sqlite_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
DibiDriverException::tryError();
|
||||
if ($this->buffered) {
|
||||
$this->resultSet = sqlite_query($this->connection, $sql);
|
||||
} else {
|
||||
$this->resultSet = sqlite_unbuffered_query($this->connection, $sql);
|
||||
}
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
throw new DibiDriverException($msg, sqlite_last_error($this->connection), $sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return sqlite_changes($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return sqlite_last_insert_rowid($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('BEGIN');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . sqlite_escape_string($value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date($this->fmtDate, $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date($this->fmtDateTime, $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return sqlite_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return sqlite_fetch_array($this->resultSet, $type ? SQLITE_ASSOC : SQLITE_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
return sqlite_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = sqlite_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => sqlite_field_name($this->resultSet, $i),
|
||||
'table' => NULL,
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for SQLite database.
|
||||
*
|
||||
* Connection options:
|
||||
* - 'database' (or 'file') - the filename of the SQLite database
|
||||
* - 'persistent' - try to find a persistent link?
|
||||
* - 'unbuffered' - sends query without fetching and buffering the result rows automatically?
|
||||
* - 'lazy' - if TRUE, connection will be established only when required
|
||||
* - 'format:date' - how to format date in SQL (@see date)
|
||||
* - 'format:datetime' - how to format datetime in SQL (@see date)
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiSqliteDriver extends /*Nette::*/Object implements IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connection resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* Resultset resource.
|
||||
* @var resource
|
||||
*/
|
||||
private $resultSet;
|
||||
|
||||
|
||||
/**
|
||||
* Is buffered (seekable and countable)?
|
||||
* @var bool
|
||||
*/
|
||||
private $buffered;
|
||||
|
||||
|
||||
/**
|
||||
* Date and datetime format.
|
||||
* @var string
|
||||
*/
|
||||
private $fmtDate, $fmtDateTime;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('sqlite')) {
|
||||
throw new DibiDriverException("PHP extension 'sqlite' is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function connect(array &$config)
|
||||
{
|
||||
DibiConnection::alias($config, 'database', 'file');
|
||||
$this->fmtDate = isset($config['format:date']) ? $config['format:date'] : 'U';
|
||||
$this->fmtDateTime = isset($config['format:datetime']) ? $config['format:datetime'] : 'U';
|
||||
|
||||
$errorMsg = '';
|
||||
if (empty($config['persistent'])) {
|
||||
$this->connection = @sqlite_open($config['database'], 0666, $errorMsg); // intentionally @
|
||||
} else {
|
||||
$this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); // intentionally @
|
||||
}
|
||||
|
||||
if (!$this->connection) {
|
||||
throw new DibiDriverException($errorMsg);
|
||||
}
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
sqlite_close($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function query($sql)
|
||||
{
|
||||
DibiDriverException::tryError();
|
||||
if ($this->buffered) {
|
||||
$this->resultSet = sqlite_query($this->connection, $sql);
|
||||
} else {
|
||||
$this->resultSet = sqlite_unbuffered_query($this->connection, $sql);
|
||||
}
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
throw new DibiDriverException($msg, sqlite_last_error($this->connection), $sql);
|
||||
}
|
||||
|
||||
return is_resource($this->resultSet) ? clone $this : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return sqlite_changes($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
public function insertId($sequence)
|
||||
{
|
||||
return sqlite_last_insert_rowid($this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('BEGIN');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function escape($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::FIELD_TEXT:
|
||||
case dibi::FIELD_BINARY:
|
||||
return "'" . sqlite_escape_string($value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
return '[' . str_replace('.', '].[', $value) . ']';
|
||||
|
||||
case dibi::FIELD_BOOL:
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::FIELD_DATE:
|
||||
return date($this->fmtDate, $value);
|
||||
|
||||
case dibi::FIELD_DATETIME:
|
||||
return date($this->fmtDateTime, $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function unescape($value, $type)
|
||||
{
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
if ($limit < 0 && $offset < 1) return;
|
||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return sqlite_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch($type)
|
||||
{
|
||||
return sqlite_fetch_array($this->resultSet, $type ? SQLITE_ASSOC : SQLITE_NUM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function seek($row)
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
return sqlite_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->resultSet = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = sqlite_num_fields($this->resultSet);
|
||||
$meta = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => sqlite_field_name($this->resultSet, $i),
|
||||
'table' => NULL,
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection()
|
||||
{}
|
||||
|
||||
}
|
||||
|
@@ -1,497 +1,501 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi connection.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiConnection extends /*Nette::*/Object
|
||||
{
|
||||
/**
|
||||
* Current connection configuration.
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* IDibiDriver.
|
||||
* @var array
|
||||
*/
|
||||
private $driver;
|
||||
|
||||
/**
|
||||
* Is connected?
|
||||
* @var bool
|
||||
*/
|
||||
private $connected = FALSE;
|
||||
|
||||
/**
|
||||
* Is in transaction?
|
||||
* @var bool
|
||||
*/
|
||||
private $inTxn = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates object and (optionally) connects to a database.
|
||||
*
|
||||
* @param array|string|Nette::Collections::Hashtable connection parameters
|
||||
* @param string connection name
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct($config, $name = NULL)
|
||||
{
|
||||
// DSN string
|
||||
if (is_string($config)) {
|
||||
parse_str($config, $config);
|
||||
|
||||
} elseif ($config instanceof /*Nette::Collections::*/Hashtable) {
|
||||
$config = (array) $config;
|
||||
|
||||
} elseif (!is_array($config)) {
|
||||
throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::Hashtable.');
|
||||
}
|
||||
|
||||
if (!isset($config['driver'])) {
|
||||
$config['driver'] = dibi::$defaultDriver;
|
||||
}
|
||||
|
||||
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
|
||||
$class = "Dibi" . $driver . "Driver";
|
||||
if (!class_exists($class, FALSE)) {
|
||||
include_once __FILE__ . "/../../drivers/$driver.php";
|
||||
|
||||
if (!class_exists($class, FALSE)) {
|
||||
throw new DibiException("Unable to create instance of dibi driver class '$class'.");
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['result:objects'])) {
|
||||
// normalize
|
||||
$val = $config['result:objects'];
|
||||
$config['result:objects'] = is_string($val) && !is_numeric($val) ? $val : (bool) $val;
|
||||
}
|
||||
|
||||
$config['name'] = $name;
|
||||
$this->config = $config;
|
||||
$this->driver = new $class;
|
||||
|
||||
if (empty($config['lazy'])) {
|
||||
$this->connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final protected function connect()
|
||||
{
|
||||
if (!$this->connected) {
|
||||
$this->driver->connect($this->config);
|
||||
$this->connected = TRUE;
|
||||
dibi::notify($this, 'connected');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public function disconnect()
|
||||
{
|
||||
if ($this->connected) {
|
||||
if ($this->inTxn) {
|
||||
$this->rollback();
|
||||
}
|
||||
$this->driver->disconnect();
|
||||
$this->connected = FALSE;
|
||||
dibi::notify($this, 'disconnected');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns TRUE when connection was established.
|
||||
*
|
||||
* @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
|
||||
* @return mixed
|
||||
*/
|
||||
final public function getConfig($key = NULL, $default = NULL)
|
||||
{
|
||||
if ($key === NULL) {
|
||||
return $this->config;
|
||||
|
||||
} elseif (isset($this->config[$key])) {
|
||||
return $this->config[$key];
|
||||
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply configuration alias or default values.
|
||||
*
|
||||
* @param array connect configuration
|
||||
* @param string key
|
||||
* @param string alias key
|
||||
* @return void
|
||||
*/
|
||||
public static function alias(&$config, $key, $alias=NULL)
|
||||
{
|
||||
if (isset($config[$key])) return;
|
||||
|
||||
if ($alias !== NULL && isset($config[$alias])) {
|
||||
$config[$key] = $config[$alias];
|
||||
unset($config[$alias]);
|
||||
} else {
|
||||
$config[$key] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
final public function getResource()
|
||||
{
|
||||
return $this->driver->getResource();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates (translates) and executes SQL query.
|
||||
*
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiResult|NULL result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
final public function query($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$this->connect();
|
||||
$trans = new DibiTranslator($this->driver);
|
||||
if ($trans->translate($args)) {
|
||||
return $this->nativeQuery($trans->sql);
|
||||
} else {
|
||||
throw new DibiException('SQL translate error: ' . $trans->sql);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates and prints SQL query.
|
||||
*
|
||||
* @param array|mixed one or more arguments
|
||||
* @return bool
|
||||
*/
|
||||
final public function test($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$this->connect();
|
||||
$trans = new DibiTranslator($this->driver);
|
||||
$ok = $trans->translate($args);
|
||||
dibi::dump($trans->sql);
|
||||
return $ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return DibiResult|NULL result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
final public function nativeQuery($sql)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
dibi::$numOfQueries++;
|
||||
dibi::$sql = $sql;
|
||||
dibi::$elapsedTime = FALSE;
|
||||
$time = -microtime(TRUE);
|
||||
dibi::notify($this, 'beforeQuery', $sql);
|
||||
|
||||
if ($res = $this->driver->query($sql)) { // intentionally =
|
||||
$res = new DibiResult($res, $this->config);
|
||||
}
|
||||
|
||||
$time += microtime(TRUE);
|
||||
dibi::$elapsedTime = $time;
|
||||
dibi::$totalTime += $time;
|
||||
dibi::notify($this, 'afterQuery', $res);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int number of rows
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
$rows = $this->driver->affectedRows();
|
||||
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
|
||||
return $rows;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @param string optional sequence name
|
||||
* @return int
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function insertId($sequence = NULL)
|
||||
{
|
||||
$id = $this->driver->insertId($sequence);
|
||||
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
|
||||
return (int) $id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->connect();
|
||||
if ($this->inTxn) {
|
||||
throw new DibiException('There is already an active transaction.');
|
||||
}
|
||||
$this->driver->begin();
|
||||
$this->inTxn = TRUE;
|
||||
dibi::notify($this, 'begin');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!$this->inTxn) {
|
||||
throw new DibiException('There is no active transaction.');
|
||||
}
|
||||
$this->driver->commit();
|
||||
$this->inTxn = FALSE;
|
||||
dibi::notify($this, 'commit');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!$this->inTxn) {
|
||||
throw new DibiException('There is no active transaction.');
|
||||
}
|
||||
$this->driver->rollback();
|
||||
$this->inTxn = FALSE;
|
||||
dibi::notify($this, 'rollback');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
$this->driver->applyLimit($sql, $limit, $offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Import SQL dump from file - extreme fast!
|
||||
*
|
||||
* @param string filename
|
||||
* @return int count of sql commands
|
||||
*/
|
||||
public function loadFile($file)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
@set_time_limit(0); // intentionally @
|
||||
|
||||
$handle = @fopen($file, 'r'); // intentionally @
|
||||
if (!$handle) {
|
||||
throw new FileNotFoundException("Cannot open file '$file'.");
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$sql = '';
|
||||
while (!feof($handle)) {
|
||||
$s = fgets($handle);
|
||||
$sql .= $s;
|
||||
if (substr(rtrim($s), -1) === ';') {
|
||||
$this->driver->query($sql);
|
||||
$sql = '';
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
return $count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
public function getDibiReflection()
|
||||
{
|
||||
throw new NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prevents unserialization.
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prevents serialization.
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi connection.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiConnection extends /*Nette::*/Object
|
||||
{
|
||||
/**
|
||||
* Current connection configuration.
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* IDibiDriver.
|
||||
* @var array
|
||||
*/
|
||||
private $driver;
|
||||
|
||||
/**
|
||||
* Is connected?
|
||||
* @var bool
|
||||
*/
|
||||
private $connected = FALSE;
|
||||
|
||||
/**
|
||||
* Is in transaction?
|
||||
* @var bool
|
||||
*/
|
||||
private $inTxn = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates object and (optionally) connects to a database.
|
||||
*
|
||||
* @param array|string|Nette::Collections::Hashtable connection parameters
|
||||
* @param string connection name
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function __construct($config, $name = NULL)
|
||||
{
|
||||
if (class_exists(/*Nette::*/'Debug', FALSE)) {
|
||||
/*Nette::*/Debug::addColophon(array('dibi', 'getColophon'));
|
||||
}
|
||||
|
||||
// DSN string
|
||||
if (is_string($config)) {
|
||||
parse_str($config, $config);
|
||||
|
||||
} elseif ($config instanceof /*Nette::Collections::*/Hashtable) {
|
||||
$config = (array) $config;
|
||||
|
||||
} elseif (!is_array($config)) {
|
||||
throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::Hashtable.');
|
||||
}
|
||||
|
||||
if (!isset($config['driver'])) {
|
||||
$config['driver'] = dibi::$defaultDriver;
|
||||
}
|
||||
|
||||
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
|
||||
$class = "Dibi" . $driver . "Driver";
|
||||
if (!class_exists($class, FALSE)) {
|
||||
include_once __FILE__ . "/../../drivers/$driver.php";
|
||||
|
||||
if (!class_exists($class, FALSE)) {
|
||||
throw new DibiException("Unable to create instance of dibi driver class '$class'.");
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['result:objects'])) {
|
||||
// normalize
|
||||
$val = $config['result:objects'];
|
||||
$config['result:objects'] = is_string($val) && !is_numeric($val) ? $val : (bool) $val;
|
||||
}
|
||||
|
||||
$config['name'] = $name;
|
||||
$this->config = $config;
|
||||
$this->driver = new $class;
|
||||
|
||||
if (empty($config['lazy'])) {
|
||||
$this->connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final protected function connect()
|
||||
{
|
||||
if (!$this->connected) {
|
||||
$this->driver->connect($this->config);
|
||||
$this->connected = TRUE;
|
||||
dibi::notify($this, 'connected');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public function disconnect()
|
||||
{
|
||||
if ($this->connected) {
|
||||
if ($this->inTxn) {
|
||||
$this->rollback();
|
||||
}
|
||||
$this->driver->disconnect();
|
||||
$this->connected = FALSE;
|
||||
dibi::notify($this, 'disconnected');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns TRUE when connection was established.
|
||||
*
|
||||
* @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
|
||||
* @return mixed
|
||||
*/
|
||||
final public function getConfig($key = NULL, $default = NULL)
|
||||
{
|
||||
if ($key === NULL) {
|
||||
return $this->config;
|
||||
|
||||
} elseif (isset($this->config[$key])) {
|
||||
return $this->config[$key];
|
||||
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply configuration alias or default values.
|
||||
*
|
||||
* @param array connect configuration
|
||||
* @param string key
|
||||
* @param string alias key
|
||||
* @return void
|
||||
*/
|
||||
public static function alias(&$config, $key, $alias=NULL)
|
||||
{
|
||||
if (isset($config[$key])) return;
|
||||
|
||||
if ($alias !== NULL && isset($config[$alias])) {
|
||||
$config[$key] = $config[$alias];
|
||||
unset($config[$alias]);
|
||||
} else {
|
||||
$config[$key] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
final public function getResource()
|
||||
{
|
||||
return $this->driver->getResource();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates (translates) and executes SQL query.
|
||||
*
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiResult|NULL result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
final public function query($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$this->connect();
|
||||
$trans = new DibiTranslator($this->driver);
|
||||
if ($trans->translate($args)) {
|
||||
return $this->nativeQuery($trans->sql);
|
||||
} else {
|
||||
throw new DibiException('SQL translate error: ' . $trans->sql);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates and prints SQL query.
|
||||
*
|
||||
* @param array|mixed one or more arguments
|
||||
* @return bool
|
||||
*/
|
||||
final public function test($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$this->connect();
|
||||
$trans = new DibiTranslator($this->driver);
|
||||
$ok = $trans->translate($args);
|
||||
dibi::dump($trans->sql);
|
||||
return $ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return DibiResult|NULL result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
final public function nativeQuery($sql)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
dibi::$numOfQueries++;
|
||||
dibi::$sql = $sql;
|
||||
dibi::$elapsedTime = FALSE;
|
||||
$time = -microtime(TRUE);
|
||||
dibi::notify($this, 'beforeQuery', $sql);
|
||||
|
||||
if ($res = $this->driver->query($sql)) { // intentionally =
|
||||
$res = new DibiResult($res, $this->config);
|
||||
}
|
||||
|
||||
$time += microtime(TRUE);
|
||||
dibi::$elapsedTime = $time;
|
||||
dibi::$totalTime += $time;
|
||||
dibi::notify($this, 'afterQuery', $res);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int number of rows
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
$rows = $this->driver->affectedRows();
|
||||
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
|
||||
return $rows;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @param string optional sequence name
|
||||
* @return int
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function insertId($sequence = NULL)
|
||||
{
|
||||
$id = $this->driver->insertId($sequence);
|
||||
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
|
||||
return (int) $id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->connect();
|
||||
if ($this->inTxn) {
|
||||
throw new DibiException('There is already an active transaction.');
|
||||
}
|
||||
$this->driver->begin();
|
||||
$this->inTxn = TRUE;
|
||||
dibi::notify($this, 'begin');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!$this->inTxn) {
|
||||
throw new DibiException('There is no active transaction.');
|
||||
}
|
||||
$this->driver->commit();
|
||||
$this->inTxn = FALSE;
|
||||
dibi::notify($this, 'commit');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!$this->inTxn) {
|
||||
throw new DibiException('There is no active transaction.');
|
||||
}
|
||||
$this->driver->rollback();
|
||||
$this->inTxn = FALSE;
|
||||
dibi::notify($this, 'rollback');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
{
|
||||
$this->driver->applyLimit($sql, $limit, $offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Import SQL dump from file - extreme fast!
|
||||
*
|
||||
* @param string filename
|
||||
* @return int count of sql commands
|
||||
*/
|
||||
public function loadFile($file)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
@set_time_limit(0); // intentionally @
|
||||
|
||||
$handle = @fopen($file, 'r'); // intentionally @
|
||||
if (!$handle) {
|
||||
throw new FileNotFoundException("Cannot open file '$file'.");
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$sql = '';
|
||||
while (!feof($handle)) {
|
||||
$s = fgets($handle);
|
||||
$sql .= $s;
|
||||
if (substr(rtrim($s), -1) === ';') {
|
||||
$this->driver->query($sql);
|
||||
$sql = '';
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
return $count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
public function getDibiReflection()
|
||||
{
|
||||
throw new NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prevents unserialization.
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prevents serialization.
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,92 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of IDataSource for dibi.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiDataSource extends /*Nette::*/Object implements IDataSource
|
||||
{
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var string */
|
||||
private $sql;
|
||||
|
||||
/** @var int */
|
||||
private $count;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string SQL command or table name, as data source
|
||||
* @param DibiConnection connection
|
||||
*/
|
||||
public function __construct($sql, DibiConnection $connection = NULL)
|
||||
{
|
||||
if (strpos($sql, ' ') === FALSE) {
|
||||
// table name
|
||||
$this->sql = $sql;
|
||||
} else {
|
||||
// SQL command
|
||||
$this->sql = '(' . $sql . ') AS [source]';
|
||||
}
|
||||
|
||||
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param int offset
|
||||
* @param int limit
|
||||
* @param array columns
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator($offset = NULL, $limit = NULL, $cols = NULL)
|
||||
{
|
||||
return $this->connection->query('
|
||||
SELECT *
|
||||
FROM', $this->sql, '
|
||||
%ofs %lmt', $offset, $limit
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
if ($this->count === NULL) {
|
||||
$this->count = $this->connection->query('
|
||||
SELECT COUNT(*) FROM', $this->sql
|
||||
)->fetchSingle();
|
||||
}
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of IDataSource for dibi.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiDataSource extends /*Nette::*/Object implements IDataSource
|
||||
{
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var string */
|
||||
private $sql;
|
||||
|
||||
/** @var int */
|
||||
private $count;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string SQL command or table name, as data source
|
||||
* @param DibiConnection connection
|
||||
*/
|
||||
public function __construct($sql, DibiConnection $connection = NULL)
|
||||
{
|
||||
if (strpos($sql, ' ') === FALSE) {
|
||||
// table name
|
||||
$this->sql = $sql;
|
||||
} else {
|
||||
// SQL command
|
||||
$this->sql = '(' . $sql . ') AS [source]';
|
||||
}
|
||||
|
||||
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param int offset
|
||||
* @param int limit
|
||||
* @param array columns
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator($offset = NULL, $limit = NULL, $cols = NULL)
|
||||
{
|
||||
return $this->connection->query('
|
||||
SELECT *
|
||||
FROM', $this->sql, '
|
||||
%ofs %lmt', $offset, $limit
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
if ($this->count === NULL) {
|
||||
$this->count = $this->connection->query('
|
||||
SELECT COUNT(*) FROM', $this->sql
|
||||
)->fetchSingle();
|
||||
}
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,159 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi common exception.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* database server exception.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiDriverException extends DibiException implements /*Nette::*/IDebuggable
|
||||
{
|
||||
/** @var string */
|
||||
private static $errorMsg;
|
||||
|
||||
/** @var string */
|
||||
private $sql;
|
||||
|
||||
|
||||
/**
|
||||
* Construct an dibi driver exception.
|
||||
*
|
||||
* @param string Message describing the exception
|
||||
* @param int Some code
|
||||
* @param string SQL command
|
||||
*/
|
||||
public function __construct($message = NULL, $code = 0, $sql = NULL)
|
||||
{
|
||||
parent::__construct($message, (int) $code);
|
||||
$this->sql = $sql;
|
||||
dibi::notify(NULL, 'exception', $this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return string The SQL passed to the constructor
|
||||
*/
|
||||
final public function getSql()
|
||||
{
|
||||
return $this->sql;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return string string represenation of exception with SQL command
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************* interface Nette::IDebuggable ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Returns custom panels.
|
||||
* @return array
|
||||
*/
|
||||
public function getPanels()
|
||||
{
|
||||
$panels = array();
|
||||
if ($this->sql !== NULL) {
|
||||
$panels['SQL'] = array(
|
||||
'expanded' => TRUE,
|
||||
'content' => dibi::dump($this->sql, TRUE),
|
||||
);
|
||||
}
|
||||
return $panels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************* error catching ****************d*g**/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Starts catching potential errors/warnings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function tryError()
|
||||
{
|
||||
set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
|
||||
self::$errorMsg = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns catched error/warning message.
|
||||
*
|
||||
* @param string catched message
|
||||
* @return bool
|
||||
*/
|
||||
public static function catchError(& $message)
|
||||
{
|
||||
restore_error_handler();
|
||||
$message = self::$errorMsg;
|
||||
self::$errorMsg = NULL;
|
||||
return $message !== NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal error handler. Do not call directly.
|
||||
*/
|
||||
public static function _errorHandler($code, $message)
|
||||
{
|
||||
restore_error_handler();
|
||||
|
||||
if (ini_get('html_errors')) {
|
||||
$message = strip_tags($message);
|
||||
$message = html_entity_decode($message);
|
||||
}
|
||||
|
||||
self::$errorMsg = $message;
|
||||
}
|
||||
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi common exception.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* database server exception.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiDriverException extends DibiException implements /*Nette::*/IDebuggable
|
||||
{
|
||||
/** @var string */
|
||||
private static $errorMsg;
|
||||
|
||||
/** @var string */
|
||||
private $sql;
|
||||
|
||||
|
||||
/**
|
||||
* Construct an dibi driver exception.
|
||||
*
|
||||
* @param string Message describing the exception
|
||||
* @param int Some code
|
||||
* @param string SQL command
|
||||
*/
|
||||
public function __construct($message = NULL, $code = 0, $sql = NULL)
|
||||
{
|
||||
parent::__construct($message, (int) $code);
|
||||
$this->sql = $sql;
|
||||
dibi::notify(NULL, 'exception', $this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return string The SQL passed to the constructor
|
||||
*/
|
||||
final public function getSql()
|
||||
{
|
||||
return $this->sql;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return string string represenation of exception with SQL command
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************* interface Nette::IDebuggable ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Returns custom panels.
|
||||
* @return array
|
||||
*/
|
||||
public function getPanels()
|
||||
{
|
||||
$panels = array();
|
||||
if ($this->sql !== NULL) {
|
||||
$panels['SQL'] = array(
|
||||
'expanded' => TRUE,
|
||||
'content' => dibi::dump($this->sql, TRUE),
|
||||
);
|
||||
}
|
||||
return $panels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************* error catching ****************d*g**/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Starts catching potential errors/warnings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function tryError()
|
||||
{
|
||||
set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
|
||||
self::$errorMsg = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns catched error/warning message.
|
||||
*
|
||||
* @param string catched message
|
||||
* @return bool
|
||||
*/
|
||||
public static function catchError(& $message)
|
||||
{
|
||||
restore_error_handler();
|
||||
$message = self::$errorMsg;
|
||||
self::$errorMsg = NULL;
|
||||
return $message !== NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal error handler. Do not call directly.
|
||||
*/
|
||||
public static function _errorHandler($code, $message)
|
||||
{
|
||||
restore_error_handler();
|
||||
|
||||
if (ini_get('html_errors')) {
|
||||
$message = strip_tags($message);
|
||||
$message = html_entity_decode($message);
|
||||
}
|
||||
|
||||
self::$errorMsg = $message;
|
||||
}
|
||||
|
||||
}
|
@@ -1,329 +1,329 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi SQL builder via fluent interfaces. EXPERIMENTAL!
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
class DibiFluent extends /*Nette::*/Object
|
||||
{
|
||||
/** @var array */
|
||||
public static $masks = array(
|
||||
'SELECT' => array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY',
|
||||
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', '%end'),
|
||||
'UPDATE' => array('UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
|
||||
'INSERT' => array('INSERT', 'INTO', 'VALUES', 'SELECT', '%end'),
|
||||
'DELETE' => array('DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
|
||||
);
|
||||
|
||||
/** @var array */
|
||||
public static $separators = array(
|
||||
'SELECT' => ',',
|
||||
'FROM' => FALSE,
|
||||
'WHERE' => 'AND',
|
||||
'GROUP BY' => ',',
|
||||
'HAVING' => 'AND',
|
||||
'ORDER BY' => ',',
|
||||
'LIMIT' => FALSE,
|
||||
'OFFSET' => FALSE,
|
||||
'SET' => ',',
|
||||
'VALUES' => ',',
|
||||
'INTO' => FALSE,
|
||||
);
|
||||
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var string */
|
||||
private $command;
|
||||
|
||||
/** @var array */
|
||||
private $clauses = array();
|
||||
|
||||
/** @var array */
|
||||
private $flags = array();
|
||||
|
||||
/** @var array */
|
||||
private $cursor;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param DibiConnection
|
||||
*/
|
||||
public function __construct(DibiConnection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Appends new argument to the clause.
|
||||
* @param string clause name
|
||||
* @param array arguments
|
||||
* @return DibiFluent provides a fluent interface
|
||||
*/
|
||||
public function __call($clause, $args)
|
||||
{
|
||||
$clause = self::_clause($clause);
|
||||
|
||||
// lazy initialization
|
||||
if ($this->command === NULL) {
|
||||
if (isset(self::$masks[$clause])) {
|
||||
$this->clauses = array_fill_keys(self::$masks[$clause], NULL);
|
||||
}
|
||||
$this->cursor = & $this->clauses[$clause];
|
||||
$this->cursor = array();
|
||||
$this->command = $clause;
|
||||
}
|
||||
|
||||
// special types or argument
|
||||
if (count($args) === 1) {
|
||||
$arg = $args[0];
|
||||
// TODO: really ignore TRUE?
|
||||
if ($arg === TRUE) {
|
||||
$args = array();
|
||||
|
||||
} elseif (is_string($arg) && preg_match('#^[a-z][a-z0-9_.]*$#i', $arg)) {
|
||||
$args = array('%n', $arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists($clause, $this->clauses)) {
|
||||
// append to clause
|
||||
$this->cursor = & $this->clauses[$clause];
|
||||
|
||||
// TODO: really delete?
|
||||
if ($args === array(FALSE)) {
|
||||
$this->cursor = NULL;
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (isset(self::$separators[$clause])) {
|
||||
$sep = self::$separators[$clause];
|
||||
if ($sep === FALSE) {
|
||||
$this->cursor = array();
|
||||
|
||||
} elseif (!empty($this->cursor)) {
|
||||
$this->cursor[] = $sep;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// append to currect flow
|
||||
if ($args === array(FALSE)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->cursor[] = $clause;
|
||||
}
|
||||
|
||||
if ($this->cursor === NULL) {
|
||||
$this->cursor = array();
|
||||
}
|
||||
|
||||
array_splice($this->cursor, count($this->cursor), 0, $args);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Switch to a clause.
|
||||
* @param string clause name
|
||||
* @return DibiFluent provides a fluent interface
|
||||
*/
|
||||
public function clause($clause, $remove = FALSE)
|
||||
{
|
||||
$this->cursor = & $this->clauses[self::_clause($clause)];
|
||||
|
||||
if ($remove) {
|
||||
$this->cursor = NULL;
|
||||
|
||||
} elseif ($this->cursor === NULL) {
|
||||
$this->cursor = array();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change a SQL flag.
|
||||
* @param string flag name
|
||||
* @param bool value
|
||||
* @return DibiFluent provides a fluent interface
|
||||
*/
|
||||
public function setFlag($flag, $value = TRUE)
|
||||
{
|
||||
$flag = strtoupper($flag);
|
||||
if ($value) {
|
||||
$this->flags[$flag] = TRUE;
|
||||
} else {
|
||||
unset($this->flags[$flag]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is a flag set?
|
||||
* @param string flag name
|
||||
* @return bool
|
||||
*/
|
||||
final public function getFlag($flag, $value = TRUE)
|
||||
{
|
||||
return isset($this->flags[strtoupper($flag)]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns SQL command.
|
||||
* @return string
|
||||
*/
|
||||
final public function getCommand()
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates and executes SQL query.
|
||||
* @return DibiResult|NULL result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
return $this->connection->query($this->_export());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates, executes SQL query and fetches the single row.
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function fetch()
|
||||
{
|
||||
if ($this->command === 'SELECT') {
|
||||
$this->clauses['LIMIT'] = array(1);
|
||||
}
|
||||
return $this->connection->query($this->_export())->fetch();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates and prints SQL query or it's part.
|
||||
* @param string clause name
|
||||
* @return bool
|
||||
*/
|
||||
public function test($clause = NULL)
|
||||
{
|
||||
return $this->connection->test($this->_export($clause));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates parameters for DibiTranslator.
|
||||
* @param string clause name
|
||||
* @return array
|
||||
*/
|
||||
protected function _export($clause = NULL)
|
||||
{
|
||||
if ($clause === NULL) {
|
||||
$data = $this->clauses;
|
||||
|
||||
} else {
|
||||
$clause = self::_clause($clause);
|
||||
if (array_key_exists($clause, $this->clauses)) {
|
||||
$data = array($clause => $this->clauses[$clause]);
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
$args = array();
|
||||
foreach ($data as $clause => $statement) {
|
||||
if ($statement !== NULL) {
|
||||
if ($clause[0] !== '%') {
|
||||
$args[] = $clause;
|
||||
if ($clause === $this->command) {
|
||||
$args[] = implode(' ', array_keys($this->flags));
|
||||
}
|
||||
}
|
||||
array_splice($args, count($args), 0, $statement);
|
||||
}
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Format camelCase clause name to UPPER CASE.
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
private static function _clause($s)
|
||||
{
|
||||
if ($s === 'order' || $s === 'group') {
|
||||
$s .= 'By';
|
||||
trigger_error("Did you mean '$s'?", E_USER_NOTICE);
|
||||
}
|
||||
return strtoupper(preg_replace('#[A-Z]#', ' $0', $s));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns (highlighted) SQL query.
|
||||
* @return string
|
||||
*/
|
||||
final public function __toString()
|
||||
{
|
||||
ob_start();
|
||||
$this->test();
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// PHP < 5.2 compatibility
|
||||
if (!function_exists('array_fill_keys')) {
|
||||
function array_fill_keys($keys, $value)
|
||||
{
|
||||
return array_combine($keys, array_fill(0, count($keys), $value));
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi SQL builder via fluent interfaces. EXPERIMENTAL!
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiFluent extends /*Nette::*/Object
|
||||
{
|
||||
/** @var array */
|
||||
public static $masks = array(
|
||||
'SELECT' => array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY',
|
||||
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', '%end'),
|
||||
'UPDATE' => array('UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
|
||||
'INSERT' => array('INSERT', 'INTO', 'VALUES', 'SELECT', '%end'),
|
||||
'DELETE' => array('DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
|
||||
);
|
||||
|
||||
/** @var array */
|
||||
public static $separators = array(
|
||||
'SELECT' => ',',
|
||||
'FROM' => FALSE,
|
||||
'WHERE' => 'AND',
|
||||
'GROUP BY' => ',',
|
||||
'HAVING' => 'AND',
|
||||
'ORDER BY' => ',',
|
||||
'LIMIT' => FALSE,
|
||||
'OFFSET' => FALSE,
|
||||
'SET' => ',',
|
||||
'VALUES' => ',',
|
||||
'INTO' => FALSE,
|
||||
);
|
||||
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var string */
|
||||
private $command;
|
||||
|
||||
/** @var array */
|
||||
private $clauses = array();
|
||||
|
||||
/** @var array */
|
||||
private $flags = array();
|
||||
|
||||
/** @var array */
|
||||
private $cursor;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param DibiConnection
|
||||
*/
|
||||
public function __construct(DibiConnection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Appends new argument to the clause.
|
||||
* @param string clause name
|
||||
* @param array arguments
|
||||
* @return DibiFluent provides a fluent interface
|
||||
*/
|
||||
public function __call($clause, $args)
|
||||
{
|
||||
$clause = self::_clause($clause);
|
||||
|
||||
// lazy initialization
|
||||
if ($this->command === NULL) {
|
||||
if (isset(self::$masks[$clause])) {
|
||||
$this->clauses = array_fill_keys(self::$masks[$clause], NULL);
|
||||
}
|
||||
$this->cursor = & $this->clauses[$clause];
|
||||
$this->cursor = array();
|
||||
$this->command = $clause;
|
||||
}
|
||||
|
||||
// special types or argument
|
||||
if (count($args) === 1) {
|
||||
$arg = $args[0];
|
||||
// TODO: really ignore TRUE?
|
||||
if ($arg === TRUE) {
|
||||
$args = array();
|
||||
|
||||
} elseif (is_string($arg) && preg_match('#^[a-z][a-z0-9_.]*$#i', $arg)) {
|
||||
$args = array('%n', $arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists($clause, $this->clauses)) {
|
||||
// append to clause
|
||||
$this->cursor = & $this->clauses[$clause];
|
||||
|
||||
// TODO: really delete?
|
||||
if ($args === array(FALSE)) {
|
||||
$this->cursor = NULL;
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (isset(self::$separators[$clause])) {
|
||||
$sep = self::$separators[$clause];
|
||||
if ($sep === FALSE) {
|
||||
$this->cursor = array();
|
||||
|
||||
} elseif (!empty($this->cursor)) {
|
||||
$this->cursor[] = $sep;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// append to currect flow
|
||||
if ($args === array(FALSE)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->cursor[] = $clause;
|
||||
}
|
||||
|
||||
if ($this->cursor === NULL) {
|
||||
$this->cursor = array();
|
||||
}
|
||||
|
||||
array_splice($this->cursor, count($this->cursor), 0, $args);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Switch to a clause.
|
||||
* @param string clause name
|
||||
* @return DibiFluent provides a fluent interface
|
||||
*/
|
||||
public function clause($clause, $remove = FALSE)
|
||||
{
|
||||
$this->cursor = & $this->clauses[self::_clause($clause)];
|
||||
|
||||
if ($remove) {
|
||||
$this->cursor = NULL;
|
||||
|
||||
} elseif ($this->cursor === NULL) {
|
||||
$this->cursor = array();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change a SQL flag.
|
||||
* @param string flag name
|
||||
* @param bool value
|
||||
* @return DibiFluent provides a fluent interface
|
||||
*/
|
||||
public function setFlag($flag, $value = TRUE)
|
||||
{
|
||||
$flag = strtoupper($flag);
|
||||
if ($value) {
|
||||
$this->flags[$flag] = TRUE;
|
||||
} else {
|
||||
unset($this->flags[$flag]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is a flag set?
|
||||
* @param string flag name
|
||||
* @return bool
|
||||
*/
|
||||
final public function getFlag($flag, $value = TRUE)
|
||||
{
|
||||
return isset($this->flags[strtoupper($flag)]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns SQL command.
|
||||
* @return string
|
||||
*/
|
||||
final public function getCommand()
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates and executes SQL query.
|
||||
* @return DibiResult|NULL result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
return $this->connection->query($this->_export());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates, executes SQL query and fetches the single row.
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function fetch()
|
||||
{
|
||||
if ($this->command === 'SELECT') {
|
||||
$this->clauses['LIMIT'] = array(1);
|
||||
}
|
||||
return $this->connection->query($this->_export())->fetch();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates and prints SQL query or it's part.
|
||||
* @param string clause name
|
||||
* @return bool
|
||||
*/
|
||||
public function test($clause = NULL)
|
||||
{
|
||||
return $this->connection->test($this->_export($clause));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates parameters for DibiTranslator.
|
||||
* @param string clause name
|
||||
* @return array
|
||||
*/
|
||||
protected function _export($clause = NULL)
|
||||
{
|
||||
if ($clause === NULL) {
|
||||
$data = $this->clauses;
|
||||
|
||||
} else {
|
||||
$clause = self::_clause($clause);
|
||||
if (array_key_exists($clause, $this->clauses)) {
|
||||
$data = array($clause => $this->clauses[$clause]);
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
$args = array();
|
||||
foreach ($data as $clause => $statement) {
|
||||
if ($statement !== NULL) {
|
||||
if ($clause[0] !== '%') {
|
||||
$args[] = $clause;
|
||||
if ($clause === $this->command) {
|
||||
$args[] = implode(' ', array_keys($this->flags));
|
||||
}
|
||||
}
|
||||
array_splice($args, count($args), 0, $statement);
|
||||
}
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Format camelCase clause name to UPPER CASE.
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
private static function _clause($s)
|
||||
{
|
||||
if ($s === 'order' || $s === 'group') {
|
||||
$s .= 'By';
|
||||
trigger_error("Did you mean '$s'?", E_USER_NOTICE);
|
||||
}
|
||||
return strtoupper(preg_replace('#[A-Z]#', ' $0', $s));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns (highlighted) SQL query.
|
||||
* @return string
|
||||
*/
|
||||
final public function __toString()
|
||||
{
|
||||
ob_start();
|
||||
$this->test();
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// PHP < 5.2 compatibility
|
||||
if (!function_exists('array_fill_keys')) {
|
||||
function array_fill_keys($keys, $value)
|
||||
{
|
||||
return array_combine($keys, array_fill(0, count($keys), $value));
|
||||
}
|
||||
}
|
||||
|
@@ -1,106 +1,106 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi basic logger & profiler (experimental).
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
final class DibiLogger extends /*Nette::*/Object
|
||||
{
|
||||
/** @var string Name of the file where SQL errors should be logged */
|
||||
private $file;
|
||||
|
||||
/** @var bool */
|
||||
public $logErrors = TRUE;
|
||||
|
||||
/** @var bool */
|
||||
public $logQueries = TRUE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string filename
|
||||
*/
|
||||
public function __construct($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback).
|
||||
*
|
||||
* @param DibiConnection
|
||||
* @param string event name
|
||||
* @param mixed
|
||||
* @return void
|
||||
*/
|
||||
public function handler($connection, $event, $arg)
|
||||
{
|
||||
if ($event === 'afterQuery' && $this->logQueries) {
|
||||
$this->write(
|
||||
"OK: " . dibi::$sql
|
||||
. ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '')
|
||||
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
|
||||
. "\n-- driver: " . $connection->getConfig('driver')
|
||||
. "\n-- " . date('Y-m-d H:i:s')
|
||||
. "\n\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event === 'exception' && $this->logErrors) {
|
||||
// $arg is DibiDriverException
|
||||
$message = $arg->getMessage();
|
||||
$code = $arg->getCode();
|
||||
if ($code) {
|
||||
$message = "[$code] $message";
|
||||
}
|
||||
|
||||
$this->write(
|
||||
"ERROR: $message"
|
||||
. "\n-- SQL: " . dibi::$sql
|
||||
. "\n-- driver: " //. $connection->getConfig('driver')
|
||||
. ";\n-- " . date('Y-m-d H:i:s')
|
||||
. "\n\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function write($message)
|
||||
{
|
||||
$handle = fopen($this->file, 'a');
|
||||
if (!$handle) return; // or throw exception?
|
||||
|
||||
flock($handle, LOCK_EX);
|
||||
fwrite($handle, $message);
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi basic logger & profiler (experimental).
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
final class DibiLogger extends /*Nette::*/Object
|
||||
{
|
||||
/** @var string Name of the file where SQL errors should be logged */
|
||||
private $file;
|
||||
|
||||
/** @var bool */
|
||||
public $logErrors = TRUE;
|
||||
|
||||
/** @var bool */
|
||||
public $logQueries = TRUE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string filename
|
||||
*/
|
||||
public function __construct($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback).
|
||||
*
|
||||
* @param DibiConnection
|
||||
* @param string event name
|
||||
* @param mixed
|
||||
* @return void
|
||||
*/
|
||||
public function handler($connection, $event, $arg)
|
||||
{
|
||||
if ($event === 'afterQuery' && $this->logQueries) {
|
||||
$this->write(
|
||||
"OK: " . dibi::$sql
|
||||
. ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '')
|
||||
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
|
||||
. "\n-- driver: " . $connection->getConfig('driver')
|
||||
. "\n-- " . date('Y-m-d H:i:s')
|
||||
. "\n\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event === 'exception' && $this->logErrors) {
|
||||
// $arg is DibiDriverException
|
||||
$message = $arg->getMessage();
|
||||
$code = $arg->getCode();
|
||||
if ($code) {
|
||||
$message = "[$code] $message";
|
||||
}
|
||||
|
||||
$this->write(
|
||||
"ERROR: $message"
|
||||
. "\n-- SQL: " . dibi::$sql
|
||||
. "\n-- driver: " //. $connection->getConfig('driver')
|
||||
. ";\n-- " . date('Y-m-d H:i:s')
|
||||
. "\n\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function write($message)
|
||||
{
|
||||
$handle = fopen($this->file, 'a');
|
||||
if (!$handle) return; // or throw exception?
|
||||
|
||||
flock($handle, LOCK_EX);
|
||||
fwrite($handle, $message);
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,290 +1,290 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Experimental object-oriented interface to database tables.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
abstract class DibiTable extends /*Nette::*/Object
|
||||
{
|
||||
/** @var string primary key mask */
|
||||
public static $primaryMask = 'id';
|
||||
|
||||
/** @var bool */
|
||||
public static $lowerCase = TRUE;
|
||||
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var string table name */
|
||||
protected $name;
|
||||
|
||||
/** @var string primary key name */
|
||||
protected $primary;
|
||||
|
||||
/** @var string primary key type */
|
||||
protected $primaryModifier = '%i';
|
||||
|
||||
/** @var array */
|
||||
protected $blankRow = array();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Table constructor.
|
||||
* @param DibiConnection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(DibiConnection $connection = NULL)
|
||||
{
|
||||
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the table name.
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the primary key name.
|
||||
* @return string
|
||||
*/
|
||||
public function getPrimary()
|
||||
{
|
||||
return $this->primary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the dibi connection.
|
||||
* @return DibiConnection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Setup object.
|
||||
* @return void
|
||||
*/
|
||||
protected function setup()
|
||||
{
|
||||
// autodetect table name
|
||||
if ($this->name === NULL) {
|
||||
$name = $this->getClass();
|
||||
if (FALSE !== ($pos = strrpos($name, ':'))) {
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
if (self::$lowerCase) {
|
||||
$name = strtolower($name);
|
||||
}
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
// autodetect primary key name
|
||||
if ($this->primary === NULL) {
|
||||
$this->primary = str_replace(
|
||||
array('%p', '%s'),
|
||||
array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-))
|
||||
self::$primaryMask
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inserts row into a table.
|
||||
* @param array|object
|
||||
* @return int new primary key
|
||||
*/
|
||||
public function insert($data)
|
||||
{
|
||||
$this->connection->query(
|
||||
'INSERT INTO %n', $this->name, '%v', $this->prepare($data)
|
||||
);
|
||||
return $this->connection->insertId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates rows in a table.
|
||||
* @param mixed primary key value(s)
|
||||
* @param array|object
|
||||
* @return int number of updated rows
|
||||
*/
|
||||
public function update($where, $data)
|
||||
{
|
||||
$this->connection->query(
|
||||
'UPDATE %n', $this->name,
|
||||
'SET %a', $this->prepare($data),
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
||||
);
|
||||
return $this->connection->affectedRows();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes rows from a table by primary key.
|
||||
* @param mixed primary key value(s)
|
||||
* @return int number of deleted rows
|
||||
*/
|
||||
public function delete($where)
|
||||
{
|
||||
$this->connection->query(
|
||||
'DELETE FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
||||
);
|
||||
return $this->connection->affectedRows();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds rows by primary key.
|
||||
* @param mixed primary key value(s)
|
||||
* @return DibiResult
|
||||
*/
|
||||
public function find($what)
|
||||
{
|
||||
if (!is_array($what)) {
|
||||
$what = func_get_args();
|
||||
}
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')'
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Selects all rows.
|
||||
* @param string column to order by
|
||||
* @return DibiResult
|
||||
*/
|
||||
public function findAll($order = NULL)
|
||||
{
|
||||
if ($order === NULL) {
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name
|
||||
));
|
||||
} else {
|
||||
$order = func_get_args();
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'ORDER BY %n', $order
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches single row.
|
||||
* @param scalar|array primary key value
|
||||
* @return array|object row
|
||||
*/
|
||||
public function fetch($conditions)
|
||||
{
|
||||
if (is_array($conditions)) {
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %and', $conditions
|
||||
))->fetch();
|
||||
}
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions
|
||||
))->fetch();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a blank row (not fetched from database).
|
||||
* @return array|object
|
||||
*/
|
||||
public function createBlank()
|
||||
{
|
||||
$row = $this->blankRow;
|
||||
$row[$this->primary] = NULL;
|
||||
|
||||
if ($class = $this->connection->getConfig('result:objects')) {
|
||||
if ($class === TRUE) {
|
||||
$row = (object) $row;
|
||||
} else {
|
||||
$row = new $class($row);
|
||||
}
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* User data pre-processing.
|
||||
* @param array|object
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare($data)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
return (array) $data;
|
||||
} elseif (is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Dataset must be array or anonymous object.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* User DibiResult post-processing.
|
||||
* @param DibiResult
|
||||
* @return DibiResult
|
||||
*/
|
||||
protected function complete($res)
|
||||
{
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Experimental object-oriented interface to database tables.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
abstract class DibiTable extends /*Nette::*/Object
|
||||
{
|
||||
/** @var string primary key mask */
|
||||
public static $primaryMask = 'id';
|
||||
|
||||
/** @var bool */
|
||||
public static $lowerCase = TRUE;
|
||||
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var string table name */
|
||||
protected $name;
|
||||
|
||||
/** @var string primary key name */
|
||||
protected $primary;
|
||||
|
||||
/** @var string primary key type */
|
||||
protected $primaryModifier = '%i';
|
||||
|
||||
/** @var array */
|
||||
protected $blankRow = array();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Table constructor.
|
||||
* @param DibiConnection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(DibiConnection $connection = NULL)
|
||||
{
|
||||
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the table name.
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the primary key name.
|
||||
* @return string
|
||||
*/
|
||||
public function getPrimary()
|
||||
{
|
||||
return $this->primary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the dibi connection.
|
||||
* @return DibiConnection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Setup object.
|
||||
* @return void
|
||||
*/
|
||||
protected function setup()
|
||||
{
|
||||
// autodetect table name
|
||||
if ($this->name === NULL) {
|
||||
$name = $this->getClass();
|
||||
if (FALSE !== ($pos = strrpos($name, ':'))) {
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
if (self::$lowerCase) {
|
||||
$name = strtolower($name);
|
||||
}
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
// autodetect primary key name
|
||||
if ($this->primary === NULL) {
|
||||
$this->primary = str_replace(
|
||||
array('%p', '%s'),
|
||||
array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-))
|
||||
self::$primaryMask
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inserts row into a table.
|
||||
* @param array|object
|
||||
* @return int new primary key
|
||||
*/
|
||||
public function insert($data)
|
||||
{
|
||||
$this->connection->query(
|
||||
'INSERT INTO %n', $this->name, '%v', $this->prepare($data)
|
||||
);
|
||||
return $this->connection->insertId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates rows in a table.
|
||||
* @param mixed primary key value(s)
|
||||
* @param array|object
|
||||
* @return int number of updated rows
|
||||
*/
|
||||
public function update($where, $data)
|
||||
{
|
||||
$this->connection->query(
|
||||
'UPDATE %n', $this->name,
|
||||
'SET %a', $this->prepare($data),
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
||||
);
|
||||
return $this->connection->affectedRows();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes rows from a table by primary key.
|
||||
* @param mixed primary key value(s)
|
||||
* @return int number of deleted rows
|
||||
*/
|
||||
public function delete($where)
|
||||
{
|
||||
$this->connection->query(
|
||||
'DELETE FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
||||
);
|
||||
return $this->connection->affectedRows();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds rows by primary key.
|
||||
* @param mixed primary key value(s)
|
||||
* @return DibiResult
|
||||
*/
|
||||
public function find($what)
|
||||
{
|
||||
if (!is_array($what)) {
|
||||
$what = func_get_args();
|
||||
}
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')'
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Selects all rows.
|
||||
* @param string column to order by
|
||||
* @return DibiResult
|
||||
*/
|
||||
public function findAll($order = NULL)
|
||||
{
|
||||
if ($order === NULL) {
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name
|
||||
));
|
||||
} else {
|
||||
$order = func_get_args();
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'ORDER BY %n', $order
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches single row.
|
||||
* @param scalar|array primary key value
|
||||
* @return array|object row
|
||||
*/
|
||||
public function fetch($conditions)
|
||||
{
|
||||
if (is_array($conditions)) {
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %and', $conditions
|
||||
))->fetch();
|
||||
}
|
||||
return $this->complete($this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions
|
||||
))->fetch();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a blank row (not fetched from database).
|
||||
* @return array|object
|
||||
*/
|
||||
public function createBlank()
|
||||
{
|
||||
$row = $this->blankRow;
|
||||
$row[$this->primary] = NULL;
|
||||
|
||||
if ($class = $this->connection->getConfig('result:objects')) {
|
||||
if ($class === TRUE) {
|
||||
$row = (object) $row;
|
||||
} else {
|
||||
$row = new $class($row);
|
||||
}
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* User data pre-processing.
|
||||
* @param array|object
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare($data)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
return (array) $data;
|
||||
} elseif (is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Dataset must be array or anonymous object.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* User DibiResult post-processing.
|
||||
* @param DibiResult
|
||||
* @return DibiResult
|
||||
*/
|
||||
protected function complete($res)
|
||||
{
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,457 +1,457 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi SQL translator.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
final class DibiTranslator extends /*Nette::*/Object
|
||||
{
|
||||
/** @var string */
|
||||
public $sql;
|
||||
|
||||
/** @var IDibiDriver */
|
||||
private $driver;
|
||||
|
||||
/** @var int */
|
||||
private $cursor;
|
||||
|
||||
/** @var array */
|
||||
private $args;
|
||||
|
||||
/** @var bool */
|
||||
private $hasError;
|
||||
|
||||
/** @var bool */
|
||||
private $comment;
|
||||
|
||||
/** @var int */
|
||||
private $ifLevel;
|
||||
|
||||
/** @var int */
|
||||
private $ifLevelStart;
|
||||
|
||||
/** @var int */
|
||||
private $limit;
|
||||
|
||||
/** @var int */
|
||||
private $offset;
|
||||
|
||||
|
||||
|
||||
public function __construct(IDibiDriver $driver)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* return IDibiDriver.
|
||||
*/
|
||||
public function getDriver()
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates SQL.
|
||||
*
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
public function translate(array $args)
|
||||
{
|
||||
$this->limit = -1;
|
||||
$this->offset = 0;
|
||||
$this->hasError = FALSE;
|
||||
$commandIns = NULL;
|
||||
$lastArr = NULL;
|
||||
// shortcuts
|
||||
$cursor = & $this->cursor;
|
||||
$cursor = 0;
|
||||
$this->args = array_values($args);
|
||||
$args = & $this->args;
|
||||
|
||||
// conditional sql
|
||||
$this->ifLevel = $this->ifLevelStart = 0;
|
||||
$comment = & $this->comment;
|
||||
$comment = FALSE;
|
||||
|
||||
// iterate
|
||||
$sql = array();
|
||||
while ($cursor < count($args))
|
||||
{
|
||||
$arg = $args[$cursor];
|
||||
$cursor++;
|
||||
|
||||
// simple string means SQL
|
||||
if (is_string($arg)) {
|
||||
// speed-up - is regexp required?
|
||||
$toSkip = strcspn($arg, '`[\'"%');
|
||||
|
||||
if (strlen($arg) === $toSkip) { // needn't be translated
|
||||
$sql[] = $arg;
|
||||
} else {
|
||||
$sql[] = substr($arg, 0, $toSkip)
|
||||
/*
|
||||
preg_replace_callback('/
|
||||
(?=`|\[|\'|"|%) ## speed-up
|
||||
(?:
|
||||
`(.+?)`| ## 1) `identifier`
|
||||
\[(.+?)\]| ## 2) [identifier]
|
||||
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
|
||||
(")((?:""|[^"])*)"| ## 5,6) "string"
|
||||
(\'|") ## 7) lone-quote
|
||||
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
|
||||
)/xs',
|
||||
*/ // note: this can change $this->args & $this->cursor & ...
|
||||
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
|
||||
array($this, 'cb'),
|
||||
substr($arg, $toSkip)
|
||||
);
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($comment) {
|
||||
$sql[] = '...';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($arg)) {
|
||||
if (is_string(key($arg))) {
|
||||
// associative array -> autoselect between SET or VALUES & LIST
|
||||
if ($commandIns === NULL) {
|
||||
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
|
||||
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
|
||||
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
|
||||
} else {
|
||||
if ($lastArr === $cursor - 1) $sql[] = ',';
|
||||
$sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a');
|
||||
}
|
||||
$lastArr = $cursor;
|
||||
continue;
|
||||
|
||||
} elseif ($cursor === 1) {
|
||||
// implicit array expansion
|
||||
$cursor = 0;
|
||||
array_splice($args, 0, 1, $arg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// default processing
|
||||
$sql[] = $this->formatValue($arg, FALSE);
|
||||
} // while
|
||||
|
||||
|
||||
if ($comment) $sql[] = "*/";
|
||||
|
||||
$sql = implode(' ', $sql);
|
||||
|
||||
// apply limit
|
||||
if ($this->limit > -1 || $this->offset > 0) {
|
||||
$this->driver->applyLimit($sql, $this->limit, $this->offset);
|
||||
}
|
||||
|
||||
$this->sql = $sql;
|
||||
return !$this->hasError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply modifier to single value.
|
||||
* @param mixed
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
public function formatValue($value, $modifier)
|
||||
{
|
||||
// array processing (with or without modifier)
|
||||
if (is_array($value)) {
|
||||
|
||||
$vx = $kx = array();
|
||||
$separator = ', ';
|
||||
switch ($modifier) {
|
||||
case 'and':
|
||||
case 'or':
|
||||
$separator = ' ' . strtoupper($modifier) . ' ';
|
||||
if (!is_string(key($value))) {
|
||||
foreach ($value as $v) {
|
||||
$vx[] = $this->formatValue($v, 'sql');
|
||||
}
|
||||
return implode($separator, $vx);
|
||||
}
|
||||
// break intentionally omitted
|
||||
case 'a': // SET key=val, key=val, ...
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||
$vx[] = $this->delimite($pair[0]) . '='
|
||||
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||
}
|
||||
return implode($separator, $vx);
|
||||
|
||||
|
||||
case 'l': // LIST (val, val, ...)
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||
}
|
||||
return '(' . implode(', ', $vx) . ')';
|
||||
|
||||
|
||||
case 'v': // (key, key, ...) VALUES (val, val, ...)
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||
$kx[] = $this->delimite($pair[0]);
|
||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||
}
|
||||
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
|
||||
|
||||
default:
|
||||
foreach ($value as $v) {
|
||||
$vx[] = $this->formatValue($v, $modifier);
|
||||
}
|
||||
return implode(', ', $vx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// with modifier procession
|
||||
if ($modifier) {
|
||||
if ($value === NULL) {
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
if ($value instanceof IDibiVariable) {
|
||||
return $value->toSql($this, $modifier);
|
||||
}
|
||||
|
||||
if (!is_scalar($value)) { // array is already processed
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected type ' . gettype($value) . '**';
|
||||
}
|
||||
|
||||
switch ($modifier) {
|
||||
case 's': // string
|
||||
case 'bin':// binary
|
||||
case 'b': // boolean
|
||||
return $this->driver->escape($value, $modifier);
|
||||
|
||||
case 'sn': // string or NULL
|
||||
return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::FIELD_TEXT); // notice two equal signs
|
||||
|
||||
case 'i': // signed int
|
||||
case 'u': // unsigned int, ignored
|
||||
// support for numbers - keep them unchanged
|
||||
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
|
||||
return $value;
|
||||
}
|
||||
return (string) (int) ($value + 0);
|
||||
|
||||
case 'f': // float
|
||||
// support for numbers - keep them unchanged
|
||||
if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) {
|
||||
return $value; // something like -9E-005 is accepted by SQL, HEX values is not
|
||||
}
|
||||
return (string) ($value + 0);
|
||||
|
||||
case 'd': // date
|
||||
case 't': // datetime
|
||||
return $this->driver->escape(is_string($value) ? strtotime($value) : $value, $modifier);
|
||||
|
||||
case 'n': // identifier name
|
||||
return $this->delimite($value);
|
||||
|
||||
case 'sql':// preserve as SQL
|
||||
$value = (string) $value;
|
||||
// speed-up - is regexp required?
|
||||
$toSkip = strcspn($value, '`[\'"');
|
||||
if (strlen($value) === $toSkip) { // needn't be translated
|
||||
return $value;
|
||||
} else {
|
||||
return substr($value, 0, $toSkip)
|
||||
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
|
||||
array($this, 'cb'),
|
||||
substr($value, $toSkip)
|
||||
);
|
||||
}
|
||||
|
||||
case 'and':
|
||||
case 'or':
|
||||
case 'a':
|
||||
case 'l':
|
||||
case 'v':
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected type ' . gettype($value) . '**';
|
||||
|
||||
default:
|
||||
$this->hasError = TRUE;
|
||||
return "**Unknown or invalid modifier %$modifier**";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// without modifier procession
|
||||
if (is_string($value))
|
||||
return $this->driver->escape($value, dibi::FIELD_TEXT);
|
||||
|
||||
if (is_int($value) || is_float($value))
|
||||
return (string) $value; // something like -9E-005 is accepted by SQL
|
||||
|
||||
if (is_bool($value))
|
||||
return $this->driver->escape($value, dibi::FIELD_BOOL);
|
||||
|
||||
if ($value === NULL)
|
||||
return 'NULL';
|
||||
|
||||
if ($value instanceof IDibiVariable)
|
||||
return $value->toSql($this, NULL);
|
||||
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected ' . gettype($value) . '**';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PREG callback from translate() or formatValue().
|
||||
* @param array
|
||||
* @return string
|
||||
*/
|
||||
private function cb($matches)
|
||||
{
|
||||
// [1] => `ident`
|
||||
// [2] => [ident]
|
||||
// [3] => '
|
||||
// [4] => string
|
||||
// [5] => "
|
||||
// [6] => string
|
||||
// [7] => lone-quote
|
||||
// [8] => modifier (when called from self::translate())
|
||||
|
||||
if (!empty($matches[8])) { // modifier
|
||||
$mod = $matches[8];
|
||||
$cursor = & $this->cursor;
|
||||
|
||||
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
|
||||
$this->hasError = TRUE;
|
||||
return "**Extra modifier %$mod**";
|
||||
}
|
||||
|
||||
if ($mod === 'if') {
|
||||
$this->ifLevel++;
|
||||
$cursor++;
|
||||
if (!$this->comment && !$this->args[$cursor - 1]) {
|
||||
// open comment
|
||||
$this->ifLevelStart = $this->ifLevel;
|
||||
$this->comment = TRUE;
|
||||
return "/*";
|
||||
}
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'else') {
|
||||
if ($this->ifLevelStart === $this->ifLevel) {
|
||||
$this->ifLevelStart = 0;
|
||||
$this->comment = FALSE;
|
||||
return "*/";
|
||||
} elseif (!$this->comment) {
|
||||
$this->ifLevelStart = $this->ifLevel;
|
||||
$this->comment = TRUE;
|
||||
return "/*";
|
||||
}
|
||||
|
||||
} elseif ($mod === 'end') {
|
||||
$this->ifLevel--;
|
||||
if ($this->ifLevelStart === $this->ifLevel + 1) {
|
||||
// close comment
|
||||
$this->ifLevelStart = 0;
|
||||
$this->comment = FALSE;
|
||||
return "*/";
|
||||
}
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'ex') { // array expansion
|
||||
array_splice($this->args, $cursor, 1, $this->args[$cursor]);
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'lmt') { // apply limit
|
||||
if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor];
|
||||
$cursor++;
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'ofs') { // apply offset
|
||||
if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor];
|
||||
$cursor++;
|
||||
return '';
|
||||
|
||||
} else { // default processing
|
||||
$cursor++;
|
||||
return $this->formatValue($this->args[$cursor - 1], $mod);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->comment) return '...';
|
||||
|
||||
if ($matches[1]) // SQL identifiers: `ident`
|
||||
return $this->delimite($matches[1]);
|
||||
|
||||
if ($matches[2]) // SQL identifiers: [ident]
|
||||
return $this->delimite($matches[2]);
|
||||
|
||||
if ($matches[3]) // SQL strings: '...'
|
||||
return $this->driver->escape( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
|
||||
|
||||
if ($matches[5]) // SQL strings: "..."
|
||||
return $this->driver->escape( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
|
||||
|
||||
if ($matches[7]) { // string quote
|
||||
$this->hasError = TRUE;
|
||||
return '**Alone quote**';
|
||||
}
|
||||
|
||||
die('this should be never executed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply substitutions to indentifier and delimites it.
|
||||
*
|
||||
* @param string indentifier
|
||||
* @return string
|
||||
*/
|
||||
private function delimite($value)
|
||||
{
|
||||
return $this->driver->escape(dibi::substitute($value), dibi::IDENTIFIER);
|
||||
}
|
||||
|
||||
|
||||
} // class DibiTranslator
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi SQL translator.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
final class DibiTranslator extends /*Nette::*/Object
|
||||
{
|
||||
/** @var string */
|
||||
public $sql;
|
||||
|
||||
/** @var IDibiDriver */
|
||||
private $driver;
|
||||
|
||||
/** @var int */
|
||||
private $cursor;
|
||||
|
||||
/** @var array */
|
||||
private $args;
|
||||
|
||||
/** @var bool */
|
||||
private $hasError;
|
||||
|
||||
/** @var bool */
|
||||
private $comment;
|
||||
|
||||
/** @var int */
|
||||
private $ifLevel;
|
||||
|
||||
/** @var int */
|
||||
private $ifLevelStart;
|
||||
|
||||
/** @var int */
|
||||
private $limit;
|
||||
|
||||
/** @var int */
|
||||
private $offset;
|
||||
|
||||
|
||||
|
||||
public function __construct(IDibiDriver $driver)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* return IDibiDriver.
|
||||
*/
|
||||
public function getDriver()
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates SQL.
|
||||
*
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
public function translate(array $args)
|
||||
{
|
||||
$this->limit = -1;
|
||||
$this->offset = 0;
|
||||
$this->hasError = FALSE;
|
||||
$commandIns = NULL;
|
||||
$lastArr = NULL;
|
||||
// shortcuts
|
||||
$cursor = & $this->cursor;
|
||||
$cursor = 0;
|
||||
$this->args = array_values($args);
|
||||
$args = & $this->args;
|
||||
|
||||
// conditional sql
|
||||
$this->ifLevel = $this->ifLevelStart = 0;
|
||||
$comment = & $this->comment;
|
||||
$comment = FALSE;
|
||||
|
||||
// iterate
|
||||
$sql = array();
|
||||
while ($cursor < count($args))
|
||||
{
|
||||
$arg = $args[$cursor];
|
||||
$cursor++;
|
||||
|
||||
// simple string means SQL
|
||||
if (is_string($arg)) {
|
||||
// speed-up - is regexp required?
|
||||
$toSkip = strcspn($arg, '`[\'"%');
|
||||
|
||||
if (strlen($arg) === $toSkip) { // needn't be translated
|
||||
$sql[] = $arg;
|
||||
} else {
|
||||
$sql[] = substr($arg, 0, $toSkip)
|
||||
/*
|
||||
preg_replace_callback('/
|
||||
(?=`|\[|\'|"|%) ## speed-up
|
||||
(?:
|
||||
`(.+?)`| ## 1) `identifier`
|
||||
\[(.+?)\]| ## 2) [identifier]
|
||||
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
|
||||
(")((?:""|[^"])*)"| ## 5,6) "string"
|
||||
(\'|") ## 7) lone-quote
|
||||
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
|
||||
)/xs',
|
||||
*/ // note: this can change $this->args & $this->cursor & ...
|
||||
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
|
||||
array($this, 'cb'),
|
||||
substr($arg, $toSkip)
|
||||
);
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($comment) {
|
||||
$sql[] = '...';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($arg)) {
|
||||
if (is_string(key($arg))) {
|
||||
// associative array -> autoselect between SET or VALUES & LIST
|
||||
if ($commandIns === NULL) {
|
||||
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
|
||||
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
|
||||
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
|
||||
} else {
|
||||
if ($lastArr === $cursor - 1) $sql[] = ',';
|
||||
$sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a');
|
||||
}
|
||||
$lastArr = $cursor;
|
||||
continue;
|
||||
|
||||
} elseif ($cursor === 1) {
|
||||
// implicit array expansion
|
||||
$cursor = 0;
|
||||
array_splice($args, 0, 1, $arg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// default processing
|
||||
$sql[] = $this->formatValue($arg, FALSE);
|
||||
} // while
|
||||
|
||||
|
||||
if ($comment) $sql[] = "*/";
|
||||
|
||||
$sql = implode(' ', $sql);
|
||||
|
||||
// apply limit
|
||||
if ($this->limit > -1 || $this->offset > 0) {
|
||||
$this->driver->applyLimit($sql, $this->limit, $this->offset);
|
||||
}
|
||||
|
||||
$this->sql = $sql;
|
||||
return !$this->hasError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply modifier to single value.
|
||||
* @param mixed
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
public function formatValue($value, $modifier)
|
||||
{
|
||||
// array processing (with or without modifier)
|
||||
if (is_array($value)) {
|
||||
|
||||
$vx = $kx = array();
|
||||
$separator = ', ';
|
||||
switch ($modifier) {
|
||||
case 'and':
|
||||
case 'or':
|
||||
$separator = ' ' . strtoupper($modifier) . ' ';
|
||||
if (!is_string(key($value))) {
|
||||
foreach ($value as $v) {
|
||||
$vx[] = $this->formatValue($v, 'sql');
|
||||
}
|
||||
return implode($separator, $vx);
|
||||
}
|
||||
// break intentionally omitted
|
||||
case 'a': // SET key=val, key=val, ...
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||
$vx[] = $this->delimite($pair[0]) . '='
|
||||
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||
}
|
||||
return implode($separator, $vx);
|
||||
|
||||
|
||||
case 'l': // LIST (val, val, ...)
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||
}
|
||||
return '(' . implode(', ', $vx) . ')';
|
||||
|
||||
|
||||
case 'v': // (key, key, ...) VALUES (val, val, ...)
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||
$kx[] = $this->delimite($pair[0]);
|
||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||
}
|
||||
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
|
||||
|
||||
default:
|
||||
foreach ($value as $v) {
|
||||
$vx[] = $this->formatValue($v, $modifier);
|
||||
}
|
||||
return implode(', ', $vx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// with modifier procession
|
||||
if ($modifier) {
|
||||
if ($value === NULL) {
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
if ($value instanceof IDibiVariable) {
|
||||
return $value->toSql($this, $modifier);
|
||||
}
|
||||
|
||||
if (!is_scalar($value)) { // array is already processed
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected type ' . gettype($value) . '**';
|
||||
}
|
||||
|
||||
switch ($modifier) {
|
||||
case 's': // string
|
||||
case 'bin':// binary
|
||||
case 'b': // boolean
|
||||
return $this->driver->escape($value, $modifier);
|
||||
|
||||
case 'sn': // string or NULL
|
||||
return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::FIELD_TEXT); // notice two equal signs
|
||||
|
||||
case 'i': // signed int
|
||||
case 'u': // unsigned int, ignored
|
||||
// support for numbers - keep them unchanged
|
||||
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
|
||||
return $value;
|
||||
}
|
||||
return (string) (int) ($value + 0);
|
||||
|
||||
case 'f': // float
|
||||
// support for numbers - keep them unchanged
|
||||
if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) {
|
||||
return $value; // something like -9E-005 is accepted by SQL, HEX values is not
|
||||
}
|
||||
return (string) ($value + 0);
|
||||
|
||||
case 'd': // date
|
||||
case 't': // datetime
|
||||
return $this->driver->escape(is_string($value) ? strtotime($value) : $value, $modifier);
|
||||
|
||||
case 'n': // identifier name
|
||||
return $this->delimite($value);
|
||||
|
||||
case 'sql':// preserve as SQL
|
||||
$value = (string) $value;
|
||||
// speed-up - is regexp required?
|
||||
$toSkip = strcspn($value, '`[\'"');
|
||||
if (strlen($value) === $toSkip) { // needn't be translated
|
||||
return $value;
|
||||
} else {
|
||||
return substr($value, 0, $toSkip)
|
||||
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
|
||||
array($this, 'cb'),
|
||||
substr($value, $toSkip)
|
||||
);
|
||||
}
|
||||
|
||||
case 'and':
|
||||
case 'or':
|
||||
case 'a':
|
||||
case 'l':
|
||||
case 'v':
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected type ' . gettype($value) . '**';
|
||||
|
||||
default:
|
||||
$this->hasError = TRUE;
|
||||
return "**Unknown or invalid modifier %$modifier**";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// without modifier procession
|
||||
if (is_string($value))
|
||||
return $this->driver->escape($value, dibi::FIELD_TEXT);
|
||||
|
||||
if (is_int($value) || is_float($value))
|
||||
return (string) $value; // something like -9E-005 is accepted by SQL
|
||||
|
||||
if (is_bool($value))
|
||||
return $this->driver->escape($value, dibi::FIELD_BOOL);
|
||||
|
||||
if ($value === NULL)
|
||||
return 'NULL';
|
||||
|
||||
if ($value instanceof IDibiVariable)
|
||||
return $value->toSql($this, NULL);
|
||||
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected ' . gettype($value) . '**';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PREG callback from translate() or formatValue().
|
||||
* @param array
|
||||
* @return string
|
||||
*/
|
||||
private function cb($matches)
|
||||
{
|
||||
// [1] => `ident`
|
||||
// [2] => [ident]
|
||||
// [3] => '
|
||||
// [4] => string
|
||||
// [5] => "
|
||||
// [6] => string
|
||||
// [7] => lone-quote
|
||||
// [8] => modifier (when called from self::translate())
|
||||
|
||||
if (!empty($matches[8])) { // modifier
|
||||
$mod = $matches[8];
|
||||
$cursor = & $this->cursor;
|
||||
|
||||
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
|
||||
$this->hasError = TRUE;
|
||||
return "**Extra modifier %$mod**";
|
||||
}
|
||||
|
||||
if ($mod === 'if') {
|
||||
$this->ifLevel++;
|
||||
$cursor++;
|
||||
if (!$this->comment && !$this->args[$cursor - 1]) {
|
||||
// open comment
|
||||
$this->ifLevelStart = $this->ifLevel;
|
||||
$this->comment = TRUE;
|
||||
return "/*";
|
||||
}
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'else') {
|
||||
if ($this->ifLevelStart === $this->ifLevel) {
|
||||
$this->ifLevelStart = 0;
|
||||
$this->comment = FALSE;
|
||||
return "*/";
|
||||
} elseif (!$this->comment) {
|
||||
$this->ifLevelStart = $this->ifLevel;
|
||||
$this->comment = TRUE;
|
||||
return "/*";
|
||||
}
|
||||
|
||||
} elseif ($mod === 'end') {
|
||||
$this->ifLevel--;
|
||||
if ($this->ifLevelStart === $this->ifLevel + 1) {
|
||||
// close comment
|
||||
$this->ifLevelStart = 0;
|
||||
$this->comment = FALSE;
|
||||
return "*/";
|
||||
}
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'ex') { // array expansion
|
||||
array_splice($this->args, $cursor, 1, $this->args[$cursor]);
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'lmt') { // apply limit
|
||||
if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor];
|
||||
$cursor++;
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'ofs') { // apply offset
|
||||
if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor];
|
||||
$cursor++;
|
||||
return '';
|
||||
|
||||
} else { // default processing
|
||||
$cursor++;
|
||||
return $this->formatValue($this->args[$cursor - 1], $mod);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->comment) return '...';
|
||||
|
||||
if ($matches[1]) // SQL identifiers: `ident`
|
||||
return $this->delimite($matches[1]);
|
||||
|
||||
if ($matches[2]) // SQL identifiers: [ident]
|
||||
return $this->delimite($matches[2]);
|
||||
|
||||
if ($matches[3]) // SQL strings: '...'
|
||||
return $this->driver->escape( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
|
||||
|
||||
if ($matches[5]) // SQL strings: "..."
|
||||
return $this->driver->escape( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
|
||||
|
||||
if ($matches[7]) { // string quote
|
||||
$this->hasError = TRUE;
|
||||
return '**Alone quote**';
|
||||
}
|
||||
|
||||
die('this should be never executed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply substitutions to indentifier and delimites it.
|
||||
*
|
||||
* @param string indentifier
|
||||
* @return string
|
||||
*/
|
||||
private function delimite($value)
|
||||
{
|
||||
return $this->driver->escape(dibi::substitute($value), dibi::IDENTIFIER);
|
||||
}
|
||||
|
||||
|
||||
} // class DibiTranslator
|
||||
|
@@ -1,48 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Default implemenation of IDibiVariable.
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiVariable extends /*Nette::*/Object implements IDibiVariable
|
||||
{
|
||||
/** @var mixed */
|
||||
public $value;
|
||||
|
||||
/** @var string */
|
||||
public $modifier;
|
||||
|
||||
|
||||
public function __construct($value, $modifier)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->modifier = $modifier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function toSql(DibiTranslator $translator, $modifier)
|
||||
{
|
||||
return $translator->formatValue($this->value, $this->modifier);
|
||||
}
|
||||
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Default implemenation of IDibiVariable.
|
||||
* @package dibi
|
||||
*/
|
||||
class DibiVariable extends /*Nette::*/Object implements IDibiVariable
|
||||
{
|
||||
/** @var mixed */
|
||||
public $value;
|
||||
|
||||
/** @var string */
|
||||
public $modifier;
|
||||
|
||||
|
||||
public function __construct($value, $modifier)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->modifier = $modifier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function toSql(DibiTranslator $translator, $modifier)
|
||||
{
|
||||
return $translator->formatValue($this->value, $this->modifier);
|
||||
}
|
||||
|
||||
}
|
@@ -1,256 +1,256 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for user variable, used for generating SQL.
|
||||
* @package dibi
|
||||
*/
|
||||
interface IDibiVariable
|
||||
{
|
||||
/**
|
||||
* Format for SQL.
|
||||
*
|
||||
* @param object DibiTranslator
|
||||
* @param string optional modifier
|
||||
* @return string SQL code
|
||||
*/
|
||||
function toSql(DibiTranslator $translator, $modifier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Provides an interface between a dataset and data-aware components.
|
||||
* @package dibi
|
||||
*/
|
||||
interface IDataSource extends Countable, IteratorAggregate
|
||||
{
|
||||
//function IteratorAggregate::getIterator();
|
||||
//function Countable::count();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi driver interface.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
interface IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Internal: Connects to a database.
|
||||
*
|
||||
* @param array
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
function connect(array &$config);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal: Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
function disconnect();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal: Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function query($sql);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
function affectedRows();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
function insertId($sequence);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function begin();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function commit();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function rollback();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
function escape($value, $type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
function unescape($value, $type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
function applyLimit(&$sql, $limit, $offset);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function rowCount();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
function seek($row);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
function fetch($type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @param resource result set resource
|
||||
* @return void
|
||||
*/
|
||||
function free();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
* @throws DibiException
|
||||
*/
|
||||
function getColumnsMeta();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getResource();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getResultResource();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection();
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com
|
||||
* @package dibi
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for user variable, used for generating SQL.
|
||||
* @package dibi
|
||||
*/
|
||||
interface IDibiVariable
|
||||
{
|
||||
/**
|
||||
* Format for SQL.
|
||||
*
|
||||
* @param object DibiTranslator
|
||||
* @param string optional modifier
|
||||
* @return string SQL code
|
||||
*/
|
||||
function toSql(DibiTranslator $translator, $modifier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Provides an interface between a dataset and data-aware components.
|
||||
* @package dibi
|
||||
*/
|
||||
interface IDataSource extends Countable, IteratorAggregate
|
||||
{
|
||||
//function IteratorAggregate::getIterator();
|
||||
//function Countable::count();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi driver interface.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
interface IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
||||
* Internal: Connects to a database.
|
||||
*
|
||||
* @param array
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
function connect(array &$config);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal: Disconnects from a database.
|
||||
*
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
function disconnect();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal: Executes the SQL query.
|
||||
*
|
||||
* @param string SQL statement.
|
||||
* @return IDibiDriver|NULL
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function query($sql);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||
*
|
||||
* @return int|FALSE number of rows or FALSE on error
|
||||
*/
|
||||
function affectedRows();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
*
|
||||
* @return int|FALSE int on success or FALSE on failure
|
||||
*/
|
||||
function insertId($sequence);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction (if supported).
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function begin();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function commit();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction.
|
||||
* @return void
|
||||
* @throws DibiDriverException
|
||||
*/
|
||||
function rollback();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data for use in an SQL statement.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
||||
* @return string encoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
function escape($value, $type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*
|
||||
* @param string value
|
||||
* @param string type (dibi::FIELD_BINARY)
|
||||
* @return string decoded value
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
function unescape($value, $type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*
|
||||
* @param string &$sql The SQL query that will be modified.
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return void
|
||||
*/
|
||||
function applyLimit(&$sql, $limit, $offset);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function rowCount();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*
|
||||
* @param int the 0-based cursor pos to seek to
|
||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||
* @throws DibiException
|
||||
*/
|
||||
function seek($row);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* internal usage only
|
||||
*
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
function fetch($type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*
|
||||
* @param resource result set resource
|
||||
* @return void
|
||||
*/
|
||||
function free();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*
|
||||
* @return array
|
||||
* @throws DibiException
|
||||
*/
|
||||
function getColumnsMeta();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getResource();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getResultResource();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information of the current database.
|
||||
*
|
||||
* @return DibiReflection
|
||||
*/
|
||||
function getDibiReflection();
|
||||
|
||||
}
|
||||
|
@@ -1,2 +1,2 @@
|
||||
Disallow: /drivers
|
||||
Disallow: /Nette
|
||||
Disallow: /drivers
|
||||
Disallow: /Nette
|
||||
|
@@ -1,34 +1,34 @@
|
||||
<h1>dibi apply limit/offset example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// no limit
|
||||
$res = dibi::query('SELECT * FROM [products]');
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
|
||||
// with limit = 2
|
||||
$res = dibi::query('SELECT * FROM [products] %lmt', 2);
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
|
||||
// with limit = 2, offset = 1
|
||||
$res = dibi::query('SELECT * FROM [products] %lmt %ofs', 2, 1);
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
<h1>dibi apply limit/offset example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// no limit
|
||||
$res = dibi::query('SELECT * FROM [products]');
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
|
||||
// with limit = 2
|
||||
$res = dibi::query('SELECT * FROM [products] %lmt', 2);
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
|
||||
// with limit = 2, offset = 1
|
||||
$res = dibi::query('SELECT * FROM [products] %lmt %ofs', 2, 1);
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
@@ -1,145 +1,145 @@
|
||||
<h1>dibi::connect() example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// connects to SQlite
|
||||
echo '<p>Connecting to Sqlite: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
'result:objects' => TRUE, // fetch rows as objects
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to MySQL using DSN
|
||||
echo '<p>Connecting to MySQL: ';
|
||||
try {
|
||||
dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=utf8');
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to MySQLi using array
|
||||
echo '<p>Connecting to MySQL: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'mysqli',
|
||||
'host' => 'localhost',
|
||||
'username' => 'root',
|
||||
'password' => 'xxx',
|
||||
'database' => 'dibi',
|
||||
'charset' => 'utf8',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to ODBC
|
||||
echo '<p>Connecting to ODBC: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'odbc',
|
||||
'username' => 'root',
|
||||
'password' => '***',
|
||||
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/sample.mdb',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to PostgreSql
|
||||
echo '<p>Connecting to PostgreSql: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'postgre',
|
||||
'string' => 'host=localhost port=5432 dbname=mary',
|
||||
'persistent' => TRUE,
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to PDO
|
||||
echo '<p>Connecting to Sqlite via PDO: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'pdo',
|
||||
'dsn' => 'sqlite2::memory:',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
// connects to MS SQL
|
||||
echo '<p>Connecting to MS SQL: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'mssql',
|
||||
'host' => 'localhost',
|
||||
'username' => 'root',
|
||||
'password' => 'xxx',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
// connects to Oracle
|
||||
echo '<p>Connecting to Oracle: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'oracle',
|
||||
'username' => 'root',
|
||||
'password' => 'xxx',
|
||||
'database' => 'db',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
<h1>dibi::connect() example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// connects to SQlite
|
||||
echo '<p>Connecting to Sqlite: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
'result:objects' => TRUE, // fetch rows as objects
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to MySQL using DSN
|
||||
echo '<p>Connecting to MySQL: ';
|
||||
try {
|
||||
dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=utf8');
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to MySQLi using array
|
||||
echo '<p>Connecting to MySQL: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'mysqli',
|
||||
'host' => 'localhost',
|
||||
'username' => 'root',
|
||||
'password' => 'xxx',
|
||||
'database' => 'dibi',
|
||||
'charset' => 'utf8',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to ODBC
|
||||
echo '<p>Connecting to ODBC: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'odbc',
|
||||
'username' => 'root',
|
||||
'password' => '***',
|
||||
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/sample.mdb',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to PostgreSql
|
||||
echo '<p>Connecting to PostgreSql: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'postgre',
|
||||
'string' => 'host=localhost port=5432 dbname=mary',
|
||||
'persistent' => TRUE,
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
|
||||
// connects to PDO
|
||||
echo '<p>Connecting to Sqlite via PDO: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'pdo',
|
||||
'dsn' => 'sqlite2::memory:',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
// connects to MS SQL
|
||||
echo '<p>Connecting to MS SQL: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'mssql',
|
||||
'host' => 'localhost',
|
||||
'username' => 'root',
|
||||
'password' => 'xxx',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
|
||||
|
||||
|
||||
// connects to Oracle
|
||||
echo '<p>Connecting to Oracle: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'oracle',
|
||||
'username' => 'root',
|
||||
'password' => 'xxx',
|
||||
'database' => 'db',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
echo "</p>\n";
|
@@ -1,28 +1,28 @@
|
||||
<h1>IDibiVariable example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// required since PHP 5.1.0
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
|
||||
// CHANGE TO REAL PARAMETERS!
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
'format:date' => "'Y-m-d'",
|
||||
'format:datetime' => "'Y-m-d H-i-s'",
|
||||
));
|
||||
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("
|
||||
INSERT INTO [mytable]", array(
|
||||
'id' => 123,
|
||||
'date' => dibi::date('12.3.2007'),
|
||||
'stamp' => dibi::dateTime('23.1.2007 10:23'),
|
||||
));
|
||||
<h1>IDibiVariable example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// required since PHP 5.1.0
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
|
||||
// CHANGE TO REAL PARAMETERS!
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
'format:date' => "'Y-m-d'",
|
||||
'format:datetime' => "'Y-m-d H-i-s'",
|
||||
));
|
||||
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("
|
||||
INSERT INTO [mytable]", array(
|
||||
'id' => 123,
|
||||
'date' => dibi::date('12.3.2007'),
|
||||
'stamp' => dibi::dateTime('23.1.2007 10:23'),
|
||||
));
|
||||
|
@@ -1,88 +1,88 @@
|
||||
<h1>DibiTable demo</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
dibi::begin();
|
||||
|
||||
|
||||
// autodetection: primary keys are customer_id, order_id, ...
|
||||
DibiTable::$primaryMask = '%s_id';
|
||||
|
||||
|
||||
// table products
|
||||
class Products extends DibiTable
|
||||
{
|
||||
// rely on autodetection...
|
||||
// protected $name = 'products';
|
||||
// protected $primary = 'product_id';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// create table object
|
||||
$products = new Products();
|
||||
|
||||
echo "Table name: $products->name\n";
|
||||
echo "Primary key: $products->primary\n";
|
||||
|
||||
|
||||
// Finds rows by primary key
|
||||
foreach ($products->find(1, 3) as $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
|
||||
// select all
|
||||
$products->findAll()->dump();
|
||||
|
||||
|
||||
// select all, order by title, product_id
|
||||
$products->findAll('title', $products->primary)->dump();
|
||||
|
||||
|
||||
// fetches single row with id 3
|
||||
$row = $products->fetch(3);
|
||||
|
||||
|
||||
// deletes row from a table
|
||||
$count = $products->delete(1);
|
||||
|
||||
// deletes multiple rows
|
||||
$count = $products->delete(array(1, 2, 3));
|
||||
var_dump($count); // number of deleted rows
|
||||
|
||||
|
||||
// update row #2 in a table
|
||||
$data = (object) NULL;
|
||||
$data->title = 'New title';
|
||||
$count = $products->update(2, $data);
|
||||
var_dump($count); // number of updated rows
|
||||
|
||||
|
||||
// update multiple rows in a table
|
||||
$count = $products->update(array(3, 5), $data);
|
||||
var_dump($count); // number of updated rows
|
||||
|
||||
|
||||
// inserts row into a table
|
||||
$data = array();
|
||||
$data['title'] = 'New product';
|
||||
$id = $products->insert($data);
|
||||
var_dump($id); // generated id
|
||||
|
||||
|
||||
// is absolutely SQL injection safe
|
||||
$key = '3 OR 1=1';
|
||||
$products->delete($key);
|
||||
// --> DELETE FROM [products] WHERE [product_id] IN ( 3 )
|
||||
<h1>DibiTable demo</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
dibi::begin();
|
||||
|
||||
|
||||
// autodetection: primary keys are customer_id, order_id, ...
|
||||
DibiTable::$primaryMask = '%s_id';
|
||||
|
||||
|
||||
// table products
|
||||
class Products extends DibiTable
|
||||
{
|
||||
// rely on autodetection...
|
||||
// protected $name = 'products';
|
||||
// protected $primary = 'product_id';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// create table object
|
||||
$products = new Products();
|
||||
|
||||
echo "Table name: $products->name\n";
|
||||
echo "Primary key: $products->primary\n";
|
||||
|
||||
|
||||
// Finds rows by primary key
|
||||
foreach ($products->find(1, 3) as $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
|
||||
// select all
|
||||
$products->findAll()->dump();
|
||||
|
||||
|
||||
// select all, order by title, product_id
|
||||
$products->findAll('title', $products->primary)->dump();
|
||||
|
||||
|
||||
// fetches single row with id 3
|
||||
$row = $products->fetch(3);
|
||||
|
||||
|
||||
// deletes row from a table
|
||||
$count = $products->delete(1);
|
||||
|
||||
// deletes multiple rows
|
||||
$count = $products->delete(array(1, 2, 3));
|
||||
var_dump($count); // number of deleted rows
|
||||
|
||||
|
||||
// update row #2 in a table
|
||||
$data = (object) NULL;
|
||||
$data->title = 'New title';
|
||||
$count = $products->update(2, $data);
|
||||
var_dump($count); // number of updated rows
|
||||
|
||||
|
||||
// update multiple rows in a table
|
||||
$count = $products->update(array(3, 5), $data);
|
||||
var_dump($count); // number of updated rows
|
||||
|
||||
|
||||
// inserts row into a table
|
||||
$data = array();
|
||||
$data['title'] = 'New product';
|
||||
$id = $products->insert($data);
|
||||
var_dump($id); // generated id
|
||||
|
||||
|
||||
// is absolutely SQL injection safe
|
||||
$key = '3 OR 1=1';
|
||||
$products->delete($key);
|
||||
// --> DELETE FROM [products] WHERE [product_id] IN ( 3 )
|
||||
|
@@ -1,30 +1,30 @@
|
||||
<h1>dibi dump example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
$res = dibi::query('
|
||||
SELECT * FROM [products]
|
||||
INNER JOIN [orders] USING ([product_id])
|
||||
INNER JOIN [customers] USING ([customer_id])
|
||||
');
|
||||
|
||||
|
||||
echo '<h2>dibi::dump()</h2>';
|
||||
|
||||
// dump last query (dibi::$sql)
|
||||
dibi::dump();
|
||||
|
||||
|
||||
// dump result table
|
||||
echo '<h2>DibiResult::dump()</h2>';
|
||||
|
||||
$res->dump();
|
||||
<h1>dibi dump example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
$res = dibi::query('
|
||||
SELECT * FROM [products]
|
||||
INNER JOIN [orders] USING ([product_id])
|
||||
INNER JOIN [customers] USING ([customer_id])
|
||||
');
|
||||
|
||||
|
||||
echo '<h2>dibi::dump()</h2>';
|
||||
|
||||
// dump last query (dibi::$sql)
|
||||
dibi::dump();
|
||||
|
||||
|
||||
// dump result table
|
||||
echo '<h2>DibiResult::dump()</h2>';
|
||||
|
||||
$res->dump();
|
||||
|
@@ -1,27 +1,27 @@
|
||||
<h1>dibi extension method example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
// using the "prototype" to add custom method to class DibiResult
|
||||
function DibiResult_prototype_fetchShuffle(DibiResult $obj)
|
||||
{
|
||||
$all = $obj->fetchAll();
|
||||
shuffle($all);
|
||||
return $all;
|
||||
}
|
||||
|
||||
|
||||
// fetch complete result set shuffled
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
$all = $res->fetchShuffle();
|
||||
print_r($all);
|
||||
<h1>dibi extension method example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
// using the "prototype" to add custom method to class DibiResult
|
||||
function DibiResult_prototype_fetchShuffle(DibiResult $obj)
|
||||
{
|
||||
$all = $obj->fetchAll();
|
||||
shuffle($all);
|
||||
return $all;
|
||||
}
|
||||
|
||||
|
||||
// fetch complete result set shuffled
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
$all = $res->fetchShuffle();
|
||||
print_r($all);
|
||||
|
@@ -1,93 +1,93 @@
|
||||
<h1>dibi fetch example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
/*
|
||||
TABLE products
|
||||
|
||||
product_id | title
|
||||
-----------+----------
|
||||
1 | Chair
|
||||
2 | Table
|
||||
3 | Computer
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// fetch a single row
|
||||
$row = dibi::fetch('SELECT title FROM [products]');
|
||||
print_r($row); // Chair
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch a single value
|
||||
$value = dibi::fetchSingle('SELECT [title] FROM [products]');
|
||||
print_r($value); // Chair
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch complete result set
|
||||
$all = dibi::fetchAll('SELECT * FROM [products]');
|
||||
print_r($all);
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch complete result set like association array
|
||||
$res = dibi::query('SELECT * FROM [products]');
|
||||
$assoc = $res->fetchAssoc('title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch complete result set like pairs key => value
|
||||
$pairs = $res->fetchPairs('product_id', 'title');
|
||||
print_r($pairs);
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch row by row
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch row by row with defined offset
|
||||
foreach ($res->getIterator(2) as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
// fetch row by row with defined offset and limit
|
||||
foreach ($res->getIterator(2, 1) as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
|
||||
// more complex association array
|
||||
$res = dibi::query('
|
||||
SELECT *
|
||||
FROM [products]
|
||||
INNER JOIN [orders] USING ([product_id])
|
||||
INNER JOIN [customers] USING ([customer_id])
|
||||
');
|
||||
|
||||
$assoc = $res->fetchAssoc('customers.name,products.title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
||||
$assoc = $res->fetchAssoc('customers.name,#,products.title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
||||
$assoc = $res->fetchAssoc('customers.name,=,products.title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
<h1>dibi fetch example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
/*
|
||||
TABLE products
|
||||
|
||||
product_id | title
|
||||
-----------+----------
|
||||
1 | Chair
|
||||
2 | Table
|
||||
3 | Computer
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// fetch a single row
|
||||
$row = dibi::fetch('SELECT title FROM [products]');
|
||||
print_r($row); // Chair
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch a single value
|
||||
$value = dibi::fetchSingle('SELECT [title] FROM [products]');
|
||||
print_r($value); // Chair
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch complete result set
|
||||
$all = dibi::fetchAll('SELECT * FROM [products]');
|
||||
print_r($all);
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch complete result set like association array
|
||||
$res = dibi::query('SELECT * FROM [products]');
|
||||
$assoc = $res->fetchAssoc('title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch complete result set like pairs key => value
|
||||
$pairs = $res->fetchPairs('product_id', 'title');
|
||||
print_r($pairs);
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch row by row
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch row by row with defined offset
|
||||
foreach ($res->getIterator(2) as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
// fetch row by row with defined offset and limit
|
||||
foreach ($res->getIterator(2, 1) as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
|
||||
// more complex association array
|
||||
$res = dibi::query('
|
||||
SELECT *
|
||||
FROM [products]
|
||||
INNER JOIN [orders] USING ([product_id])
|
||||
INNER JOIN [customers] USING ([customer_id])
|
||||
');
|
||||
|
||||
$assoc = $res->fetchAssoc('customers.name,products.title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
||||
$assoc = $res->fetchAssoc('customers.name,#,products.title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
||||
$assoc = $res->fetchAssoc('customers.name,=,products.title'); // key
|
||||
print_r($assoc);
|
||||
echo '<hr>';
|
||||
|
@@ -1,63 +1,63 @@
|
||||
<h1>dibi dump example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$id = 10;
|
||||
$record = array(
|
||||
'title' => 'Drtička na trávu',
|
||||
'price' => 318,
|
||||
'active' => TRUE,
|
||||
);
|
||||
|
||||
// SELECT ...
|
||||
dibi::select('product_id')->as('id')
|
||||
->select('title')
|
||||
->from('products')
|
||||
->innerJoin('orders')->using('(product_id)')
|
||||
->innerJoin('customers USING (customer_id)')
|
||||
->orderBy('title')
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// INSERT ...
|
||||
dibi::insert('products', $record)
|
||||
->setFlag('IGNORE')
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// UPDATE ...
|
||||
dibi::update('products', $record)
|
||||
->where('product_id = %d', $id)
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// DELETE ...
|
||||
dibi::delete('products')
|
||||
->where('product_id = %d', $id)
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// custom commands
|
||||
dibi::command()
|
||||
->update('products')
|
||||
->where('product_id = %d', $id)
|
||||
->set($record)
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
dibi::command()
|
||||
->truncate('products')
|
||||
->test();
|
||||
<h1>dibi dump example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$id = 10;
|
||||
$record = array(
|
||||
'title' => 'Drtička na trávu',
|
||||
'price' => 318,
|
||||
'active' => TRUE,
|
||||
);
|
||||
|
||||
// SELECT ...
|
||||
dibi::select('product_id')->as('id')
|
||||
->select('title')
|
||||
->from('products')
|
||||
->innerJoin('orders')->using('(product_id)')
|
||||
->innerJoin('customers USING (customer_id)')
|
||||
->orderBy('title')
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// INSERT ...
|
||||
dibi::insert('products', $record)
|
||||
->setFlag('IGNORE')
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// UPDATE ...
|
||||
dibi::update('products', $record)
|
||||
->where('product_id = %d', $id)
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// DELETE ...
|
||||
dibi::delete('products')
|
||||
->where('product_id = %d', $id)
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
// custom commands
|
||||
dibi::command()
|
||||
->update('products')
|
||||
->where('product_id = %d', $id)
|
||||
->set($record)
|
||||
->test();
|
||||
|
||||
echo "\n";
|
||||
|
||||
dibi::command()
|
||||
->truncate('products')
|
||||
->test();
|
||||
|
@@ -1,16 +1,16 @@
|
||||
<h1>dibi import SQL dump example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$count = dibi::loadFile('compress.zlib://dump.sql.gz');
|
||||
|
||||
<h1>dibi import SQL dump example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$count = dibi::loadFile('compress.zlib://dump.sql.gz');
|
||||
|
||||
echo 'Number of SQL commands:', $count;
|
@@ -1,32 +1,32 @@
|
||||
<h1>dibi logger example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
// enable log to this file, TRUE means "log all queries"
|
||||
dibi::startLogger('log.sql', TRUE);
|
||||
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
try {
|
||||
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] = %i', 1);
|
||||
|
||||
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', 5);
|
||||
|
||||
$res = dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38);
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo '<p>', get_class($e), ': ', $e->getMessage(), '</p>';
|
||||
}
|
||||
|
||||
|
||||
echo "<h2>File log.sql:</h2>";
|
||||
|
||||
echo '<pre>', file_get_contents('log.sql'), '</pre>';
|
||||
<h1>dibi logger example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
// enable log to this file, TRUE means "log all queries"
|
||||
dibi::startLogger('log.sql', TRUE);
|
||||
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
try {
|
||||
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] = %i', 1);
|
||||
|
||||
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', 5);
|
||||
|
||||
$res = dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38);
|
||||
|
||||
} catch (DibiException $e) {
|
||||
echo '<p>', get_class($e), ': ', $e->getMessage(), '</p>';
|
||||
}
|
||||
|
||||
|
||||
echo "<h2>File log.sql:</h2>";
|
||||
|
||||
echo '<pre>', file_get_contents('log.sql'), '</pre>';
|
||||
|
@@ -1,21 +1,21 @@
|
||||
<h1>dibi metatypes example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
|
||||
// auto-convert this column to integer
|
||||
$res->setType('customer_id', Dibi::FIELD_INTEGER);
|
||||
$res->setType('added', Dibi::FIELD_DATETIME, 'H:i j.n.Y');
|
||||
|
||||
$row = $res->fetch();
|
||||
var_dump($row);
|
||||
<h1>dibi metatypes example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
|
||||
// auto-convert this column to integer
|
||||
$res->setType('customer_id', Dibi::FIELD_INTEGER);
|
||||
$res->setType('added', Dibi::FIELD_DATETIME, 'H:i j.n.Y');
|
||||
|
||||
$row = $res->fetch();
|
||||
var_dump($row);
|
||||
|
@@ -1,19 +1,19 @@
|
||||
<h1>Nette::Debug && dibi example</h1>
|
||||
<?php
|
||||
|
||||
require_once 'Nette/Debug.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
Debug::enable();
|
||||
Debug::enableProfiler();
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
// throws error
|
||||
dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38);
|
||||
<h1>Nette::Debug && dibi example</h1>
|
||||
<?php
|
||||
|
||||
require_once 'Nette/Debug.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
Debug::enable();
|
||||
Debug::enableProfiler();
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
||||
// throws error
|
||||
dibi::query('SELECT FROM [customers] WHERE [customer_id] < %i', 38);
|
||||
|
@@ -1,25 +1,25 @@
|
||||
<h1>Dibi profiler example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
for ($i=0; $i<20; $i++) {
|
||||
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', $i);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<p>Last query: <strong><?php echo dibi::$sql; ?></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>Total elapsed time: <strong><?php echo sprintf('%0.3f', dibi::$totalTime * 1000); ?> ms</strong></p>
|
||||
<h1>Dibi profiler example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
for ($i=0; $i<20; $i++) {
|
||||
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < %i', $i);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<p>Last query: <strong><?php echo dibi::$sql; ?></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>Total elapsed time: <strong><?php echo sprintf('%0.3f', dibi::$totalTime * 1000); ?> ms</strong></p>
|
||||
|
@@ -1,66 +1,66 @@
|
||||
<style>
|
||||
pre.dibi { padding-bottom: 10px; }
|
||||
</style>
|
||||
<h1>dibi SQL builder example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
// required since PHP 5.1.0
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// dibi detects INSERT or REPLACE command
|
||||
dibi::test('
|
||||
REPLACE INTO [products]', array(
|
||||
'title' => 'Drti<74>ka na tr<74>vu',
|
||||
'price' => 318,
|
||||
'active' => TRUE,
|
||||
));
|
||||
|
||||
|
||||
// multiple INSERT command
|
||||
$array = array(
|
||||
'title' => 'Super Product',
|
||||
'price' => 12,
|
||||
'brand' => NULL,
|
||||
'created' => dibi::datetime(),
|
||||
);
|
||||
dibi::test("INSERT INTO [products]", $array, $array, $array);
|
||||
|
||||
|
||||
// dibi detects UPDATE command
|
||||
dibi::test("
|
||||
UPDATE [colors] SET", array(
|
||||
'color' => 'blue',
|
||||
'order' => 12,
|
||||
), "
|
||||
WHERE [id]=%i", 123);
|
||||
|
||||
|
||||
// SELECT
|
||||
$ipMask = '192.168.%';
|
||||
$timestamp = mktime(0, 0, 0, 10, 13, 1997);
|
||||
|
||||
dibi::test('
|
||||
SELECT COUNT(*) as [count]
|
||||
FROM [comments]
|
||||
WHERE [ip] LIKE %s', $ipMask, '
|
||||
AND [date] > ', dibi::date($timestamp)
|
||||
);
|
||||
|
||||
|
||||
// IN array
|
||||
$array = array(1, 2, 3);
|
||||
dibi::test("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] IN (", $array, ")
|
||||
");
|
||||
<style>
|
||||
pre.dibi { padding-bottom: 10px; }
|
||||
</style>
|
||||
<h1>dibi SQL builder example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
// required since PHP 5.1.0
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// dibi detects INSERT or REPLACE command
|
||||
dibi::test('
|
||||
REPLACE INTO [products]', array(
|
||||
'title' => 'Drti<74>ka na tr<74>vu',
|
||||
'price' => 318,
|
||||
'active' => TRUE,
|
||||
));
|
||||
|
||||
|
||||
// multiple INSERT command
|
||||
$array = array(
|
||||
'title' => 'Super Product',
|
||||
'price' => 12,
|
||||
'brand' => NULL,
|
||||
'created' => dibi::datetime(),
|
||||
);
|
||||
dibi::test("INSERT INTO [products]", $array, $array, $array);
|
||||
|
||||
|
||||
// dibi detects UPDATE command
|
||||
dibi::test("
|
||||
UPDATE [colors] SET", array(
|
||||
'color' => 'blue',
|
||||
'order' => 12,
|
||||
), "
|
||||
WHERE [id]=%i", 123);
|
||||
|
||||
|
||||
// SELECT
|
||||
$ipMask = '192.168.%';
|
||||
$timestamp = mktime(0, 0, 0, 10, 13, 1997);
|
||||
|
||||
dibi::test('
|
||||
SELECT COUNT(*) as [count]
|
||||
FROM [comments]
|
||||
WHERE [ip] LIKE %s', $ipMask, '
|
||||
AND [date] > ', dibi::date($timestamp)
|
||||
);
|
||||
|
||||
|
||||
// IN array
|
||||
$array = array(1, 2, 3);
|
||||
dibi::test("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] IN (", $array, ")
|
||||
");
|
||||
|
@@ -1,51 +1,51 @@
|
||||
<style>
|
||||
pre.dibi { padding-bottom: 10px; }
|
||||
</style>
|
||||
<h1>dibi conditional SQL example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$cond1 = rand(0,2) < 1;
|
||||
$cond2 = rand(0,2) < 1;
|
||||
$foo = -1;
|
||||
$bar = 2;
|
||||
|
||||
|
||||
$name = $cond1 ? 'K%' : NULL;
|
||||
|
||||
// if & end
|
||||
dibi::test('
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
%if', isset($name), 'WHERE [name] LIKE %s', $name, '%end'
|
||||
);
|
||||
|
||||
|
||||
// if & else & (optional) end
|
||||
dibi::test("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] > 0
|
||||
%if", ($foo > 0), "AND [foo]=%i", $foo, "
|
||||
%else %if", ($bar > 0), "AND [bar]=%i", $bar, "
|
||||
");
|
||||
|
||||
|
||||
// nested condition
|
||||
dibi::test('
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
WHERE
|
||||
%if', isset($name), '[name] LIKE %s', $name, '
|
||||
%if', $cond2, 'AND [admin]=1 %end
|
||||
%else 1 LIMIT 10 %end'
|
||||
);
|
||||
<style>
|
||||
pre.dibi { padding-bottom: 10px; }
|
||||
</style>
|
||||
<h1>dibi conditional SQL example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
$cond1 = rand(0,2) < 1;
|
||||
$cond2 = rand(0,2) < 1;
|
||||
$foo = -1;
|
||||
$bar = 2;
|
||||
|
||||
|
||||
$name = $cond1 ? 'K%' : NULL;
|
||||
|
||||
// if & end
|
||||
dibi::test('
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
%if', isset($name), 'WHERE [name] LIKE %s', $name, '%end'
|
||||
);
|
||||
|
||||
|
||||
// if & else & (optional) end
|
||||
dibi::test("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] > 0
|
||||
%if", ($foo > 0), "AND [foo]=%i", $foo, "
|
||||
%else %if", ($bar > 0), "AND [bar]=%i", $bar, "
|
||||
");
|
||||
|
||||
|
||||
// nested condition
|
||||
dibi::test('
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
WHERE
|
||||
%if', isset($name), '[name] LIKE %s', $name, '
|
||||
%if', $cond2, 'AND [admin]=1 %end
|
||||
%else 1 LIMIT 10 %end'
|
||||
);
|
||||
|
@@ -1,44 +1,44 @@
|
||||
<h1>dibi prefix & substitute example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// create new substitution :blog: ==> wp_
|
||||
dibi::addSubst('blog', 'wp_');
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("UPDATE [:blog:items] SET [text]='Hello World'");
|
||||
|
||||
|
||||
|
||||
|
||||
// create new substitution :: (empty) ==> my_
|
||||
dibi::addSubst('', 'my_');
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("UPDATE [database.::table] SET [text]='Hello World'");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function substFallBack($expr)
|
||||
{
|
||||
return 'the_' . $expr;
|
||||
}
|
||||
|
||||
// create substitution fallback
|
||||
dibi::setSubstFallBack('substFallBack');
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("UPDATE [:account:user] SET [name]='John Doe'");
|
||||
<h1>dibi prefix & substitute example</h1>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// create new substitution :blog: ==> wp_
|
||||
dibi::addSubst('blog', 'wp_');
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("UPDATE [:blog:items] SET [text]='Hello World'");
|
||||
|
||||
|
||||
|
||||
|
||||
// create new substitution :: (empty) ==> my_
|
||||
dibi::addSubst('', 'my_');
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("UPDATE [database.::table] SET [text]='Hello World'");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function substFallBack($expr)
|
||||
{
|
||||
return 'the_' . $expr;
|
||||
}
|
||||
|
||||
// create substitution fallback
|
||||
dibi::setSubstFallBack('substFallBack');
|
||||
|
||||
|
||||
// generate and dump SQL
|
||||
dibi::test("UPDATE [:account:user] SET [name]='John Doe'");
|
||||
|
@@ -1,28 +1,28 @@
|
||||
<h1>dibi transaction example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
echo "<h2>Before:</h2>\n";
|
||||
dibi::query('SELECT * FROM [products]')->dump();
|
||||
|
||||
|
||||
|
||||
dibi::begin();
|
||||
dibi::query('INSERT INTO [products]', array(
|
||||
'title' => 'Test product',
|
||||
));
|
||||
dibi::rollback(); // or dibi::commit();
|
||||
|
||||
|
||||
|
||||
echo "<h2>After:</h2>\n";
|
||||
<h1>dibi transaction example</h1>
|
||||
<pre>
|
||||
<?php
|
||||
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
echo "<h2>Before:</h2>\n";
|
||||
dibi::query('SELECT * FROM [products]')->dump();
|
||||
|
||||
|
||||
|
||||
dibi::begin();
|
||||
dibi::query('INSERT INTO [products]', array(
|
||||
'title' => 'Test product',
|
||||
));
|
||||
dibi::rollback(); // or dibi::commit();
|
||||
|
||||
|
||||
|
||||
echo "<h2>After:</h2>\n";
|
||||
dibi::query('SELECT * FROM [products]')->dump();
|
@@ -1,2 +1,2 @@
|
||||
<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>
|
||||
<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>
|
||||
|
136
license.cs.txt
136
license.cs.txt
@@ -1,69 +1,69 @@
|
||||
----------------------------------------------------------------------------------
|
||||
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>
|
||||
anglick<EFBFBD> verze licence.
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Dibi Licence, verze 1
|
||||
======================
|
||||
|
||||
Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
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)
|
||||
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,
|
||||
porozum<EFBFBD>li a budete jednat v souladu s podm<64>nkami t<>to licence.
|
||||
|
||||
|
||||
POVOLEN<EFBFBD> POU<4F>IT<49>
|
||||
----------------
|
||||
|
||||
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,
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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>.
|
||||
|
||||
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
|
||||
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>
|
||||
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",
|
||||
ani se nesm<73> "dibi" objevit v jejich n<>zvu bez p<>edchoz<6F>ho
|
||||
p<>semn<6D>ho souhlasu Autora.
|
||||
|
||||
|
||||
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
|
||||
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,
|
||||
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.
|
||||
|
||||
|
||||
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>"
|
||||
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.
|
||||
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,
|
||||
<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>
|
||||
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>
|
||||
----------------------------------------------------------------------------------
|
||||
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>
|
||||
anglick<EFBFBD> verze licence.
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Dibi Licence, verze 1
|
||||
======================
|
||||
|
||||
Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
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)
|
||||
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,
|
||||
porozum<EFBFBD>li a budete jednat v souladu s podm<64>nkami t<>to licence.
|
||||
|
||||
|
||||
POVOLEN<EFBFBD> POU<4F>IT<49>
|
||||
----------------
|
||||
|
||||
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,
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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>.
|
||||
|
||||
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
|
||||
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>
|
||||
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",
|
||||
ani se nesm<73> "dibi" objevit v jejich n<>zvu bez p<>edchoz<6F>ho
|
||||
p<>semn<6D>ho souhlasu Autora.
|
||||
|
||||
|
||||
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
|
||||
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,
|
||||
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.
|
||||
|
||||
|
||||
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>"
|
||||
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.
|
||||
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,
|
||||
<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>
|
||||
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>
|
||||
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.
|
124
license.txt
124
license.txt
@@ -1,62 +1,62 @@
|
||||
The Dibi License, Version 1
|
||||
============================
|
||||
|
||||
Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
All rights reserved.
|
||||
|
||||
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
|
||||
copying the Software, you agree that you have read, understood, and will
|
||||
comply with the terms and conditions of this license.
|
||||
|
||||
|
||||
PERMITTED USE
|
||||
-------------
|
||||
|
||||
You are permitted to use, copy, modify, and distribute the Software and its
|
||||
documentation, with or without modification, for any purpose, provided that
|
||||
the following conditions are met:
|
||||
|
||||
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
|
||||
all source code files.
|
||||
|
||||
3. Redistributions in binary form must reproduce the above copyright notice
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
4. Products derived from the Software must include an acknowledgment that
|
||||
they are derived from "dibi" in their documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
5. The name "dibi" must not be used to endorse or promote products
|
||||
derived from the Software without prior written permission from Author.
|
||||
|
||||
6. Products derived from the Software may not be called "dibi",
|
||||
nor may "dibi" appear in their name, without prior written
|
||||
permission from Author.
|
||||
|
||||
|
||||
INDEMNITY
|
||||
---------
|
||||
|
||||
You agree to indemnify and hold harmless the Author and any contributors
|
||||
for any direct, indirect, incidental, or consequential third-party claims,
|
||||
actions or suits, as well as any related expenses, liabilities, damages,
|
||||
settlements or fees arising from your use or misuse of the Software,
|
||||
or a violation of any terms of this license.
|
||||
|
||||
|
||||
DISCLAIMER OF WARRANTY
|
||||
----------------------
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
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
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
The Dibi License, Version 1
|
||||
============================
|
||||
|
||||
Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
||||
All rights reserved.
|
||||
|
||||
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
|
||||
copying the Software, you agree that you have read, understood, and will
|
||||
comply with the terms and conditions of this license.
|
||||
|
||||
|
||||
PERMITTED USE
|
||||
-------------
|
||||
|
||||
You are permitted to use, copy, modify, and distribute the Software and its
|
||||
documentation, with or without modification, for any purpose, provided that
|
||||
the following conditions are met:
|
||||
|
||||
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
|
||||
all source code files.
|
||||
|
||||
3. Redistributions in binary form must reproduce the above copyright notice
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
4. Products derived from the Software must include an acknowledgment that
|
||||
they are derived from "dibi" in their documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
5. The name "dibi" must not be used to endorse or promote products
|
||||
derived from the Software without prior written permission from Author.
|
||||
|
||||
6. Products derived from the Software may not be called "dibi",
|
||||
nor may "dibi" appear in their name, without prior written
|
||||
permission from Author.
|
||||
|
||||
|
||||
INDEMNITY
|
||||
---------
|
||||
|
||||
You agree to indemnify and hold harmless the Author and any contributors
|
||||
for any direct, indirect, incidental, or consequential third-party claims,
|
||||
actions or suits, as well as any related expenses, liabilities, damages,
|
||||
settlements or fees arising from your use or misuse of the Software,
|
||||
or a violation of any terms of this license.
|
||||
|
||||
|
||||
DISCLAIMER OF WARRANTY
|
||||
----------------------
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
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
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
82
readme.txt
82
readme.txt
@@ -1,41 +1,41 @@
|
||||
Dibi (c) David Grudl, 2005-2008 (http://davidgrudl.com)
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Thank you for downloading Dibi!
|
||||
|
||||
Database access functions in PHP are not standardised. This is class library
|
||||
to hide the differences between the different databases access.
|
||||
|
||||
The files in this archive are released under the Dibi license.
|
||||
See license.txt in this directory for a copy of the license.
|
||||
|
||||
|
||||
|
||||
Documentation and Examples
|
||||
--------------------------
|
||||
|
||||
Refer to the 'examples' directory for examples. Dibi documentation is
|
||||
available on the homepage:
|
||||
|
||||
http://dibiphp.com
|
||||
|
||||
|
||||
|
||||
Dibi.compact
|
||||
------------
|
||||
|
||||
This is shrinked single-file version of whole Dibi, useful when you don't
|
||||
want to modify library, but just use it.
|
||||
|
||||
This is exactly the same as normal version, just only comments and
|
||||
whitespaces are removed.
|
||||
|
||||
|
||||
|
||||
-----
|
||||
For more information, visit the author's weblog (in czech language):
|
||||
http://phpfashion.com
|
||||
Dibi (c) David Grudl, 2005-2008 (http://davidgrudl.com)
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Thank you for downloading Dibi!
|
||||
|
||||
Database access functions in PHP are not standardised. This is class library
|
||||
to hide the differences between the different databases access.
|
||||
|
||||
The files in this archive are released under the Dibi license.
|
||||
See license.txt in this directory for a copy of the license.
|
||||
|
||||
|
||||
|
||||
Documentation and Examples
|
||||
--------------------------
|
||||
|
||||
Refer to the 'examples' directory for examples. Dibi documentation is
|
||||
available on the homepage:
|
||||
|
||||
http://dibiphp.com
|
||||
|
||||
|
||||
|
||||
Dibi.compact
|
||||
------------
|
||||
|
||||
This is shrinked single-file version of whole Dibi, useful when you don't
|
||||
want to modify library, but just use it.
|
||||
|
||||
This is exactly the same as normal version, just only comments and
|
||||
whitespaces are removed.
|
||||
|
||||
|
||||
|
||||
-----
|
||||
For more information, visit the author's weblog (in czech language):
|
||||
http://phpfashion.com
|
||||
|
@@ -1,4 +1,3 @@
|
||||
Dibi version 0.9
|
||||
|
||||
Revision: $WCREV$
|
||||
Date: $WCDATE$
|
||||
Dibi 0.9 (revision $WCREV$)
|
||||
|
||||
Released on $WCDATE$
|
||||
|
Reference in New Issue
Block a user