mirror of
https://github.com/dg/dibi.git
synced 2025-09-04 11:45:27 +02:00
Compare commits
82 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3b2ca19d42 | ||
|
16f6d537e0 | ||
|
6d353c0b5d | ||
|
698c12eadc | ||
|
70ba2f065c | ||
|
7e539f8f4f | ||
|
532ed3a316 | ||
|
08e70fda61 | ||
|
217de42d20 | ||
|
fa6d771813 | ||
|
3777bacc02 | ||
|
9850a2f78b | ||
|
031bd2b767 | ||
|
7c6932807d | ||
|
208a579d6f | ||
|
eeba6cfc91 | ||
|
8cc1d8b948 | ||
|
c2a2a4cd18 | ||
|
5e3bc8d0e9 | ||
|
6f34e56bd6 | ||
|
18a7665bec | ||
|
fb026ef45d | ||
|
2d69d4a18e | ||
|
0d79d16d2c | ||
|
a3f673e82b | ||
|
6ff605ef0a | ||
|
6f4641c3ee | ||
|
77efc27681 | ||
|
e52cee8cbc | ||
|
74178a5596 | ||
|
c67bcd5598 | ||
|
bf15d60fd1 | ||
|
9c435acd2e | ||
|
1e08a91e66 | ||
|
43c7e70e90 | ||
|
fb8054d21a | ||
|
564a0e534e | ||
|
bba85b5441 | ||
|
98d43e0815 | ||
|
6589519419 | ||
|
496c224be5 | ||
|
aa05a85dfb | ||
|
5946b7e1f6 | ||
|
a9afe1e397 | ||
|
97969edace | ||
|
d0097d6c9c | ||
|
7969289aaa | ||
|
5c2245a9d7 | ||
|
2f86997ca7 | ||
|
d2f1beba57 | ||
|
14b731e002 | ||
|
60559d9a9f | ||
|
b958e37fdf | ||
|
a26744388d | ||
|
0b0596dbeb | ||
|
419929f813 | ||
|
8df67d0de2 | ||
|
60662bdae1 | ||
|
dd6ffc3d0e | ||
|
46d79fc305 | ||
|
32ed383326 | ||
|
bf6dc1cbd1 | ||
|
a5a1da19a7 | ||
|
5ecfaf7ab1 | ||
|
47d1180aee | ||
|
7c0c4db0f6 | ||
|
c24f2b8705 | ||
|
84172591d5 | ||
|
ca87994189 | ||
|
c5f8a260c7 | ||
|
96acdb46dc | ||
|
348af48ecd | ||
|
52a9e316b8 | ||
|
e5a1877ed9 | ||
|
4b189b93d6 | ||
|
781274ba65 | ||
|
9244a1b1b5 | ||
|
4b7b7de87a | ||
|
fb2621eb04 | ||
|
2f690b63f9 | ||
|
9f8b19f1fb | ||
|
d08a5d3856 |
@@ -3,14 +3,14 @@
|
|||||||
/**
|
/**
|
||||||
* Nette Framework
|
* Nette Framework
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "Nette license" that is bundled
|
* This source file is subject to the "Nette license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://nettephp.com
|
* For more information please see http://nettephp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
* @copyright Copyright (c) 2004, 2009 David Grudl
|
||||||
* @license http://nettephp.com/license Nette license
|
* @license http://nettephp.com/license Nette license
|
||||||
* @link http://nettephp.com
|
* @link http://nettephp.com
|
||||||
* @category Nette
|
* @category Nette
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom output for Nette::Debug.
|
* Custom output for Nette\Debug.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2004, 2008 David Grudl
|
* @copyright Copyright (c) 2004, 2009 David Grudl
|
||||||
* @package Nette
|
* @package Nette
|
||||||
*/
|
*/
|
||||||
interface IDebuggable
|
interface IDebuggable
|
||||||
|
197
dibi/dibi.php
197
dibi/dibi.php
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -26,6 +25,7 @@ if (version_compare(PHP_VERSION, '5.1.0', '<')) {
|
|||||||
throw new Exception('dibi needs PHP 5.1.0 or newer.');
|
throw new Exception('dibi needs PHP 5.1.0 or newer.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@set_magic_quotes_runtime(FALSE); // intentionally @
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ if (!class_exists('FileNotFoundException', FALSE)) {
|
|||||||
class FileNotFoundException extends IOException {}
|
class FileNotFoundException extends IOException {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!interface_exists(/*Nette::*/'IDebuggable', FALSE)) {
|
if (!interface_exists(/*Nette\*/'IDebuggable', FALSE)) {
|
||||||
require_once dirname(__FILE__) . '/Nette/IDebuggable.php';
|
require_once dirname(__FILE__) . '/Nette/IDebuggable.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +66,10 @@ require_once dirname(__FILE__) . '/libs/DibiObject.php';
|
|||||||
require_once dirname(__FILE__) . '/libs/DibiException.php';
|
require_once dirname(__FILE__) . '/libs/DibiException.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiConnection.php';
|
require_once dirname(__FILE__) . '/libs/DibiConnection.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiResult.php';
|
require_once dirname(__FILE__) . '/libs/DibiResult.php';
|
||||||
|
require_once dirname(__FILE__) . '/libs/DibiResultIterator.php';
|
||||||
|
require_once dirname(__FILE__) . '/libs/DibiRow.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiTranslator.php';
|
require_once dirname(__FILE__) . '/libs/DibiTranslator.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiVariable.php';
|
require_once dirname(__FILE__) . '/libs/DibiVariable.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiTableX.php';
|
|
||||||
require_once dirname(__FILE__) . '/libs/DibiDataSource.php';
|
require_once dirname(__FILE__) . '/libs/DibiDataSource.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiFluent.php';
|
require_once dirname(__FILE__) . '/libs/DibiFluent.php';
|
||||||
require_once dirname(__FILE__) . '/libs/DibiDatabaseInfo.php';
|
require_once dirname(__FILE__) . '/libs/DibiDatabaseInfo.php';
|
||||||
@@ -85,40 +86,52 @@ require_once dirname(__FILE__) . '/libs/DibiProfiler.php';
|
|||||||
* store connections info.
|
* store connections info.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class dibi
|
class dibi
|
||||||
{
|
{
|
||||||
/**#@+
|
/**#@+
|
||||||
* dibi column type
|
* dibi data type
|
||||||
*/
|
*/
|
||||||
const FIELD_TEXT = 's'; // as 'string'
|
const TEXT = 's'; // as 'string'
|
||||||
const FIELD_BINARY = 'bin';
|
const BINARY = 'bin';
|
||||||
const FIELD_BOOL = 'b';
|
const BOOL = 'b';
|
||||||
const FIELD_INTEGER = 'i';
|
const INTEGER = 'i';
|
||||||
const FIELD_FLOAT = 'f';
|
const FLOAT = 'f';
|
||||||
const FIELD_DATE = 'd';
|
const DATE = 'd';
|
||||||
const FIELD_DATETIME = 't';
|
const DATETIME = 't';
|
||||||
const FIELD_TIME = 't';
|
const TIME = 't';
|
||||||
|
const IDENTIFIER = 'n';
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**#@+
|
||||||
* Identifier type
|
* @deprecated column types
|
||||||
*/
|
*/
|
||||||
const IDENTIFIER = 'n';
|
const FIELD_TEXT = self::TEXT;
|
||||||
|
const FIELD_BINARY = self::BINARY;
|
||||||
|
const FIELD_BOOL = self::BOOL;
|
||||||
|
const FIELD_INTEGER = self::INTEGER;
|
||||||
|
const FIELD_FLOAT = self::FLOAT;
|
||||||
|
const FIELD_DATE = self::DATE;
|
||||||
|
const FIELD_DATETIME = self::DATETIME;
|
||||||
|
const FIELD_TIME = self::TIME;
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* dibi version
|
* dibi version
|
||||||
*/
|
*/
|
||||||
const VERSION = '1.0';
|
const VERSION = '1.2';
|
||||||
const REVISION = '$WCREV$ released on $WCDATE$';
|
const REVISION = '$WCREV$ released on $WCDATE$';
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**#@+
|
||||||
* Configuration options
|
* Configuration options
|
||||||
*/
|
*/
|
||||||
const RESULT_WITH_TABLES = 'resultWithTables'; // for MySQL
|
const RESULT_WITH_TABLES = 'resultWithTables'; // for MySQL
|
||||||
|
const ROW_CLASS = 'rowClass';
|
||||||
|
const ASC = 'ASC', DESC = 'DESC';
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
/** @var DibiConnection[] Connection registry storage for DibiConnection objects */
|
/** @var DibiConnection[] Connection registry storage for DibiConnection objects */
|
||||||
private static $registry = array();
|
private static $registry = array();
|
||||||
@@ -127,10 +140,10 @@ class dibi
|
|||||||
private static $connection;
|
private static $connection;
|
||||||
|
|
||||||
/** @var array Substitutions for identifiers */
|
/** @var array Substitutions for identifiers */
|
||||||
private static $substs = array();
|
public static $substs = array();
|
||||||
|
|
||||||
/** @var callback Substitution fallback */
|
/** @var callback Substitution fallback */
|
||||||
private static $substFallBack;
|
public static $substFallBack = array(__CLASS__, 'defaultSubstFallback');
|
||||||
|
|
||||||
/** @var array @see addHandler */
|
/** @var array @see addHandler */
|
||||||
private static $handlers = array();
|
private static $handlers = array();
|
||||||
@@ -259,7 +272,7 @@ class dibi
|
|||||||
/**
|
/**
|
||||||
* Generates and executes SQL query - Monostate for DibiConnection::query().
|
* Generates and executes SQL query - Monostate for DibiConnection::query().
|
||||||
* @param array|mixed one or more arguments
|
* @param array|mixed one or more arguments
|
||||||
* @return DibiResult|NULL result set object (if any)
|
* @return DibiResult|int result set object (if any)
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public static function query($args)
|
public static function query($args)
|
||||||
@@ -273,7 +286,7 @@ class dibi
|
|||||||
/**
|
/**
|
||||||
* Executes the SQL query - Monostate for DibiConnection::nativeQuery().
|
* Executes the SQL query - Monostate for DibiConnection::nativeQuery().
|
||||||
* @param string SQL statement.
|
* @param string SQL statement.
|
||||||
* @return DibiResult|NULL result set object (if any)
|
* @return DibiResult|int result set object (if any)
|
||||||
*/
|
*/
|
||||||
public static function nativeQuery($sql)
|
public static function nativeQuery($sql)
|
||||||
{
|
{
|
||||||
@@ -295,6 +308,19 @@ class dibi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates and returns SQL query as DibiDataSource - Monostate for DibiConnection::test().
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return DibiDataSource
|
||||||
|
*/
|
||||||
|
public static function dataSource($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
return self::getConnection()->dataSource($args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes SQL query and fetch result - Monostate for DibiConnection::query() & fetch().
|
* Executes SQL query and fetch result - Monostate for DibiConnection::query() & fetch().
|
||||||
* @param array|mixed one or more arguments
|
* @param array|mixed one or more arguments
|
||||||
@@ -353,63 +379,91 @@ class dibi
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of affected rows.
|
* Gets the number of affected rows.
|
||||||
* Monostate for DibiConnection::affectedRows()
|
* Monostate for DibiConnection::getAffectedRows()
|
||||||
|
* @return int number of rows
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public static function getAffectedRows()
|
||||||
|
{
|
||||||
|
return self::getConnection()->getAffectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of affected rows. Alias for getAffectedRows().
|
||||||
* @return int number of rows
|
* @return int number of rows
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public static function affectedRows()
|
public static function affectedRows()
|
||||||
{
|
{
|
||||||
return self::getConnection()->affectedRows();
|
return self::getConnection()->getAffectedRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* Monostate for DibiConnection::insertId()
|
* Monostate for DibiConnection::getInsertId()
|
||||||
|
* @param string optional sequence name
|
||||||
|
* @return int
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public static function getInsertId($sequence=NULL)
|
||||||
|
{
|
||||||
|
return self::getConnection()->getInsertId($sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
|
||||||
* @param string optional sequence name
|
* @param string optional sequence name
|
||||||
* @return int
|
* @return int
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public static function insertId($sequence=NULL)
|
public static function insertId($sequence=NULL)
|
||||||
{
|
{
|
||||||
return self::getConnection()->insertId($sequence);
|
return self::getConnection()->getInsertId($sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction - Monostate for DibiConnection::begin().
|
* Begins a transaction - Monostate for DibiConnection::begin().
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public static function begin()
|
public static function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
self::getConnection()->begin();
|
self::getConnection()->begin($savepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction - Monostate for DibiConnection::commit().
|
* Commits statements in a transaction - Monostate for DibiConnection::commit($savepoint = NULL).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public static function commit()
|
public static function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
self::getConnection()->commit();
|
self::getConnection()->commit($savepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction - Monostate for DibiConnection::rollback().
|
* Rollback changes in a transaction - Monostate for DibiConnection::rollback().
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public static function rollback()
|
public static function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
self::getConnection()->rollback();
|
self::getConnection()->rollback($savepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -471,7 +525,7 @@ class dibi
|
|||||||
public static function select($args)
|
public static function select($args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
return self::getConnection()->command()->__call('select', $args);
|
return call_user_func_array(array(self::getConnection(), 'select'), $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -481,7 +535,7 @@ class dibi
|
|||||||
* @param array
|
* @param array
|
||||||
* @return DibiFluent
|
* @return DibiFluent
|
||||||
*/
|
*/
|
||||||
public static function update($table, array $args)
|
public static function update($table, $args)
|
||||||
{
|
{
|
||||||
return self::getConnection()->update($table, $args);
|
return self::getConnection()->update($table, $args);
|
||||||
}
|
}
|
||||||
@@ -493,7 +547,7 @@ class dibi
|
|||||||
* @param array
|
* @param array
|
||||||
* @return DibiFluent
|
* @return DibiFluent
|
||||||
*/
|
*/
|
||||||
public static function insert($table, array $args)
|
public static function insert($table, $args)
|
||||||
{
|
{
|
||||||
return self::getConnection()->insert($table, $args);
|
return self::getConnection()->insert($table, $args);
|
||||||
}
|
}
|
||||||
@@ -524,12 +578,14 @@ class dibi
|
|||||||
{
|
{
|
||||||
if ($time === NULL) {
|
if ($time === NULL) {
|
||||||
$time = time(); // current time
|
$time = time(); // current time
|
||||||
|
|
||||||
|
} elseif (is_numeric($time)) {
|
||||||
|
$time = (int) $time; // timestamp
|
||||||
|
|
||||||
} elseif (is_string($time)) {
|
} elseif (is_string($time)) {
|
||||||
$time = strtotime($time); // try convert to timestamp
|
$time = class_exists('DateTime', FALSE) ? new DateTime($time) : strtotime($time); // DateTime is since PHP 5.2
|
||||||
} else {
|
|
||||||
$time = (int) $time;
|
|
||||||
}
|
}
|
||||||
return new DibiVariable($time, dibi::FIELD_DATETIME);
|
return new DibiVariable($time, dibi::DATETIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -542,7 +598,7 @@ class dibi
|
|||||||
public static function date($date = NULL)
|
public static function date($date = NULL)
|
||||||
{
|
{
|
||||||
$var = self::datetime($date);
|
$var = self::datetime($date);
|
||||||
$var->modifier = dibi::FIELD_DATE;
|
$var->modifier = dibi::DATE;
|
||||||
return $var;
|
return $var;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,22 +621,6 @@ class dibi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets substitution fallback handler.
|
|
||||||
* @param callback
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function setSubstFallback($callback)
|
|
||||||
{
|
|
||||||
if (!is_callable($callback)) {
|
|
||||||
throw new InvalidArgumentException("Invalid callback.");
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$substFallBack = $callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove substitution pair.
|
* Remove substitution pair.
|
||||||
* @param mixed from or TRUE
|
* @param mixed from or TRUE
|
||||||
@@ -598,39 +638,30 @@ class dibi
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides substitution.
|
* Sets substitution fallback handler.
|
||||||
* @param string
|
* @param callback
|
||||||
* @return string
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function substitute($value)
|
public static function setSubstFallback($callback)
|
||||||
{
|
{
|
||||||
if (strpos($value, ':') === FALSE) {
|
if (!is_callable($callback)) {
|
||||||
return $value;
|
$able = is_callable($callback, TRUE, $textual);
|
||||||
|
throw new InvalidArgumentException("Handler '$textual' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
|
||||||
} else {
|
|
||||||
return preg_replace_callback('#:(.*):#U', array('dibi', 'subCb'), $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::$substFallBack = $callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Substitution callback.
|
* Default substitution fallback handler.
|
||||||
* @param array
|
* @param string
|
||||||
* @return string
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
private static function subCb($m)
|
public static function defaultSubstFallback($expr)
|
||||||
{
|
{
|
||||||
$m = $m[1];
|
throw new InvalidStateException("Missing substitution for '$expr' expression.");
|
||||||
if (isset(self::$substs[$m])) {
|
|
||||||
return self::$substs[$m];
|
|
||||||
|
|
||||||
} elseif (self::$substFallBack) {
|
|
||||||
return self::$substs[$m] = call_user_func(self::$substFallBack, $m);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return $m;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -658,7 +689,7 @@ class dibi
|
|||||||
static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE';
|
static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE';
|
||||||
|
|
||||||
// insert new lines
|
// insert new lines
|
||||||
$sql = ' ' . $sql;
|
$sql = " $sql ";
|
||||||
$sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
|
$sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
|
||||||
|
|
||||||
// reduce spaces
|
// reduce spaces
|
||||||
|
835
dibi/drivers/firebird.php
Normal file
835
dibi/drivers/firebird.php
Normal file
@@ -0,0 +1,835 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
|
* ----------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2009 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, 2009 David Grudl
|
||||||
|
* @license http://dibiphp.com/license dibi license
|
||||||
|
* @link http://dibiphp.com
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dibi driver for Firebird/InterBase database.
|
||||||
|
*
|
||||||
|
* Connection options:
|
||||||
|
* - 'database' - the path to database file (server:/path/database.fdb)
|
||||||
|
* - 'username' (or 'user')
|
||||||
|
* - 'password' (or 'pass')
|
||||||
|
* - 'charset' - character encoding to set
|
||||||
|
* - 'buffers' - buffers is the number of database buffers to allocate for the server-side cache. If 0 or omitted, server chooses its own default.
|
||||||
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
|
*
|
||||||
|
* @author Tomáš Kraina, Roman Sklenář
|
||||||
|
* @copyright Copyright (c) 2009
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiFirebirdDriver extends DibiObject implements IDibiDriver
|
||||||
|
{
|
||||||
|
const ERROR_EXCEPTION_THROWN = -836;
|
||||||
|
|
||||||
|
/** @var resource Connection resource */
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
/** @var resource Resultset resource */
|
||||||
|
private $resultSet;
|
||||||
|
|
||||||
|
/** @var resource Resultset resource */
|
||||||
|
private $transaction;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $inTransaction = FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (!extension_loaded('interbase')) {
|
||||||
|
throw new DibiDriverException("PHP extension 'interbase' is not loaded.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to a database.
|
||||||
|
* @return void
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function connect(array &$config)
|
||||||
|
{
|
||||||
|
DibiConnection::alias($config, 'database', 'db');
|
||||||
|
|
||||||
|
if (isset($config['resource'])) {
|
||||||
|
$this->connection = $config['resource'];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// default values
|
||||||
|
if (!isset($config['username'])) $config['username'] = ini_get('ibase.default_password');
|
||||||
|
if (!isset($config['password'])) $config['password'] = ini_get('ibase.default_user');
|
||||||
|
if (!isset($config['database'])) $config['database'] = ini_get('ibase.default_db');
|
||||||
|
if (!isset($config['charset'])) $config['charset'] = ini_get('ibase.default_charset');
|
||||||
|
if (!isset($config['buffers'])) $config['buffers'] = 0;
|
||||||
|
|
||||||
|
DibiDriverException::tryError();
|
||||||
|
if (empty($config['persistent'])) {
|
||||||
|
$this->connection = ibase_connect($config['database'], $config['username'], $config['password'], $config['charset'], $config['buffers']); // intentionally @
|
||||||
|
} else {
|
||||||
|
$this->connection = ibase_pconnect($config['database'], $config['username'], $config['password'], $config['charset'], $config['buffers']); // intentionally @
|
||||||
|
}
|
||||||
|
if (DibiDriverException::catchError($msg)) {
|
||||||
|
throw new DibiDriverException($msg, ibase_errcode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_resource($this->connection)) {
|
||||||
|
throw new DibiDriverException(ibase_errmsg(), ibase_errcode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects from a database.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function disconnect()
|
||||||
|
{
|
||||||
|
ibase_close($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the SQL query.
|
||||||
|
* @param string SQL statement.
|
||||||
|
* @return IDibiDriver|NULL
|
||||||
|
* @throws DibiDriverException|DibiException
|
||||||
|
*/
|
||||||
|
public function query($sql)
|
||||||
|
{
|
||||||
|
DibiDriverException::tryError();
|
||||||
|
$resource = $this->inTransaction ? $this->transaction : $this->connection;
|
||||||
|
$this->resultSet = ibase_query($resource, $sql);
|
||||||
|
|
||||||
|
if (DibiDriverException::catchError($msg)) {
|
||||||
|
if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
|
||||||
|
preg_match('/exception (\d+) (\w+) (.*)/i', ibase_errmsg(), $match);
|
||||||
|
throw new DibiProcedureException($match[3], $match[1], $match[2], dibi::$sql);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new DibiDriverException(ibase_errmsg(), ibase_errcode(), dibi::$sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->resultSet === FALSE) {
|
||||||
|
throw new DibiDriverException(ibase_errmsg(), ibase_errcode(), $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 getAffectedRows()
|
||||||
|
{
|
||||||
|
return ibase_affected_rows($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
|
* @param string generator name
|
||||||
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
|
*/
|
||||||
|
public function getInsertId($sequence)
|
||||||
|
{
|
||||||
|
return ibase_gen_id($sequence, 0, $this->connection);
|
||||||
|
//throw new NotSupportedException('Firebird/InterBase does not support autoincrementing.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
|
* @return void
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function begin($savepoint = NULL)
|
||||||
|
{
|
||||||
|
if ($savepoint !== NULL) {
|
||||||
|
throw new DibiDriverException('Savepoints are not supported in Firebird/Interbase.');
|
||||||
|
}
|
||||||
|
$this->transaction = ibase_trans($this->resource);
|
||||||
|
$this->inTransaction = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
|
* @return void
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function commit($savepoint = NULL)
|
||||||
|
{
|
||||||
|
if ($savepoint !== NULL) {
|
||||||
|
throw new DibiDriverException('Savepoints are not supported in Firebird/Interbase.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ibase_commit($this->transaction)) {
|
||||||
|
DibiDriverException('Unable to handle operation - failure when commiting transaction.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->inTransaction = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
|
* @return void
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function rollback($savepoint = NULL)
|
||||||
|
{
|
||||||
|
if ($savepoint !== NULL) {
|
||||||
|
throw new DibiDriverException('Savepoints are not supported in Firebird/Interbase.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ibase_rollback($this->transaction)) {
|
||||||
|
DibiDriverException('Unable to handle operation - failure when rolbacking transaction.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->inTransaction = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connection resource.
|
||||||
|
* @return resource
|
||||||
|
*/
|
||||||
|
public function getResource()
|
||||||
|
{
|
||||||
|
return $this->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* SQL ********************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes data for use in a SQL statement.
|
||||||
|
* @param mixed value
|
||||||
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
|
* @return string encoded value
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function escape($value, $type)
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case dibi::TEXT:
|
||||||
|
case dibi::BINARY:
|
||||||
|
return "'" . str_replace("'", "''", $value) . "'";
|
||||||
|
|
||||||
|
case dibi::IDENTIFIER:
|
||||||
|
return $value;
|
||||||
|
|
||||||
|
case dibi::BOOL:
|
||||||
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
|
case dibi::DATE:
|
||||||
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
|
case dibi::DATETIME:
|
||||||
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : 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::BINARY)
|
||||||
|
* @return string decoded value
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function unescape($value, $type)
|
||||||
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
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://scott.yang.id.au/2004/01/limit-in-select-statements-in-firebird/
|
||||||
|
$sql = 'SELECT FIRST ' . (int) $limit . ($offset > 0 ? ' SKIP ' . (int) $offset : '') . ' * FROM (' . $sql . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* result set ********************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of rows in a result set.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getRowCount()
|
||||||
|
{
|
||||||
|
return ibase_num_fields($this->resultSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||||
|
* @param bool TRUE for associative array, FALSE for numeric
|
||||||
|
* @return array array on success, nonarray if no next record
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function fetch($assoc)
|
||||||
|
{
|
||||||
|
DibiDriverException::tryError();
|
||||||
|
$result = $assoc ? ibase_fetch_assoc($this->resultSet) : ibase_fetch_row($this->resultSet); // intentionally @
|
||||||
|
|
||||||
|
if (DibiDriverException::catchError($msg)) {
|
||||||
|
if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
|
||||||
|
preg_match('/exception (\d+) (\w+) (.*)/i', ibase_errmsg(), $match);
|
||||||
|
throw new DibiProcedureException($match[3], $match[1], $match[2], dibi::$sql);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new DibiDriverException($msg, ibase_errcode(), dibi::$sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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("Firebird/Interbase do not support seek in result set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the resources allocated for this result set.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function free()
|
||||||
|
{
|
||||||
|
ibase_free_result($this->resultSet);
|
||||||
|
$this->resultSet = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the result set resource.
|
||||||
|
* @return mysqli_result
|
||||||
|
*/
|
||||||
|
public function getResultResource()
|
||||||
|
{
|
||||||
|
return $this->resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all columns in a result set.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getColumnsMeta()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* reflection ********************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of tables.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTables()
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$RELATION_NAME),
|
||||||
|
CASE RDB\$VIEW_BLR WHEN NULL THEN 'TRUE' ELSE 'FALSE' END
|
||||||
|
FROM RDB\$RELATIONS
|
||||||
|
WHERE RDB\$SYSTEM_FLAG = 0;"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = array(
|
||||||
|
'name' => $row[0],
|
||||||
|
'view' => $row[1] === 'TRUE',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all columns in a table.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getColumns($table)
|
||||||
|
{
|
||||||
|
$table = strtoupper($table);
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(r.RDB\$FIELD_NAME) AS FIELD_NAME,
|
||||||
|
CASE f.RDB\$FIELD_TYPE
|
||||||
|
WHEN 261 THEN 'BLOB'
|
||||||
|
WHEN 14 THEN 'CHAR'
|
||||||
|
WHEN 40 THEN 'CSTRING'
|
||||||
|
WHEN 11 THEN 'D_FLOAT'
|
||||||
|
WHEN 27 THEN 'DOUBLE'
|
||||||
|
WHEN 10 THEN 'FLOAT'
|
||||||
|
WHEN 16 THEN 'INT64'
|
||||||
|
WHEN 8 THEN 'INTEGER'
|
||||||
|
WHEN 9 THEN 'QUAD'
|
||||||
|
WHEN 7 THEN 'SMALLINT'
|
||||||
|
WHEN 12 THEN 'DATE'
|
||||||
|
WHEN 13 THEN 'TIME'
|
||||||
|
WHEN 35 THEN 'TIMESTAMP'
|
||||||
|
WHEN 37 THEN 'VARCHAR'
|
||||||
|
ELSE 'UNKNOWN'
|
||||||
|
END AS FIELD_TYPE,
|
||||||
|
f.RDB\$FIELD_LENGTH AS FIELD_LENGTH,
|
||||||
|
r.RDB\$DEFAULT_VALUE AS DEFAULT_VALUE,
|
||||||
|
CASE r.RDB\$NULL_FLAG
|
||||||
|
WHEN 1 THEN 'FALSE' ELSE 'TRUE'
|
||||||
|
END AS NULLABLE
|
||||||
|
FROM RDB\$RELATION_FIELDS r
|
||||||
|
LEFT JOIN RDB\$FIELDS f ON r.RDB\$FIELD_SOURCE = f.RDB\$FIELD_NAME
|
||||||
|
WHERE r.RDB\$RELATION_NAME = '$table'
|
||||||
|
ORDER BY r.RDB\$FIELD_POSITION;"
|
||||||
|
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(TRUE)) {
|
||||||
|
$key = $row['FIELD_NAME'];
|
||||||
|
$res[$key] = array(
|
||||||
|
'name' => $key,
|
||||||
|
'table' => $table,
|
||||||
|
'nativetype' => trim($row['FIELD_TYPE']),
|
||||||
|
'size' => $row['FIELD_LENGTH'],
|
||||||
|
'nullable' => $row['NULLABLE'] === 'TRUE',
|
||||||
|
'default' => $row['DEFAULT_VALUE'],
|
||||||
|
'autoincrement' => FALSE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all indexes in a table (the constraints are included).
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getIndexes($table)
|
||||||
|
{
|
||||||
|
$table = strtoupper($table);
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(s.RDB\$INDEX_NAME) AS INDEX_NAME,
|
||||||
|
TRIM(s.RDB\$FIELD_NAME) AS FIELD_NAME,
|
||||||
|
i.RDB\$UNIQUE_FLAG AS UNIQUE_FLAG,
|
||||||
|
i.RDB\$FOREIGN_KEY AS FOREIGN_KEY,
|
||||||
|
TRIM(r.RDB\$CONSTRAINT_TYPE) AS CONSTRAINT_TYPE,
|
||||||
|
s.RDB\$FIELD_POSITION AS FIELD_POSITION
|
||||||
|
FROM RDB\$INDEX_SEGMENTS s
|
||||||
|
LEFT JOIN RDB\$INDICES i ON i.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
|
||||||
|
LEFT JOIN RDB\$RELATION_CONSTRAINTS r ON r.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
|
||||||
|
WHERE UPPER(i.RDB\$RELATION_NAME) = '$table'
|
||||||
|
ORDER BY s.RDB\$FIELD_POSITION"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(TRUE)) {
|
||||||
|
$key = $row['INDEX_NAME'];
|
||||||
|
$res[$key]['name'] = $key;
|
||||||
|
$res[$key]['unique'] = $row['UNIQUE_FLAG'] === 1;
|
||||||
|
$res[$key]['primary'] = $row['CONSTRAINT_TYPE'] === 'PRIMARY KEY';
|
||||||
|
$res[$key]['table'] = $table;
|
||||||
|
$res[$key]['columns'][$row['FIELD_POSITION']] = $row['FIELD_NAME'];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all foreign keys in a table.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getForeignKeys($table)
|
||||||
|
{
|
||||||
|
$table = strtoupper($table);
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(s.RDB\$INDEX_NAME) AS INDEX_NAME,
|
||||||
|
TRIM(s.RDB\$FIELD_NAME) AS FIELD_NAME,
|
||||||
|
FROM RDB\$INDEX_SEGMENTS s
|
||||||
|
LEFT JOIN RDB\$RELATION_CONSTRAINTS r ON r.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME
|
||||||
|
WHERE UPPER(i.RDB\$RELATION_NAME) = '$table'
|
||||||
|
AND r.RDB\$CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||||
|
ORDER BY s.RDB\$FIELD_POSITION"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(TRUE)) {
|
||||||
|
$key = $row['INDEX_NAME'];
|
||||||
|
$res[$key] = array(
|
||||||
|
'name' => $key,
|
||||||
|
'column' => $row['FIELD_NAME'],
|
||||||
|
'table' => $table,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of indices in given table (the constraints are not listed).
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getIndices($table)
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$INDEX_NAME)
|
||||||
|
FROM RDB\$INDICES
|
||||||
|
WHERE RDB\$RELATION_NAME = UPPER('$table')
|
||||||
|
AND RDB\$UNIQUE_FLAG IS NULL
|
||||||
|
AND RDB\$FOREIGN_KEY IS NULL;"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = $row[0];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of constraints in given table.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getConstraints($table)
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$INDEX_NAME)
|
||||||
|
FROM RDB\$INDICES
|
||||||
|
WHERE RDB\$RELATION_NAME = UPPER('$table')
|
||||||
|
AND (
|
||||||
|
RDB\$UNIQUE_FLAG IS NOT NULL
|
||||||
|
OR RDB\$FOREIGN_KEY IS NOT NULL
|
||||||
|
);"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = $row[0];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all triggers in a table or database.
|
||||||
|
* (Only if user has permissions on ALTER TABLE, INSERT/UPDATE/DELETE record in table)
|
||||||
|
* @param string
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTriggersMeta($table = NULL)
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$TRIGGER_NAME) AS TRIGGER_NAME,
|
||||||
|
TRIM(RDB\$RELATION_NAME) AS TABLE_NAME,
|
||||||
|
CASE RDB\$TRIGGER_TYPE
|
||||||
|
WHEN 1 THEN 'BEFORE'
|
||||||
|
WHEN 2 THEN 'AFTER'
|
||||||
|
WHEN 3 THEN 'BEFORE'
|
||||||
|
WHEN 4 THEN 'AFTER'
|
||||||
|
WHEN 5 THEN 'BEFORE'
|
||||||
|
WHEN 6 THEN 'AFTER'
|
||||||
|
END AS TRIGGER_TYPE,
|
||||||
|
CASE RDB\$TRIGGER_TYPE
|
||||||
|
WHEN 1 THEN 'INSERT'
|
||||||
|
WHEN 2 THEN 'INSERT'
|
||||||
|
WHEN 3 THEN 'UPDATE'
|
||||||
|
WHEN 4 THEN 'UPDATE'
|
||||||
|
WHEN 5 THEN 'DELETE'
|
||||||
|
WHEN 6 THEN 'DELETE'
|
||||||
|
END AS TRIGGER_EVENT,
|
||||||
|
CASE RDB\$TRIGGER_INACTIVE
|
||||||
|
WHEN 1 THEN 'FALSE' ELSE 'TRUE'
|
||||||
|
END AS TRIGGER_ENABLED
|
||||||
|
FROM RDB\$TRIGGERS
|
||||||
|
WHERE RDB\$SYSTEM_FLAG = 0"
|
||||||
|
. ($table === NULL ? ";" : " AND RDB\$RELATION_NAME = UPPER('$table');")
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(TRUE)) {
|
||||||
|
$res[$row['TRIGGER_NAME']] = array(
|
||||||
|
'name' => $row['TRIGGER_NAME'],
|
||||||
|
'table' => $row['TABLE_NAME'],
|
||||||
|
'type' => trim($row['TRIGGER_TYPE']),
|
||||||
|
'event' => trim($row['TRIGGER_EVENT']),
|
||||||
|
'enabled' => trim($row['TRIGGER_ENABLED']) === 'TRUE',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of triggers for given table.
|
||||||
|
* (Only if user has permissions on ALTER TABLE, INSERT/UPDATE/DELETE record in table)
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTriggers($table = NULL)
|
||||||
|
{
|
||||||
|
$q = "SELECT TRIM(RDB\$TRIGGER_NAME)
|
||||||
|
FROM RDB\$TRIGGERS
|
||||||
|
WHERE RDB\$SYSTEM_FLAG = 0";
|
||||||
|
$q .= $table === NULL ? ";" : " AND RDB\$RELATION_NAME = UPPER('$table')";
|
||||||
|
|
||||||
|
$this->query($q);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = $row[0];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata from stored procedures and their input and output parameters.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getProceduresMeta()
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT
|
||||||
|
TRIM(p.RDB\$PARAMETER_NAME) AS PARAMETER_NAME,
|
||||||
|
TRIM(p.RDB\$PROCEDURE_NAME) AS PROCEDURE_NAME,
|
||||||
|
CASE p.RDB\$PARAMETER_TYPE
|
||||||
|
WHEN 0 THEN 'INPUT'
|
||||||
|
WHEN 1 THEN 'OUTPUT'
|
||||||
|
ELSE 'UNKNOWN'
|
||||||
|
END AS PARAMETER_TYPE,
|
||||||
|
CASE f.RDB\$FIELD_TYPE
|
||||||
|
WHEN 261 THEN 'BLOB'
|
||||||
|
WHEN 14 THEN 'CHAR'
|
||||||
|
WHEN 40 THEN 'CSTRING'
|
||||||
|
WHEN 11 THEN 'D_FLOAT'
|
||||||
|
WHEN 27 THEN 'DOUBLE'
|
||||||
|
WHEN 10 THEN 'FLOAT'
|
||||||
|
WHEN 16 THEN 'INT64'
|
||||||
|
WHEN 8 THEN 'INTEGER'
|
||||||
|
WHEN 9 THEN 'QUAD'
|
||||||
|
WHEN 7 THEN 'SMALLINT'
|
||||||
|
WHEN 12 THEN 'DATE'
|
||||||
|
WHEN 13 THEN 'TIME'
|
||||||
|
WHEN 35 THEN 'TIMESTAMP'
|
||||||
|
WHEN 37 THEN 'VARCHAR'
|
||||||
|
ELSE 'UNKNOWN'
|
||||||
|
END AS FIELD_TYPE,
|
||||||
|
f.RDB\$FIELD_LENGTH AS FIELD_LENGTH,
|
||||||
|
p.RDB\$PARAMETER_NUMBER AS PARAMETER_NUMBER
|
||||||
|
FROM RDB\$PROCEDURE_PARAMETERS p
|
||||||
|
LEFT JOIN RDB\$FIELDS f ON f.RDB\$FIELD_NAME = p.RDB\$FIELD_SOURCE
|
||||||
|
ORDER BY p.RDB\$PARAMETER_TYPE, p.RDB\$PARAMETER_NUMBER;"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(TRUE)) {
|
||||||
|
$key = $row['PROCEDURE_NAME'];
|
||||||
|
$io = trim($row['PARAMETER_TYPE']);
|
||||||
|
$num = $row['PARAMETER_NUMBER'];
|
||||||
|
$res[$key]['name'] = $row['PROCEDURE_NAME'];
|
||||||
|
$res[$key]['params'][$io][$num]['name'] = $row['PARAMETER_NAME'];
|
||||||
|
$res[$key]['params'][$io][$num]['type'] = trim($row['FIELD_TYPE']);
|
||||||
|
$res[$key]['params'][$io][$num]['size'] = $row['FIELD_LENGTH'];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of stored procedures.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getProcedures()
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$PROCEDURE_NAME)
|
||||||
|
FROM RDB\$PROCEDURES;"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = $row[0];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of generators.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getGenerators()
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$GENERATOR_NAME)
|
||||||
|
FROM RDB\$GENERATORS
|
||||||
|
WHERE RDB\$SYSTEM_FLAG = 0;"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = $row[0];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of user defined functions (UDF).
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
$this->query("
|
||||||
|
SELECT TRIM(RDB\$FUNCTION_NAME)
|
||||||
|
FROM RDB\$FUNCTIONS
|
||||||
|
WHERE RDB\$SYSTEM_FLAG = 0;"
|
||||||
|
);
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
$res[] = $row[0];
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database procedure exception.
|
||||||
|
*
|
||||||
|
* @author Roman Sklenář
|
||||||
|
* @copyright Copyright (c) 2009
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiProcedureException extends DibiException
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
protected $severity;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the exception.
|
||||||
|
* @param string Message describing the exception
|
||||||
|
* @param int Some code
|
||||||
|
* @param string SQL command
|
||||||
|
*/
|
||||||
|
public function __construct($message = NULL, $code = 0, $severity = NULL, $sql = NULL)
|
||||||
|
{
|
||||||
|
parent::__construct($message, (int) $code, $sql);
|
||||||
|
$this->severity = $severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the exception severity.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSeverity()
|
||||||
|
{
|
||||||
|
$this->severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -29,18 +28,17 @@
|
|||||||
* - 'persistent' - try to find a persistent link?
|
* - 'persistent' - try to find a persistent link?
|
||||||
* - 'database' - the database name to select
|
* - 'database' - the database name to select
|
||||||
* - 'lazy' - if TRUE, connection will be established only when required
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var resource Connection resource */
|
/** @var resource Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var resource Resultset resource */
|
/** @var resource Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
@@ -65,11 +63,9 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
public function connect(array &$config)
|
||||||
{
|
{
|
||||||
DibiConnection::alias($config, 'username', 'user');
|
if (isset($config['resource'])) {
|
||||||
DibiConnection::alias($config, 'password', 'pass');
|
$this->connection = $config['resource'];
|
||||||
DibiConnection::alias($config, 'host', 'hostname');
|
} elseif (empty($config['persistent'])) {
|
||||||
|
|
||||||
if (empty($config['persistent'])) {
|
|
||||||
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @
|
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @
|
||||||
} else {
|
} else {
|
||||||
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @
|
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @
|
||||||
@@ -120,7 +116,7 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return mssql_rows_affected($this->connection);
|
return mssql_rows_affected($this->connection);
|
||||||
}
|
}
|
||||||
@@ -131,19 +127,25 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException('MS SQL does not support autoincrementing.');
|
$res = mssql_query('SELECT @@IDENTITY', $this->connection);
|
||||||
|
if (is_resource($res)) {
|
||||||
|
$row = mssql_fetch_row($res);
|
||||||
|
return $row[0];
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('BEGIN TRANSACTION');
|
$this->query('BEGIN TRANSACTION');
|
||||||
}
|
}
|
||||||
@@ -152,10 +154,11 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('COMMIT');
|
$this->query('COMMIT');
|
||||||
}
|
}
|
||||||
@@ -164,10 +167,11 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('ROLLBACK');
|
$this->query('ROLLBACK');
|
||||||
}
|
}
|
||||||
@@ -190,17 +194,17 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
return "'" . str_replace("'", "''", $value) . "'";
|
return "'" . str_replace("'", "''", $value) . "'";
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
@@ -208,14 +212,14 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
$value = str_replace(array('[', ']'), array('[[', ']]'), $value);
|
$value = str_replace(array('[', ']'), array('[[', ']]'), $value);
|
||||||
return '[' . str_replace('.', '].[', $value) . ']';
|
return '[' . str_replace('.', '].[', $value) . ']';
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? -1 : 0;
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("'Y-m-d'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("'Y-m-d H:i:s'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -227,12 +231,15 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +254,7 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function applyLimit(&$sql, $limit, $offset)
|
public function applyLimit(&$sql, $limit, $offset)
|
||||||
{
|
{
|
||||||
// offset suppot is missing...
|
// offset support is missing
|
||||||
if ($limit >= 0) {
|
if ($limit >= 0) {
|
||||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||||
}
|
}
|
||||||
@@ -267,7 +274,7 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
return mssql_num_rows($this->resultSet);
|
return mssql_num_rows($this->resultSet);
|
||||||
}
|
}
|
||||||
@@ -291,7 +298,6 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
|
|||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
* @param int the 0-based cursor pos to seek to
|
* @param int the 0-based cursor pos to seek to
|
||||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
public function seek($row)
|
public function seek($row)
|
||||||
{
|
{
|
||||||
|
410
dibi/drivers/mssql2005.php
Normal file
410
dibi/drivers/mssql2005.php
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
|
* ----------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2009 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, 2009 David Grudl
|
||||||
|
* @license http://dibiphp.com/license dibi license
|
||||||
|
* @link http://dibiphp.com
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dibi driver for MS SQL Driver 2005 database.
|
||||||
|
*
|
||||||
|
* Connection options:
|
||||||
|
* - 'host' - the MS SQL server host name. It can also include a port number (hostname:port)
|
||||||
|
* - 'options' - connection info array {@link http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx}
|
||||||
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'charset' - character encoding to set (default is UTF-8)
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
|
*
|
||||||
|
* @author David Grudl
|
||||||
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiMsSql2005Driver extends DibiObject implements IDibiDriver
|
||||||
|
{
|
||||||
|
/** @var resource Connection resource */
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
/** @var resource Resultset resource */
|
||||||
|
private $resultSet;
|
||||||
|
|
||||||
|
/** @var string character encoding */
|
||||||
|
private $charset;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (!extension_loaded('sqlsrv')) {
|
||||||
|
throw new DibiDriverException("PHP extension 'sqlsrv' is not loaded.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to a database.
|
||||||
|
* @return void
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function connect(array &$config)
|
||||||
|
{
|
||||||
|
if (isset($config['resource'])) {
|
||||||
|
$this->connection = $config['resource'];
|
||||||
|
} elseif (isset($config['options'])) {
|
||||||
|
$this->connection = sqlsrv_connect($config['host'], $config['options']);
|
||||||
|
} else {
|
||||||
|
$this->connection = sqlsrv_connect($config['host']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_resource($this->connection)) {
|
||||||
|
$info = sqlsrv_errors();
|
||||||
|
throw new DibiDriverException($info[0]['message'], $info[0]['code']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->charset = empty($config['charset']) ? 'UTF-8' : $config['charset'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects from a database.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function disconnect()
|
||||||
|
{
|
||||||
|
sqlsrv_close($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the SQL query.
|
||||||
|
* @param string SQL statement.
|
||||||
|
* @return IDibiDriver|NULL
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function query($sql)
|
||||||
|
{
|
||||||
|
$sql = iconv($this->charset, 'UTF-16LE', $sql);
|
||||||
|
$this->resultSet = sqlsrv_query($this->connection, $sql);
|
||||||
|
|
||||||
|
if ($this->resultSet === FALSE) {
|
||||||
|
$info = sqlsrv_errors();
|
||||||
|
throw new DibiDriverException($info[0]['message'], $info[0]['code'], $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 getAffectedRows()
|
||||||
|
{
|
||||||
|
return sqlsrv_rows_affected($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 getInsertId($sequence)
|
||||||
|
{
|
||||||
|
$res = sqlsrv_query($this->connection, 'SELECT @@IDENTITY');
|
||||||
|
if (is_resource($res)) {
|
||||||
|
$row = sqlsrv_fetch_array($res, SQLSRV_FETCH_NUMERIC);
|
||||||
|
return $row[0];
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
|
* @return void
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function begin($savepoint = NULL)
|
||||||
|
{
|
||||||
|
$this->query('BEGIN TRANSACTION');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
|
* @return void
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function commit($savepoint = NULL)
|
||||||
|
{
|
||||||
|
$this->query('COMMIT');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
|
* @return void
|
||||||
|
* @throws DibiDriverException
|
||||||
|
*/
|
||||||
|
public function rollback($savepoint = NULL)
|
||||||
|
{
|
||||||
|
$this->query('ROLLBACK');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connection resource.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getResource()
|
||||||
|
{
|
||||||
|
return $this->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* SQL ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes data for use in a SQL statement.
|
||||||
|
* @param mixed value
|
||||||
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
|
* @return string encoded value
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function escape($value, $type)
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case dibi::TEXT:
|
||||||
|
case dibi::BINARY:
|
||||||
|
return "'" . str_replace("'", "''", $value) . "'";
|
||||||
|
|
||||||
|
case dibi::IDENTIFIER:
|
||||||
|
// @see http://msdn.microsoft.com/en-us/library/ms176027.aspx
|
||||||
|
$value = str_replace(array('[', ']'), array('[[', ']]'), $value);
|
||||||
|
return '[' . str_replace('.', '].[', $value) . ']';
|
||||||
|
|
||||||
|
case dibi::BOOL:
|
||||||
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
|
case dibi::DATE:
|
||||||
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
|
case dibi::DATETIME:
|
||||||
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : 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::BINARY)
|
||||||
|
* @return string decoded value
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function unescape($value, $type)
|
||||||
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
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 support is missing
|
||||||
|
if ($limit >= 0) {
|
||||||
|
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($offset) {
|
||||||
|
throw new NotImplementedException('Offset is not implemented.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* result set ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of rows in a result set.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getRowCount()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException('Row count is not available for unbuffered queries.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||||
|
* @param bool TRUE for associative array, FALSE for numeric
|
||||||
|
* @return array array on success, nonarray if no next record
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function fetch($assoc)
|
||||||
|
{
|
||||||
|
$row = sqlsrv_fetch_array($this->resultSet, $assoc ? SQLSRV_FETCH_ASSOC : SQLSRV_FETCH_NUMERIC);
|
||||||
|
foreach ($row as $k => $v) {
|
||||||
|
if (is_string($v)) {
|
||||||
|
$row[$k] = iconv('UTF-16LE', $this->charset, $v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves cursor position without fetching row.
|
||||||
|
* @param int the 0-based cursor pos to seek to
|
||||||
|
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||||
|
*/
|
||||||
|
public function seek($row)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException('Cannot seek an unbuffered result set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the resources allocated for this result set.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function free()
|
||||||
|
{
|
||||||
|
sqlsrv_free_stmt($this->resultSet);
|
||||||
|
$this->resultSet = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all columns in a result set.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getColumnsMeta()
|
||||||
|
{
|
||||||
|
$count = sqlsrv_num_fields($this->resultSet);
|
||||||
|
$res = array();
|
||||||
|
for ($i = 0; $i < $count; $i++) {
|
||||||
|
$row = (array) sqlsrv_field_metadata($this->resultSet, $i);
|
||||||
|
$res[] = array(
|
||||||
|
'name' => $row['Name'],
|
||||||
|
'fullname' => $row['Name'],
|
||||||
|
'nativetype' => $row['Type'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the result set resource.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getResultResource()
|
||||||
|
{
|
||||||
|
return $this->resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* reflection ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of tables.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTables()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all columns in a table.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getColumns($table)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all indexes in a table.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getIndexes($table)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns metadata for all foreign keys in a table.
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getForeignKeys($table)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -35,22 +34,24 @@
|
|||||||
* - 'options' - driver specific constants (MYSQL_*)
|
* - 'options' - driver specific constants (MYSQL_*)
|
||||||
* - 'sqlmode' - see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
|
* - '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
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
const ERROR_ACCESS_DENIED = 1045;
|
||||||
|
const ERROR_DUPLICATE_ENTRY = 1062;
|
||||||
|
const ERROR_DATA_TRUNCATED = 1265;
|
||||||
|
|
||||||
/** @var resource Connection resource */
|
/** @var resource Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var resource Resultset resource */
|
/** @var resource Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var bool Is buffered (seekable and countable)? */
|
/** @var bool Is buffered (seekable and countable)? */
|
||||||
private $buffered;
|
private $buffered;
|
||||||
|
|
||||||
@@ -75,35 +76,37 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
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, 'options');
|
||||||
|
|
||||||
// default values
|
if (isset($config['resource'])) {
|
||||||
if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user');
|
$this->connection = $config['resource'];
|
||||||
if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password');
|
|
||||||
if (!isset($config['host'])) {
|
} else {
|
||||||
$host = ini_get('mysql.default_host');
|
// default values
|
||||||
if ($host) {
|
if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user');
|
||||||
$config['host'] = $host;
|
if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password');
|
||||||
$config['port'] = ini_get('mysql.default_port');
|
if (!isset($config['host'])) {
|
||||||
} else {
|
$host = ini_get('mysql.default_host');
|
||||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysql.default_socket');
|
if ($host) {
|
||||||
$config['host'] = NULL;
|
$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'])) {
|
if (empty($config['socket'])) {
|
||||||
$host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']);
|
$host = $config['host'] . (empty($config['port']) ? '' : ':' . $config['port']);
|
||||||
} else {
|
} else {
|
||||||
$host = ':' . $config['socket'];
|
$host = ':' . $config['socket'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($config['persistent'])) {
|
if (empty($config['persistent'])) {
|
||||||
$this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); // intentionally @
|
$this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['options']); // intentionally @
|
||||||
} else {
|
} else {
|
||||||
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); // intentionally @
|
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['options']); // intentionally @
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_resource($this->connection)) {
|
if (!is_resource($this->connection)) {
|
||||||
@@ -175,11 +178,27 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves information about the most recently executed query.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getInfo()
|
||||||
|
{
|
||||||
|
$res = array();
|
||||||
|
preg_match_all('#(.+?): +(\d+) *#', mysql_info($this->connection), $matches, PREG_SET_ORDER);
|
||||||
|
foreach ($matches as $m) {
|
||||||
|
$res[$m[1]] = (int) $m[2];
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return mysql_affected_rows($this->connection);
|
return mysql_affected_rows($this->connection);
|
||||||
}
|
}
|
||||||
@@ -190,7 +209,7 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
return mysql_insert_id($this->connection);
|
return mysql_insert_id($this->connection);
|
||||||
}
|
}
|
||||||
@@ -199,36 +218,39 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('START TRANSACTION');
|
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('COMMIT');
|
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('ROLLBACK');
|
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -249,32 +271,34 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
case dibi::FIELD_BINARY:
|
|
||||||
return "'" . mysql_real_escape_string($value, $this->connection) . "'";
|
return "'" . mysql_real_escape_string($value, $this->connection) . "'";
|
||||||
|
|
||||||
|
case dibi::BINARY:
|
||||||
|
return "_binary'" . mysql_real_escape_string($value, $this->connection) . "'";
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
// @see http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
|
// @see http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
|
||||||
$value = str_replace('`', '``', $value);
|
$value = str_replace('`', '``', $value);
|
||||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? 1 : 0;
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("'Y-m-d'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("'Y-m-d H:i:s'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -286,12 +310,15 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +350,7 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
if (!$this->buffered) {
|
if (!$this->buffered) {
|
||||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||||
@@ -440,7 +467,7 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function getColumns($table)
|
public function getColumns($table)
|
||||||
{
|
{
|
||||||
$this->query("SHOW COLUMNS FROM `$table`");
|
$this->query("SHOW FULL COLUMNS FROM `$table`");
|
||||||
$res = array();
|
$res = array();
|
||||||
while ($row = $this->fetch(TRUE)) {
|
while ($row = $this->fetch(TRUE)) {
|
||||||
$type = explode('(', $row['Type']);
|
$type = explode('(', $row['Type']);
|
||||||
@@ -452,6 +479,7 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
|
|||||||
'nullable' => $row['Null'] === 'YES',
|
'nullable' => $row['Null'] === 'YES',
|
||||||
'default' => $row['Default'],
|
'default' => $row['Default'],
|
||||||
'autoincrement' => $row['Extra'] === 'auto_increment',
|
'autoincrement' => $row['Extra'] === 'auto_increment',
|
||||||
|
'vendor' => $row,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->free();
|
$this->free();
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -35,22 +34,24 @@
|
|||||||
* - 'options' - driver specific constants (MYSQLI_*)
|
* - 'options' - driver specific constants (MYSQLI_*)
|
||||||
* - 'sqlmode' - see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
|
* - '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
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
const ERROR_ACCESS_DENIED = 1045;
|
||||||
|
const ERROR_DUPLICATE_ENTRY = 1062;
|
||||||
|
const ERROR_DATA_TRUNCATED = 1265;
|
||||||
|
|
||||||
/** @var mysqli Connection resource */
|
/** @var mysqli Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var mysqli_result Resultset resource */
|
/** @var mysqli_result Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var bool Is buffered (seekable and countable)? */
|
/** @var bool Is buffered (seekable and countable)? */
|
||||||
private $buffered;
|
private $buffered;
|
||||||
|
|
||||||
@@ -75,33 +76,35 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
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, 'options');
|
||||||
DibiConnection::alias($config, 'database');
|
DibiConnection::alias($config, 'database');
|
||||||
|
|
||||||
// default values
|
if (isset($config['resource'])) {
|
||||||
if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user');
|
$this->connection = $config['resource'];
|
||||||
if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw');
|
|
||||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket');
|
} else {
|
||||||
if (!isset($config['port'])) $config['port'] = NULL;
|
// default values
|
||||||
if (!isset($config['host'])) {
|
if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user');
|
||||||
$host = ini_get('mysqli.default_host');
|
if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw');
|
||||||
if ($host) {
|
if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket');
|
||||||
$config['host'] = $host;
|
if (!isset($config['port'])) $config['port'] = NULL;
|
||||||
$config['port'] = ini_get('mysqli.default_port');
|
if (!isset($config['host'])) {
|
||||||
} else {
|
$host = ini_get('mysqli.default_host');
|
||||||
$config['host'] = NULL;
|
if ($host) {
|
||||||
$config['port'] = NULL;
|
$config['host'] = $host;
|
||||||
|
$config['port'] = ini_get('mysqli.default_port');
|
||||||
|
} else {
|
||||||
|
$config['host'] = NULL;
|
||||||
|
$config['port'] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$this->connection = mysqli_init();
|
$this->connection = mysqli_init();
|
||||||
@mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); // intentionally @
|
@mysqli_real_connect($this->connection, $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['options']); // intentionally @
|
||||||
|
|
||||||
if ($errno = mysqli_connect_errno()) {
|
if ($errno = mysqli_connect_errno()) {
|
||||||
throw new DibiDriverException(mysqli_connect_error(), $errno);
|
throw new DibiDriverException(mysqli_connect_error(), $errno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($config['charset'])) {
|
if (isset($config['charset'])) {
|
||||||
@@ -159,11 +162,27 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves information about the most recently executed query.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getInfo()
|
||||||
|
{
|
||||||
|
$res = array();
|
||||||
|
preg_match_all('#(.+?): +(\d+) *#', mysqli_info($this->connection), $matches, PREG_SET_ORDER);
|
||||||
|
foreach ($matches as $m) {
|
||||||
|
$res[$m[1]] = (int) $m[2];
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return mysqli_affected_rows($this->connection);
|
return mysqli_affected_rows($this->connection);
|
||||||
}
|
}
|
||||||
@@ -174,7 +193,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
return mysqli_insert_id($this->connection);
|
return mysqli_insert_id($this->connection);
|
||||||
}
|
}
|
||||||
@@ -183,36 +202,39 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('START TRANSACTION');
|
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('COMMIT');
|
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('ROLLBACK');
|
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -233,31 +255,33 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
case dibi::FIELD_BINARY:
|
|
||||||
return "'" . mysqli_real_escape_string($this->connection, $value) . "'";
|
return "'" . mysqli_real_escape_string($this->connection, $value) . "'";
|
||||||
|
|
||||||
|
case dibi::BINARY:
|
||||||
|
return "_binary'" . mysqli_real_escape_string($this->connection, $value) . "'";
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
$value = str_replace('`', '``', $value);
|
$value = str_replace('`', '``', $value);
|
||||||
return '`' . str_replace('.', '`.`', $value) . '`';
|
return '`' . str_replace('.', '`.`', $value) . '`';
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? 1 : 0;
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("'Y-m-d'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("'Y-m-d H:i:s'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -269,12 +293,15 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +333,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
if (!$this->buffered) {
|
if (!$this->buffered) {
|
||||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||||
@@ -437,13 +464,13 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function getColumns($table)
|
public function getColumns($table)
|
||||||
{
|
{
|
||||||
/*$table = $this->escape($table, dibi::FIELD_TEXT);
|
/*$table = $this->escape($table, dibi::TEXT);
|
||||||
$this->query("
|
$this->query("
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM INFORMATION_SCHEMA.COLUMNS
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
WHERE TABLE_NAME = $table AND TABLE_SCHEMA = DATABASE()
|
WHERE TABLE_NAME = $table AND TABLE_SCHEMA = DATABASE()
|
||||||
");*/
|
");*/
|
||||||
$this->query("SHOW COLUMNS FROM `$table`");
|
$this->query("SHOW FULL COLUMNS FROM `$table`");
|
||||||
$res = array();
|
$res = array();
|
||||||
while ($row = $this->fetch(TRUE)) {
|
while ($row = $this->fetch(TRUE)) {
|
||||||
$type = explode('(', $row['Type']);
|
$type = explode('(', $row['Type']);
|
||||||
@@ -455,6 +482,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
'nullable' => $row['Null'] === 'YES',
|
'nullable' => $row['Null'] === 'YES',
|
||||||
'default' => $row['Default'],
|
'default' => $row['Default'],
|
||||||
'autoincrement' => $row['Extra'] === 'auto_increment',
|
'autoincrement' => $row['Extra'] === 'auto_increment',
|
||||||
|
'vendor' => $row,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->free();
|
$this->free();
|
||||||
@@ -470,7 +498,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function getIndexes($table)
|
public function getIndexes($table)
|
||||||
{
|
{
|
||||||
/*$table = $this->escape($table, dibi::FIELD_TEXT);
|
/*$table = $this->escape($table, dibi::TEXT);
|
||||||
$this->query("
|
$this->query("
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -28,22 +27,20 @@
|
|||||||
* - 'password' (or 'pass')
|
* - 'password' (or 'pass')
|
||||||
* - 'persistent' - try to find a persistent link?
|
* - 'persistent' - try to find a persistent link?
|
||||||
* - 'lazy' - if TRUE, connection will be established only when required
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var resource Connection resource */
|
/** @var resource Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var resource Resultset resource */
|
/** @var resource Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var int Cursor */
|
/** @var int Cursor */
|
||||||
private $row = 0;
|
private $row = 0;
|
||||||
|
|
||||||
@@ -68,18 +65,19 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
public function connect(array &$config)
|
||||||
{
|
{
|
||||||
DibiConnection::alias($config, 'username', 'user');
|
if (isset($config['resource'])) {
|
||||||
DibiConnection::alias($config, 'password', 'pass');
|
$this->connection = $config['resource'];
|
||||||
|
|
||||||
// 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 {
|
} else {
|
||||||
$this->connection = @odbc_pconnect($config['dsn'], $config['username'], $config['password']); // intentionally @
|
// 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)) {
|
if (!is_resource($this->connection)) {
|
||||||
@@ -123,7 +121,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return odbc_num_rows($this->resultSet);
|
return odbc_num_rows($this->resultSet);
|
||||||
}
|
}
|
||||||
@@ -134,7 +132,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException('ODBC does not support autoincrementing.');
|
throw new NotSupportedException('ODBC does not support autoincrementing.');
|
||||||
}
|
}
|
||||||
@@ -143,10 +141,11 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!odbc_autocommit($this->connection, FALSE)) {
|
if (!odbc_autocommit($this->connection, FALSE)) {
|
||||||
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
|
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
|
||||||
@@ -157,10 +156,11 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!odbc_commit($this->connection)) {
|
if (!odbc_commit($this->connection)) {
|
||||||
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
|
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
|
||||||
@@ -172,10 +172,11 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!odbc_rollback($this->connection)) {
|
if (!odbc_rollback($this->connection)) {
|
||||||
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
|
throw new DibiDriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
|
||||||
@@ -201,31 +202,31 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
return "'" . str_replace("'", "''", $value) . "'";
|
return "'" . str_replace("'", "''", $value) . "'";
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
$value = str_replace(array('[', ']'), array('[[', ']]'), $value);
|
$value = str_replace(array('[', ']'), array('[[', ']]'), $value);
|
||||||
return '[' . str_replace('.', '].[', $value) . ']';
|
return '[' . str_replace('.', '].[', $value) . ']';
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? -1 : 0;
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("#m/d/Y#", $value);
|
return $value instanceof DateTime ? $value->format("#m/d/Y#") : date("#m/d/Y#", $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("#m/d/Y H:i:s#", $value);
|
return $value instanceof DateTime ? $value->format("#m/d/Y H:i:s#") : date("#m/d/Y H:i:s#", $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -237,12 +238,15 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +261,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function applyLimit(&$sql, $limit, $offset)
|
public function applyLimit(&$sql, $limit, $offset)
|
||||||
{
|
{
|
||||||
// offset suppot is missing...
|
// offset support is missing
|
||||||
if ($limit >= 0) {
|
if ($limit >= 0) {
|
||||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||||
}
|
}
|
||||||
@@ -275,7 +279,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
// will return -1 with many drivers :-(
|
// will return -1 with many drivers :-(
|
||||||
return odbc_num_rows($this->resultSet);
|
return odbc_num_rows($this->resultSet);
|
||||||
@@ -309,7 +313,6 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
|
|||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
* @param int the 0-based cursor pos to seek to
|
* @param int the 0-based cursor pos to seek to
|
||||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
public function seek($row)
|
public function seek($row)
|
||||||
{
|
{
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -26,27 +25,30 @@
|
|||||||
* - 'database' (or 'db') - the name of the local Oracle instance or the name of the entry in tnsnames.ora
|
* - 'database' (or 'db') - the name of the local Oracle instance or the name of the entry in tnsnames.ora
|
||||||
* - 'username' (or 'user')
|
* - 'username' (or 'user')
|
||||||
* - 'password' (or 'pass')
|
* - 'password' (or 'pass')
|
||||||
* - 'charset' - character encoding to set
|
|
||||||
* - 'lazy' - if TRUE, connection will be established only when required
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'formatDate' - how to format date in SQL (@see date)
|
||||||
|
* - 'formatDateTime' - how to format datetime in SQL (@see date)
|
||||||
|
* - 'charset' - character encoding to set
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiOracleDriver extends DibiObject implements IDibiDriver
|
class DibiOracleDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var resource Connection resource */
|
/** @var resource Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var resource Resultset resource */
|
/** @var resource Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $autocommit = TRUE;
|
private $autocommit = TRUE;
|
||||||
|
|
||||||
|
/** @var string Date and datetime format */
|
||||||
|
private $fmtDate, $fmtDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,12 +70,15 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
public function connect(array &$config)
|
||||||
{
|
{
|
||||||
DibiConnection::alias($config, 'username', 'user');
|
|
||||||
DibiConnection::alias($config, 'password', 'pass');
|
|
||||||
DibiConnection::alias($config, 'database', 'db');
|
|
||||||
DibiConnection::alias($config, 'charset');
|
DibiConnection::alias($config, 'charset');
|
||||||
|
$this->fmtDate = isset($config['formatDate']) ? $config['formatDate'] : 'U';
|
||||||
|
$this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U';
|
||||||
|
|
||||||
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
if (isset($config['resource'])) {
|
||||||
|
$this->connection = $config['resource'];
|
||||||
|
} else {
|
||||||
|
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->connection) {
|
if (!$this->connection) {
|
||||||
$err = oci_error();
|
$err = oci_error();
|
||||||
@@ -124,7 +129,7 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException;
|
throw new NotImplementedException;
|
||||||
}
|
}
|
||||||
@@ -135,7 +140,7 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException('Oracle does not support autoincrementing.');
|
throw new NotSupportedException('Oracle does not support autoincrementing.');
|
||||||
}
|
}
|
||||||
@@ -144,10 +149,10 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->autocommit = FALSE;
|
$this->autocommit = FALSE;
|
||||||
}
|
}
|
||||||
@@ -156,10 +161,11 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!oci_commit($this->connection)) {
|
if (!oci_commit($this->connection)) {
|
||||||
$err = oci_error($this->connection);
|
$err = oci_error($this->connection);
|
||||||
@@ -172,10 +178,11 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!oci_rollback($this->connection)) {
|
if (!oci_rollback($this->connection)) {
|
||||||
$err = oci_error($this->connection);
|
$err = oci_error($this->connection);
|
||||||
@@ -202,17 +209,17 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested
|
return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
@@ -220,14 +227,14 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
$value = str_replace('"', '""', $value);
|
$value = str_replace('"', '""', $value);
|
||||||
return '"' . str_replace('.', '"."', $value) . '"';
|
return '"' . str_replace('.', '"."', $value) . '"';
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? 1 : 0;
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("U", $value);
|
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("U", $value);
|
return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -239,12 +246,15 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,8 +269,13 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function applyLimit(&$sql, $limit, $offset)
|
public function applyLimit(&$sql, $limit, $offset)
|
||||||
{
|
{
|
||||||
if ($limit < 0 && $offset < 1) return;
|
if ($offset > 0) {
|
||||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
// see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
|
||||||
|
$sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t ' . ($limit >= 0 ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '') . ') WHERE "__rnum" > '. (int) $offset;
|
||||||
|
|
||||||
|
} elseif ($limit >= 0) {
|
||||||
|
$sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -273,9 +288,9 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
return oci_num_rows($this->resultSet);
|
throw new NotSupportedException('Row count is not available for unbuffered queries.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -297,7 +312,6 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
* @param int the 0-based cursor pos to seek to
|
* @param int the 0-based cursor pos to seek to
|
||||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
public function seek($row)
|
public function seek($row)
|
||||||
{
|
{
|
||||||
@@ -360,7 +374,18 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function getTables()
|
public function getTables()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException;
|
$this->query('SELECT * FROM cat');
|
||||||
|
$res = array();
|
||||||
|
while ($row = $this->fetch(FALSE)) {
|
||||||
|
if ($row[1] === 'TABLE' || $row[1] === 'VIEW') {
|
||||||
|
$res[] = array(
|
||||||
|
'name' => $row[0],
|
||||||
|
'view' => $row[1] === 'VIEW',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->free();
|
||||||
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -27,24 +26,21 @@
|
|||||||
* - 'username' (or 'user')
|
* - 'username' (or 'user')
|
||||||
* - 'password' (or 'pass')
|
* - 'password' (or 'pass')
|
||||||
* - 'options' - driver specific options array
|
* - 'options' - driver specific options array
|
||||||
* - 'pdo' - PDO object (optional)
|
* - 'resource' - PDO object (optional)
|
||||||
* - 'lazy' - if TRUE, connection will be established only when required
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiPdoDriver extends DibiObject implements IDibiDriver
|
class DibiPdoDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var PDO Connection resource */
|
/** @var PDO Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var PDOStatement Resultset resource */
|
/** @var PDOStatement Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var int|FALSE Affected rows */
|
/** @var int|FALSE Affected rows */
|
||||||
private $affectedRows = FALSE;
|
private $affectedRows = FALSE;
|
||||||
|
|
||||||
@@ -69,14 +65,12 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
public function connect(array &$config)
|
||||||
{
|
{
|
||||||
DibiConnection::alias($config, 'username', 'user');
|
|
||||||
DibiConnection::alias($config, 'password', 'pass');
|
|
||||||
DibiConnection::alias($config, 'dsn');
|
DibiConnection::alias($config, 'dsn');
|
||||||
DibiConnection::alias($config, 'pdo');
|
DibiConnection::alias($config, 'resource', 'pdo');
|
||||||
DibiConnection::alias($config, 'options');
|
DibiConnection::alias($config, 'options');
|
||||||
|
|
||||||
if ($config['pdo'] instanceof PDO) {
|
if ($config['resource'] instanceof PDO) {
|
||||||
$this->connection = $config['pdo'];
|
$this->connection = $config['resource'];
|
||||||
|
|
||||||
} else try {
|
} else try {
|
||||||
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
|
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
|
||||||
@@ -145,7 +139,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return $this->affectedRows;
|
return $this->affectedRows;
|
||||||
}
|
}
|
||||||
@@ -156,7 +150,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
return $this->connection->lastInsertId();
|
return $this->connection->lastInsertId();
|
||||||
}
|
}
|
||||||
@@ -165,10 +159,11 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!$this->connection->beginTransaction()) {
|
if (!$this->connection->beginTransaction()) {
|
||||||
$err = $this->connection->errorInfo();
|
$err = $this->connection->errorInfo();
|
||||||
@@ -180,10 +175,11 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!$this->connection->commit()) {
|
if (!$this->connection->commit()) {
|
||||||
$err = $this->connection->errorInfo();
|
$err = $this->connection->errorInfo();
|
||||||
@@ -195,10 +191,11 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!$this->connection->rollBack()) {
|
if (!$this->connection->rollBack()) {
|
||||||
$err = $this->connection->errorInfo();
|
$err = $this->connection->errorInfo();
|
||||||
@@ -224,19 +221,19 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
return $this->connection->quote($value, PDO::PARAM_STR);
|
return $this->connection->quote($value, PDO::PARAM_STR);
|
||||||
|
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
return $this->connection->quote($value, PDO::PARAM_LOB);
|
return $this->connection->quote($value, PDO::PARAM_LOB);
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
@@ -266,14 +263,14 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $this->connection->quote($value, PDO::PARAM_BOOL);
|
return $this->connection->quote($value, PDO::PARAM_BOOL);
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("'Y-m-d'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("'Y-m-d H:i:s'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -285,12 +282,15 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +305,43 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function applyLimit(&$sql, $limit, $offset)
|
public function applyLimit(&$sql, $limit, $offset)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException('PDO does not support applying limit or offset.');
|
if ($limit < 0 && $offset < 1) return;
|
||||||
|
|
||||||
|
switch ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||||
|
case 'mysql':
|
||||||
|
$sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit)
|
||||||
|
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'pgsql':
|
||||||
|
if ($limit >= 0) $sql .= ' LIMIT ' . (int) $limit;
|
||||||
|
if ($offset > 0) $sql .= ' OFFSET ' . (int) $offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sqlite':
|
||||||
|
case 'sqlite2':
|
||||||
|
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'oci':
|
||||||
|
if ($offset > 0) {
|
||||||
|
$sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t ' . ($limit >= 0 ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '') . ') WHERE "__rnum" > '. (int) $offset;
|
||||||
|
} elseif ($limit >= 0) {
|
||||||
|
$sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'odbc':
|
||||||
|
case 'mssql':
|
||||||
|
if ($offset < 1) {
|
||||||
|
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// intentionally break omitted
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException('PDO or driver does not support applying limit or offset.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -318,9 +354,9 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
throw new NotSupportedException('Row count is not available for unbuffered queries.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -342,11 +378,10 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
|
|||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
* @param int the 0-based cursor pos to seek to
|
* @param int the 0-based cursor pos to seek to
|
||||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
public function seek($row)
|
public function seek($row)
|
||||||
{
|
{
|
||||||
throw new DibiDriverException('Cannot seek an unbuffered result set.');
|
throw new NotSupportedException('Cannot seek an unbuffered result set.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -29,22 +28,20 @@
|
|||||||
* - 'charset' - character encoding to set
|
* - 'charset' - character encoding to set
|
||||||
* - 'schema' - the schema search path
|
* - 'schema' - the schema search path
|
||||||
* - 'lazy' - if TRUE, connection will be established only when required
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var resource Connection resource */
|
/** @var resource Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var resource Resultset resource */
|
/** @var resource Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var bool Escape method */
|
/** @var bool Escape method */
|
||||||
private $escMethod = FALSE;
|
private $escMethod = FALSE;
|
||||||
|
|
||||||
@@ -69,23 +66,29 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function connect(array &$config)
|
public function connect(array &$config)
|
||||||
{
|
{
|
||||||
if (isset($config['string'])) {
|
if (isset($config['resource'])) {
|
||||||
$string = $config['string'];
|
$this->connection = $config['resource'];
|
||||||
} 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 (empty($config['persistent'])) {
|
|
||||||
$this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW);
|
|
||||||
} else {
|
} else {
|
||||||
$this->connection = pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW);
|
if (isset($config['string'])) {
|
||||||
}
|
$string = $config['string'];
|
||||||
if (DibiDriverException::catchError($msg)) {
|
} else {
|
||||||
throw new DibiDriverException($msg, 0);
|
$string = '';
|
||||||
|
DibiConnection::alias($config, 'user', 'username');
|
||||||
|
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 (empty($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)) {
|
if (!is_resource($this->connection)) {
|
||||||
@@ -101,7 +104,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($config['schema'])) {
|
if (isset($config['schema'])) {
|
||||||
$this->query('SET search_path TO ' . $config['schema']);
|
$this->query('SET search_path TO "' . $config['schema'] . '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
|
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||||
@@ -144,7 +147,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return pg_affected_rows($this->resultSet);
|
return pg_affected_rows($this->resultSet);
|
||||||
}
|
}
|
||||||
@@ -155,7 +158,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
if ($sequence === NULL) {
|
if ($sequence === NULL) {
|
||||||
// PostgreSQL 8.1 is needed
|
// PostgreSQL 8.1 is needed
|
||||||
@@ -175,36 +178,39 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('START TRANSACTION');
|
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('COMMIT');
|
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('ROLLBACK');
|
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -225,23 +231,23 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
if ($this->escMethod) {
|
if ($this->escMethod) {
|
||||||
return "'" . pg_escape_string($this->connection, $value) . "'";
|
return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||||
} else {
|
} else {
|
||||||
return "'" . pg_escape_string($value) . "'";
|
return "'" . pg_escape_string($value) . "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
if ($this->escMethod) {
|
if ($this->escMethod) {
|
||||||
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
||||||
} else {
|
} else {
|
||||||
@@ -258,14 +264,14 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
|
return substr($value, 0, $a) . '."' . str_replace('"', '""', substr($value, $a + 1)) . '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? 'TRUE' : 'FALSE';
|
return $value ? 'TRUE' : 'FALSE';
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date("'Y-m-d'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date("'Y-m-d H:i:s'", $value);
|
return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -277,19 +283,16 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
if ($type === dibi::BINARY) {
|
||||||
case dibi::FIELD_BINARY:
|
|
||||||
return pg_unescape_bytea($value);
|
return pg_unescape_bytea($value);
|
||||||
|
|
||||||
default:
|
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
|
||||||
}
|
}
|
||||||
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -320,7 +323,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
return pg_num_rows($this->resultSet);
|
return pg_num_rows($this->resultSet);
|
||||||
}
|
}
|
||||||
@@ -344,7 +347,6 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
* @param int the 0-based cursor pos to seek to
|
* @param int the 0-based cursor pos to seek to
|
||||||
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
* @return boolean TRUE on success, FALSE if unable to seek to specified record
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
public function seek($row)
|
public function seek($row)
|
||||||
{
|
{
|
||||||
@@ -411,7 +413,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
{
|
{
|
||||||
$version = pg_version($this->connection);
|
$version = pg_version($this->connection);
|
||||||
if ($version['server'] < 8) {
|
if ($version['server'] < 8) {
|
||||||
throw new NotSupportedException('Reflection requires PostgreSQL 8.');
|
throw new DibiDriverException('Reflection requires PostgreSQL 8.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->query("
|
$this->query("
|
||||||
@@ -433,7 +435,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function getColumns($table)
|
public function getColumns($table)
|
||||||
{
|
{
|
||||||
$_table = $this->escape($table, dibi::FIELD_TEXT);
|
$_table = $this->escape($table, dibi::TEXT);
|
||||||
$this->query("
|
$this->query("
|
||||||
SELECT indkey
|
SELECT indkey
|
||||||
FROM pg_class
|
FROM pg_class
|
||||||
@@ -475,7 +477,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function getIndexes($table)
|
public function getIndexes($table)
|
||||||
{
|
{
|
||||||
$_table = $this->escape($table, dibi::FIELD_TEXT);
|
$_table = $this->escape($table, dibi::TEXT);
|
||||||
$this->query("
|
$this->query("
|
||||||
SELECT ordinal_position, column_name
|
SELECT ordinal_position, column_name
|
||||||
FROM information_schema.columns
|
FROM information_schema.columns
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -29,29 +28,31 @@
|
|||||||
* - 'lazy' - if TRUE, connection will be established only when required
|
* - 'lazy' - if TRUE, connection will be established only when required
|
||||||
* - 'formatDate' - how to format date in SQL (@see date)
|
* - 'formatDate' - how to format date in SQL (@see date)
|
||||||
* - 'formatDateTime' - how to format datetime in SQL (@see date)
|
* - 'formatDateTime' - how to format datetime in SQL (@see date)
|
||||||
|
* - 'dbcharset' - database character encoding (will be converted to 'charset')
|
||||||
|
* - 'charset' - character encoding to set (default is UTF-8)
|
||||||
|
* - 'resource' - connection resource (optional)
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var resource Connection resource */
|
/** @var resource Connection resource */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
|
||||||
/** @var resource Resultset resource */
|
/** @var resource Resultset resource */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
|
|
||||||
/** @var bool Is buffered (seekable and countable)? */
|
/** @var bool Is buffered (seekable and countable)? */
|
||||||
private $buffered;
|
private $buffered;
|
||||||
|
|
||||||
|
|
||||||
/** @var string Date and datetime format */
|
/** @var string Date and datetime format */
|
||||||
private $fmtDate, $fmtDateTime;
|
private $fmtDate, $fmtDateTime;
|
||||||
|
|
||||||
|
/** @var string character encoding */
|
||||||
|
private $dbcharset, $charset;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +79,9 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
$this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U';
|
$this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U';
|
||||||
|
|
||||||
$errorMsg = '';
|
$errorMsg = '';
|
||||||
if (empty($config['persistent'])) {
|
if (isset($config['resource'])) {
|
||||||
|
$this->connection = $config['resource'];
|
||||||
|
} elseif (empty($config['persistent'])) {
|
||||||
$this->connection = @sqlite_open($config['database'], 0666, $errorMsg); // intentionally @
|
$this->connection = @sqlite_open($config['database'], 0666, $errorMsg); // intentionally @
|
||||||
} else {
|
} else {
|
||||||
$this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); // intentionally @
|
$this->connection = @sqlite_popen($config['database'], 0666, $errorMsg); // intentionally @
|
||||||
@@ -89,6 +92,12 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->buffered = empty($config['unbuffered']);
|
$this->buffered = empty($config['unbuffered']);
|
||||||
|
|
||||||
|
$this->dbcharset = empty($config['dbcharset']) ? 'UTF-8' : $config['dbcharset'];
|
||||||
|
$this->charset = empty($config['charset']) ? 'UTF-8' : $config['charset'];
|
||||||
|
if (strcasecmp($this->dbcharset, $this->charset) === 0) {
|
||||||
|
$this->dbcharset = $this->charset = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,6 +121,10 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
*/
|
*/
|
||||||
public function query($sql)
|
public function query($sql)
|
||||||
{
|
{
|
||||||
|
if ($this->dbcharset !== NULL) {
|
||||||
|
$sql = iconv($this->charset, $this->dbcharset . '//IGNORE', $sql);
|
||||||
|
}
|
||||||
|
|
||||||
DibiDriverException::tryError();
|
DibiDriverException::tryError();
|
||||||
if ($this->buffered) {
|
if ($this->buffered) {
|
||||||
$this->resultSet = sqlite_query($this->connection, $sql);
|
$this->resultSet = sqlite_query($this->connection, $sql);
|
||||||
@@ -131,7 +144,7 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
return sqlite_changes($this->connection);
|
return sqlite_changes($this->connection);
|
||||||
}
|
}
|
||||||
@@ -142,7 +155,7 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence)
|
public function getInsertId($sequence)
|
||||||
{
|
{
|
||||||
return sqlite_last_insert_rowid($this->connection);
|
return sqlite_last_insert_rowid($this->connection);
|
||||||
}
|
}
|
||||||
@@ -151,10 +164,11 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('BEGIN');
|
$this->query('BEGIN');
|
||||||
}
|
}
|
||||||
@@ -163,10 +177,11 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('COMMIT');
|
$this->query('COMMIT');
|
||||||
}
|
}
|
||||||
@@ -175,10 +190,11 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->query('ROLLBACK');
|
$this->query('ROLLBACK');
|
||||||
}
|
}
|
||||||
@@ -201,30 +217,33 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param mixed value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type)
|
public function escape($value, $type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
return "'" . sqlite_escape_string($value) . "'";
|
return "'" . sqlite_escape_string($value) . "'";
|
||||||
|
|
||||||
|
/*case dibi::BINARY: // SQLite 3
|
||||||
|
return "X'" . bin2hex((string) $value) . "'";*/
|
||||||
|
|
||||||
case dibi::IDENTIFIER:
|
case dibi::IDENTIFIER:
|
||||||
return '[' . str_replace('.', '].[', strtr($value, '[]', ' ')) . ']';
|
return '[' . str_replace('.', '].[', strtr($value, '[]', ' ')) . ']';
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
case dibi::BOOL:
|
||||||
return $value ? 1 : 0;
|
return $value ? 1 : 0;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
return date($this->fmtDate, $value);
|
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
|
||||||
|
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
return date($this->fmtDateTime, $value);
|
return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
@@ -236,12 +255,15 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type)
|
public function unescape($value, $type)
|
||||||
{
|
{
|
||||||
|
if ($type === dibi::BINARY) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
throw new InvalidArgumentException('Unsupported type.');
|
throw new InvalidArgumentException('Unsupported type.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +292,7 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function rowCount()
|
public function getRowCount()
|
||||||
{
|
{
|
||||||
if (!$this->buffered) {
|
if (!$this->buffered) {
|
||||||
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
throw new DibiDriverException('Row count is not available for unbuffered queries.');
|
||||||
@@ -289,9 +311,13 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
public function fetch($assoc)
|
public function fetch($assoc)
|
||||||
{
|
{
|
||||||
$row = sqlite_fetch_array($this->resultSet, $assoc ? SQLITE_ASSOC : SQLITE_NUM);
|
$row = sqlite_fetch_array($this->resultSet, $assoc ? SQLITE_ASSOC : SQLITE_NUM);
|
||||||
if ($assoc && $row) {
|
$charset = $this->charset === NULL ? NULL : $this->charset . '//TRANSLIT';
|
||||||
|
if ($row && ($assoc || $charset)) {
|
||||||
$tmp = array();
|
$tmp = array();
|
||||||
foreach ($row as $k => $v) {
|
foreach ($row as $k => $v) {
|
||||||
|
if ($charset !== NULL && is_string($v)) {
|
||||||
|
$v = iconv($this->dbcharset, $charset, $v);
|
||||||
|
}
|
||||||
$tmp[str_replace(array('[', ']'), '', $k)] = $v;
|
$tmp[str_replace(array('[', ']'), '', $k)] = $v;
|
||||||
}
|
}
|
||||||
return $tmp;
|
return $tmp;
|
||||||
@@ -378,7 +404,10 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
SELECT name, type = 'view' as view FROM sqlite_temp_master WHERE type IN ('table', 'view')
|
SELECT name, type = 'view' as view FROM sqlite_temp_master WHERE type IN ('table', 'view')
|
||||||
ORDER BY name
|
ORDER BY name
|
||||||
");
|
");
|
||||||
$res = sqlite_fetch_all($this->resultSet, SQLITE_ASSOC);
|
$res = array();
|
||||||
|
while ($row = $this->fetch(TRUE)) {
|
||||||
|
$res[] = $row;
|
||||||
|
}
|
||||||
$this->free();
|
$this->free();
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
@@ -419,4 +448,37 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
|
|||||||
throw new NotImplementedException;
|
throw new NotImplementedException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* user defined functions ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an user defined function for use in SQL statements.
|
||||||
|
* @param string function name
|
||||||
|
* @param mixed callback
|
||||||
|
* @param int num of arguments
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function registerFunction($name, $callback, $numArgs = -1)
|
||||||
|
{
|
||||||
|
sqlite_create_function($this->connection, $name, $callback, $numArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an aggregating user defined function for use in SQL statements.
|
||||||
|
* @param string function name
|
||||||
|
* @param mixed callback called for each row of the result set
|
||||||
|
* @param mixed callback called to aggregate the "stepped" data from each row
|
||||||
|
* @param int num of arguments
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function registerAggregateFunction($name, $rowCallback, $agrCallback, $numArgs = -1)
|
||||||
|
{
|
||||||
|
sqlite_create_aggregate($this->connection, $name, $rowCallback, $agrCallback, $numArgs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@
|
|||||||
* dibi connection.
|
* dibi connection.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiConnection extends DibiObject
|
class DibiConnection extends DibiObject
|
||||||
@@ -54,8 +53,8 @@ class DibiConnection extends DibiObject
|
|||||||
*/
|
*/
|
||||||
public function __construct($config, $name = NULL)
|
public function __construct($config, $name = NULL)
|
||||||
{
|
{
|
||||||
if (class_exists(/*Nette::*/'Debug', FALSE)) {
|
if (class_exists(/*Nette\*/'Debug', FALSE)) {
|
||||||
/*Nette::*/Debug::addColophon(array('dibi', 'getColophon'));
|
/*Nette\*/Debug::addColophon(array('dibi', 'getColophon'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// DSN string
|
// DSN string
|
||||||
@@ -69,6 +68,10 @@ class DibiConnection extends DibiObject
|
|||||||
throw new InvalidArgumentException('Configuration must be array, string or ArrayObject.');
|
throw new InvalidArgumentException('Configuration must be array, string or ArrayObject.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::alias($config, 'username', 'user');
|
||||||
|
self::alias($config, 'password', 'pass');
|
||||||
|
self::alias($config, 'host', 'hostname');
|
||||||
|
|
||||||
if (!isset($config['driver'])) {
|
if (!isset($config['driver'])) {
|
||||||
$config['driver'] = dibi::$defaultDriver;
|
$config['driver'] = dibi::$defaultDriver;
|
||||||
}
|
}
|
||||||
@@ -98,6 +101,12 @@ class DibiConnection extends DibiObject
|
|||||||
$this->setProfiler(new $class);
|
$this->setProfiler(new $class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($config['substitutes'])) {
|
||||||
|
foreach ($config['substitutes'] as $key => $value) {
|
||||||
|
dibi::addSubst($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($config['lazy'])) {
|
if (empty($config['lazy'])) {
|
||||||
$this->connect();
|
$this->connect();
|
||||||
}
|
}
|
||||||
@@ -208,12 +217,25 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connection resource.
|
||||||
|
* @return IDibiDriver
|
||||||
|
*/
|
||||||
|
final public function getDriver()
|
||||||
|
{
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the connection resource.
|
* Returns the connection resource.
|
||||||
* @return resource
|
* @return resource
|
||||||
|
* @deprecated use getDriver()->getResource()
|
||||||
*/
|
*/
|
||||||
final public function getResource()
|
final public function getResource()
|
||||||
{
|
{
|
||||||
|
trigger_error('Deprecated: use getDriver()->getResource(...) instead.', E_USER_WARNING);
|
||||||
return $this->driver->getResource();
|
return $this->driver->getResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,19 +244,31 @@ class DibiConnection extends DibiObject
|
|||||||
/**
|
/**
|
||||||
* Generates (translates) and executes SQL query.
|
* Generates (translates) and executes SQL query.
|
||||||
* @param array|mixed one or more arguments
|
* @param array|mixed one or more arguments
|
||||||
* @return DibiResult|NULL result set object (if any)
|
* @return DibiResult|int result set object (if any)
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
final public function query($args)
|
final public function query($args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$this->connect();
|
$this->connect();
|
||||||
$trans = new DibiTranslator($this->driver);
|
$translator = new DibiTranslator($this->driver);
|
||||||
if ($trans->translate($args)) {
|
return $this->nativeQuery($translator->translate($args));
|
||||||
return $this->nativeQuery($trans->sql);
|
}
|
||||||
} else {
|
|
||||||
throw new DibiException('SQL translate error: ' . $trans->sql);
|
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Generates and returns SQL query.
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return string
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
final public function sql($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
$this->connect();
|
||||||
|
$translator = new DibiTranslator($this->driver);
|
||||||
|
return $translator->translate($args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -248,10 +282,31 @@ class DibiConnection extends DibiObject
|
|||||||
{
|
{
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$this->connect();
|
$this->connect();
|
||||||
$trans = new DibiTranslator($this->driver);
|
try {
|
||||||
$ok = $trans->translate($args);
|
$translator = new DibiTranslator($this->driver);
|
||||||
dibi::dump($trans->sql);
|
dibi::dump($translator->translate($args));
|
||||||
return $ok;
|
return TRUE;
|
||||||
|
|
||||||
|
} catch (DibiException $e) {
|
||||||
|
dibi::dump($e->getSql());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates (translates) and returns SQL query as DibiDataSource.
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return DibiDataSource
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
final public function dataSource($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
$this->connect();
|
||||||
|
$translator = new DibiTranslator($this->driver);
|
||||||
|
return new DibiDataSource($translator->translate($args), $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -259,7 +314,7 @@ class DibiConnection extends DibiObject
|
|||||||
/**
|
/**
|
||||||
* Executes the SQL query.
|
* Executes the SQL query.
|
||||||
* @param string SQL statement.
|
* @param string SQL statement.
|
||||||
* @return DibiResult|NULL result set object (if any)
|
* @return DibiResult|int result set object (if any)
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
final public function nativeQuery($sql)
|
final public function nativeQuery($sql)
|
||||||
@@ -285,6 +340,8 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
if ($res = $this->driver->query($sql)) { // intentionally =
|
if ($res = $this->driver->query($sql)) { // intentionally =
|
||||||
$res = new DibiResult($res, $this->config);
|
$res = new DibiResult($res, $this->config);
|
||||||
|
} else {
|
||||||
|
$res = $this->driver->getAffectedRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
$time += microtime(TRUE);
|
$time += microtime(TRUE);
|
||||||
@@ -304,44 +361,74 @@ class DibiConnection extends DibiObject
|
|||||||
* @return int number of rows
|
* @return int number of rows
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public function affectedRows()
|
public function getAffectedRows()
|
||||||
{
|
{
|
||||||
$rows = $this->driver->affectedRows();
|
$rows = $this->driver->getAffectedRows();
|
||||||
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
|
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
|
||||||
return $rows;
|
return $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of affected rows. Alias for getAffectedRows().
|
||||||
|
* @return int number of rows
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function affectedRows()
|
||||||
|
{
|
||||||
|
return $this->getAffectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @param string optional sequence name
|
* @param string optional sequence name
|
||||||
* @return int
|
* @return int
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public function insertId($sequence = NULL)
|
public function getInsertId($sequence = NULL)
|
||||||
{
|
{
|
||||||
$id = $this->driver->insertId($sequence);
|
$id = $this->driver->getInsertId($sequence);
|
||||||
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
|
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
|
||||||
return (int) $id;
|
return (int) $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
|
||||||
|
* @param string optional sequence name
|
||||||
|
* @return int
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function insertId($sequence = NULL)
|
||||||
|
{
|
||||||
|
return $this->getInsertId($sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function begin()
|
public function begin($savepoint = NULL)
|
||||||
{
|
{
|
||||||
$this->connect();
|
$this->connect();
|
||||||
if ($this->inTxn) {
|
if (!$savepoint && $this->inTxn) {
|
||||||
throw new DibiException('There is already an active transaction.');
|
throw new DibiException('There is already an active transaction.');
|
||||||
}
|
}
|
||||||
if ($this->profiler !== NULL) {
|
if ($this->profiler !== NULL) {
|
||||||
$ticket = $this->profiler->before($this, IDibiProfiler::BEGIN);
|
$ticket = $this->profiler->before($this, IDibiProfiler::BEGIN, $savepoint);
|
||||||
}
|
}
|
||||||
$this->driver->begin();
|
if ($savepoint && !$this->inTxn) {
|
||||||
|
$this->driver->begin();
|
||||||
|
}
|
||||||
|
$this->driver->begin($savepoint);
|
||||||
|
|
||||||
$this->inTxn = TRUE;
|
$this->inTxn = TRUE;
|
||||||
if (isset($ticket)) {
|
if (isset($ticket)) {
|
||||||
$this->profiler->after($ticket);
|
$this->profiler->after($ticket);
|
||||||
@@ -352,18 +439,19 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function commit()
|
public function commit($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!$this->inTxn) {
|
if (!$this->inTxn) {
|
||||||
throw new DibiException('There is no active transaction.');
|
throw new DibiException('There is no active transaction.');
|
||||||
}
|
}
|
||||||
if ($this->profiler !== NULL) {
|
if ($this->profiler !== NULL) {
|
||||||
$ticket = $this->profiler->before($this, IDibiProfiler::COMMIT);
|
$ticket = $this->profiler->before($this, IDibiProfiler::COMMIT, $savepoint);
|
||||||
}
|
}
|
||||||
$this->driver->commit();
|
$this->driver->commit($savepoint);
|
||||||
$this->inTxn = FALSE;
|
$this->inTxn = (bool) $savepoint;
|
||||||
if (isset($ticket)) {
|
if (isset($ticket)) {
|
||||||
$this->profiler->after($ticket);
|
$this->profiler->after($ticket);
|
||||||
}
|
}
|
||||||
@@ -373,18 +461,19 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function rollback()
|
public function rollback($savepoint = NULL)
|
||||||
{
|
{
|
||||||
if (!$this->inTxn) {
|
if (!$this->inTxn) {
|
||||||
throw new DibiException('There is no active transaction.');
|
throw new DibiException('There is no active transaction.');
|
||||||
}
|
}
|
||||||
if ($this->profiler !== NULL) {
|
if ($this->profiler !== NULL) {
|
||||||
$ticket = $this->profiler->before($this, IDibiProfiler::ROLLBACK);
|
$ticket = $this->profiler->before($this, IDibiProfiler::ROLLBACK, $savepoint);
|
||||||
}
|
}
|
||||||
$this->driver->rollback();
|
$this->driver->rollback($savepoint);
|
||||||
$this->inTxn = FALSE;
|
$this->inTxn = (bool) $savepoint;
|
||||||
if (isset($ticket)) {
|
if (isset($ticket)) {
|
||||||
$this->profiler->after($ticket);
|
$this->profiler->after($ticket);
|
||||||
}
|
}
|
||||||
@@ -393,13 +482,26 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Is in transaction?
|
||||||
* @param string unescaped string
|
* @return bool
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
|
||||||
* @return string escaped and quoted string
|
|
||||||
*/
|
*/
|
||||||
public function escape($value, $type = dibi::FIELD_TEXT)
|
public function inTransaction()
|
||||||
{
|
{
|
||||||
|
return $this->inTxn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes data for use in a SQL statement.
|
||||||
|
* @param string unescaped string
|
||||||
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
|
* @return string escaped and quoted string
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public function escape($value, $type = dibi::TEXT)
|
||||||
|
{
|
||||||
|
trigger_error('Deprecated: use getDriver()->escape(...) instead.', E_USER_WARNING);
|
||||||
$this->connect(); // MySQL & PDO require connection
|
$this->connect(); // MySQL & PDO require connection
|
||||||
return $this->driver->escape($value, $type);
|
return $this->driver->escape($value, $type);
|
||||||
}
|
}
|
||||||
@@ -409,11 +511,13 @@ class DibiConnection extends DibiObject
|
|||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function unescape($value, $type = dibi::FIELD_BINARY)
|
public function unescape($value, $type = dibi::BINARY)
|
||||||
{
|
{
|
||||||
|
trigger_error('Deprecated: use getDriver()->unescape(...) instead.', E_USER_WARNING);
|
||||||
return $this->driver->unescape($value, $type);
|
return $this->driver->unescape($value, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,9 +527,11 @@ class DibiConnection extends DibiObject
|
|||||||
* Delimites identifier (table's or column's name, etc.).
|
* Delimites identifier (table's or column's name, etc.).
|
||||||
* @param string identifier
|
* @param string identifier
|
||||||
* @return string delimited identifier
|
* @return string delimited identifier
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function delimite($value)
|
public function delimite($value)
|
||||||
{
|
{
|
||||||
|
trigger_error('Deprecated: use getDriver()->escape(...) instead.', E_USER_WARNING);
|
||||||
return $this->driver->escape($value, dibi::IDENTIFIER);
|
return $this->driver->escape($value, dibi::IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,9 +543,11 @@ class DibiConnection extends DibiObject
|
|||||||
* @param int $limit
|
* @param int $limit
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @return void
|
* @return void
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function applyLimit(&$sql, $limit, $offset)
|
public function applyLimit(&$sql, $limit, $offset)
|
||||||
{
|
{
|
||||||
|
trigger_error('Deprecated: use getDriver()->applyLimit(...) instead.', E_USER_WARNING);
|
||||||
$this->driver->applyLimit($sql, $limit, $offset);
|
$this->driver->applyLimit($sql, $limit, $offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,8 +584,11 @@ class DibiConnection extends DibiObject
|
|||||||
* @param array
|
* @param array
|
||||||
* @return DibiFluent
|
* @return DibiFluent
|
||||||
*/
|
*/
|
||||||
public function update($table, array $args)
|
public function update($table, $args)
|
||||||
{
|
{
|
||||||
|
if (!(is_array($args) || $args instanceof ArrayObject)) {
|
||||||
|
throw new InvalidArgumentException('Arguments must be array or ArrayObject.');
|
||||||
|
}
|
||||||
return $this->command()->update('%n', $table)->set($args);
|
return $this->command()->update('%n', $table)->set($args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,10 +599,15 @@ class DibiConnection extends DibiObject
|
|||||||
* @param array
|
* @param array
|
||||||
* @return DibiFluent
|
* @return DibiFluent
|
||||||
*/
|
*/
|
||||||
public function insert($table, array $args)
|
public function insert($table, $args)
|
||||||
{
|
{
|
||||||
|
if ($args instanceof ArrayObject) {
|
||||||
|
$args = (array) $args;
|
||||||
|
} elseif (!is_array($args)) {
|
||||||
|
throw new InvalidArgumentException('Arguments must be array or ArrayObject.');
|
||||||
|
}
|
||||||
return $this->command()->insert()
|
return $this->command()->insert()
|
||||||
->into('%n', $table, '(%n)', array_keys($args))->values('%l', array_values($args));
|
->into('%n', $table, '(%n)', array_keys($args))->values('%l', $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -513,11 +629,12 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param IDibiProfiler
|
* @param IDibiProfiler
|
||||||
* @return void
|
* @return DibiConnection provides a fluent interface
|
||||||
*/
|
*/
|
||||||
public function setProfiler(IDibiProfiler $profiler = NULL)
|
public function setProfiler(IDibiProfiler $profiler = NULL)
|
||||||
{
|
{
|
||||||
$this->profiler = $profiler;
|
$this->profiler = $profiler;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -532,6 +649,66 @@ class DibiConnection extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* shortcuts ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes SQL query and fetch result - shortcut for query() & fetch().
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return DibiRow
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function fetch($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
return $this->query($args)->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes SQL query and fetch results - shortcut for query() & fetchAll().
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return array of DibiRow
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function fetchAll($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
return $this->query($args)->fetchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes SQL query and fetch first column - shortcut for query() & fetchSingle().
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return string
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function fetchSingle($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
return $this->query($args)->fetchSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes SQL query and fetch pairs - shortcut for query() & fetchPairs().
|
||||||
|
* @param array|mixed one or more arguments
|
||||||
|
* @return string
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
public function fetchPairs($args)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
return $this->query($args)->fetchPairs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************* misc ****************d*g**/
|
/********************* misc ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
@@ -575,6 +752,7 @@ class DibiConnection extends DibiObject
|
|||||||
*/
|
*/
|
||||||
public function getDatabaseInfo()
|
public function getDatabaseInfo()
|
||||||
{
|
{
|
||||||
|
$this->connect();
|
||||||
return new DibiDatabaseInfo($this->driver, isset($this->config['database']) ? $this->config['database'] : NULL);
|
return new DibiDatabaseInfo($this->driver, isset($this->config['database']) ? $this->config['database'] : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@
|
|||||||
* Default implementation of IDataSource for dibi.
|
* Default implementation of IDataSource for dibi.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiDataSource extends DibiObject implements IDataSource
|
class DibiDataSource extends DibiObject implements IDataSource
|
||||||
@@ -35,58 +34,306 @@ class DibiDataSource extends DibiObject implements IDataSource
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
private $sql;
|
private $sql;
|
||||||
|
|
||||||
|
/** @var DibiResult */
|
||||||
|
private $result;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
private $count;
|
private $count;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $totalCount;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $cols = array();
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $sorting = array();
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $conds = array();
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $offset;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $limit;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string SQL command or table name, as data source
|
* @param string SQL command or table or view name, as data source
|
||||||
* @param DibiConnection connection
|
* @param DibiConnection connection
|
||||||
*/
|
*/
|
||||||
public function __construct($sql, DibiConnection $connection = NULL)
|
public function __construct($sql, DibiConnection $connection)
|
||||||
{
|
{
|
||||||
if (strpos($sql, ' ') === FALSE) {
|
if (strpos($sql, ' ') === FALSE) {
|
||||||
// table name
|
$this->sql = $connection->getDriver()->escape($sql, dibi::IDENTIFIER); // table name
|
||||||
$this->sql = $sql;
|
|
||||||
} else {
|
} else {
|
||||||
// SQL command
|
$this->sql = '(' . $sql . ') t'; // SQL command
|
||||||
$this->sql = '(' . $sql . ') AS [source]';
|
|
||||||
}
|
}
|
||||||
|
$this->connection = $connection;
|
||||||
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int offset
|
* Selects columns to query.
|
||||||
* @param int limit
|
* @param string|array column name or array of column names
|
||||||
* @param array columns
|
* @param string column alias
|
||||||
* @return ArrayIterator
|
* @return DibiDataSource provides a fluent interface
|
||||||
*/
|
*/
|
||||||
public function getIterator($offset = NULL, $limit = NULL)
|
public function select($col, $as = NULL)
|
||||||
{
|
{
|
||||||
return $this->connection->query('
|
if (is_array($col)) {
|
||||||
SELECT *
|
$this->cols = $col;
|
||||||
FROM', $this->sql, '
|
} else {
|
||||||
%ofs %lmt', $offset, $limit
|
$this->cols[$col] = $as;
|
||||||
|
}
|
||||||
|
$this->result = NULL;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds conditions to query.
|
||||||
|
* @param mixed conditions
|
||||||
|
* @return DibiDataSource provides a fluent interface
|
||||||
|
*/
|
||||||
|
public function where($cond)
|
||||||
|
{
|
||||||
|
if (is_array($cond)) {
|
||||||
|
// TODO: not consistent with select and orderBy
|
||||||
|
$this->conds[] = $cond;
|
||||||
|
} else {
|
||||||
|
$this->conds[] = func_get_args();
|
||||||
|
}
|
||||||
|
$this->result = $this->count = NULL;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects columns to order by.
|
||||||
|
* @param string|array column name or array of column names
|
||||||
|
* @param string sorting direction
|
||||||
|
* @return DibiDataSource provides a fluent interface
|
||||||
|
*/
|
||||||
|
public function orderBy($row, $sorting = 'ASC')
|
||||||
|
{
|
||||||
|
if (is_array($row)) {
|
||||||
|
$this->sorting = $row;
|
||||||
|
} else {
|
||||||
|
$this->sorting[$row] = $sorting;
|
||||||
|
}
|
||||||
|
$this->result = NULL;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limits number of rows.
|
||||||
|
* @param int limit
|
||||||
|
* @param int offset
|
||||||
|
* @return DibiDataSource provides a fluent interface
|
||||||
|
*/
|
||||||
|
public function applyLimit($limit, $offset = NULL)
|
||||||
|
{
|
||||||
|
$this->limit = $limit;
|
||||||
|
$this->offset = $offset;
|
||||||
|
$this->result = $this->count = NULL;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dibi connection.
|
||||||
|
* @return DibiConnection
|
||||||
|
*/
|
||||||
|
final public function getConnection()
|
||||||
|
{
|
||||||
|
return $this->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* executing ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns (and queries) DibiResult.
|
||||||
|
* @return DibiResult
|
||||||
|
*/
|
||||||
|
public function getResult()
|
||||||
|
{
|
||||||
|
if ($this->result === NULL) {
|
||||||
|
$this->result = $this->connection->nativeQuery($this->__toString());
|
||||||
|
}
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DibiResultIterator
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return $this->getResult()->getIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates, executes SQL query and fetches the single row.
|
||||||
|
* @return DibiRow|FALSE array on success, FALSE if no next record
|
||||||
|
*/
|
||||||
|
public function fetch()
|
||||||
|
{
|
||||||
|
return $this->getResult()->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like fetch(), but returns only first field.
|
||||||
|
* @return mixed value on success, FALSE if no next record
|
||||||
|
*/
|
||||||
|
public function fetchSingle()
|
||||||
|
{
|
||||||
|
return $this->getResult()->fetchSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches all records from table.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function fetchAll()
|
||||||
|
{
|
||||||
|
return $this->getResult()->fetchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches all records from table and returns associative tree.
|
||||||
|
* @param string associative descriptor
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function fetchAssoc($assoc)
|
||||||
|
{
|
||||||
|
return $this->getResult()->fetchAssoc($assoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches all records from table like $key => $value pairs.
|
||||||
|
* @param string associative key
|
||||||
|
* @param string value
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function fetchPairs($key = NULL, $value = NULL)
|
||||||
|
{
|
||||||
|
return $this->getResult()->fetchPairs($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discards the internal cache.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function release()
|
||||||
|
{
|
||||||
|
$this->result = $this->count = $this->totalCount = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* exporting ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns this data source wrapped in DibiFluent object.
|
||||||
|
* @return DibiFluent
|
||||||
|
*/
|
||||||
|
public function toFluent()
|
||||||
|
{
|
||||||
|
return $this->connection->select('*')->from('(%SQL) AS t', $this->__toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns this data source wrapped in DibiDataSource object.
|
||||||
|
* @return DibiDataSource
|
||||||
|
*/
|
||||||
|
public function toDataSource()
|
||||||
|
{
|
||||||
|
return new self($this->__toString(), $this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns SQL query.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
final public function __toString()
|
||||||
|
{
|
||||||
|
return $this->connection->sql('
|
||||||
|
SELECT %n', (empty($this->cols) ? '*' : $this->cols), '
|
||||||
|
FROM %SQL', $this->sql, '
|
||||||
|
%ex', $this->conds ? array('WHERE %and', $this->conds) : NULL, '
|
||||||
|
%ex', $this->sorting ? array('ORDER BY %by', $this->sorting) : NULL, '
|
||||||
|
%ofs %lmt', $this->offset, $this->limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* counting ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the number of rows in a given data source.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
if ($this->count === NULL) {
|
if ($this->count === NULL) {
|
||||||
$this->count = $this->connection->query('
|
$this->count = $this->conds || $this->offset || $this->limit
|
||||||
SELECT COUNT(*) FROM', $this->sql
|
? (int) $this->connection->nativeQuery(
|
||||||
)->fetchSingle();
|
'SELECT COUNT(*) FROM (' . $this->__toString() . ') AS t'
|
||||||
|
)->fetchSingle()
|
||||||
|
: $this->getTotalCount();
|
||||||
}
|
}
|
||||||
return $this->count;
|
return $this->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of rows in a given data source.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTotalCount()
|
||||||
|
{
|
||||||
|
if ($this->totalCount === NULL) {
|
||||||
|
$this->totalCount = (int) $this->connection->nativeQuery(
|
||||||
|
'SELECT COUNT(*) FROM ' . $this->sql
|
||||||
|
)->fetchSingle();
|
||||||
|
}
|
||||||
|
return $this->totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@
|
|||||||
* Reflection metadata class for a database.
|
* Reflection metadata class for a database.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiDatabaseInfo extends DibiObject
|
class DibiDatabaseInfo extends DibiObject
|
||||||
@@ -85,7 +84,7 @@ class DibiDatabaseInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
* @return DibiTableInfo
|
* @return DibiTableInfo
|
||||||
*/
|
*/
|
||||||
public function getTable($name)
|
public function getTable($name)
|
||||||
@@ -103,7 +102,7 @@ class DibiDatabaseInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function hasTable($name)
|
public function hasTable($name)
|
||||||
@@ -136,7 +135,7 @@ class DibiDatabaseInfo extends DibiObject
|
|||||||
* Reflection metadata class for a database table.
|
* Reflection metadata class for a database table.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiTableInfo extends DibiObject
|
class DibiTableInfo extends DibiObject
|
||||||
@@ -220,7 +219,7 @@ class DibiTableInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
* @return DibiColumnInfo
|
* @return DibiColumnInfo
|
||||||
*/
|
*/
|
||||||
public function getColumn($name)
|
public function getColumn($name)
|
||||||
@@ -238,7 +237,7 @@ class DibiTableInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function hasColumn($name)
|
public function hasColumn($name)
|
||||||
@@ -333,10 +332,112 @@ class DibiTableInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reflection metadata class for a table column.
|
* Reflection metadata class for a result set.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiResultInfo extends DibiObject
|
||||||
|
{
|
||||||
|
/** @var IDibiDriver */
|
||||||
|
private $driver;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $columns;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $names;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(IDibiDriver $driver)
|
||||||
|
{
|
||||||
|
$this->driver = $driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array of DibiColumnInfo
|
||||||
|
*/
|
||||||
|
public function getColumns()
|
||||||
|
{
|
||||||
|
$this->initColumns();
|
||||||
|
return array_values($this->columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool
|
||||||
|
* @return array of string
|
||||||
|
*/
|
||||||
|
public function getColumnNames($fullNames = FALSE)
|
||||||
|
{
|
||||||
|
$this->initColumns();
|
||||||
|
$res = array();
|
||||||
|
foreach ($this->columns as $column) {
|
||||||
|
$res[] = $fullNames ? $column->getFullName() : $column->getName();
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
* @return DibiColumnInfo
|
||||||
|
*/
|
||||||
|
public function getColumn($name)
|
||||||
|
{
|
||||||
|
$this->initColumns();
|
||||||
|
$l = strtolower($name);
|
||||||
|
if (isset($this->names[$l])) {
|
||||||
|
return $this->names[$l];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new DibiException("Result set has no column '$name'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasColumn($name)
|
||||||
|
{
|
||||||
|
$this->initColumns();
|
||||||
|
return isset($this->names[strtolower($name)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function initColumns()
|
||||||
|
{
|
||||||
|
if ($this->columns === NULL) {
|
||||||
|
$this->columns = array();
|
||||||
|
foreach ($this->driver->getColumnsMeta() as $info) {
|
||||||
|
$this->columns[] = $this->names[$info['name']] = new DibiColumnInfo($this->driver, $info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflection metadata class for a table or result set column.
|
||||||
|
*
|
||||||
|
* @author David Grudl
|
||||||
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiColumnInfo extends DibiObject
|
class DibiColumnInfo extends DibiObject
|
||||||
@@ -359,7 +460,6 @@ class DibiColumnInfo extends DibiObject
|
|||||||
{
|
{
|
||||||
$this->driver = $driver;
|
$this->driver = $driver;
|
||||||
$this->info = $info;
|
$this->info = $info;
|
||||||
$this->type = self::detectType($this->info['nativetype']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -374,6 +474,16 @@ class DibiColumnInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFullName()
|
||||||
|
{
|
||||||
|
return $this->info['fullname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -402,6 +512,9 @@ class DibiColumnInfo extends DibiObject
|
|||||||
*/
|
*/
|
||||||
public function getType()
|
public function getType()
|
||||||
{
|
{
|
||||||
|
if ($this->type === NULL) {
|
||||||
|
$this->type = self::detectType($this->info['nativetype']);
|
||||||
|
}
|
||||||
return $this->type;
|
return $this->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,20 +586,21 @@ class DibiColumnInfo extends DibiObject
|
|||||||
* @param string
|
* @param string
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function detectType($type)
|
private static function detectType($type)
|
||||||
{
|
{
|
||||||
static $patterns = array(
|
static $patterns = array(
|
||||||
'BYTE|COUNTER|SERIAL|INT|LONG' => dibi::FIELD_INTEGER,
|
'BYTEA|BLOB|BIN' => dibi::BINARY,
|
||||||
'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC' => dibi::FIELD_FLOAT,
|
'TEXT|CHAR' => dibi::TEXT,
|
||||||
'^TIME$' => dibi::FIELD_TIME,
|
'BYTE|COUNTER|SERIAL|INT|LONG' => dibi::INTEGER,
|
||||||
'TIME' => dibi::FIELD_DATETIME, // DATETIME, TIMESTAMP
|
'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER' => dibi::FLOAT,
|
||||||
'YEAR|DATE' => dibi::FIELD_DATE,
|
'^TIME$' => dibi::TIME,
|
||||||
'BYTEA|BLOB|BIN' => dibi::FIELD_BINARY,
|
'TIME' => dibi::DATETIME, // DATETIME, TIMESTAMP
|
||||||
'BOOL|BIT' => dibi::FIELD_BOOL,
|
'YEAR|DATE' => dibi::DATE,
|
||||||
|
'BOOL|BIT' => dibi::BOOL,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isset(self::$types[$type])) {
|
if (!isset(self::$types[$type])) {
|
||||||
self::$types[$type] = dibi::FIELD_TEXT;
|
self::$types[$type] = dibi::TEXT;
|
||||||
foreach ($patterns as $s => $val) {
|
foreach ($patterns as $s => $val) {
|
||||||
if (preg_match("#$s#i", $type)) {
|
if (preg_match("#$s#i", $type)) {
|
||||||
return self::$types[$type] = $val;
|
return self::$types[$type] = $val;
|
||||||
@@ -505,7 +619,7 @@ class DibiColumnInfo extends DibiObject
|
|||||||
* Reflection metadata class for a foreign key.
|
* Reflection metadata class for a foreign key.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @todo
|
* @todo
|
||||||
*/
|
*/
|
||||||
@@ -551,10 +665,10 @@ class DibiForeignKeyInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reflection metadata class for a index or primary key
|
* Reflection metadata class for a index or primary key.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiIndexInfo extends DibiObject
|
class DibiIndexInfo extends DibiObject
|
||||||
@@ -600,7 +714,6 @@ class DibiIndexInfo extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,36 +23,19 @@
|
|||||||
* dibi common exception.
|
* dibi common exception.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiException extends Exception
|
class DibiException extends Exception implements /*Nette\*/IDebuggable
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 */
|
/** @var string */
|
||||||
private $sql;
|
private $sql;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an dibi driver exception.
|
* Construct a dibi exception.
|
||||||
* @param string Message describing the exception
|
* @param string Message describing the exception
|
||||||
* @param int Some code
|
* @param int Some code
|
||||||
* @param string SQL command
|
* @param string SQL command
|
||||||
*/
|
*/
|
||||||
public function __construct($message = NULL, $code = 0, $sql = NULL)
|
public function __construct($message = NULL, $code = 0, $sql = NULL)
|
||||||
@@ -85,7 +67,7 @@ class DibiDriverException extends DibiException implements /*Nette::*/IDebuggabl
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************* interface Nette::IDebuggable ****************d*g**/
|
/********************* interface Nette\IDebuggable ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,14 +86,32 @@ class DibiDriverException extends DibiException implements /*Nette::*/IDebuggabl
|
|||||||
return $panels;
|
return $panels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* database server exception.
|
||||||
|
*
|
||||||
|
* @author David Grudl
|
||||||
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiDriverException extends DibiException
|
||||||
|
{
|
||||||
|
|
||||||
/********************* error catching ****************d*g**/
|
/********************* error catching ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private static $errorMsg;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts catching potential errors/warnings
|
* Starts catching potential errors/warnings.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function tryError()
|
public static function tryError()
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,23 +23,24 @@
|
|||||||
* dibi SQL builder via fluent interfaces. EXPERIMENTAL!
|
* dibi SQL builder via fluent interfaces. EXPERIMENTAL!
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiFluent extends DibiObject
|
class DibiFluent extends DibiObject implements IDataSource
|
||||||
{
|
{
|
||||||
/** @var array */
|
/** @var array */
|
||||||
public static $masks = array(
|
public static $masks = array(
|
||||||
'SELECT' => array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY',
|
'SELECT' => array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY',
|
||||||
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', '%end'),
|
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET'),
|
||||||
'UPDATE' => array('UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
|
'UPDATE' => array('UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT'),
|
||||||
'INSERT' => array('INSERT', 'INTO', 'VALUES', 'SELECT', '%end'),
|
'INSERT' => array('INSERT', 'INTO', 'VALUES', 'SELECT'),
|
||||||
'DELETE' => array('DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT', '%end'),
|
'DELETE' => array('DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT'),
|
||||||
);
|
);
|
||||||
|
|
||||||
/** @var array */
|
/** @var array default modifiers for arrays */
|
||||||
public static $modifiers = array(
|
public static $modifiers = array(
|
||||||
'SELECT' => '%n',
|
'SELECT' => '%n',
|
||||||
|
'FROM' => '%n',
|
||||||
'IN' => '%l',
|
'IN' => '%l',
|
||||||
'VALUES' => '%l',
|
'VALUES' => '%l',
|
||||||
'SET' => '%a',
|
'SET' => '%a',
|
||||||
@@ -50,7 +50,7 @@ class DibiFluent extends DibiObject
|
|||||||
'GROUP BY' => '%by',
|
'GROUP BY' => '%by',
|
||||||
);
|
);
|
||||||
|
|
||||||
/** @var array */
|
/** @var array clauses separators */
|
||||||
public static $separators = array(
|
public static $separators = array(
|
||||||
'SELECT' => ',',
|
'SELECT' => ',',
|
||||||
'FROM' => FALSE,
|
'FROM' => FALSE,
|
||||||
@@ -119,17 +119,20 @@ class DibiFluent extends DibiObject
|
|||||||
if ($arg === TRUE) { // flag
|
if ($arg === TRUE) { // flag
|
||||||
$args = array();
|
$args = array();
|
||||||
|
|
||||||
} elseif (is_string($arg) && preg_match('#^[a-z][a-z0-9_.]*$#i', $arg)) { // identifier
|
} elseif (is_string($arg) && preg_match('#^[a-z:_][a-z0-9_.:]*$#i', $arg)) { // identifier
|
||||||
$args = array('%n', $arg);
|
$args = array('%n', $arg);
|
||||||
|
|
||||||
} elseif (is_array($arg)) { // any array
|
} elseif ($arg instanceof self) {
|
||||||
|
$args = array_merge(array('('), $arg->_export(), array(')'));
|
||||||
|
|
||||||
|
} elseif (is_array($arg) || $arg instanceof ArrayObject) { // any array
|
||||||
if (isset(self::$modifiers[$clause])) {
|
if (isset(self::$modifiers[$clause])) {
|
||||||
$args = array(self::$modifiers[$clause], $arg);
|
$args = array(self::$modifiers[$clause], $arg);
|
||||||
|
|
||||||
} elseif (is_string(key($arg))) { // associative array
|
} elseif (is_string(key($arg))) { // associative array
|
||||||
$args = array('%a', $arg);
|
$args = array('%a', $arg);
|
||||||
}
|
}
|
||||||
}
|
} // case $arg === FALSE is handled below
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists($clause, $this->clauses)) {
|
if (array_key_exists($clause, $this->clauses)) {
|
||||||
@@ -234,14 +237,31 @@ class DibiFluent extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dibi connection.
|
||||||
|
* @return DibiConnection
|
||||||
|
*/
|
||||||
|
final public function getConnection()
|
||||||
|
{
|
||||||
|
return $this->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* executing ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and executes SQL query.
|
* Generates and executes SQL query.
|
||||||
* @return DibiResult|NULL result set object (if any)
|
* @param mixed what to return?
|
||||||
|
* @return DibiResult|int result set object (if any)
|
||||||
* @throws DibiException
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public function execute()
|
public function execute($return = NULL)
|
||||||
{
|
{
|
||||||
return $this->connection->query($this->_export());
|
$res = $this->connection->query($this->_export());
|
||||||
|
return $return === dibi::IDENTIFIER ? $this->connection->getInsertId() : $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -249,14 +269,14 @@ class DibiFluent extends DibiObject
|
|||||||
/**
|
/**
|
||||||
* Generates, executes SQL query and fetches the single row.
|
* Generates, executes SQL query and fetches the single row.
|
||||||
* @return DibiRow|FALSE array on success, FALSE if no next record
|
* @return DibiRow|FALSE array on success, FALSE if no next record
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
public function fetch()
|
public function fetch()
|
||||||
{
|
{
|
||||||
if ($this->command === 'SELECT') {
|
if ($this->command === 'SELECT') {
|
||||||
$this->clauses['LIMIT'] = array(1);
|
return $this->connection->query($this->_export(NULL, array('%lmt', 1)))->fetch();
|
||||||
|
} else {
|
||||||
|
return $this->connection->query($this->_export())->fetch();
|
||||||
}
|
}
|
||||||
return $this->execute()->fetch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -268,9 +288,10 @@ class DibiFluent extends DibiObject
|
|||||||
public function fetchSingle()
|
public function fetchSingle()
|
||||||
{
|
{
|
||||||
if ($this->command === 'SELECT') {
|
if ($this->command === 'SELECT') {
|
||||||
$this->clauses['LIMIT'] = array(1);
|
return $this->connection->query($this->_export(NULL, array('%lmt', 1)))->fetchSingle();
|
||||||
|
} else {
|
||||||
|
return $this->connection->query($this->_export())->fetchSingle();
|
||||||
}
|
}
|
||||||
return $this->execute()->fetchSingle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -283,22 +304,19 @@ class DibiFluent extends DibiObject
|
|||||||
*/
|
*/
|
||||||
public function fetchAll($offset = NULL, $limit = NULL)
|
public function fetchAll($offset = NULL, $limit = NULL)
|
||||||
{
|
{
|
||||||
return $this->execute()->fetchAll($offset, $limit);
|
return $this->connection->query($this->_export(NULL, array('%ofs %lmt', $offset, $limit)))->fetchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all records from table and returns associative tree.
|
* Fetches all records from table and returns associative tree.
|
||||||
* Associative descriptor: assoc1,#,assoc2,=,assoc3,@
|
|
||||||
* builds a tree: $data[assoc1][index][assoc2]['assoc3']->value = {record}
|
|
||||||
* @param string associative descriptor
|
* @param string associative descriptor
|
||||||
* @return array
|
* @return array
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
*/
|
||||||
public function fetchAssoc($assoc)
|
public function fetchAssoc($assoc)
|
||||||
{
|
{
|
||||||
return $this->execute()->fetchAssoc($assoc);
|
return $this->connection->query($this->_export())->fetchAssoc($assoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -308,11 +326,23 @@ class DibiFluent extends DibiObject
|
|||||||
* @param string associative key
|
* @param string associative key
|
||||||
* @param string value
|
* @param string value
|
||||||
* @return array
|
* @return array
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
*/
|
||||||
public function fetchPairs($key = NULL, $value = NULL)
|
public function fetchPairs($key = NULL, $value = NULL)
|
||||||
{
|
{
|
||||||
return $this->execute()->fetchPairs($key, $value);
|
return $this->connection->query($this->_export())->fetchPairs($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required by the IteratorAggregate interface.
|
||||||
|
* @param int offset
|
||||||
|
* @param int limit
|
||||||
|
* @return DibiResultIterator
|
||||||
|
*/
|
||||||
|
public function getIterator($offset = NULL, $limit = NULL)
|
||||||
|
{
|
||||||
|
return $this->connection->query($this->_export(NULL, array('%ofs %lmt', $offset, $limit)))->getIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -329,12 +359,49 @@ class DibiFluent extends DibiObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return (int) $this->connection->query(
|
||||||
|
'SELECT COUNT(*) FROM (%ex', $this->_export(), ') AS [data]'
|
||||||
|
)->fetchSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* exporting ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DibiDataSource
|
||||||
|
*/
|
||||||
|
public function toDataSource()
|
||||||
|
{
|
||||||
|
return new DibiDataSource($this->connection->sql($this->_export()), $this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns SQL query.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
final public function __toString()
|
||||||
|
{
|
||||||
|
return $this->connection->sql($this->_export());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates parameters for DibiTranslator.
|
* Generates parameters for DibiTranslator.
|
||||||
* @param string clause name
|
* @param string clause name
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function _export($clause = NULL)
|
protected function _export($clause = NULL, $args = array())
|
||||||
{
|
{
|
||||||
if ($clause === NULL) {
|
if ($clause === NULL) {
|
||||||
$data = $this->clauses;
|
$data = $this->clauses;
|
||||||
@@ -348,18 +415,16 @@ class DibiFluent extends DibiObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$args = array();
|
|
||||||
foreach ($data as $clause => $statement) {
|
foreach ($data as $clause => $statement) {
|
||||||
if ($statement !== NULL) {
|
if ($statement !== NULL) {
|
||||||
if ($clause[0] !== '%') {
|
$args[] = $clause;
|
||||||
$args[] = $clause;
|
if ($clause === $this->command) {
|
||||||
if ($clause === $this->command) {
|
$args[] = implode(' ', array_keys($this->flags));
|
||||||
$args[] = implode(' ', array_keys($this->flags));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
array_splice($args, count($args), 0, $statement);
|
array_splice($args, count($args), 0, $statement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,19 +445,6 @@ class DibiFluent extends DibiObject
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns (highlighted) SQL query.
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
final public function __toString()
|
|
||||||
{
|
|
||||||
ob_start();
|
|
||||||
$this->test();
|
|
||||||
return ob_get_clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@
|
|||||||
/**
|
/**
|
||||||
* DibiObject is the ultimate ancestor of all instantiable classes.
|
* DibiObject is the ultimate ancestor of all instantiable classes.
|
||||||
*
|
*
|
||||||
* DibiObject is copy of Nette::Object from Nette Framework (http://nettephp.com).
|
* DibiObject is copy of Nette\Object from Nette Framework (http://nettephp.com).
|
||||||
*
|
*
|
||||||
* It defines some handful methods and enhances object core of PHP:
|
* It defines some handful methods and enhances object core of PHP:
|
||||||
* - access to undeclared members throws exceptions
|
* - access to undeclared members throws exceptions
|
||||||
@@ -59,7 +58,7 @@
|
|||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
abstract class DibiObject
|
abstract class DibiObject
|
||||||
@@ -82,11 +81,11 @@ abstract class DibiObject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to reflection.
|
* Access to reflection.
|
||||||
* @return ReflectionObject
|
* @return \ReflectionObject
|
||||||
*/
|
*/
|
||||||
final public function getReflection()
|
final public function getReflection()
|
||||||
{
|
{
|
||||||
return new ReflectionObject($this);
|
return new /*\*/ReflectionObject($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -96,22 +95,22 @@ abstract class DibiObject
|
|||||||
* @param string method name
|
* @param string method name
|
||||||
* @param array arguments
|
* @param array arguments
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws ::MemberAccessException
|
* @throws \MemberAccessException
|
||||||
*/
|
*/
|
||||||
public function __call($name, $args)
|
public function __call($name, $args)
|
||||||
{
|
{
|
||||||
$class = get_class($this);
|
$class = get_class($this);
|
||||||
|
|
||||||
if ($name === '') {
|
if ($name === '') {
|
||||||
throw new /*::*/MemberAccessException("Call to class '$class' method without name.");
|
throw new /*\*/MemberAccessException("Call to class '$class' method without name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// event functionality
|
// event functionality
|
||||||
if (preg_match('#^on[A-Z]#', $name)) {
|
if (preg_match('#^on[A-Z]#', $name)) {
|
||||||
$rp = new ReflectionProperty($class, $name);
|
$rp = new /*\*/ReflectionProperty($class, $name);
|
||||||
if ($rp->isPublic() && !$rp->isStatic()) {
|
if ($rp->isPublic() && !$rp->isStatic()) {
|
||||||
$list = $this->$name;
|
$list = $this->$name;
|
||||||
if (is_array($list) || $list instanceof Traversable) {
|
if (is_array($list) || $list instanceof /*\*/Traversable) {
|
||||||
foreach ($list as $handler) {
|
foreach ($list as $handler) {
|
||||||
/**/if (is_object($handler)) {
|
/**/if (is_object($handler)) {
|
||||||
call_user_func_array(array($handler, '__invoke'), $args);
|
call_user_func_array(array($handler, '__invoke'), $args);
|
||||||
@@ -131,7 +130,7 @@ abstract class DibiObject
|
|||||||
return call_user_func_array($cb, $args);
|
return call_user_func_array($cb, $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new /*::*/MemberAccessException("Call to undefined method $class::$name().");
|
throw new /*\*/MemberAccessException("Call to undefined method $class::$name().");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -141,12 +140,12 @@ abstract class DibiObject
|
|||||||
* @param string method name (in lower case!)
|
* @param string method name (in lower case!)
|
||||||
* @param array arguments
|
* @param array arguments
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws ::MemberAccessException
|
* @throws \MemberAccessException
|
||||||
*/
|
*/
|
||||||
public static function __callStatic($name, $args)
|
public static function __callStatic($name, $args)
|
||||||
{
|
{
|
||||||
$class = get_called_class();
|
$class = get_called_class();
|
||||||
throw new /*::*/MemberAccessException("Call to undefined static method $class::$name().");
|
throw new /*\*/MemberAccessException("Call to undefined static method $class::$name().");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -217,14 +216,14 @@ abstract class DibiObject
|
|||||||
* Returns property value. Do not call directly.
|
* Returns property value. Do not call directly.
|
||||||
* @param string property name
|
* @param string property name
|
||||||
* @return mixed property value
|
* @return mixed property value
|
||||||
* @throws ::MemberAccessException if the property is not defined.
|
* @throws \MemberAccessException if the property is not defined.
|
||||||
*/
|
*/
|
||||||
public function &__get($name)
|
public function &__get($name)
|
||||||
{
|
{
|
||||||
$class = get_class($this);
|
$class = get_class($this);
|
||||||
|
|
||||||
if ($name === '') {
|
if ($name === '') {
|
||||||
throw new /*::*/MemberAccessException("Cannot read an class '$class' property without name.");
|
throw new /*\*/MemberAccessException("Cannot read a class '$class' property without name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// property getter support
|
// property getter support
|
||||||
@@ -232,7 +231,7 @@ abstract class DibiObject
|
|||||||
$m = 'get' . $name;
|
$m = 'get' . $name;
|
||||||
if (self::hasAccessor($class, $m)) {
|
if (self::hasAccessor($class, $m)) {
|
||||||
// ampersands:
|
// ampersands:
|
||||||
// - uses &__get() because declaration should be forward compatible (e.g. with Nette::Web::Html)
|
// - uses &__get() because declaration should be forward compatible (e.g. with Nette\Web\Html)
|
||||||
// - doesn't call &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
|
// - doesn't call &$this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
|
||||||
$val = $this->$m();
|
$val = $this->$m();
|
||||||
return $val;
|
return $val;
|
||||||
@@ -245,7 +244,7 @@ abstract class DibiObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
$name = func_get_arg(0);
|
$name = func_get_arg(0);
|
||||||
throw new /*::*/MemberAccessException("Cannot read an undeclared property $class::\$$name.");
|
throw new /*\*/MemberAccessException("Cannot read an undeclared property $class::\$$name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -255,14 +254,14 @@ abstract class DibiObject
|
|||||||
* @param string property name
|
* @param string property name
|
||||||
* @param mixed property value
|
* @param mixed property value
|
||||||
* @return void
|
* @return void
|
||||||
* @throws ::MemberAccessException if the property is not defined or is read-only
|
* @throws \MemberAccessException if the property is not defined or is read-only
|
||||||
*/
|
*/
|
||||||
public function __set($name, $value)
|
public function __set($name, $value)
|
||||||
{
|
{
|
||||||
$class = get_class($this);
|
$class = get_class($this);
|
||||||
|
|
||||||
if ($name === '') {
|
if ($name === '') {
|
||||||
throw new /*::*/MemberAccessException("Cannot assign to an class '$class' property without name.");
|
throw new /*\*/MemberAccessException("Cannot assign to a class '$class' property without name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// property setter support
|
// property setter support
|
||||||
@@ -275,12 +274,12 @@ abstract class DibiObject
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
$name = func_get_arg(0);
|
$name = func_get_arg(0);
|
||||||
throw new /*::*/MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
|
throw new /*\*/MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$name = func_get_arg(0);
|
$name = func_get_arg(0);
|
||||||
throw new /*::*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
|
throw new /*\*/MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -302,12 +301,12 @@ abstract class DibiObject
|
|||||||
* Access to undeclared property.
|
* Access to undeclared property.
|
||||||
* @param string property name
|
* @param string property name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws ::MemberAccessException
|
* @throws \MemberAccessException
|
||||||
*/
|
*/
|
||||||
public function __unset($name)
|
public function __unset($name)
|
||||||
{
|
{
|
||||||
$class = get_class($this);
|
$class = get_class($this);
|
||||||
throw new /*::*/MemberAccessException("Cannot unset an property $class::\$$name.");
|
throw new /*\*/MemberAccessException("Cannot unset the property $class::\$$name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,16 +23,22 @@
|
|||||||
* dibi basic logger & profiler (experimental).
|
* dibi basic logger & profiler (experimental).
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiProfiler extends DibiObject implements IDibiProfiler
|
class DibiProfiler extends DibiObject implements IDibiProfiler
|
||||||
{
|
{
|
||||||
|
/** maximum number of rows */
|
||||||
|
const FIREBUG_MAX_ROWS = 30;
|
||||||
|
|
||||||
|
/** maximum SQL length */
|
||||||
|
const FIREBUG_MAX_LENGTH = 500;
|
||||||
|
|
||||||
/** @var string Name of the file where SQL errors should be logged */
|
/** @var string Name of the file where SQL errors should be logged */
|
||||||
private $file;
|
private $file;
|
||||||
|
|
||||||
/** @var bool log to firebug? */
|
/** @var bool log to firebug? */
|
||||||
private $useFirebug;
|
public $useFirebug;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
private $filter = self::ALL;
|
private $filter = self::ALL;
|
||||||
@@ -55,22 +60,24 @@ class DibiProfiler extends DibiObject implements IDibiProfiler
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string filename
|
* @param string filename
|
||||||
* @return void
|
* @return DibiProfiler provides a fluent interface
|
||||||
*/
|
*/
|
||||||
public function setFile($file)
|
public function setFile($file)
|
||||||
{
|
{
|
||||||
$this->file = $file;
|
$this->file = $file;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int
|
* @param int
|
||||||
* @return void
|
* @return DibiProfiler provides a fluent interface
|
||||||
*/
|
*/
|
||||||
public function setFilter($filter)
|
public function setFilter($filter)
|
||||||
{
|
{
|
||||||
$this->filter = (int) $filter;
|
$this->filter = (int) $filter;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -104,17 +111,26 @@ class DibiProfiler extends DibiObject implements IDibiProfiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
list($connection, $event, $sql) = $this->tickets[$ticket];
|
list($connection, $event, $sql) = $this->tickets[$ticket];
|
||||||
|
$sql = trim($sql);
|
||||||
|
|
||||||
if (($event & $this->filter) === 0) return;
|
if (($event & $this->filter) === 0) return;
|
||||||
|
|
||||||
if ($event & self::QUERY) {
|
if ($event & self::QUERY) {
|
||||||
if ($this->useFirebug) {
|
try {
|
||||||
self::$table[] = array(
|
$count = $res instanceof DibiResult ? count($res) : '-';
|
||||||
sprintf('%0.3f', dibi::$elapsedTime * 1000),
|
} catch (Exception $e) {
|
||||||
trim($sql),
|
$count = '?';
|
||||||
$res instanceof DibiResult ? count($res) : '-',
|
}
|
||||||
$connection->getConfig('driver') . '/' . $connection->getConfig('name')
|
|
||||||
);
|
if ($this->useFirebug && !headers_sent()) {
|
||||||
|
if (count(self::$table) < self::FIREBUG_MAX_ROWS) {
|
||||||
|
self::$table[] = array(
|
||||||
|
sprintf('%0.3f', dibi::$elapsedTime * 1000),
|
||||||
|
strlen($sql) > self::FIREBUG_MAX_LENGTH ? substr($sql, 0, self::FIREBUG_MAX_LENGTH) . '...' : $sql,
|
||||||
|
$count,
|
||||||
|
$connection->getConfig('driver') . '/' . $connection->getConfig('name')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
header('X-Wf-Protocol-dibi: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
|
header('X-Wf-Protocol-dibi: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
|
||||||
header('X-Wf-dibi-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');
|
header('X-Wf-dibi-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');
|
||||||
@@ -133,13 +149,12 @@ class DibiProfiler extends DibiObject implements IDibiProfiler
|
|||||||
header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index
|
header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index
|
||||||
}
|
}
|
||||||
header("X-Wf-dibi-1-1-d$num: |$s|");
|
header("X-Wf-dibi-1-1-d$num: |$s|");
|
||||||
header("X-Wf-dibi-Index: d$num");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file) {
|
if ($this->file) {
|
||||||
$this->writeFile(
|
$this->writeFile(
|
||||||
"OK: " . $sql
|
"OK: " . $sql
|
||||||
. ($res instanceof DibiResult ? ";\n-- rows: " . count($res) : '')
|
. ($res instanceof DibiResult ? ";\n-- rows: " . $count : '')
|
||||||
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
|
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
|
||||||
. "\n-- driver: " . $connection->getConfig('driver') . '/' . $connection->getConfig('name')
|
. "\n-- driver: " . $connection->getConfig('driver') . '/' . $connection->getConfig('name')
|
||||||
. "\n-- " . date('Y-m-d H:i:s')
|
. "\n-- " . date('Y-m-d H:i:s')
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@
|
|||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
class DibiResult extends DibiObject implements IDataSource
|
class DibiResult extends DibiObject implements IDataSource
|
||||||
@@ -48,7 +47,7 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
/** @var array Translate table */
|
/** @var array Translate table */
|
||||||
private $xlat;
|
private $xlat;
|
||||||
|
|
||||||
/** @var array Cache for $driver->getColumnsMeta() */
|
/** @var DibiResultInfo */
|
||||||
private $meta;
|
private $meta;
|
||||||
|
|
||||||
/** @var bool Already fetched? Used for allowance for first seek(0) */
|
/** @var bool Already fetched? Used for allowance for first seek(0) */
|
||||||
@@ -57,6 +56,9 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
/** @var array|FALSE Qualifiy each column name with the table name? */
|
/** @var array|FALSE Qualifiy each column name with the table name? */
|
||||||
private $withTables = FALSE;
|
private $withTables = FALSE;
|
||||||
|
|
||||||
|
/** @var string returned object class */
|
||||||
|
private $class = 'DibiRow';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,17 +76,6 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Automatically frees the resources allocated for this result set.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
@$this->free(); // intentionally @
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the result set resource.
|
* Returns the result set resource.
|
||||||
* @return mixed
|
* @return mixed
|
||||||
@@ -96,6 +87,40 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the resources allocated for this result set.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
final public function free()
|
||||||
|
{
|
||||||
|
if ($this->driver !== NULL) {
|
||||||
|
$this->driver->free();
|
||||||
|
$this->driver = $this->meta = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safe access to property $driver.
|
||||||
|
* @return IDibiDriver
|
||||||
|
* @throws InvalidStateException
|
||||||
|
*/
|
||||||
|
private function getDriver()
|
||||||
|
{
|
||||||
|
if ($this->driver === NULL) {
|
||||||
|
throw new InvalidStateException('Result-set was released from memory.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* rows ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
* @param int the 0-based cursor pos to seek to
|
* @param int the 0-based cursor pos to seek to
|
||||||
@@ -109,66 +134,76 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required by the Countable interface.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
final public function count()
|
||||||
|
{
|
||||||
|
return $this->getDriver()->getRowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
|
final public function getRowCount()
|
||||||
|
{
|
||||||
|
return $this->getDriver()->getRowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of rows in a result set. Alias for getRowCount().
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
final public function rowCount()
|
final public function rowCount()
|
||||||
{
|
{
|
||||||
return $this->getDriver()->rowCount();
|
return $this->getDriver()->getRowCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the resources allocated for this result set.
|
* Required by the IteratorAggregate interface.
|
||||||
* @return void
|
* @param int offset
|
||||||
|
* @param int limit
|
||||||
|
* @return DibiResultIterator
|
||||||
*/
|
*/
|
||||||
final public function free()
|
final public function getIterator($offset = NULL, $limit = NULL)
|
||||||
{
|
{
|
||||||
if ($this->driver !== NULL) {
|
return new DibiResultIterator($this, $offset, $limit);
|
||||||
$this->driver->free();
|
}
|
||||||
$this->driver = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/********************* fetching rows ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set fetched object class. This class should extend the DibiRow class.
|
||||||
|
* @param string
|
||||||
|
* @return DibiResult provides a fluent interface
|
||||||
|
*/
|
||||||
|
public function setRowClass($class)
|
||||||
|
{
|
||||||
|
$this->class = $class;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Qualifiy each column name with the table name?
|
* Returns fetched object class name.
|
||||||
* @param bool
|
* @return string
|
||||||
* @return void
|
|
||||||
* @throws DibiException
|
|
||||||
*/
|
*/
|
||||||
final public function setWithTables($val)
|
public function getRowClass()
|
||||||
{
|
{
|
||||||
if ($val) {
|
return $this->class;
|
||||||
$cols = array();
|
|
||||||
foreach ($this->getMeta() as $info) {
|
|
||||||
$name = $info['fullname'];
|
|
||||||
if (isset($cols[$name])) {
|
|
||||||
$fix = 1;
|
|
||||||
while (isset($cols[$name . '#' . $fix])) $fix++;
|
|
||||||
$name .= '#' . $fix;
|
|
||||||
}
|
|
||||||
$cols[$name] = TRUE;
|
|
||||||
}
|
|
||||||
$this->withTables = array_keys($cols);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$this->withTables = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Qualifiy each key with the table name?
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
final public function getWithTables()
|
|
||||||
{
|
|
||||||
return (bool) $this->withTables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -201,7 +236,7 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DibiRow($row, 2);
|
return new $this->class($row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -401,16 +436,61 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* meta info ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Qualifiy each column name with the table name?
|
||||||
|
* @param bool
|
||||||
|
* @return DibiResult provides a fluent interface
|
||||||
|
* @throws DibiException
|
||||||
|
*/
|
||||||
|
final public function setWithTables($val)
|
||||||
|
{
|
||||||
|
if ($val) {
|
||||||
|
$cols = array();
|
||||||
|
foreach ($this->getInfo()->getColumns() as $col) {
|
||||||
|
$name = $col->getFullname();
|
||||||
|
if (isset($cols[$name])) {
|
||||||
|
$fix = 1;
|
||||||
|
while (isset($cols[$name . '#' . $fix])) $fix++;
|
||||||
|
$name .= '#' . $fix;
|
||||||
|
}
|
||||||
|
$cols[$name] = TRUE;
|
||||||
|
}
|
||||||
|
$this->withTables = array_keys($cols);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$this->withTables = FALSE;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Qualifiy each key with the table name?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
final public function getWithTables()
|
||||||
|
{
|
||||||
|
return (bool) $this->withTables;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define column type.
|
* Define column type.
|
||||||
* @param string column
|
* @param string column
|
||||||
* @param string type (use constant Dibi::FIELD_*)
|
* @param string type (use constant Dibi::*)
|
||||||
* @param string optional format
|
* @param string optional format
|
||||||
* @return void
|
* @return DibiResult provides a fluent interface
|
||||||
*/
|
*/
|
||||||
final public function setType($col, $type, $format = NULL)
|
final public function setType($col, $type, $format = NULL)
|
||||||
{
|
{
|
||||||
$this->xlat[$col] = array('type' => $type, 'format' => $format);
|
$this->xlat[$col] = array('type' => $type, 'format' => $format);
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -421,8 +501,8 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
*/
|
*/
|
||||||
final public function detectTypes()
|
final public function detectTypes()
|
||||||
{
|
{
|
||||||
foreach ($this->getMeta() as $info) {
|
foreach ($this->getInfo()->getColumns() as $col) {
|
||||||
$this->xlat[$info['name']] = array('type' => $info['type'], 'format' => NULL);
|
$this->xlat[$col->getName()] = array('type' => $col->getType(), 'format' => NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,13 +510,14 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Define multiple columns types.
|
* Define multiple columns types.
|
||||||
* @param array
|
* @param array
|
||||||
* @return void
|
* @return DibiResult provides a fluent interface
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
final public function setTypes(array $types)
|
final public function setTypes(array $types)
|
||||||
{
|
{
|
||||||
$this->xlat = $types;
|
$this->xlat = $types;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -453,34 +534,54 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts value to specified type and format
|
* Converts value to specified type and format.
|
||||||
* @return array ($type, $format)
|
* @param mixed value
|
||||||
|
* @param int type
|
||||||
|
* @param string format
|
||||||
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
final public function convert($value, $type, $format = NULL)
|
final public function convert($value, $type, $format = NULL)
|
||||||
{
|
{
|
||||||
if ($value === NULL || $value === FALSE) {
|
if ($value === NULL || $value === FALSE) {
|
||||||
return $value;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case dibi::FIELD_TEXT:
|
case dibi::TEXT:
|
||||||
return (string) $value;
|
return (string) $value;
|
||||||
|
|
||||||
case dibi::FIELD_BINARY:
|
case dibi::BINARY:
|
||||||
return $this->getDriver()->unescape($value, $type);
|
return $this->getDriver()->unescape($value, $type);
|
||||||
|
|
||||||
case dibi::FIELD_INTEGER:
|
case dibi::INTEGER:
|
||||||
return (int) $value;
|
return (int) $value;
|
||||||
|
|
||||||
case dibi::FIELD_FLOAT:
|
case dibi::FLOAT:
|
||||||
return (float) $value;
|
return (float) $value;
|
||||||
|
|
||||||
case dibi::FIELD_DATE:
|
case dibi::DATE:
|
||||||
case dibi::FIELD_DATETIME:
|
case dibi::DATETIME:
|
||||||
$value = strtotime($value);
|
if ($value == NULL) { // intentionally ==
|
||||||
return $format === NULL ? $value : date($format, $value);
|
return NULL;
|
||||||
|
|
||||||
case dibi::FIELD_BOOL:
|
} elseif ($format === NULL) { // return timestamp (default)
|
||||||
|
return is_numeric($value) ? (int) $value : strtotime($value);
|
||||||
|
|
||||||
|
} elseif ($format === TRUE) { // return DateTime object
|
||||||
|
return new DateTime(is_numeric($value) ? date('Y-m-d H:i:s', $value) : $value);
|
||||||
|
|
||||||
|
} elseif (is_numeric($value)) { // single timestamp
|
||||||
|
return date($format, $value);
|
||||||
|
|
||||||
|
} elseif (class_exists('DateTime', FALSE)) { // since PHP 5.2
|
||||||
|
$value = new DateTime($value);
|
||||||
|
return $value ? $value->format($format) : NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return date($format, strtotime($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
case dibi::BOOL:
|
||||||
return ((bool) $value) && $value !== 'f' && $value !== 'F';
|
return ((bool) $value) && $value !== 'f' && $value !== 'F';
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -491,35 +592,43 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an array of meta informations about columns.
|
* Returns a meta information about the current result set.
|
||||||
* @return array of DibiColumnInfo
|
* @return DibiResultInfo
|
||||||
*/
|
*/
|
||||||
final public function getColumns()
|
public function getInfo()
|
||||||
{
|
{
|
||||||
$cols = array();
|
if ($this->meta === NULL) {
|
||||||
foreach ($this->getMeta() as $info) {
|
$this->meta = new DibiResultInfo($this->getDriver());
|
||||||
$cols[] = new DibiColumnInfo($this->driver, $info);
|
|
||||||
}
|
}
|
||||||
return $cols;
|
return $this->meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool
|
* @deprecated
|
||||||
* @return array of string
|
|
||||||
*/
|
*/
|
||||||
public function getColumnNames($withTables = FALSE)
|
final public function getColumns()
|
||||||
{
|
{
|
||||||
$cols = array();
|
return $this->getInfo()->getColumns();
|
||||||
foreach ($this->getMeta() as $info) {
|
|
||||||
$cols[] = $info[$withTables ? 'fullname' : 'name'];
|
|
||||||
}
|
|
||||||
return $cols;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public function getColumnNames($fullNames = FALSE)
|
||||||
|
{
|
||||||
|
return $this->getInfo()->getColumnNames($fullNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************* misc tools ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays complete result-set as HTML table for debug purposes.
|
* Displays complete result-set as HTML table for debug purposes.
|
||||||
* @return void
|
* @return void
|
||||||
@@ -555,75 +664,4 @@ class DibiResult extends DibiObject implements IDataSource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Required by the IteratorAggregate interface.
|
|
||||||
* @param int offset
|
|
||||||
* @param int limit
|
|
||||||
* @return ArrayIterator
|
|
||||||
*/
|
|
||||||
final public function getIterator($offset = NULL, $limit = NULL)
|
|
||||||
{
|
|
||||||
return new ArrayIterator($this->fetchAll($offset, $limit));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Required by the Countable interface.
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
final public function count()
|
|
||||||
{
|
|
||||||
return $this->rowCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safe access to property $driver.
|
|
||||||
* @return IDibiDriver
|
|
||||||
* @throws InvalidStateException
|
|
||||||
*/
|
|
||||||
private function getDriver()
|
|
||||||
{
|
|
||||||
if ($this->driver === NULL) {
|
|
||||||
throw new InvalidStateException('Resultset was released from memory.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Meta lazy initialization.
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getMeta()
|
|
||||||
{
|
|
||||||
if ($this->meta === NULL) {
|
|
||||||
$this->meta = $this->getDriver()->getColumnsMeta();
|
|
||||||
foreach ($this->meta as & $row) {
|
|
||||||
$row['type'] = DibiColumnInfo::detectType($row['nativetype']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dibi result-set row
|
|
||||||
*
|
|
||||||
* @author David Grudl
|
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
|
||||||
* @package dibi
|
|
||||||
*/
|
|
||||||
class DibiRow extends ArrayObject
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
145
dibi/libs/DibiResultIterator.php
Normal file
145
dibi/libs/DibiResultIterator.php
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
|
* ----------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2009 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, 2009 David Grudl
|
||||||
|
* @license http://dibiphp.com/license dibi license
|
||||||
|
* @link http://dibiphp.com
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External result set iterator.
|
||||||
|
*
|
||||||
|
* This can be returned by DibiResult::getIterator() method or using foreach
|
||||||
|
* <code>
|
||||||
|
* $result = dibi::query('SELECT * FROM table');
|
||||||
|
* foreach ($result as $row) {
|
||||||
|
* print_r($row);
|
||||||
|
* }
|
||||||
|
* unset($result);
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* Optionally you can specify offset and limit:
|
||||||
|
* <code>
|
||||||
|
* foreach ($result->getIterator(2, 3) as $row) {
|
||||||
|
* print_r($row);
|
||||||
|
* }
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @author David Grudl
|
||||||
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiResultIterator implements Iterator, Countable
|
||||||
|
{
|
||||||
|
/** @var DibiResult */
|
||||||
|
private $result;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $offset;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $limit;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $row;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $pointer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DibiResult
|
||||||
|
* @param int offset
|
||||||
|
* @param int limit
|
||||||
|
*/
|
||||||
|
public function __construct(DibiResult $result, $offset = NULL, $limit = NULL)
|
||||||
|
{
|
||||||
|
$this->result = $result;
|
||||||
|
$this->offset = (int) $offset;
|
||||||
|
$this->limit = $limit === NULL ? -1 : (int) $limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewinds the iterator to the first element.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
$this->pointer = 0;
|
||||||
|
$this->result->seek($this->offset);
|
||||||
|
$this->row = $this->result->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key of the current element.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
return $this->pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current element.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return $this->row;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves forward to next element.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
//$this->result->seek($this->offset + $this->pointer + 1);
|
||||||
|
$this->row = $this->result->fetch();
|
||||||
|
$this->pointer++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there is a current element after calls to rewind() or next().
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required by the Countable interface.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return $this->result->getRowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
101
dibi/libs/DibiRow.php
Normal file
101
dibi/libs/DibiRow.php
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
|
* ----------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2009 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, 2009 David Grudl
|
||||||
|
* @license http://dibiphp.com/license dibi license
|
||||||
|
* @link http://dibiphp.com
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result-set single row.
|
||||||
|
*
|
||||||
|
* @author David Grudl
|
||||||
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
|
* @package dibi
|
||||||
|
*/
|
||||||
|
class DibiRow extends ArrayObject
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array
|
||||||
|
*/
|
||||||
|
public function __construct($arr)
|
||||||
|
{
|
||||||
|
parent::__construct($arr, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts value to date-time format.
|
||||||
|
* @param string key
|
||||||
|
* @param string format (TRUE means DateTime object)
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function asDate($key, $format = NULL)
|
||||||
|
{
|
||||||
|
$time = $this[$key];
|
||||||
|
if ($time == NULL) { // intentionally ==
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
} elseif ($format === NULL) { // return timestamp (default)
|
||||||
|
return is_numeric($time) ? (int) $time : strtotime($time);
|
||||||
|
|
||||||
|
} elseif ($format === TRUE) { // return DateTime object
|
||||||
|
return new DateTime(is_numeric($time) ? date('Y-m-d H:i:s', $time) : $time);
|
||||||
|
|
||||||
|
} elseif (is_numeric($time)) { // single timestamp
|
||||||
|
return date($format, $time);
|
||||||
|
|
||||||
|
} elseif (class_exists('DateTime', FALSE)) { // since PHP 5.2
|
||||||
|
$time = new DateTime($time);
|
||||||
|
return $time ? $time->format($format) : NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return date($format, strtotime($time));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts value to boolean.
|
||||||
|
* @param string key
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function asBool($key)
|
||||||
|
{
|
||||||
|
$value = $this[$key];
|
||||||
|
if ($value === NULL || $value === FALSE) {
|
||||||
|
return $value;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return ((bool) $value) && $value !== 'f' && $value !== 'F';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHP < 5.3 workaround
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __wakeup()
|
||||||
|
{
|
||||||
|
$this->setFlags(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,420 +0,0 @@
|
|||||||
<?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 DibiTableX extends DibiObject
|
|
||||||
{
|
|
||||||
/** @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 bool primary key is auto increment */
|
|
||||||
protected $primaryAutoIncrement = TRUE;
|
|
||||||
|
|
||||||
/** @var array */
|
|
||||||
protected $blankRow = array();
|
|
||||||
|
|
||||||
/** @var mixed; TRUE means autodetect, or array of pairs [type, format] */
|
|
||||||
protected $types = 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************* basic commands ****************d*g**/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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->primaryAutoIncrement ? $this->connection->insertId() : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
$data = $this->prepare($data);
|
|
||||||
if ($where === NULL && isset($data[$this->primary])) {;
|
|
||||||
$where = $data[$this->primary];
|
|
||||||
unset($data[$this->primary]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->connection->query(
|
|
||||||
'UPDATE %n', $this->name,
|
|
||||||
'SET %a', $data,
|
|
||||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
|
||||||
);
|
|
||||||
return $this->connection->affectedRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts or updates rows in a table.
|
|
||||||
* @param array|object
|
|
||||||
* @return int (new) primary key
|
|
||||||
*/
|
|
||||||
public function insertOrUpdate($data)
|
|
||||||
{
|
|
||||||
$data = $this->prepare($data);
|
|
||||||
if (!isset($data[$this->primary])) {
|
|
||||||
throw new InvalidArgumentException("Missing primary key '$this->primary' in dataset.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->connection->query(
|
|
||||||
'INSERT INTO %n', $this->name, '%v', $data
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (DibiDriverException $e) {
|
|
||||||
$where = $data[$this->primary];
|
|
||||||
unset($data[$this->primary]);
|
|
||||||
$this->connection->query(
|
|
||||||
'UPDATE %n', $this->name,
|
|
||||||
'SET %a', $data,
|
|
||||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 array conditions
|
|
||||||
* @param string|array column to order by
|
|
||||||
* @return DibiResult
|
|
||||||
*/
|
|
||||||
public function findAll($conditions = NULL, $order = NULL)
|
|
||||||
{
|
|
||||||
if (!is_array($order)) {
|
|
||||||
$order = func_get_args();
|
|
||||||
if (is_array($conditions)) {
|
|
||||||
array_shift($order);
|
|
||||||
} else {
|
|
||||||
$conditions = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->complete($this->connection->query(
|
|
||||||
'SELECT * FROM %n', $this->name,
|
|
||||||
'%ex', $conditions ? array('WHERE %and', $conditions) : NULL,
|
|
||||||
'%ex', $order ? array('ORDER BY %by', $order) : NULL
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches single row.
|
|
||||||
* @param scalar|array primary key value
|
|
||||||
* @return DibiRow
|
|
||||||
*/
|
|
||||||
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 DibiRow
|
|
||||||
*/
|
|
||||||
public function createBlank()
|
|
||||||
{
|
|
||||||
$row = new DibiRow($this->blankRow, 2);
|
|
||||||
$row[$this->primary] = NULL;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (is_array($this->types)) {
|
|
||||||
$res->setTypes($this->types);
|
|
||||||
|
|
||||||
} elseif ($this->types === TRUE) {
|
|
||||||
$res->detectTypes();
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************* fluent SQL builders ****************d*g**/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates fluent SQL builder.
|
|
||||||
* @return DibiFluent
|
|
||||||
*/
|
|
||||||
public function command()
|
|
||||||
{
|
|
||||||
return new DibiFluent($this->connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string column name
|
|
||||||
* @return DibiFluent
|
|
||||||
*/
|
|
||||||
public function select($args)
|
|
||||||
{
|
|
||||||
$args = func_get_args();
|
|
||||||
return $this->command()->__call('select', $args)->from($this->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************* magic fetching ****************d*g**/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Magic fetch.
|
|
||||||
* - $row = $model->fetchByUrl('about-us');
|
|
||||||
* - $arr = $model->fetchAllByCategoryIdAndVisibility(5, TRUE);
|
|
||||||
*
|
|
||||||
* @param string
|
|
||||||
* @param array
|
|
||||||
* @return DibiRow|array
|
|
||||||
*/
|
|
||||||
public function __call($name, $args)
|
|
||||||
{
|
|
||||||
if (strncmp($name, 'fetchBy', 7) === 0) { // single row
|
|
||||||
$single = TRUE;
|
|
||||||
$name = substr($name, 7);
|
|
||||||
|
|
||||||
} elseif (strncmp($name, 'fetchAllBy', 10) === 0) { // multi row
|
|
||||||
$name = substr($name, 10);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
parent::__call($name, $args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProductIdAndTitle -> array('product', 'title')
|
|
||||||
$parts = explode('_and_', strtolower(preg_replace('#(.)(?=[A-Z])#', '$1_', $name)));
|
|
||||||
|
|
||||||
if (count($parts) !== count($args)) {
|
|
||||||
throw new InvalidArgumentException("Magic fetch expects " . count($parts) . " parameters, but " . count($args) . " was given.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($single)) {
|
|
||||||
return $this->complete($this->connection->query(
|
|
||||||
'SELECT * FROM %n', $this->name,
|
|
||||||
'WHERE %and', array_combine($parts, $args),
|
|
||||||
'LIMIT 1'
|
|
||||||
))->fetch();
|
|
||||||
} else {
|
|
||||||
return $this->complete($this->connection->query(
|
|
||||||
'SELECT * FROM %n', $this->name,
|
|
||||||
'WHERE %and', array_combine($parts, $args)
|
|
||||||
))->fetchAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
abstract class DibiTable extends DibiTableX
|
|
||||||
{
|
|
||||||
}
|
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -24,14 +23,11 @@
|
|||||||
* dibi SQL translator.
|
* dibi SQL translator.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
final class DibiTranslator extends DibiObject
|
final class DibiTranslator extends DibiObject
|
||||||
{
|
{
|
||||||
/** @var string */
|
|
||||||
public $sql;
|
|
||||||
|
|
||||||
/** @var IDibiDriver */
|
/** @var IDibiDriver */
|
||||||
private $driver;
|
private $driver;
|
||||||
|
|
||||||
@@ -81,7 +77,8 @@ final class DibiTranslator extends DibiObject
|
|||||||
/**
|
/**
|
||||||
* Generates SQL.
|
* Generates SQL.
|
||||||
* @param array
|
* @param array
|
||||||
* @return bool
|
* @return string
|
||||||
|
* @throws DibiException
|
||||||
*/
|
*/
|
||||||
public function translate(array $args)
|
public function translate(array $args)
|
||||||
{
|
{
|
||||||
@@ -111,7 +108,7 @@ final class DibiTranslator extends DibiObject
|
|||||||
// simple string means SQL
|
// simple string means SQL
|
||||||
if (is_string($arg)) {
|
if (is_string($arg)) {
|
||||||
// speed-up - is regexp required?
|
// speed-up - is regexp required?
|
||||||
$toSkip = strcspn($arg, '`[\'"%');
|
$toSkip = strcspn($arg, '`[\'":%');
|
||||||
|
|
||||||
if (strlen($arg) === $toSkip) { // needn't be translated
|
if (strlen($arg) === $toSkip) { // needn't be translated
|
||||||
$sql[] = $arg;
|
$sql[] = $arg;
|
||||||
@@ -119,17 +116,19 @@ final class DibiTranslator extends DibiObject
|
|||||||
$sql[] = substr($arg, 0, $toSkip)
|
$sql[] = substr($arg, 0, $toSkip)
|
||||||
/*
|
/*
|
||||||
preg_replace_callback('/
|
preg_replace_callback('/
|
||||||
(?=`|\[|\'|"|%) ## speed-up
|
(?=[`[\'":%?]) ## speed-up
|
||||||
(?:
|
(?:
|
||||||
`(.+?)`| ## 1) `identifier`
|
`(.+?)`| ## 1) `identifier`
|
||||||
\[(.+?)\]| ## 2) [identifier]
|
\[(.+?)\]| ## 2) [identifier]
|
||||||
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
|
(\')((?:\'\'|[^\'])*)\'| ## 3,4) 'string'
|
||||||
(")((?:""|[^"])*)"| ## 5,6) "string"
|
(")((?:""|[^"])*)"| ## 5,6) "string"
|
||||||
(\'|") ## 7) lone-quote
|
(\'|")| ## 7) lone quote
|
||||||
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
|
:(\S*?:)([a-zA-Z0-9._]?)| ## 8,9) substitution
|
||||||
|
%([a-zA-Z]{1,4})(?![a-zA-Z]) ## 10) modifier
|
||||||
|
(\?) ## 11) placeholder
|
||||||
)/xs',
|
)/xs',
|
||||||
*/ // note: this can change $this->args & $this->cursor & ...
|
*/ // note: this can change $this->args & $this->cursor & ...
|
||||||
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
|
. preg_replace_callback('/(?=[`[\'":%?])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?)|%([a-zA-Z]{1,4})(?![a-zA-Z])|(\?))/s',
|
||||||
array($this, 'cb'),
|
array($this, 'cb'),
|
||||||
substr($arg, $toSkip)
|
substr($arg, $toSkip)
|
||||||
);
|
);
|
||||||
@@ -143,6 +142,10 @@ final class DibiTranslator extends DibiObject
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($arg instanceof ArrayObject) {
|
||||||
|
$arg = (array) $arg;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_array($arg)) {
|
if (is_array($arg)) {
|
||||||
if (is_string(key($arg))) {
|
if (is_string(key($arg))) {
|
||||||
// associative array -> autoselect between SET or VALUES & LIST
|
// associative array -> autoselect between SET or VALUES & LIST
|
||||||
@@ -174,13 +177,16 @@ final class DibiTranslator extends DibiObject
|
|||||||
|
|
||||||
$sql = implode(' ', $sql);
|
$sql = implode(' ', $sql);
|
||||||
|
|
||||||
|
if ($this->hasError) {
|
||||||
|
throw new DibiException('SQL translate error', 0, $sql);
|
||||||
|
}
|
||||||
|
|
||||||
// apply limit
|
// apply limit
|
||||||
if ($this->limit > -1 || $this->offset > 0) {
|
if ($this->limit > -1 || $this->offset > 0) {
|
||||||
$this->driver->applyLimit($sql, $this->limit, $this->offset);
|
$this->driver->applyLimit($sql, $this->limit, $this->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sql = $sql;
|
return $sql;
|
||||||
return !$this->hasError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -194,58 +200,105 @@ final class DibiTranslator extends DibiObject
|
|||||||
public function formatValue($value, $modifier)
|
public function formatValue($value, $modifier)
|
||||||
{
|
{
|
||||||
// array processing (with or without modifier)
|
// array processing (with or without modifier)
|
||||||
if (is_array($value) || $value instanceof ArrayObject) {
|
if ($value instanceof ArrayObject) {
|
||||||
|
$value = (array) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
$vx = $kx = array();
|
$vx = $kx = array();
|
||||||
$operator = ', ';
|
|
||||||
switch ($modifier) {
|
switch ($modifier) {
|
||||||
case 'and':
|
case 'and':
|
||||||
case 'or': // key=val AND key IS NULL AND ...
|
case 'or': // key=val AND key IS NULL AND ...
|
||||||
$operator = ' ' . strtoupper($modifier) . ' ';
|
|
||||||
if (empty($value)) {
|
if (empty($value)) {
|
||||||
return '1';
|
return '1=1';
|
||||||
|
}
|
||||||
|
|
||||||
} elseif (!is_string(key($value))) {
|
foreach ($value as $k => $v) {
|
||||||
foreach ($value as $v) {
|
if (is_string($k)) {
|
||||||
$vx[] = $this->formatValue($v, 'sql');
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
foreach ($value as $k => $v) {
|
|
||||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
$k = $this->delimite($pair[0]);
|
$k = $this->delimite($pair[0]) . ' ';
|
||||||
$v = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
if (!isset($pair[1])) {
|
||||||
$op = isset($pair[1]) && $pair[1] === 'l' ? 'IN' : ($v === 'NULL' ? 'IS' : '=');
|
$v = $this->formatValue($v, FALSE);
|
||||||
$vx[] = $k . ' ' . $op . ' ' . $v;
|
$vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
|
||||||
|
|
||||||
|
} elseif ($pair[1] === 'ex') { // TODO: this will be removed
|
||||||
|
$vx[] = $k . $this->formatValue($v, 'ex');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$v = $this->formatValue($v, $pair[1]);
|
||||||
|
$vx[] = $k . ($pair[1] === 'l' ? 'IN ' : ($v === 'NULL' ? 'IS ' : '= ')) . $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$vx[] = $this->formatValue($v, 'ex');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return implode($operator, $vx);
|
return '(' . implode(') ' . strtoupper($modifier) . ' (', $vx) . ')';
|
||||||
|
|
||||||
|
case 'n': // key, key, ... identifier names
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
if (is_string($k)) {
|
||||||
|
$vx[] = $this->delimite($k) . (empty($v) ? '' : ' AS ' . $v);
|
||||||
|
} else {
|
||||||
|
$pair = explode('%', $v, 2); // split into identifier & modifier
|
||||||
|
$vx[] = $this->delimite($pair[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return implode(', ', $vx);
|
||||||
|
|
||||||
|
|
||||||
case 'a': // key=val, key=val, ...
|
case 'a': // key=val, key=val, ...
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
$vx[] = $this->delimite($pair[0]) . '='
|
$vx[] = $this->delimite($pair[0]) . '='
|
||||||
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
|
||||||
}
|
}
|
||||||
return implode($operator, $vx);
|
return implode(', ', $vx);
|
||||||
|
|
||||||
|
|
||||||
case 'l': // (val, val, ...)
|
case 'l': // (val, val, ...)
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
|
||||||
}
|
}
|
||||||
return '(' . implode(', ', $vx) . ')';
|
return '(' . ($vx ? implode(', ', $vx) : 'NULL') . ')';
|
||||||
|
|
||||||
|
|
||||||
case 'v': // (key, key, ...) VALUES (val, val, ...)
|
case 'v': // (key, key, ...) VALUES (val, val, ...)
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
$pair = explode('%', $k, 2); // split into identifier & modifier
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
$kx[] = $this->delimite($pair[0]);
|
$kx[] = $this->delimite($pair[0]);
|
||||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
|
||||||
}
|
}
|
||||||
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
|
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
|
||||||
|
|
||||||
|
case 'm': // (key, key, ...) VALUES (val, val, ...), (val, val, ...), ...
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
if (is_array($v)) {
|
||||||
|
if (isset($proto)) {
|
||||||
|
if ($proto !== array_keys($v)) {
|
||||||
|
$this->hasError = TRUE;
|
||||||
|
return '**Multi-insert array "' . $k . '" is different.**';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$proto = array_keys($v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->hasError = TRUE;
|
||||||
|
return '**Unexpected type ' . gettype($v) . '**';
|
||||||
|
}
|
||||||
|
|
||||||
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
|
$kx[] = $this->delimite($pair[0]);
|
||||||
|
foreach ($v as $k2 => $v2) {
|
||||||
|
$vx[$k2][] = $this->formatValue($v2, isset($pair[1]) ? $pair[1] : (is_array($v2) ? 'ex' : FALSE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($vx as $k => $v) {
|
||||||
|
$vx[$k] = '(' . ($v ? implode(', ', $v) : 'NULL') . ')';
|
||||||
|
}
|
||||||
|
return '(' . implode(', ', $kx) . ') VALUES ' . implode(', ', $vx);
|
||||||
|
|
||||||
case 'by': // key ASC, key DESC
|
case 'by': // key ASC, key DESC
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
if (is_string($k)) {
|
if (is_string($k)) {
|
||||||
@@ -257,26 +310,26 @@ final class DibiTranslator extends DibiObject
|
|||||||
}
|
}
|
||||||
return implode(', ', $vx);
|
return implode(', ', $vx);
|
||||||
|
|
||||||
|
case 'ex':
|
||||||
|
case 'sql':
|
||||||
|
$translator = new self($this->driver);
|
||||||
|
return $translator->translate($value);
|
||||||
|
|
||||||
default: // value, value, value - all with the same modifier
|
default: // value, value, value - all with the same modifier
|
||||||
foreach ($value as $v) {
|
foreach ($value as $v) {
|
||||||
$vx[] = $this->formatValue($v, $modifier);
|
$vx[] = $this->formatValue($v, $modifier);
|
||||||
}
|
}
|
||||||
return implode(', ', $vx);
|
return $vx ? implode(', ', $vx) : 'NULL';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// with modifier procession
|
// with modifier procession
|
||||||
if ($modifier) {
|
if ($modifier) {
|
||||||
if ($value === NULL) {
|
|
||||||
return 'NULL';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value instanceof IDibiVariable) {
|
if ($value instanceof IDibiVariable) {
|
||||||
return $value->toSql($this, $modifier);
|
return $value->toSql($this, $modifier);
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_scalar($value)) { // array is already processed
|
} elseif ($value !== NULL && !is_scalar($value) && !($value instanceof DateTime)) { // array is already processed
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return '**Unexpected type ' . gettype($value) . '**';
|
return '**Unexpected type ' . gettype($value) . '**';
|
||||||
}
|
}
|
||||||
@@ -285,48 +338,69 @@ final class DibiTranslator extends DibiObject
|
|||||||
case 's': // string
|
case 's': // string
|
||||||
case 'bin':// binary
|
case 'bin':// binary
|
||||||
case 'b': // boolean
|
case 'b': // boolean
|
||||||
return $this->driver->escape($value, $modifier);
|
return $value === NULL ? 'NULL' : $this->driver->escape($value, $modifier);
|
||||||
|
|
||||||
case 'sn': // string or NULL
|
case 'sn': // string or NULL
|
||||||
return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::FIELD_TEXT); // notice two equal signs
|
return $value == '' ? 'NULL' : $this->driver->escape($value, dibi::TEXT); // notice two equal signs
|
||||||
|
|
||||||
|
case 'in': // signed int or NULL
|
||||||
|
if ($value == '') $value = NULL;
|
||||||
|
// intentionally break omitted
|
||||||
|
|
||||||
case 'i': // signed int
|
case 'i': // signed int
|
||||||
case 'u': // unsigned int, ignored
|
case 'u': // unsigned int, ignored
|
||||||
// support for long numbers - keep them unchanged
|
// support for long numbers - keep them unchanged
|
||||||
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
|
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
|
||||||
return $value;
|
return $value;
|
||||||
|
} else {
|
||||||
|
return $value === NULL ? 'NULL' : (string) (int) ($value + 0);
|
||||||
}
|
}
|
||||||
return (string) (int) ($value + 0);
|
|
||||||
|
|
||||||
case 'f': // float
|
case 'f': // float
|
||||||
// support for extreme numbers - keep them unchanged
|
// support for extreme numbers - keep them unchanged
|
||||||
if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
|
if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
|
||||||
return $value; // something like -9E-005 is accepted by SQL, HEX values are not
|
return $value; // something like -9E-005 is accepted by SQL, HEX values are not
|
||||||
|
} else {
|
||||||
|
return $value === NULL ? 'NULL' : rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
|
||||||
}
|
}
|
||||||
return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
|
|
||||||
|
|
||||||
case 'd': // date
|
case 'd': // date
|
||||||
case 't': // datetime
|
case 't': // datetime
|
||||||
return $this->driver->escape(is_string($value) ? strtotime($value) : $value, $modifier);
|
if ($value === NULL) {
|
||||||
|
return 'NULL';
|
||||||
|
} else {
|
||||||
|
if (is_numeric($value)) {
|
||||||
|
$value = (int) $value; // timestamp
|
||||||
|
|
||||||
|
} elseif (is_string($value)) {
|
||||||
|
$value = class_exists('DateTime', FALSE) ? new DateTime($value) : strtotime($value);
|
||||||
|
}
|
||||||
|
return $this->driver->escape($value, $modifier);
|
||||||
|
}
|
||||||
|
|
||||||
case 'by':
|
case 'by':
|
||||||
case 'n': // identifier name
|
case 'n': // identifier name
|
||||||
return $this->delimite($value);
|
return $this->delimite($value);
|
||||||
|
|
||||||
case 'sql':// preserve as SQL
|
case 'ex':
|
||||||
|
case 'sql': // preserve as dibi-SQL (TODO: leave only %ex)
|
||||||
$value = (string) $value;
|
$value = (string) $value;
|
||||||
// speed-up - is regexp required?
|
// speed-up - is regexp required?
|
||||||
$toSkip = strcspn($value, '`[\'"');
|
$toSkip = strcspn($value, '`[\'":');
|
||||||
if (strlen($value) === $toSkip) { // needn't be translated
|
if (strlen($value) === $toSkip) { // needn't be translated
|
||||||
return $value;
|
return $value;
|
||||||
} else {
|
} else {
|
||||||
return substr($value, 0, $toSkip)
|
return substr($value, 0, $toSkip)
|
||||||
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
|
. preg_replace_callback(
|
||||||
array($this, 'cb'),
|
'/(?=[`[\'":])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?))/s',
|
||||||
substr($value, $toSkip)
|
array($this, 'cb'),
|
||||||
|
substr($value, $toSkip)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'SQL': // preserve as real SQL (TODO: rename to %sql)
|
||||||
|
return (string) $value;
|
||||||
|
|
||||||
case 'and':
|
case 'and':
|
||||||
case 'or':
|
case 'or':
|
||||||
case 'a':
|
case 'a':
|
||||||
@@ -344,13 +418,13 @@ final class DibiTranslator extends DibiObject
|
|||||||
|
|
||||||
// without modifier procession
|
// without modifier procession
|
||||||
if (is_string($value))
|
if (is_string($value))
|
||||||
return $this->driver->escape($value, dibi::FIELD_TEXT);
|
return $this->driver->escape($value, dibi::TEXT);
|
||||||
|
|
||||||
if (is_int($value) || is_float($value))
|
if (is_int($value) || is_float($value))
|
||||||
return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
|
return rtrim(rtrim(number_format($value, 5, '.', ''), '0'), '.');
|
||||||
|
|
||||||
if (is_bool($value))
|
if (is_bool($value))
|
||||||
return $this->driver->escape($value, dibi::FIELD_BOOL);
|
return $this->driver->escape($value, dibi::BOOL);
|
||||||
|
|
||||||
if ($value === NULL)
|
if ($value === NULL)
|
||||||
return 'NULL';
|
return 'NULL';
|
||||||
@@ -358,6 +432,9 @@ final class DibiTranslator extends DibiObject
|
|||||||
if ($value instanceof IDibiVariable)
|
if ($value instanceof IDibiVariable)
|
||||||
return $value->toSql($this, NULL);
|
return $value->toSql($this, NULL);
|
||||||
|
|
||||||
|
if ($value instanceof DateTime)
|
||||||
|
return $this->driver->escape($value, dibi::DATETIME);
|
||||||
|
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return '**Unexpected ' . gettype($value) . '**';
|
return '**Unexpected ' . gettype($value) . '**';
|
||||||
}
|
}
|
||||||
@@ -378,10 +455,26 @@ final class DibiTranslator extends DibiObject
|
|||||||
// [5] => "
|
// [5] => "
|
||||||
// [6] => string
|
// [6] => string
|
||||||
// [7] => lone-quote
|
// [7] => lone-quote
|
||||||
// [8] => modifier (when called from self::translate())
|
// [8] => substitution
|
||||||
|
// [9] => substitution flag
|
||||||
|
// [10] => modifier (when called from self::translate())
|
||||||
|
// [11] => placeholder (when called from self::translate())
|
||||||
|
|
||||||
if (!empty($matches[8])) { // modifier
|
|
||||||
$mod = $matches[8];
|
if (!empty($matches[11])) { // placeholder
|
||||||
|
$cursor = & $this->cursor;
|
||||||
|
|
||||||
|
if ($cursor >= count($this->args)) {
|
||||||
|
$this->hasError = TRUE;
|
||||||
|
return "**Extra placeholder**";
|
||||||
|
}
|
||||||
|
|
||||||
|
$cursor++;
|
||||||
|
return $this->formatValue($this->args[$cursor - 1], FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($matches[10])) { // modifier
|
||||||
|
$mod = $matches[10];
|
||||||
$cursor = & $this->cursor;
|
$cursor = & $this->cursor;
|
||||||
|
|
||||||
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
|
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
|
||||||
@@ -450,16 +543,22 @@ final class DibiTranslator extends DibiObject
|
|||||||
return $this->delimite($matches[2]);
|
return $this->delimite($matches[2]);
|
||||||
|
|
||||||
if ($matches[3]) // SQL strings: '...'
|
if ($matches[3]) // SQL strings: '...'
|
||||||
return $this->driver->escape( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
|
return $this->driver->escape( str_replace("''", "'", $matches[4]), dibi::TEXT);
|
||||||
|
|
||||||
if ($matches[5]) // SQL strings: "..."
|
if ($matches[5]) // SQL strings: "..."
|
||||||
return $this->driver->escape( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
|
return $this->driver->escape( str_replace('""', '"', $matches[6]), dibi::TEXT);
|
||||||
|
|
||||||
if ($matches[7]) { // string quote
|
if ($matches[7]) { // string quote
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return '**Alone quote**';
|
return '**Alone quote**';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($matches[8]) { // SQL identifier substitution
|
||||||
|
$m = substr($matches[8], 0, -1);
|
||||||
|
$m = isset(dibi::$substs[$m]) ? dibi::$substs[$m] : call_user_func(dibi::$substFallBack, $m);
|
||||||
|
return $matches[9] == '' ? $this->formatValue($m, FALSE) : $m . $matches[9]; // value or identifier
|
||||||
|
}
|
||||||
|
|
||||||
die('this should be never executed');
|
die('this should be never executed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,8 +571,27 @@ final class DibiTranslator extends DibiObject
|
|||||||
*/
|
*/
|
||||||
private function delimite($value)
|
private function delimite($value)
|
||||||
{
|
{
|
||||||
return $this->driver->escape(dibi::substitute($value), dibi::IDENTIFIER);
|
if ($value === '*') {
|
||||||
|
return '*';
|
||||||
|
|
||||||
|
} elseif (strpos($value, ':') !== FALSE) { // provide substitution
|
||||||
|
$value = preg_replace_callback('#:(.*):#U', array(__CLASS__, 'subCb'), $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->driver->escape($value, dibi::IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // class DibiTranslator
|
|
||||||
|
/**
|
||||||
|
* Substitution callback.
|
||||||
|
* @param array
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function subCb($m)
|
||||||
|
{
|
||||||
|
$m = $m[1];
|
||||||
|
return isset(dibi::$substs[$m]) ? dibi::$substs[$m] : call_user_func(dibi::$substFallBack, $m);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
* dibi - tiny'n'smart database abstraction layer
|
* dibi - tiny'n'smart database abstraction layer
|
||||||
* ----------------------------------------------
|
* ----------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005, 2008 David Grudl (http://davidgrudl.com)
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
||||||
*
|
*
|
||||||
* This source file is subject to the "dibi license" that is bundled
|
* This source file is subject to the "dibi license" that is bundled
|
||||||
* with this package in the file license.txt.
|
* with this package in the file license.txt.
|
||||||
*
|
*
|
||||||
* For more information please see http://dibiphp.com
|
* For more information please see http://dibiphp.com
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @license http://dibiphp.com/license dibi license
|
* @license http://dibiphp.com/license dibi license
|
||||||
* @link http://dibiphp.com
|
* @link http://dibiphp.com
|
||||||
* @package dibi
|
* @package dibi
|
||||||
* @version $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +107,7 @@ interface IDibiProfiler
|
|||||||
* dibi driver interface.
|
* dibi driver interface.
|
||||||
*
|
*
|
||||||
* @author David Grudl
|
* @author David Grudl
|
||||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
||||||
* @package dibi
|
* @package dibi
|
||||||
*/
|
*/
|
||||||
interface IDibiDriver
|
interface IDibiDriver
|
||||||
@@ -122,8 +121,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function connect(array &$config);
|
function connect(array &$config);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects from a database.
|
* Disconnects from a database.
|
||||||
* @return void
|
* @return void
|
||||||
@@ -131,8 +128,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function disconnect();
|
function disconnect();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal: Executes the SQL query.
|
* Internal: Executes the SQL query.
|
||||||
* @param string SQL statement.
|
* @param string SQL statement.
|
||||||
@@ -141,50 +136,41 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function query($sql);
|
function query($sql);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
|
||||||
* @return int|FALSE number of rows or FALSE on error
|
* @return int|FALSE number of rows or FALSE on error
|
||||||
*/
|
*/
|
||||||
function affectedRows();
|
function getAffectedRows();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||||
* @return int|FALSE int on success or FALSE on failure
|
* @return int|FALSE int on success or FALSE on failure
|
||||||
*/
|
*/
|
||||||
function insertId($sequence);
|
function getInsertId($sequence);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins a transaction (if supported).
|
* Begins a transaction (if supported).
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
function begin();
|
function begin($savepoint = NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits statements in a transaction.
|
* Commits statements in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
function commit();
|
function commit($savepoint = NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback changes in a transaction.
|
* Rollback changes in a transaction.
|
||||||
|
* @param string optional savepoint name
|
||||||
* @return void
|
* @return void
|
||||||
* @throws DibiDriverException
|
* @throws DibiDriverException
|
||||||
*/
|
*/
|
||||||
function rollback();
|
function rollback($savepoint = NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the connection resource.
|
* Returns the connection resource.
|
||||||
@@ -199,27 +185,23 @@ interface IDibiDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes data for use in an SQL statement.
|
* Encodes data for use in a SQL statement.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, ...)
|
* @param string type (dibi::TEXT, dibi::BOOL, ...)
|
||||||
* @return string encoded value
|
* @return string encoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function escape($value, $type);
|
function escape($value, $type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes data from result set.
|
* Decodes data from result set.
|
||||||
* @param string value
|
* @param string value
|
||||||
* @param string type (dibi::FIELD_BINARY)
|
* @param string type (dibi::BINARY)
|
||||||
* @return string decoded value
|
* @return string decoded value
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function unescape($value, $type);
|
function unescape($value, $type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injects LIMIT/OFFSET to the SQL query.
|
* Injects LIMIT/OFFSET to the SQL query.
|
||||||
* @param string &$sql The SQL query that will be modified.
|
* @param string &$sql The SQL query that will be modified.
|
||||||
@@ -239,9 +221,7 @@ interface IDibiDriver
|
|||||||
* Returns the number of rows in a result set.
|
* Returns the number of rows in a result set.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
function rowCount();
|
function getRowCount();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves cursor position without fetching row.
|
* Moves cursor position without fetching row.
|
||||||
@@ -251,8 +231,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function seek($row);
|
function seek($row);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||||
* @param bool TRUE for associative array, FALSE for numeric
|
* @param bool TRUE for associative array, FALSE for numeric
|
||||||
@@ -261,8 +239,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function fetch($type);
|
function fetch($type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the resources allocated for this result set.
|
* Frees the resources allocated for this result set.
|
||||||
* @param resource result set resource
|
* @param resource result set resource
|
||||||
@@ -270,8 +246,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function free();
|
function free();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns metadata for all columns in a result set.
|
* Returns metadata for all columns in a result set.
|
||||||
* @return array
|
* @return array
|
||||||
@@ -279,8 +253,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function getColumnsMeta();
|
function getColumnsMeta();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the result set resource.
|
* Returns the result set resource.
|
||||||
* @return mixed
|
* @return mixed
|
||||||
@@ -299,8 +271,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function getTables();
|
function getTables();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns metadata for all columns in a table.
|
* Returns metadata for all columns in a table.
|
||||||
* @param string
|
* @param string
|
||||||
@@ -308,8 +278,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function getColumns($table);
|
function getColumns($table);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns metadata for all indexes in a table.
|
* Returns metadata for all indexes in a table.
|
||||||
* @param string
|
* @param string
|
||||||
@@ -317,8 +285,6 @@ interface IDibiDriver
|
|||||||
*/
|
*/
|
||||||
function getIndexes($table);
|
function getIndexes($table);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns metadata for all foreign keys in a table.
|
* Returns metadata for all foreign keys in a table.
|
||||||
* @param string
|
* @param string
|
||||||
|
3
examples/.gitignore
vendored
Normal file
3
examples/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
_test.bat
|
||||||
|
ref
|
||||||
|
output
|
File diff suppressed because it is too large
Load Diff
1
examples/Nette/netterobots.txt
Normal file
1
examples/Nette/netterobots.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Disallow: /
|
@@ -4,8 +4,6 @@
|
|||||||
require_once 'Nette/Debug.php';
|
require_once 'Nette/Debug.php';
|
||||||
require_once '../dibi/dibi.php';
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
|
|
||||||
// required since PHP 5.1.0
|
|
||||||
date_default_timezone_set('Europe/Prague');
|
date_default_timezone_set('Europe/Prague');
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,101 +0,0 @@
|
|||||||
<h1>DibiTableX demo</h1>
|
|
||||||
<pre>
|
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once 'Nette/Debug.php';
|
|
||||||
require_once '../dibi/dibi.php';
|
|
||||||
|
|
||||||
|
|
||||||
dibi::connect(array(
|
|
||||||
'driver' => 'sqlite',
|
|
||||||
'database' => 'sample.sdb',
|
|
||||||
));
|
|
||||||
|
|
||||||
dibi::begin();
|
|
||||||
|
|
||||||
|
|
||||||
// autodetection: primary keys are customer_id, order_id, ...
|
|
||||||
DibiTableX::$primaryMask = '%s_id';
|
|
||||||
|
|
||||||
|
|
||||||
// table products
|
|
||||||
class Products extends DibiTableX
|
|
||||||
{
|
|
||||||
// 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) {
|
|
||||||
Debug::dump($row);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// select all
|
|
||||||
$products->findAll()->dump();
|
|
||||||
|
|
||||||
|
|
||||||
// select all, order by title, product_id
|
|
||||||
$products->findAll('title', $products->primary)->dump();
|
|
||||||
$products->findAll(array('title' => 'Chair'), 'title')->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));
|
|
||||||
Debug::dump($count); // number of deleted rows
|
|
||||||
|
|
||||||
|
|
||||||
// update row #2 in a table
|
|
||||||
$data = (object) NULL;
|
|
||||||
$data->title = 'New title';
|
|
||||||
$count = $products->update(2, $data);
|
|
||||||
Debug::dump($count); // number of updated rows
|
|
||||||
|
|
||||||
|
|
||||||
// update multiple rows in a table
|
|
||||||
$count = $products->update(array(3, 5), $data);
|
|
||||||
Debug::dump($count); // number of updated rows
|
|
||||||
|
|
||||||
|
|
||||||
// inserts row into a table
|
|
||||||
$data = array();
|
|
||||||
$data['title'] = 'New product';
|
|
||||||
$id = $products->insert($data);
|
|
||||||
Debug::dump($id); // generated id
|
|
||||||
|
|
||||||
|
|
||||||
// inserts or updates row into a table
|
|
||||||
$data = array();
|
|
||||||
$data['title'] = 'New product';
|
|
||||||
$data[$products->primary] = 5;
|
|
||||||
$products->insertOrUpdate($data);
|
|
||||||
|
|
||||||
|
|
||||||
// is absolutely SQL injection safe
|
|
||||||
$key = '3 OR 1=1';
|
|
||||||
$products->delete($key);
|
|
||||||
// --> DELETE FROM [products] WHERE [product_id] IN ( 3 )
|
|
||||||
|
|
||||||
|
|
||||||
// select all using fluent interface
|
|
||||||
Debug::dump($products->select('*')->orderBy('title')->fetchAll());
|
|
@@ -4,6 +4,8 @@
|
|||||||
require_once 'Nette/Debug.php';
|
require_once 'Nette/Debug.php';
|
||||||
require_once '../dibi/dibi.php';
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
|
date_default_timezone_set('Europe/Prague');
|
||||||
|
|
||||||
|
|
||||||
dibi::connect(array(
|
dibi::connect(array(
|
||||||
'driver' => 'sqlite',
|
'driver' => 'sqlite',
|
||||||
|
@@ -4,6 +4,8 @@
|
|||||||
require_once 'Nette/Debug.php';
|
require_once 'Nette/Debug.php';
|
||||||
require_once '../dibi/dibi.php';
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
|
date_default_timezone_set('Europe/Prague');
|
||||||
|
|
||||||
|
|
||||||
dibi::connect(array(
|
dibi::connect(array(
|
||||||
'driver' => 'sqlite',
|
'driver' => 'sqlite',
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
require_once 'Nette/Debug.php';
|
require_once 'Nette/Debug.php';
|
||||||
require_once '../dibi/dibi.php';
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
|
date_default_timezone_set('Europe/Prague');
|
||||||
|
|
||||||
|
|
||||||
dibi::connect(array(
|
dibi::connect(array(
|
||||||
'driver' => 'sqlite',
|
'driver' => 'sqlite',
|
||||||
@@ -15,8 +17,8 @@ dibi::connect(array(
|
|||||||
$res = dibi::query('SELECT * FROM [customers]');
|
$res = dibi::query('SELECT * FROM [customers]');
|
||||||
|
|
||||||
// auto-converts this column to integer
|
// auto-converts this column to integer
|
||||||
$res->setType('customer_id', Dibi::FIELD_INTEGER);
|
$res->setType('customer_id', Dibi::INTEGER);
|
||||||
$res->setType('added', Dibi::FIELD_DATETIME, 'H:i j.n.Y');
|
$res->setType('added', Dibi::DATETIME, 'H:i j.n.Y');
|
||||||
|
|
||||||
$row = $res->fetch();
|
$row = $res->fetch();
|
||||||
Debug::dump($row);
|
Debug::dump($row);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<h1>Nette::Debug & dibi example</h1>
|
<h1>Nette\Debug & dibi example</h1>
|
||||||
|
|
||||||
|
|
||||||
<p>Dibi can display and log exceptions via Nette::Debug, part of Nette Framework.</p>
|
<p>Dibi can display and log exceptions via Nette\Debug, part of Nette Framework.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Nette Framework: http://nettephp.com
|
<li>Nette Framework: http://nettephp.com
|
||||||
@@ -13,7 +13,7 @@ require_once 'Nette/Debug.php';
|
|||||||
require_once '../dibi/dibi.php';
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
|
|
||||||
// enable Nette::Debug
|
// enable Nette\Debug
|
||||||
Debug::enable();
|
Debug::enable();
|
||||||
|
|
||||||
|
|
||||||
|
28
examples/nette-debug2.php
Normal file
28
examples/nette-debug2.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<h1>Nette\Debug & dibi example 2</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Dibi can dump variables via Nette\Debug, part of Nette Framework.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Nette Framework: http://nettephp.com
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'Nette/Debug.php';
|
||||||
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
|
|
||||||
|
// enable Nette\Debug
|
||||||
|
Debug::enable();
|
||||||
|
|
||||||
|
|
||||||
|
dibi::connect(array(
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'database' => 'sample.sdb',
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// throws error
|
||||||
|
Debug::consoleDump( dibi::fetchAll('SELECT * FROM [customers] WHERE [customer_id] < %i', 38), '[customers]' );
|
Binary file not shown.
Binary file not shown.
@@ -8,7 +8,6 @@ pre.dibi { padding-bottom: 10px; }
|
|||||||
require_once 'Nette/Debug.php';
|
require_once 'Nette/Debug.php';
|
||||||
require_once '../dibi/dibi.php';
|
require_once '../dibi/dibi.php';
|
||||||
|
|
||||||
// required since PHP 5.1.0
|
|
||||||
date_default_timezone_set('Europe/Prague');
|
date_default_timezone_set('Europe/Prague');
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,8 +16,8 @@ dibi::connect(array(
|
|||||||
// create new substitution :blog: ==> wp_
|
// create new substitution :blog: ==> wp_
|
||||||
dibi::addSubst('blog', 'wp_');
|
dibi::addSubst('blog', 'wp_');
|
||||||
|
|
||||||
dibi::test("UPDATE [:blog:items] SET [text]='Hello World'");
|
dibi::test("UPDATE :blog:items SET [text]='Hello World'");
|
||||||
// -> UPDATE [wp_items] SET [text]='Hello World'
|
// -> UPDATE wp_items SET [text]='Hello World'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -36,10 +36,14 @@ dibi::test("UPDATE [database.::table] SET [text]='Hello World'");
|
|||||||
// create substitution fallback
|
// create substitution fallback
|
||||||
function substFallBack($expr)
|
function substFallBack($expr)
|
||||||
{
|
{
|
||||||
return 'the_' . $expr;
|
if (defined($expr)) {
|
||||||
|
return constant($expr);
|
||||||
|
} else {
|
||||||
|
return 'the_' . $expr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dibi::setSubstFallBack('substFallBack');
|
dibi::setSubstFallBack('substFallBack');
|
||||||
|
|
||||||
dibi::test("UPDATE [:account:user] SET [name]='John Doe'");
|
dibi::test("UPDATE [:account:user] SET [name]='John Doe', [active]=:true:");
|
||||||
// -> UPDATE [the_accountuser] SET [name]='John Doe'
|
// -> UPDATE [the_accountuser] SET [name]='John Doe', [active]=1
|
@@ -1,4 +1,4 @@
|
|||||||
Dibi (c) David Grudl, 2005-2008 (http://davidgrudl.com)
|
Dibi (c) David Grudl, 2005-2009 (http://davidgrudl.com)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ http://dibiphp.com
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Dibi.compact
|
Dibi.minified
|
||||||
------------
|
-------------
|
||||||
|
|
||||||
This is shrinked single-file version of whole Dibi, useful when you don't
|
This is shrinked single-file version of whole Dibi, useful when you don't
|
||||||
want to modify library, but just use it.
|
want to modify library, but just use it.
|
||||||
|
@@ -1 +1 @@
|
|||||||
Dibi 1.0 (revision $WCREV$ released on $WCDATE$)
|
Dibi 1.2 (revision $WCREV$ released on $WCDATE$)
|
||||||
|
Reference in New Issue
Block a user