mirror of
https://github.com/dg/dibi.git
synced 2025-08-30 09:19:48 +02:00
Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
697ffcd44a | ||
|
4535bc5458 | ||
|
bf36cf96ee | ||
|
1912a15831 | ||
|
d4429546e2 | ||
|
a007ea95f9 | ||
|
247f38bb6b | ||
|
ed95fc2ddf | ||
|
2dcf08a90c | ||
|
204cb75bf0 | ||
|
8112fe10d0 | ||
|
6f99db544f | ||
|
c399d79ab8 | ||
|
67f8468a38 | ||
|
72944ae012 | ||
|
4843882e61 | ||
|
669ce73096 | ||
|
6e4a6474cd | ||
|
2dc30747e5 | ||
|
23531a0f3d | ||
|
22c6f2dfda | ||
|
f51ac0b67e | ||
|
43f5e08296 | ||
|
997f5a98f8 | ||
|
e4b3cfb12c | ||
|
26082294b6 | ||
|
b3052b4ce2 | ||
|
efa3a48232 | ||
|
24511a1d96 | ||
|
a20ba29b13 | ||
|
a606be0efa |
30
.travis.yml
30
.travis.yml
@@ -1,30 +0,0 @@
|
||||
language: php
|
||||
php:
|
||||
- 5.3.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
|
||||
script:
|
||||
- vendor/bin/tester tests -s -p php -c tests/php-unix.ini
|
||||
- php code-checker/src/code-checker.php
|
||||
|
||||
after_failure:
|
||||
# Print *.actual content
|
||||
- for i in $(find tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done
|
||||
|
||||
before_script:
|
||||
# Install Nette Tester & Code Checker
|
||||
- composer install --no-interaction --dev --prefer-source
|
||||
- composer create-project nette/code-checker code-checker ~2.3 --no-interaction --prefer-source
|
||||
|
||||
# Create databases.ini
|
||||
- cp ./tests/databases.sample.ini ./tests/databases.ini
|
||||
|
||||
# Create Postgre database
|
||||
- psql -c 'CREATE DATABASE dibi_test' -U postgres
|
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "dibi/dibi",
|
||||
"description": "Dibi is Database Abstraction Library for PHP",
|
||||
"description": "Dibi is Database Abstraction Library for PHP 5.",
|
||||
"keywords": ["database", "dbal", "mysql", "postgresql", "sqlite", "mssql", "oracle", "access", "pdo", "odbc"],
|
||||
"homepage": "http://dibiphp.com",
|
||||
"homepage": "http://dibiphp.com/",
|
||||
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
|
||||
"authors": [
|
||||
{
|
||||
@@ -10,22 +10,7 @@
|
||||
"homepage": "http://davidgrudl.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"tracy/tracy": "~2.2",
|
||||
"nette/tester": "~1.3"
|
||||
},
|
||||
"replace": {
|
||||
"dg/dibi": "self.version"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": ["dibi/"]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,18 +2,22 @@
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
*
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the file license.txt that was distributed with this source code.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Dibi extension for Nette Framework 2.1. Creates 'connection' service.
|
||||
* Dibi extension for Nette Framework. Creates 'connection' service.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package dibi\nette
|
||||
* @phpversion 5.3
|
||||
*/
|
||||
class DibiNette21Extension extends Nette\DI\CompilerExtension
|
||||
class DibiNetteExtension extends Nette\Config\CompilerExtension
|
||||
{
|
||||
|
||||
public function loadConfiguration()
|
||||
@@ -23,7 +27,7 @@ class DibiNette21Extension extends Nette\DI\CompilerExtension
|
||||
|
||||
$useProfiler = isset($config['profiler'])
|
||||
? $config['profiler']
|
||||
: $container->parameters['debugMode'];
|
||||
: !$container->parameters['productionMode'];
|
||||
|
||||
unset($config['profiler']);
|
||||
|
||||
@@ -41,8 +45,8 @@ class DibiNette21Extension extends Nette\DI\CompilerExtension
|
||||
if ($useProfiler) {
|
||||
$panel = $container->addDefinition($this->prefix('panel'))
|
||||
->setClass('DibiNettePanel')
|
||||
->addSetup('Nette\Diagnostics\Debugger::getBar()->addPanel(?)', array('@self'))
|
||||
->addSetup('Nette\Diagnostics\Debugger::getBlueScreen()->addPanel(?)', array('DibiNettePanel::renderException'));
|
||||
->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array('@self'))
|
||||
->addSetup('Nette\Diagnostics\Debugger::$blueScreen->addPanel(?)', array(array('@self', 'renderException')));
|
||||
|
||||
$connection->addSetup('$service->onEvent[] = ?', array(array($panel, 'logEvent')));
|
||||
}
|
@@ -5,7 +5,10 @@
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*/
|
||||
|
||||
use Nette\Diagnostics\Debugger;
|
||||
|
||||
if (interface_exists('Nette\Diagnostics\IBarPanel')) {
|
||||
class_alias('Nette\Diagnostics\IBarPanel', 'IBarPanel');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,7 +17,7 @@ use Nette\Diagnostics\Debugger;
|
||||
* @author David Grudl
|
||||
* @package dibi\nette
|
||||
*/
|
||||
class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
|
||||
class DibiNettePanel extends DibiObject implements IBarPanel
|
||||
{
|
||||
/** @var int maximum SQL length */
|
||||
static public $maxLength = 1000;
|
||||
@@ -38,9 +41,18 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
|
||||
|
||||
public function register(DibiConnection $connection)
|
||||
{
|
||||
Debugger::getBar()->addPanel($this);
|
||||
Debugger::getBlueScreen()->addPanel(array(__CLASS__, 'renderException'));
|
||||
$connection->onEvent[] = array($this, 'logEvent');
|
||||
if (is_callable('Nette\Diagnostics\Debugger::enable') && !class_exists('NDebugger')) {
|
||||
class_alias('Nette\Diagnostics\Debugger', 'NDebugger'); // PHP 5.2 code compatibility
|
||||
}
|
||||
if (is_callable('NDebugger::enable')) {
|
||||
NDebugger::$bar && NDebugger::$bar->addPanel($this);
|
||||
NDebugger::$blueScreen && NDebugger::$blueScreen->addPanel(array($this, 'renderException'), __CLASS__);
|
||||
$connection->onEvent[] = array($this, 'logEvent');
|
||||
} elseif (is_callable('Debugger::enable')) {
|
||||
Debugger::$bar && Debugger::$bar->addPanel($this);
|
||||
Debugger::$blueScreen && Debugger::$blueScreen->addPanel(array($this, 'renderException'), __CLASS__);
|
||||
$connection->onEvent[] = array($this, 'logEvent');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +73,7 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
|
||||
* Returns blue-screen custom tab.
|
||||
* @return mixed
|
||||
*/
|
||||
public static function renderException($e)
|
||||
public function renderException($e)
|
||||
{
|
||||
if ($e instanceof DibiException && $e->getSql()) {
|
||||
return array(
|
||||
@@ -114,7 +126,7 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
|
||||
if ($explain) {
|
||||
static $counter;
|
||||
$counter++;
|
||||
$s .= "<br /><a href='#nette-debug-DibiProfiler-row-$counter' class='nette-toggler nette-toggle-collapsed' rel='#nette-debug-DibiProfiler-row-$counter'>explain</a>";
|
||||
$s .= "<br /><a href='#' class='nette-toggler' rel='#nette-debug-DibiProfiler-row-$counter'>explain ►</a>";
|
||||
}
|
||||
|
||||
$s .= '</td><td class="nette-DibiProfiler-sql">' . dibi::dump(strlen($event->sql) > self::$maxLength ? substr($event->sql, 0, self::$maxLength) . '...' : $event->sql, TRUE);
|
@@ -1,12 +0,0 @@
|
||||
# This will create service named 'dibi.connection'.
|
||||
# Requires Nette Framework 2.1
|
||||
|
||||
extensions:
|
||||
dibi: DibiNette21Extension
|
||||
|
||||
dibi:
|
||||
host: localhost
|
||||
username: root
|
||||
password: ***
|
||||
database: foo
|
||||
lazy: TRUE
|
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*/
|
||||
|
||||
namespace Dibi\Bridges\Nette;
|
||||
|
||||
use dibi,
|
||||
Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Dibi extension for Nette Framework 2.2. Creates 'connection' & 'panel' services.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package dibi\nette
|
||||
*/
|
||||
class DibiExtension22 extends Nette\DI\CompilerExtension
|
||||
{
|
||||
|
||||
public function loadConfiguration()
|
||||
{
|
||||
$container = $this->getContainerBuilder();
|
||||
$config = $this->getConfig();
|
||||
|
||||
$useProfiler = isset($config['profiler'])
|
||||
? $config['profiler']
|
||||
: class_exists('Tracy\Debugger') && $container->parameters['debugMode'];
|
||||
|
||||
unset($config['profiler']);
|
||||
|
||||
if (isset($config['flags'])) {
|
||||
$flags = 0;
|
||||
foreach ((array) $config['flags'] as $flag) {
|
||||
$flags |= constant($flag);
|
||||
}
|
||||
$config['flags'] = $flags;
|
||||
}
|
||||
|
||||
$connection = $container->addDefinition($this->prefix('connection'))
|
||||
->setClass('DibiConnection', array($config));
|
||||
|
||||
if ($useProfiler) {
|
||||
$panel = $container->addDefinition($this->prefix('panel'))
|
||||
->setClass('Dibi\Bridges\Tracy\Panel');
|
||||
$connection->addSetup(array($panel, 'register'), array($connection));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
# This will create service named 'dibi.connection'.
|
||||
# Requires Nette Framework 2.2
|
||||
|
||||
extensions:
|
||||
dibi: Dibi\Bridges\Nette\DibiExtension22
|
||||
|
||||
dibi:
|
||||
host: localhost
|
||||
username: root
|
||||
password: ***
|
||||
database: foo
|
||||
lazy: TRUE
|
@@ -1,145 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*/
|
||||
|
||||
namespace Dibi\Bridges\Tracy;
|
||||
|
||||
use dibi,
|
||||
Tracy;
|
||||
|
||||
|
||||
/**
|
||||
* Dibi panel for Tracy.
|
||||
*
|
||||
* @author David Grudl
|
||||
*/
|
||||
class Panel extends \DibiObject implements Tracy\IBarPanel
|
||||
{
|
||||
/** @var int maximum SQL length */
|
||||
static public $maxLength = 1000;
|
||||
|
||||
/** @var bool explain queries? */
|
||||
public $explain;
|
||||
|
||||
/** @var int */
|
||||
public $filter;
|
||||
|
||||
/** @var array */
|
||||
private $events = array();
|
||||
|
||||
|
||||
public function __construct($explain = TRUE, $filter = NULL)
|
||||
{
|
||||
$this->filter = $filter ? (int) $filter : \DibiEvent::QUERY;
|
||||
$this->explain = $explain;
|
||||
}
|
||||
|
||||
|
||||
public function register(\DibiConnection $connection)
|
||||
{
|
||||
Tracy\Debugger::getBar()->addPanel($this);
|
||||
Tracy\Debugger::getBlueScreen()->addPanel(array(__CLASS__, 'renderException'));
|
||||
$connection->onEvent[] = array($this, 'logEvent');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* After event notification.
|
||||
* @return void
|
||||
*/
|
||||
public function logEvent(\DibiEvent $event)
|
||||
{
|
||||
if (($event->type & $this->filter) === 0) {
|
||||
return;
|
||||
}
|
||||
$this->events[] = $event;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns blue-screen custom tab.
|
||||
* @return mixed
|
||||
*/
|
||||
public static function renderException($e)
|
||||
{
|
||||
if ($e instanceof \DibiException && $e->getSql()) {
|
||||
return array(
|
||||
'tab' => 'SQL',
|
||||
'panel' => dibi::dump($e->getSql(), TRUE),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns HTML code for custom tab. (Tracy\IBarPanel)
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTab()
|
||||
{
|
||||
$totalTime = 0;
|
||||
foreach ($this->events as $event) {
|
||||
$totalTime += $event->time;
|
||||
}
|
||||
return '<span title="dibi"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC" />'
|
||||
. count($this->events) . ' queries'
|
||||
. ($totalTime ? sprintf(' / %0.1f ms', $totalTime * 1000) : '')
|
||||
. '</span>';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns HTML code for custom panel. (Tracy\IBarPanel)
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPanel()
|
||||
{
|
||||
$totalTime = $s = NULL;
|
||||
$h = 'htmlSpecialChars';
|
||||
foreach ($this->events as $event) {
|
||||
$totalTime += $event->time;
|
||||
$explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS()
|
||||
if ($this->explain && $event->type === \DibiEvent::SELECT) {
|
||||
try {
|
||||
$backup = array($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime);
|
||||
$event->connection->onEvent = NULL;
|
||||
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN' : 'EXPLAIN');
|
||||
$explain = dibi::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
|
||||
} catch (\DibiException $e) {}
|
||||
list($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime) = $backup;
|
||||
}
|
||||
|
||||
$s .= '<tr><td>' . sprintf('%0.3f', $event->time * 1000);
|
||||
if ($explain) {
|
||||
static $counter;
|
||||
$counter++;
|
||||
$s .= "<br /><a href='#tracy-debug-DibiProfiler-row-$counter' class='tracy-toggle tracy-collapsed' rel='#tracy-debug-DibiProfiler-row-$counter'>explain</a>";
|
||||
}
|
||||
|
||||
$s .= '</td><td class="tracy-DibiProfiler-sql">' . dibi::dump(strlen($event->sql) > self::$maxLength ? substr($event->sql, 0, self::$maxLength) . '...' : $event->sql, TRUE);
|
||||
if ($explain) {
|
||||
$s .= "<div id='tracy-debug-DibiProfiler-row-$counter' class='tracy-collapsed'>{$explain}</div>";
|
||||
}
|
||||
if ($event->source) {
|
||||
$s .= Tracy\Helpers::editorLink($event->source[0], $event->source[1]);//->class('tracy-DibiProfiler-source');
|
||||
}
|
||||
|
||||
$s .= "</td><td>{$event->count}</td><td>{$h($event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name'))}</td></tr>";
|
||||
}
|
||||
|
||||
return empty($this->events) ? '' :
|
||||
'<style> #tracy-debug td.tracy-DibiProfiler-sql { background: white !important }
|
||||
#tracy-debug .tracy-DibiProfiler-source { color: #999 !important }
|
||||
#tracy-debug tracy-DibiProfiler tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style>
|
||||
<h1>Queries: ' . count($this->events) . ($totalTime === NULL ? '' : sprintf(', time: %0.3f ms', $totalTime * 1000)) . '</h1>
|
||||
<div class="tracy-inner tracy-DibiProfiler">
|
||||
<table>
|
||||
<tr><th>Time ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . '
|
||||
</table>
|
||||
</div>';
|
||||
}
|
||||
|
||||
}
|
574
dibi/dibi.php
574
dibi/dibi.php
@@ -16,7 +16,6 @@ if (version_compare(PHP_VERSION, '5.2.0', '<')) {
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/libs/interfaces.php';
|
||||
require_once dirname(__FILE__) . '/libs/Dibi.php';
|
||||
require_once dirname(__FILE__) . '/libs/DibiDateTime.php';
|
||||
require_once dirname(__FILE__) . '/libs/DibiObject.php';
|
||||
require_once dirname(__FILE__) . '/libs/DibiLiteral.php';
|
||||
@@ -33,3 +32,576 @@ require_once dirname(__FILE__) . '/libs/DibiDatabaseInfo.php';
|
||||
require_once dirname(__FILE__) . '/libs/DibiEvent.php';
|
||||
require_once dirname(__FILE__) . '/libs/DibiFileLogger.php';
|
||||
require_once dirname(__FILE__) . '/libs/DibiFirePhpLogger.php';
|
||||
if (interface_exists('Nette\Diagnostics\IBarPanel') || interface_exists('IBarPanel')) {
|
||||
require_once dirname(__FILE__) . '/bridges/Nette-2.0/DibiNettePanel.php';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface for database drivers.
|
||||
*
|
||||
* This class is static container class for creating DB objects and
|
||||
* store connections info.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class dibi
|
||||
{
|
||||
/** column type */
|
||||
const TEXT = 's', // as 'string'
|
||||
BINARY = 'bin',
|
||||
BOOL = 'b',
|
||||
INTEGER = 'i',
|
||||
FLOAT = 'f',
|
||||
DATE = 'd',
|
||||
DATETIME = 't',
|
||||
TIME = 't';
|
||||
|
||||
const IDENTIFIER = 'n';
|
||||
|
||||
/** @deprecated */
|
||||
const FIELD_TEXT = dibi::TEXT,
|
||||
FIELD_BINARY = dibi::BINARY,
|
||||
FIELD_BOOL = dibi::BOOL,
|
||||
FIELD_INTEGER = dibi::INTEGER,
|
||||
FIELD_FLOAT = dibi::FLOAT,
|
||||
FIELD_DATE = dibi::DATE,
|
||||
FIELD_DATETIME = dibi::DATETIME,
|
||||
FIELD_TIME = dibi::TIME;
|
||||
|
||||
/** version */
|
||||
const VERSION = '2.0.5',
|
||||
REVISION = 'released on 2015-01-13';
|
||||
|
||||
/** sorting order */
|
||||
const ASC = 'ASC',
|
||||
DESC = 'DESC';
|
||||
|
||||
/** @var DibiConnection[] Connection registry storage for DibiConnection objects */
|
||||
private static $registry = array();
|
||||
|
||||
/** @var DibiConnection Current connection */
|
||||
private static $connection;
|
||||
|
||||
/** @var array @see addHandler */
|
||||
private static $handlers = array();
|
||||
|
||||
/** @var string Last SQL command @see dibi::query() */
|
||||
public static $sql;
|
||||
|
||||
/** @var int Elapsed time for last query */
|
||||
public static $elapsedTime;
|
||||
|
||||
/** @var int Elapsed time for all queries */
|
||||
public static $totalTime;
|
||||
|
||||
/** @var int Number or queries */
|
||||
public static $numOfQueries = 0;
|
||||
|
||||
/** @var string Default dibi driver */
|
||||
public static $defaultDriver = 'mysql';
|
||||
|
||||
|
||||
/**
|
||||
* Static class - cannot be instantiated.
|
||||
*/
|
||||
final public function __construct()
|
||||
{
|
||||
throw new LogicException("Cannot instantiate static class " . get_class($this));
|
||||
}
|
||||
|
||||
|
||||
/********************* connections handling ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new DibiConnection object and connects it to specified database.
|
||||
* @param mixed connection parameters
|
||||
* @param string connection name
|
||||
* @return DibiConnection
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function connect($config = array(), $name = 0)
|
||||
{
|
||||
return self::$connection = self::$registry[$name] = new DibiConnection($config, $name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from database (doesn't destroy DibiConnection object).
|
||||
* @return void
|
||||
*/
|
||||
public static function disconnect()
|
||||
{
|
||||
self::getConnection()->disconnect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns TRUE when connection was established.
|
||||
* @return bool
|
||||
*/
|
||||
public static function isConnected()
|
||||
{
|
||||
return (self::$connection !== NULL) && self::$connection->isConnected();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve active connection.
|
||||
* @param string connection registy name
|
||||
* @return DibiConnection
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function getConnection($name = NULL)
|
||||
{
|
||||
if ($name === NULL) {
|
||||
if (self::$connection === NULL) {
|
||||
throw new DibiException('Dibi is not connected to database.');
|
||||
}
|
||||
|
||||
return self::$connection;
|
||||
}
|
||||
|
||||
if (!isset(self::$registry[$name])) {
|
||||
throw new DibiException("There is no connection named '$name'.");
|
||||
}
|
||||
|
||||
return self::$registry[$name];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets connection.
|
||||
* @param DibiConnection
|
||||
* @return DibiConnection
|
||||
*/
|
||||
public static function setConnection(DibiConnection $connection)
|
||||
{
|
||||
return self::$connection = $connection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change active connection.
|
||||
* @param string connection registy name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function activate($name)
|
||||
{
|
||||
self::$connection = self::getConnection($name);
|
||||
}
|
||||
|
||||
|
||||
/********************* monostate for active connection ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Generates and executes SQL query - Monostate for DibiConnection::query().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiResult|int result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function query($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query - Monostate for DibiConnection::nativeQuery().
|
||||
* @param string SQL statement.
|
||||
* @return DibiResult|int result set object (if any)
|
||||
*/
|
||||
public static function nativeQuery($sql)
|
||||
{
|
||||
return self::getConnection()->nativeQuery($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates and prints SQL query - Monostate for DibiConnection::test().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return bool
|
||||
*/
|
||||
public static function test($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->test($args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiRow
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetch($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetch();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes SQL query and fetch results - Monostate for DibiConnection::query() & fetchAll().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiRow[]
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetchAll($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetchAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes SQL query and fetch first column - Monostate for DibiConnection::query() & fetchSingle().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return string
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetchSingle($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetchSingle();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes SQL query and fetch pairs - Monostate for DibiConnection::query() & fetchPairs().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return string
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetchPairs($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetchPairs();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows.
|
||||
* 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
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function affectedRows()
|
||||
{
|
||||
return self::getConnection()->getAffectedRows();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
* 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
|
||||
* @return int
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function insertId($sequence=NULL)
|
||||
{
|
||||
return self::getConnection()->getInsertId($sequence);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction - Monostate for DibiConnection::begin().
|
||||
* @param string optional savepoint name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function begin($savepoint = NULL)
|
||||
{
|
||||
self::getConnection()->begin($savepoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction - Monostate for DibiConnection::commit($savepoint = NULL).
|
||||
* @param string optional savepoint name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function commit($savepoint = NULL)
|
||||
{
|
||||
self::getConnection()->commit($savepoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction - Monostate for DibiConnection::rollback().
|
||||
* @param string optional savepoint name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function rollback($savepoint = NULL)
|
||||
{
|
||||
self::getConnection()->rollback($savepoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information about the current database - Monostate for DibiConnection::getDatabaseInfo().
|
||||
* @return DibiDatabaseInfo
|
||||
*/
|
||||
public static function getDatabaseInfo()
|
||||
{
|
||||
return self::getConnection()->getDatabaseInfo();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Import SQL dump from file - extreme fast!
|
||||
* @param string filename
|
||||
* @return int count of sql commands
|
||||
*/
|
||||
public static function loadFile($file)
|
||||
{
|
||||
return self::getConnection()->loadFile($file);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replacement for majority of dibi::methods() in future.
|
||||
*/
|
||||
public static function __callStatic($name, $args)
|
||||
{
|
||||
//if ($name = 'select', 'update', ...') {
|
||||
// return self::command()->$name($args);
|
||||
//}
|
||||
return call_user_func_array(array(self::getConnection(), $name), $args);
|
||||
}
|
||||
|
||||
|
||||
/********************* fluent SQL builders ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function command()
|
||||
{
|
||||
return self::getConnection()->command();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string column name
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function select($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array(self::getConnection(), 'select'), $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string table
|
||||
* @param array
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function update($table, $args)
|
||||
{
|
||||
return self::getConnection()->update($table, $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string table
|
||||
* @param array
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function insert($table, $args)
|
||||
{
|
||||
return self::getConnection()->insert($table, $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string table
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function delete($table)
|
||||
{
|
||||
return self::getConnection()->delete($table);
|
||||
}
|
||||
|
||||
|
||||
/********************* data types ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function datetime($time = NULL)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; create DibiDateTime object instead.', E_USER_WARNING);
|
||||
return new DibiDateTime($time);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function date($date = NULL)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; create DibiDateTime object instead.', E_USER_WARNING);
|
||||
return new DibiDateTime($date);
|
||||
}
|
||||
|
||||
|
||||
/********************* substitutions ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Returns substitution hashmap - Monostate for DibiConnection::getSubstitutes().
|
||||
* @return DibiHashMap
|
||||
*/
|
||||
public static function getSubstitutes()
|
||||
{
|
||||
return self::getConnection()->getSubstitutes();
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public static function addSubst($expr, $subst)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; use dibi::getSubstitutes()->expr = val; instead.', E_USER_WARNING);
|
||||
self::getSubstitutes()->$expr = $subst;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public static function removeSubst($expr)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; use unset(dibi::getSubstitutes()->expr) instead.', E_USER_WARNING);
|
||||
$substitutes = self::getSubstitutes();
|
||||
if ($expr === TRUE) {
|
||||
foreach ($substitutes as $expr => $foo) {
|
||||
unset($substitutes->$expr);
|
||||
}
|
||||
} else {
|
||||
unset($substitutes->$expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public static function setSubstFallback($callback)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; use dibi::getSubstitutes()->setCallback() instead.', E_USER_WARNING);
|
||||
self::getSubstitutes()->setCallback($callback);
|
||||
}
|
||||
|
||||
|
||||
/********************* misc tools ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Prints out a syntax highlighted version of the SQL command or DibiResult.
|
||||
* @param string|DibiResult
|
||||
* @param bool return output instead of printing it?
|
||||
* @return string
|
||||
*/
|
||||
public static function dump($sql = NULL, $return = FALSE)
|
||||
{
|
||||
ob_start();
|
||||
if ($sql instanceof DibiResult) {
|
||||
$sql->dump();
|
||||
|
||||
} else {
|
||||
if ($sql === NULL) {
|
||||
$sql = self::$sql;
|
||||
}
|
||||
|
||||
static $keywords1 = 'SELECT|(?:ON\s+DUPLICATE\s+KEY)?UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|CALL|UNION|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE';
|
||||
static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|RLIKE|REGEXP|TRUE|FALSE';
|
||||
|
||||
// insert new lines
|
||||
$sql = " $sql ";
|
||||
$sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
|
||||
|
||||
// reduce spaces
|
||||
$sql = preg_replace('#[ \t]{2,}#', " ", $sql);
|
||||
|
||||
$sql = wordwrap($sql, 100);
|
||||
$sql = preg_replace("#([ \t]*\r?\n){2,}#", "\n", $sql);
|
||||
|
||||
if (PHP_SAPI === 'cli') {
|
||||
echo trim($sql) . "\n\n";
|
||||
} else {
|
||||
// syntax highlight
|
||||
$sql = htmlSpecialChars($sql);
|
||||
$sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", array('dibi', 'highlightCallback'), $sql);
|
||||
echo '<pre class="dump">', trim($sql), "</pre>\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
return ob_get_clean();
|
||||
} else {
|
||||
ob_end_flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static function highlightCallback($matches)
|
||||
{
|
||||
if (!empty($matches[1])) { // comment
|
||||
return '<em style="color:gray">' . $matches[1] . '</em>';
|
||||
|
||||
} elseif (!empty($matches[2])) { // error
|
||||
return '<strong style="color:red">' . $matches[2] . '</strong>';
|
||||
|
||||
} elseif (!empty($matches[3])) { // most important keywords
|
||||
return '<strong style="color:blue">' . $matches[3] . '</strong>';
|
||||
|
||||
} elseif (!empty($matches[4])) { // other keywords
|
||||
return '<strong style="color:green">' . $matches[4] . '</strong>';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,133 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi reflector for MSSQL2005 databases.
|
||||
*
|
||||
* @author Daniel Kouba
|
||||
* @package dibi\drivers
|
||||
* @internal
|
||||
*/
|
||||
class DibiMsSql2005Reflector extends DibiObject implements IDibiReflector
|
||||
{
|
||||
/** @var IDibiDriver */
|
||||
private $driver;
|
||||
|
||||
|
||||
public function __construct(IDibiDriver $driver)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns list of tables.
|
||||
* @return array
|
||||
*/
|
||||
public function getTables()
|
||||
{
|
||||
$res = $this->driver->query('SELECT TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES');
|
||||
$tables = array();
|
||||
while ($row = $res->fetch(FALSE)) {
|
||||
$tables[] = array(
|
||||
'name' => $row[0],
|
||||
'view' => isset($row[1]) && $row[1] === 'VIEW',
|
||||
);
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT c.name as COLUMN_NAME, c.is_identity AS AUTO_INCREMENT
|
||||
FROM sys.columns c
|
||||
INNER JOIN sys.tables t ON c.object_id = t.object_id
|
||||
WHERE t.name = {$this->driver->escape($table, dibi::TEXT)}
|
||||
");
|
||||
|
||||
$autoIncrements = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$autoIncrements[$row['COLUMN_NAME']] = (bool) $row['AUTO_INCREMENT'];
|
||||
}
|
||||
|
||||
$res = $this->driver->query("
|
||||
SELECT C.COLUMN_NAME, C.DATA_TYPE, C.CHARACTER_MAXIMUM_LENGTH , C.COLUMN_DEFAULT , C.NUMERIC_PRECISION, C.NUMERIC_SCALE , C.IS_NULLABLE, Case When Z.CONSTRAINT_NAME Is Null Then 0 Else 1 End As IsPartOfPrimaryKey
|
||||
FROM INFORMATION_SCHEMA.COLUMNS As C
|
||||
Outer Apply (
|
||||
SELECT CCU.CONSTRAINT_NAME
|
||||
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS As TC
|
||||
Join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE As CCU
|
||||
On CCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
|
||||
WHERE TC.TABLE_SCHEMA = C.TABLE_SCHEMA
|
||||
And TC.TABLE_NAME = C.TABLE_NAME
|
||||
And TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
|
||||
And CCU.COLUMN_NAME = C.COLUMN_NAME
|
||||
) As Z
|
||||
WHERE C.TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}
|
||||
");
|
||||
$columns = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$columns[] = array(
|
||||
'name' => $row['COLUMN_NAME'],
|
||||
'table' => $table,
|
||||
'nativetype' => strtoupper($row['DATA_TYPE']),
|
||||
'size' => $row['CHARACTER_MAXIMUM_LENGTH'],
|
||||
'unsigned' => TRUE,
|
||||
'nullable' => $row['IS_NULLABLE'] === 'YES',
|
||||
'default' => $row['COLUMN_DEFAULT'],
|
||||
'autoincrement' => $autoIncrements[$row['COLUMN_NAME']],
|
||||
'vendor' => $row,
|
||||
);
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all indexes in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
$keyUsagesRes = $this->driver->query("SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}");
|
||||
$keyUsages = array();
|
||||
while( $row = $keyUsagesRes->fetch(TRUE) ) {
|
||||
$keyUsages[$row['CONSTRAINT_NAME']][(int) $row['ORDINAL_POSITION'] - 1] = $row['COLUMN_NAME'];
|
||||
}
|
||||
|
||||
$res = $this->driver->query("SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}");
|
||||
$indexes = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$indexes[$row['CONSTRAINT_NAME']]['name'] = $row['CONSTRAINT_NAME'];
|
||||
$indexes[$row['CONSTRAINT_NAME']]['unique'] = $row['CONSTRAINT_TYPE'] === 'UNIQUE';
|
||||
$indexes[$row['CONSTRAINT_NAME']]['primary'] = $row['CONSTRAINT_TYPE'] === 'PRIMARY KEY';
|
||||
$indexes[$row['CONSTRAINT_NAME']]['columns'] = isset($keyUsages[$row['CONSTRAINT_NAME']]) ? $keyUsages[$row['CONSTRAINT_NAME']] : array();
|
||||
}
|
||||
return array_values($indexes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all foreign keys in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
throw new DibiNotImplementedException;
|
||||
}
|
||||
|
||||
}
|
@@ -66,13 +66,11 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
|
||||
|
||||
} else {
|
||||
// default values
|
||||
$config += array(
|
||||
'username' => ini_get('ibase.default_password'),
|
||||
'password' => ini_get('ibase.default_user'),
|
||||
'database' => ini_get('ibase.default_db'),
|
||||
'charset' => ini_get('ibase.default_charset'),
|
||||
'buffers' => 0,
|
||||
);
|
||||
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'])) {
|
||||
@@ -277,11 +275,10 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
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.');
|
||||
@@ -349,7 +346,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
|
||||
*/
|
||||
public function getRowCount()
|
||||
{
|
||||
throw new DibiNotSupportedException("Firebird/Interbase do not support returning number of rows in result set.");
|
||||
return ibase_num_fields($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
@@ -365,7 +362,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
|
||||
|
||||
if (DibiDriverException::catchError($msg)) {
|
||||
if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
|
||||
preg_match('/exception (\d+) (\w+) (.*)/is', ibase_errmsg(), $match);
|
||||
preg_match('/exception (\d+) (\w+) (.*)/i', ibase_errmsg(), $match);
|
||||
throw new DibiProcedureException($match[3], $match[1], $match[2], dibi::$sql);
|
||||
|
||||
} else {
|
||||
@@ -402,7 +399,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource
|
||||
* @return mysqli_result
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
@@ -5,7 +5,7 @@
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiMsSqlReflector.php';
|
||||
require_once dirname(__FILE__) . '/mssql.reflector.php';
|
||||
|
||||
/**
|
||||
* The dibi driver for MS SQL database.
|
||||
@@ -218,11 +218,10 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
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.');
|
432
dibi/drivers/DibiMsSqlReflector.php → dibi/drivers/mssql.reflector.php
Normal file → Executable file
432
dibi/drivers/DibiMsSqlReflector.php → dibi/drivers/mssql.reflector.php
Normal file → Executable file
@@ -1,216 +1,216 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
*
|
||||
* Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* @package dibi\drivers
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi reflector for MsSQL databases.
|
||||
*
|
||||
* @author Steven Bredenberg
|
||||
* @package dibi\drivers
|
||||
* @internal
|
||||
*/
|
||||
class DibiMsSqlReflector extends DibiObject implements IDibiReflector
|
||||
{
|
||||
/** @var IDibiDriver */
|
||||
private $driver;
|
||||
|
||||
|
||||
public function __construct(IDibiDriver $driver)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns list of tables.
|
||||
* @return array
|
||||
*/
|
||||
public function getTables()
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT TABLE_NAME, TABLE_TYPE
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
");
|
||||
$tables = array();
|
||||
while ($row = $res->fetch(FALSE)) {
|
||||
$tables[] = array(
|
||||
'name' => $row[0],
|
||||
'view' => isset($row[1]) && $row[1] === 'VIEW',
|
||||
);
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns count of rows in a table
|
||||
* @param string
|
||||
* @return integer
|
||||
*/
|
||||
public function getTableCount($table, $fallback=true)
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
}
|
||||
$result = $this->driver->query("
|
||||
SELECT MAX(rowcnt)
|
||||
FROM sys.sysindexes
|
||||
WHERE id=OBJECT_ID({$this->driver->escape($table, dibi::IDENTIFIER)})
|
||||
");
|
||||
$row = $result->fetch(FALSE);
|
||||
|
||||
if (!is_array($row) || count($row) < 1) {
|
||||
if ($fallback) {
|
||||
$row = $this->driver->query("SELECT COUNT(*) FROM {$this->driver->escape($table, dibi::IDENTIFIER)}")->fetch(FALSE);
|
||||
$count = intval($row[0]);
|
||||
} else {
|
||||
$count = false;
|
||||
}
|
||||
} else {
|
||||
$count = intval($row[0]);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT * FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}
|
||||
ORDER BY TABLE_NAME, ORDINAL_POSITION
|
||||
");
|
||||
$columns = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$size = false;
|
||||
$type = strtoupper($row['DATA_TYPE']);
|
||||
|
||||
$size_cols = array(
|
||||
'DATETIME'=>'DATETIME_PRECISION',
|
||||
'DECIMAL'=>'NUMERIC_PRECISION',
|
||||
'CHAR'=>'CHARACTER_MAXIMUM_LENGTH',
|
||||
'NCHAR'=>'CHARACTER_OCTET_LENGTH',
|
||||
'NVARCHAR'=>'CHARACTER_OCTET_LENGTH',
|
||||
'VARCHAR'=>'CHARACTER_OCTET_LENGTH'
|
||||
);
|
||||
|
||||
if (isset($size_cols[$type])) {
|
||||
if ($size_cols[$type]) {
|
||||
$size = $row[$size_cols[$type]];
|
||||
}
|
||||
}
|
||||
|
||||
$columns[] = array(
|
||||
'name' => $row['COLUMN_NAME'],
|
||||
'table' => $table,
|
||||
'nativetype' => $type,
|
||||
'size' => $size,
|
||||
'unsigned' => NULL,
|
||||
'nullable' => $row['IS_NULLABLE'] === 'YES',
|
||||
'default' => $row['COLUMN_DEFAULT'],
|
||||
'autoincrement' => false,
|
||||
'vendor' => $row,
|
||||
);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all indexes in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
$res = $this->driver->query(
|
||||
"SELECT ind.name index_name, ind.index_id, ic.index_column_id,
|
||||
col.name column_name, ind.is_unique, ind.is_primary_key
|
||||
FROM sys.indexes ind
|
||||
INNER JOIN sys.index_columns ic ON
|
||||
(ind.object_id = ic.object_id AND ind.index_id = ic.index_id)
|
||||
INNER JOIN sys.columns col ON
|
||||
(ic.object_id = col.object_id and ic.column_id = col.column_id)
|
||||
INNER JOIN sys.tables t ON
|
||||
(ind.object_id = t.object_id)
|
||||
WHERE t.name = {$this->driver->escape($table, dibi::TEXT)}
|
||||
AND t.is_ms_shipped = 0
|
||||
ORDER BY
|
||||
t.name, ind.name, ind.index_id, ic.index_column_id
|
||||
");
|
||||
|
||||
$indexes = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$index_name = $row['index_name'];
|
||||
|
||||
if (!isset($indexes[$index_name])) {
|
||||
$indexes[$index_name] = array();
|
||||
$indexes[$index_name]['name'] = $index_name;
|
||||
$indexes[$index_name]['unique'] = (bool)$row['is_unique'];
|
||||
$indexes[$index_name]['primary'] = (bool)$row['is_primary_key'];
|
||||
$indexes[$index_name]['columns'] = array();
|
||||
}
|
||||
$indexes[$index_name]['columns'][] = $row['column_name'];
|
||||
}
|
||||
|
||||
return array_values($indexes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all foreign keys in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT f.name AS foreign_key,
|
||||
OBJECT_NAME(f.parent_object_id) AS table_name,
|
||||
COL_NAME(fc.parent_object_id,
|
||||
fc.parent_column_id) AS column_name,
|
||||
OBJECT_NAME (f.referenced_object_id) AS reference_table_name,
|
||||
COL_NAME(fc.referenced_object_id,
|
||||
fc.referenced_column_id) AS reference_column_name,
|
||||
fc.*
|
||||
FROM sys.foreign_keys AS f
|
||||
INNER JOIN sys.foreign_key_columns AS fc
|
||||
ON f.OBJECT_ID = fc.constraint_object_id
|
||||
WHERE OBJECT_NAME(f.parent_object_id) = {$this->driver->escape($table, dibi::TEXT)}
|
||||
");
|
||||
|
||||
$keys = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$key_name = $row['foreign_key'];
|
||||
|
||||
if (!isset($keys[$key_name])) {
|
||||
$keys[$key_name]['name'] = $row['foreign_key']; // foreign key name
|
||||
$keys[$key_name]['local'] = array($row['column_name']); // local columns
|
||||
$keys[$key_name]['table'] = $row['reference_table_name']; // referenced table
|
||||
$keys[$key_name]['foreign'] = array($row['reference_column_name']); // referenced columns
|
||||
$keys[$key_name]['onDelete'] = false;
|
||||
$keys[$key_name]['onUpdate'] = false;
|
||||
} else {
|
||||
$keys[$key_name]['local'][] = $row['column_name']; // local columns
|
||||
$keys[$key_name]['foreign'][] = $row['reference_column_name']; // referenced columns
|
||||
}
|
||||
}
|
||||
return array_values($keys);
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
*
|
||||
* Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
|
||||
*
|
||||
* @package dibi\drivers
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The dibi reflector for MsSQL databases.
|
||||
*
|
||||
* @author Steven Bredenberg
|
||||
* @package dibi\drivers
|
||||
* @internal
|
||||
*/
|
||||
class DibiMsSqlReflector extends DibiObject implements IDibiReflector
|
||||
{
|
||||
/** @var IDibiDriver */
|
||||
private $driver;
|
||||
|
||||
|
||||
public function __construct(IDibiDriver $driver)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns list of tables.
|
||||
* @return array
|
||||
*/
|
||||
public function getTables()
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT TABLE_NAME, TABLE_TYPE
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
");
|
||||
$tables = array();
|
||||
while ($row = $res->fetch(FALSE)) {
|
||||
$tables[] = array(
|
||||
'name' => $row[0],
|
||||
'view' => isset($row[1]) && $row[1] === 'VIEW',
|
||||
);
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns count of rows in a table
|
||||
* @param string
|
||||
* @return integer
|
||||
*/
|
||||
public function getTableCount($table, $fallback=true)
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
}
|
||||
$result = $this->driver->query("
|
||||
SELECT MAX(rowcnt)
|
||||
FROM sys.sysindexes
|
||||
WHERE id=OBJECT_ID({$this->driver->escape($table, dibi::IDENTIFIER)})
|
||||
");
|
||||
$row = $result->fetch(FALSE);
|
||||
|
||||
if (!is_array($row) || count($row) < 1) {
|
||||
if ($fallback) {
|
||||
$row = $this->driver->query("SELECT COUNT(*) FROM {$this->driver->escape($table, dibi::IDENTIFIER)}")->fetch(FALSE);
|
||||
$count = intval($row[0]);
|
||||
} else {
|
||||
$count = false;
|
||||
}
|
||||
} else {
|
||||
$count = intval($row[0]);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT * FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}
|
||||
ORDER BY TABLE_NAME, ORDINAL_POSITION
|
||||
");
|
||||
$columns = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$size = false;
|
||||
$type = strtoupper($row['DATA_TYPE']);
|
||||
|
||||
$size_cols = array(
|
||||
'DATETIME'=>'DATETIME_PRECISION',
|
||||
'DECIMAL'=>'NUMERIC_PRECISION',
|
||||
'CHAR'=>'CHARACTER_MAXIMUM_LENGTH',
|
||||
'NCHAR'=>'CHARACTER_OCTET_LENGTH',
|
||||
'NVARCHAR'=>'CHARACTER_OCTET_LENGTH',
|
||||
'VARCHAR'=>'CHARACTER_OCTET_LENGTH'
|
||||
);
|
||||
|
||||
if (isset($size_cols[$type])) {
|
||||
if ($size_cols[$type]) {
|
||||
$size = $row[$size_cols[$type]];
|
||||
}
|
||||
}
|
||||
|
||||
$columns[] = array(
|
||||
'name' => $row['COLUMN_NAME'],
|
||||
'table' => $table,
|
||||
'nativetype' => $type,
|
||||
'size' => $size,
|
||||
'unsigned' => NULL,
|
||||
'nullable' => $row['IS_NULLABLE'] === 'YES',
|
||||
'default' => $row['COLUMN_DEFAULT'],
|
||||
'autoincrement' => false,
|
||||
'vendor' => $row,
|
||||
);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all indexes in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
$res = $this->driver->query(
|
||||
"SELECT ind.name index_name, ind.index_id, ic.index_column_id,
|
||||
col.name column_name, ind.is_unique, ind.is_primary_key
|
||||
FROM sys.indexes ind
|
||||
INNER JOIN sys.index_columns ic ON
|
||||
(ind.object_id = ic.object_id AND ind.index_id = ic.index_id)
|
||||
INNER JOIN sys.columns col ON
|
||||
(ic.object_id = col.object_id and ic.column_id = col.column_id)
|
||||
INNER JOIN sys.tables t ON
|
||||
(ind.object_id = t.object_id)
|
||||
WHERE t.name = {$this->driver->escape($table, dibi::TEXT)}
|
||||
AND t.is_ms_shipped = 0
|
||||
ORDER BY
|
||||
t.name, ind.name, ind.index_id, ic.index_column_id
|
||||
");
|
||||
|
||||
$indexes = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$index_name = $row['index_name'];
|
||||
|
||||
if (!isset($indexes[$index_name])) {
|
||||
$indexes[$index_name] = array();
|
||||
$indexes[$index_name]['name'] = $index_name;
|
||||
$indexes[$index_name]['unique'] = (bool)$row['is_unique'];
|
||||
$indexes[$index_name]['primary'] = (bool)$row['is_primary_key'];
|
||||
$indexes[$index_name]['columns'] = array();
|
||||
}
|
||||
$indexes[$index_name]['columns'][] = $row['column_name'];
|
||||
}
|
||||
|
||||
return array_values($indexes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all foreign keys in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
$res = $this->driver->query("
|
||||
SELECT f.name AS foreign_key,
|
||||
OBJECT_NAME(f.parent_object_id) AS table_name,
|
||||
COL_NAME(fc.parent_object_id,
|
||||
fc.parent_column_id) AS column_name,
|
||||
OBJECT_NAME (f.referenced_object_id) AS reference_table_name,
|
||||
COL_NAME(fc.referenced_object_id,
|
||||
fc.referenced_column_id) AS reference_column_name,
|
||||
fc.*
|
||||
FROM sys.foreign_keys AS f
|
||||
INNER JOIN sys.foreign_key_columns AS fc
|
||||
ON f.OBJECT_ID = fc.constraint_object_id
|
||||
WHERE OBJECT_NAME(f.parent_object_id) = {$this->driver->escape($table, dibi::TEXT)}
|
||||
");
|
||||
|
||||
$keys = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$key_name = $row['foreign_key'];
|
||||
|
||||
if (!isset($keys[$key_name])) {
|
||||
$keys[$key_name]['name'] = $row['foreign_key']; // foreign key name
|
||||
$keys[$key_name]['local'] = array($row['column_name']); // local columns
|
||||
$keys[$key_name]['table'] = $row['reference_table_name']; // referenced table
|
||||
$keys[$key_name]['foreign'] = array($row['reference_column_name']); // referenced columns
|
||||
$keys[$key_name]['onDelete'] = false;
|
||||
$keys[$key_name]['onUpdate'] = false;
|
||||
} else {
|
||||
$keys[$key_name]['local'][] = $row['column_name']; // local columns
|
||||
$keys[$key_name]['foreign'][] = $row['reference_column_name']; // referenced columns
|
||||
}
|
||||
}
|
||||
return array_values($keys);
|
||||
}
|
||||
|
||||
}
|
@@ -6,9 +6,6 @@
|
||||
*/
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiMsSql2005Reflector.php';
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for MS SQL Driver 2005 database.
|
||||
*
|
||||
@@ -67,11 +64,6 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
|
||||
$this->connection = $config['resource'];
|
||||
|
||||
} else {
|
||||
// Default values
|
||||
if (!isset($config['options']['CharacterSet'])) {
|
||||
$config['options']['CharacterSet'] = 'UTF-8';
|
||||
}
|
||||
|
||||
$this->connection = sqlsrv_connect($config['host'], (array) $config['options']);
|
||||
}
|
||||
|
||||
@@ -191,7 +183,7 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
|
||||
*/
|
||||
public function getReflector()
|
||||
{
|
||||
return new DibiMssql2005Reflector($this);
|
||||
throw new DibiNotSupportedException;
|
||||
}
|
||||
|
||||
|
||||
@@ -227,17 +219,16 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
// @see http://msdn.microsoft.com/en-us/library/ms176027.aspx
|
||||
return '[' . str_replace(']', ']]', $value) . ']';
|
||||
return '[' . str_replace(array('[', ']'), array('[[', ']]'), $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:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
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.');
|
||||
@@ -282,7 +273,7 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
|
||||
{
|
||||
// offset support is missing
|
||||
if ($limit >= 0) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') AS T ';
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
}
|
||||
|
||||
if ($offset) {
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiMySqlReflector.php';
|
||||
require_once dirname(__FILE__) . '/mysql.reflector.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -73,12 +73,9 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
|
||||
} else {
|
||||
// default values
|
||||
DibiConnection::alias($config, 'flags', 'options');
|
||||
$config += array(
|
||||
'charset' => 'utf8',
|
||||
'timezone' => date('P'),
|
||||
'username' => ini_get('mysql.default_user'),
|
||||
'password' => ini_get('mysql.default_password'),
|
||||
);
|
||||
if (!isset($config['charset'])) $config['charset'] = 'utf8';
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('mysql.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('mysql.default_password');
|
||||
if (!isset($config['host'])) {
|
||||
$host = ini_get('mysql.default_host');
|
||||
if ($host) {
|
||||
@@ -130,9 +127,7 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
|
||||
$this->query("SET sql_mode='$config[sqlmode]'");
|
||||
}
|
||||
|
||||
if (isset($config['timezone'])) {
|
||||
$this->query("SET time_zone='$config[timezone]'");
|
||||
}
|
||||
$this->query("SET time_zone='" . date('P') . "'");
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
@@ -312,11 +307,10 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
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.');
|
@@ -111,40 +111,10 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
|
||||
* Returns metadata for all foreign keys in a table.
|
||||
* @param string
|
||||
* @return array
|
||||
* @throws DibiNotSupportedException
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
$data = $this->driver->query("SELECT `ENGINE` FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}")->fetch(TRUE);
|
||||
if ($data['ENGINE'] !== 'InnoDB') {
|
||||
throw new DibiNotSupportedException("Foreign keys are not supported in {$data['ENGINE']} tables.");
|
||||
}
|
||||
|
||||
$res = $this->driver->query("
|
||||
SELECT rc.CONSTRAINT_NAME, rc.UPDATE_RULE, rc.DELETE_RULE, kcu.REFERENCED_TABLE_NAME,
|
||||
GROUP_CONCAT(kcu.REFERENCED_COLUMN_NAME ORDER BY kcu.ORDINAL_POSITION) AS REFERENCED_COLUMNS,
|
||||
GROUP_CONCAT(kcu.COLUMN_NAME ORDER BY kcu.ORDINAL_POSITION) AS COLUMNS
|
||||
FROM information_schema.REFERENTIAL_CONSTRAINTS rc
|
||||
INNER JOIN information_schema.KEY_COLUMN_USAGE kcu ON
|
||||
kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
|
||||
AND kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA
|
||||
WHERE rc.CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND rc.TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}
|
||||
GROUP BY rc.CONSTRAINT_NAME
|
||||
");
|
||||
|
||||
$foreignKeys = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$keyName = $row['CONSTRAINT_NAME'];
|
||||
|
||||
$foreignKeys[$keyName]['name'] = $keyName;
|
||||
$foreignKeys[$keyName]['local'] = explode(",", $row['COLUMNS']);
|
||||
$foreignKeys[$keyName]['table'] = $row['REFERENCED_TABLE_NAME'];
|
||||
$foreignKeys[$keyName]['foreign'] = explode(",", $row['REFERENCED_COLUMNS']);
|
||||
$foreignKeys[$keyName]['onDelete'] = $row['DELETE_RULE'];
|
||||
$foreignKeys[$keyName]['onUpdate'] = $row['UPDATE_RULE'];
|
||||
}
|
||||
return array_values($foreignKeys);
|
||||
throw new DibiNotImplementedException;
|
||||
}
|
||||
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiMySqlReflector.php';
|
||||
require_once dirname(__FILE__) . '/mysql.reflector.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -74,14 +74,11 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
|
||||
} else {
|
||||
// default values
|
||||
$config += array(
|
||||
'charset' => 'utf8',
|
||||
'timezone' => date('P'),
|
||||
'username' => ini_get('mysqli.default_user'),
|
||||
'password' => ini_get('mysqli.default_pw'),
|
||||
'socket' => (string) ini_get('mysqli.default_socket'),
|
||||
'port' => NULL,
|
||||
);
|
||||
if (!isset($config['charset'])) $config['charset'] = 'utf8';
|
||||
if (!isset($config['username'])) $config['username'] = ini_get('mysqli.default_user');
|
||||
if (!isset($config['password'])) $config['password'] = ini_get('mysqli.default_pw');
|
||||
if (!isset($config['socket'])) $config['socket'] = ini_get('mysqli.default_socket');
|
||||
if (!isset($config['port'])) $config['port'] = NULL;
|
||||
if (!isset($config['host'])) {
|
||||
$host = ini_get('mysqli.default_host');
|
||||
if ($host) {
|
||||
@@ -115,7 +112,12 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
if (!@mysqli_set_charset($this->connection, $config['charset'])) {
|
||||
$ok = FALSE;
|
||||
if (version_compare(PHP_VERSION , '5.1.5', '>=')) {
|
||||
// affects the character set used by mysql_real_escape_string() (was added in MySQL 5.0.7 and PHP 5.0.5, fixed in PHP 5.1.5)
|
||||
$ok = @mysqli_set_charset($this->connection, $config['charset']); // intentionally @
|
||||
}
|
||||
if (!$ok) {
|
||||
$this->query("SET NAMES '$config[charset]'");
|
||||
}
|
||||
}
|
||||
@@ -124,9 +126,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
$this->query("SET sql_mode='$config[sqlmode]'");
|
||||
}
|
||||
|
||||
if (isset($config['timezone'])) {
|
||||
$this->query("SET time_zone='$config[timezone]'");
|
||||
}
|
||||
$this->query("SET time_zone='" . date('P') . "'");
|
||||
|
||||
$this->buffered = empty($config['unbuffered']);
|
||||
}
|
||||
@@ -295,11 +295,10 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
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.');
|
||||
@@ -420,10 +419,9 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
public function getResultColumns()
|
||||
{
|
||||
static $types;
|
||||
if ($types === NULL) {
|
||||
if (empty($types)) {
|
||||
$consts = get_defined_constants(TRUE);
|
||||
$types = array();
|
||||
foreach (isset($consts['mysqli']) ? $consts['mysqli'] : array() as $key => $value) {
|
||||
foreach ($consts['mysqli'] as $key => $value) {
|
||||
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
|
||||
$types[$value] = substr($key, 12);
|
||||
}
|
||||
@@ -439,7 +437,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
'name' => $row['name'],
|
||||
'table' => $row['orgtable'],
|
||||
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
|
||||
'nativetype' => isset($types[$row['type']]) ? $types[$row['type']] : $row['type'],
|
||||
'nativetype' => $types[$row['type']],
|
||||
'vendor' => $row,
|
||||
);
|
||||
}
|
||||
@@ -454,7 +452,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = FALSE;
|
||||
return $this->resultSet;
|
||||
return $this->resultSet === NULL || $this->resultSet->type === NULL ? NULL : $this->resultSet;
|
||||
}
|
||||
|
||||
}
|
@@ -60,11 +60,9 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
|
||||
$this->connection = $config['resource'];
|
||||
} else {
|
||||
// default values
|
||||
$config += array(
|
||||
'username' => ini_get('odbc.default_user'),
|
||||
'password' => ini_get('odbc.default_pw'),
|
||||
'dsn' => ini_get('odbc.default_db'),
|
||||
);
|
||||
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 @
|
||||
@@ -241,11 +239,10 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("#m/d/Y#") : date("#m/d/Y#", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "#m/d/Y H:i:s#" : "#m/d/Y#");
|
||||
return $value instanceof DateTime ? $value->format("#m/d/Y H:i:s#") : date("#m/d/Y H:i:s#", $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
@@ -290,7 +287,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
|
||||
{
|
||||
// offset support is missing
|
||||
if ($limit >= 0) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
}
|
||||
|
||||
if ($offset) {
|
@@ -14,11 +14,9 @@
|
||||
* - username (or user)
|
||||
* - password (or pass)
|
||||
* - charset => character encoding to set
|
||||
* - schema => alters session schema
|
||||
* - formatDate => how to format date in SQL (@see date)
|
||||
* - formatDateTime => how to format datetime in SQL (@see date)
|
||||
* - resource (resource) => existing connection resource
|
||||
* - persistent => Creates persistent connections with oci_pconnect instead of oci_new_connect
|
||||
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
|
||||
*
|
||||
* @author David Grudl
|
||||
@@ -66,20 +64,14 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
|
||||
if (isset($config['resource'])) {
|
||||
$this->connection = $config['resource'];
|
||||
} elseif (empty($config['persistent'])) {
|
||||
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
||||
} else {
|
||||
$this->connection = @oci_pconnect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
||||
$this->connection = @oci_new_connect($config['username'], $config['password'], $config['database'], $config['charset']); // intentionally @
|
||||
}
|
||||
|
||||
if (!$this->connection) {
|
||||
$err = oci_error();
|
||||
throw new DibiDriverException($err['message'], $err['code']);
|
||||
}
|
||||
|
||||
if (isset($config['schema'])) {
|
||||
$this->query('ALTER SESSION SET CURRENT_SCHEMA=' . $config['schema']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -240,11 +232,10 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? $this->fmtDateTime : $this->fmtDate);
|
||||
return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
@@ -290,9 +281,7 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
{
|
||||
if ($offset > 0) {
|
||||
// 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;
|
||||
$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;
|
@@ -6,8 +6,8 @@
|
||||
*/
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiMySqlReflector.php';
|
||||
require_once dirname(__FILE__) . '/DibiSqliteReflector.php';
|
||||
require_once dirname(__FILE__) . '/mysql.reflector.php';
|
||||
require_once dirname(__FILE__) . '/sqlite.reflector.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -68,12 +68,13 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
|
||||
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
if ($e->getMessage() === 'could not find driver') {
|
||||
throw new DibiNotSupportedException("PHP extension for PDO is not loaded.");
|
||||
}
|
||||
throw new DibiDriverException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
if (!$this->connection) {
|
||||
throw new DibiDriverException('Connecting error.');
|
||||
}
|
||||
|
||||
$this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
|
||||
@@ -244,12 +245,10 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::TEXT:
|
||||
return $this->connection->quote($value, PDO::PARAM_STR);
|
||||
|
||||
case dibi::BINARY:
|
||||
if ($this->driverName === 'odbc') {
|
||||
return "'" . str_replace("'", "''", $value) . "'";
|
||||
} else {
|
||||
return $this->connection->quote($value, $type === dibi::TEXT ? PDO::PARAM_STR : PDO::PARAM_LOB);
|
||||
}
|
||||
return $this->connection->quote($value, PDO::PARAM_LOB);
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
switch ($this->driverName) {
|
||||
@@ -268,30 +267,18 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
|
||||
case 'mssql':
|
||||
return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']';
|
||||
|
||||
case 'sqlsrv':
|
||||
return '[' . str_replace(']', ']]', $value) . ']';
|
||||
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
|
||||
case dibi::BOOL:
|
||||
if ($this->driverName === 'pgsql') {
|
||||
return $value ? 'TRUE' : 'FALSE';
|
||||
} else {
|
||||
return $value ? 1 : 0;
|
||||
}
|
||||
return $this->connection->quote($value, PDO::PARAM_BOOL);
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
if ($this->driverName === 'odbc') {
|
||||
return $value->format($type === dibi::DATETIME ? "#m/d/Y H:i:s#" : "#m/d/Y#");
|
||||
} else {
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
}
|
||||
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.');
|
||||
@@ -307,36 +294,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
|
||||
*/
|
||||
public function escapeLike($value, $pos)
|
||||
{
|
||||
switch ($this->driverName) {
|
||||
case 'mysql':
|
||||
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_");
|
||||
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
|
||||
|
||||
case 'oci':
|
||||
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_");
|
||||
$value = str_replace("'", "''", $value);
|
||||
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
|
||||
|
||||
case 'pgsql':
|
||||
$bs = substr($this->connection->quote('\\', PDO::PARAM_STR), 1, -1); // standard_conforming_strings = on/off
|
||||
$value = substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1);
|
||||
$value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\'));
|
||||
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
|
||||
|
||||
case 'sqlite':
|
||||
case 'sqlite2':
|
||||
$value = addcslashes(substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1), '%_\\');
|
||||
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'";
|
||||
|
||||
case 'odbc':
|
||||
case 'mssql':
|
||||
case 'sqlsrv':
|
||||
$value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]'));
|
||||
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
|
||||
|
||||
default:
|
||||
throw new DibiNotImplementedException;
|
||||
}
|
||||
throw new DibiNotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
@@ -388,20 +346,16 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
|
||||
|
||||
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;
|
||||
$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 'dblib':
|
||||
case 'mssql':
|
||||
case 'sqlsrv':
|
||||
if ($offset < 1) {
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
|
||||
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
|
||||
break;
|
||||
}
|
||||
// intentionally break omitted
|
@@ -35,6 +35,9 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
/** @var int|FALSE Affected rows */
|
||||
private $affectedRows = FALSE;
|
||||
|
||||
/** @var bool Escape method */
|
||||
private $escMethod = FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiNotSupportedException
|
||||
@@ -58,9 +61,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
$this->connection = $config['resource'];
|
||||
|
||||
} else {
|
||||
$config += array(
|
||||
'charset' => 'utf8',
|
||||
);
|
||||
if (!isset($config['charset'])) $config['charset'] = 'utf8';
|
||||
if (isset($config['string'])) {
|
||||
$string = $config['string'];
|
||||
} else {
|
||||
@@ -100,6 +101,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
if (isset($config['schema'])) {
|
||||
$this->query('SET search_path TO "' . $config['schema'] . '"');
|
||||
}
|
||||
|
||||
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
}
|
||||
|
||||
|
||||
@@ -113,16 +116,6 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pings database.
|
||||
* @return boolean
|
||||
*/
|
||||
public function ping()
|
||||
{
|
||||
return pg_ping($this->connection);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query.
|
||||
* @param string SQL statement.
|
||||
@@ -271,16 +264,24 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
{
|
||||
switch ($type) {
|
||||
case dibi::TEXT:
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiException('Lost connection to server.');
|
||||
if ($this->escMethod) {
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiException('Lost connection to server.');
|
||||
}
|
||||
return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||
} else {
|
||||
return "'" . pg_escape_string($value) . "'";
|
||||
}
|
||||
return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||
|
||||
case dibi::BINARY:
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiException('Lost connection to server.');
|
||||
if ($this->escMethod) {
|
||||
if (!is_resource($this->connection)) {
|
||||
throw new DibiException('Lost connection to server.');
|
||||
}
|
||||
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
||||
} else {
|
||||
return "'" . pg_escape_bytea($value) . "'";
|
||||
}
|
||||
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
||||
|
||||
case dibi::IDENTIFIER:
|
||||
// @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
|
||||
@@ -290,11 +291,10 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
return $value ? 'TRUE' : 'FALSE';
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
|
||||
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.');
|
||||
@@ -310,9 +310,13 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
*/
|
||||
public function escapeLike($value, $pos)
|
||||
{
|
||||
$bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off
|
||||
$value = pg_escape_string($this->connection, $value);
|
||||
$value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\'));
|
||||
if ($this->escMethod) {
|
||||
$value = pg_escape_string($this->connection, $value);
|
||||
} else {
|
||||
$value = pg_escape_string($value);
|
||||
}
|
||||
|
||||
$value = strtr($value, array( '%' => '\\\\%', '_' => '\\\\_'));
|
||||
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
|
||||
}
|
||||
|
||||
@@ -411,12 +415,13 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
*/
|
||||
public function getResultColumns()
|
||||
{
|
||||
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
$count = pg_num_fields($this->resultSet);
|
||||
$columns = array();
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = array(
|
||||
'name' => pg_field_name($this->resultSet, $i),
|
||||
'table' => pg_field_table($this->resultSet, $i),
|
||||
'table' => $hasTable ? pg_field_table($this->resultSet, $i) : NULL,
|
||||
'nativetype'=> pg_field_type($this->resultSet, $i),
|
||||
);
|
||||
$row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'];
|
||||
@@ -451,7 +456,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
throw new DibiDriverException('Reflection requires PostgreSQL 7.4 and newer.');
|
||||
}
|
||||
|
||||
$query = "
|
||||
$res = $this->query("
|
||||
SELECT
|
||||
table_name AS name,
|
||||
CASE table_type
|
||||
@@ -461,20 +466,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
FROM
|
||||
information_schema.tables
|
||||
WHERE
|
||||
table_schema = ANY (current_schemas(false))";
|
||||
|
||||
if ($version >= 9.3) {
|
||||
$query .= "
|
||||
UNION ALL
|
||||
SELECT
|
||||
matviewname, 1
|
||||
FROM
|
||||
pg_matviews
|
||||
WHERE
|
||||
schemaname = ANY (current_schemas(false))";
|
||||
}
|
||||
|
||||
$res = $this->query($query);
|
||||
table_schema = current_schema()
|
||||
");
|
||||
$tables = pg_fetch_all($res->resultSet);
|
||||
return $tables ? $tables : array();
|
||||
}
|
||||
@@ -492,43 +485,16 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
SELECT indkey
|
||||
FROM pg_class
|
||||
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
|
||||
WHERE pg_class.oid = $_table::regclass
|
||||
WHERE pg_class.relname = $_table
|
||||
");
|
||||
$primary = (int) pg_fetch_object($res->resultSet)->indkey;
|
||||
|
||||
$res = $this->query("
|
||||
SELECT *
|
||||
FROM information_schema.columns c
|
||||
JOIN pg_class ON pg_class.relname = c.table_name
|
||||
JOIN pg_namespace nsp ON nsp.oid = pg_class.relnamespace AND nsp.nspname = c.table_schema
|
||||
WHERE pg_class.oid = $_table::regclass
|
||||
ORDER BY c.ordinal_position
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = $_table AND table_schema = current_schema()
|
||||
ORDER BY ordinal_position
|
||||
");
|
||||
|
||||
if (!$res->getRowCount()) {
|
||||
$res = $this->query("
|
||||
SELECT
|
||||
a.attname AS column_name,
|
||||
pg_type.typname AS udt_name,
|
||||
a.attlen AS numeric_precision,
|
||||
a.atttypmod-4 AS character_maximum_length,
|
||||
NOT a.attnotnull AS is_nullable,
|
||||
a.attnum AS ordinal_position,
|
||||
adef.adsrc AS column_default
|
||||
FROM
|
||||
pg_attribute a
|
||||
JOIN pg_type ON a.atttypid = pg_type.oid
|
||||
JOIN pg_class cls ON a.attrelid = cls.oid
|
||||
LEFT JOIN pg_attrdef adef ON adef.adnum = a.attnum AND adef.adrelid = a.attrelid
|
||||
WHERE
|
||||
cls.relkind IN ('r', 'v', 'mv')
|
||||
AND a.attrelid = $_table::regclass
|
||||
AND a.attnum > 0
|
||||
AND NOT a.attisdropped
|
||||
ORDER BY ordinal_position
|
||||
");
|
||||
}
|
||||
|
||||
$columns = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$size = (int) max($row['character_maximum_length'], $row['numeric_precision']);
|
||||
@@ -536,8 +502,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
'name' => $row['column_name'],
|
||||
'table' => $table,
|
||||
'nativetype' => strtoupper($row['udt_name']),
|
||||
'size' => $size > 0 ? $size : NULL,
|
||||
'nullable' => $row['is_nullable'] === 'YES' || $row['is_nullable'] === 't',
|
||||
'size' => $size ? $size : NULL,
|
||||
'nullable' => $row['is_nullable'] === 'YES',
|
||||
'default' => $row['column_default'],
|
||||
'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'], 0, 7) === 'nextval',
|
||||
'vendor' => $row,
|
||||
@@ -556,16 +522,9 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
{
|
||||
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT);
|
||||
$res = $this->query("
|
||||
SELECT
|
||||
a.attnum AS ordinal_position,
|
||||
a.attname AS column_name
|
||||
FROM
|
||||
pg_attribute a
|
||||
JOIN pg_class cls ON a.attrelid = cls.oid
|
||||
WHERE
|
||||
a.attrelid = $_table::regclass
|
||||
AND a.attnum > 0
|
||||
AND NOT a.attisdropped
|
||||
SELECT ordinal_position, column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = $_table AND table_schema = current_schema()
|
||||
ORDER BY ordinal_position
|
||||
");
|
||||
|
||||
@@ -579,7 +538,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
FROM pg_class
|
||||
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid
|
||||
INNER JOIN pg_class as pg_class2 on pg_class2.oid = pg_index.indexrelid
|
||||
WHERE pg_class.oid = $_table::regclass
|
||||
WHERE pg_class.relname = $_table
|
||||
");
|
||||
|
||||
$indexes = array();
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiSqliteReflector.php';
|
||||
require_once dirname(__FILE__) . '/sqlite.reflector.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -239,11 +239,10 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? $this->fmtDateTime : $this->fmtDate);
|
||||
return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
@@ -286,7 +285,7 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver, IDibiResultDri
|
||||
public function applyLimit(& $sql, $limit, $offset)
|
||||
{
|
||||
if ($limit >= 0 || $offset > 0) {
|
||||
$sql .= ' LIMIT ' . (int) $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
}
|
||||
|
@@ -62,6 +62,7 @@ class DibiSqliteReflector extends DibiObject implements IDibiReflector
|
||||
$columns = array();
|
||||
while ($row = $res->fetch(TRUE)) {
|
||||
$column = $row['name'];
|
||||
$pattern = "/(\"$column\"|\[$column\]|$column)\\s+[^,]+\\s+PRIMARY\\s+KEY\\s+AUTOINCREMENT/Ui";
|
||||
$type = explode('(', $row['type']);
|
||||
$columns[] = array(
|
||||
'name' => $column,
|
||||
@@ -71,7 +72,7 @@ class DibiSqliteReflector extends DibiObject implements IDibiReflector
|
||||
'size' => isset($type[1]) ? (int) $type[1] : NULL,
|
||||
'nullable' => $row['notnull'] == '0',
|
||||
'default' => $row['dflt_value'],
|
||||
'autoincrement' => $row['pk'] && $type[0] === 'INTEGER',
|
||||
'autoincrement' => (bool) preg_match($pattern, $meta['sql']),
|
||||
'vendor' => $row,
|
||||
);
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
|
||||
require_once dirname(__FILE__) . '/DibiSqliteReflector.php';
|
||||
require_once dirname(__FILE__) . '/sqlite.reflector.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -234,11 +234,10 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
return $value ? 1 : 0;
|
||||
|
||||
case dibi::DATE:
|
||||
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
|
||||
|
||||
case dibi::DATETIME:
|
||||
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
|
||||
$value = new DibiDateTime($value);
|
||||
}
|
||||
return $value->format($type === dibi::DATETIME ? $this->fmtDateTime : $this->fmtDate);
|
||||
return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported type.');
|
||||
@@ -282,7 +281,7 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
|
||||
public function applyLimit(& $sql, $limit, $offset)
|
||||
{
|
||||
if ($limit >= 0 || $offset > 0) {
|
||||
$sql .= ' LIMIT ' . (int) $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
$sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
|
||||
}
|
||||
}
|
||||
|
@@ -1,544 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This class is static container class for creating DB objects and
|
||||
* store connections info.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package dibi
|
||||
*/
|
||||
class dibi
|
||||
{
|
||||
/** column type */
|
||||
const TEXT = 's', // as 'string'
|
||||
BINARY = 'bin',
|
||||
BOOL = 'b',
|
||||
INTEGER = 'i',
|
||||
FLOAT = 'f',
|
||||
DATE = 'd',
|
||||
DATETIME = 't',
|
||||
TIME = 't';
|
||||
|
||||
const IDENTIFIER = 'n',
|
||||
AFFECTED_ROWS = 'a';
|
||||
|
||||
/** @deprecated */
|
||||
const FIELD_TEXT = dibi::TEXT,
|
||||
FIELD_BINARY = dibi::BINARY,
|
||||
FIELD_BOOL = dibi::BOOL,
|
||||
FIELD_INTEGER = dibi::INTEGER,
|
||||
FIELD_FLOAT = dibi::FLOAT,
|
||||
FIELD_DATE = dibi::DATE,
|
||||
FIELD_DATETIME = dibi::DATETIME,
|
||||
FIELD_TIME = dibi::TIME;
|
||||
|
||||
/** version */
|
||||
const VERSION = '2.3.0',
|
||||
REVISION = 'released on 2015-01-23';
|
||||
|
||||
/** sorting order */
|
||||
const ASC = 'ASC',
|
||||
DESC = 'DESC';
|
||||
|
||||
/** @var DibiConnection[] Connection registry storage for DibiConnection objects */
|
||||
private static $registry = array();
|
||||
|
||||
/** @var DibiConnection Current connection */
|
||||
private static $connection;
|
||||
|
||||
/** @var array @see addHandler */
|
||||
private static $handlers = array();
|
||||
|
||||
/** @var string Last SQL command @see dibi::query() */
|
||||
public static $sql;
|
||||
|
||||
/** @var int Elapsed time for last query */
|
||||
public static $elapsedTime;
|
||||
|
||||
/** @var int Elapsed time for all queries */
|
||||
public static $totalTime;
|
||||
|
||||
/** @var int Number or queries */
|
||||
public static $numOfQueries = 0;
|
||||
|
||||
/** @var string Default dibi driver */
|
||||
public static $defaultDriver = 'mysqli';
|
||||
|
||||
|
||||
/**
|
||||
* Static class - cannot be instantiated.
|
||||
*/
|
||||
final public function __construct()
|
||||
{
|
||||
throw new LogicException("Cannot instantiate static class " . get_class($this));
|
||||
}
|
||||
|
||||
|
||||
/********************* connections handling ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new DibiConnection object and connects it to specified database.
|
||||
* @param mixed connection parameters
|
||||
* @return DibiConnection
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function connect($config = array(), $name = 0)
|
||||
{
|
||||
if ($name) {
|
||||
trigger_error(__METHOD__ . '(): named connections are deprecated.', E_USER_DEPRECATED);
|
||||
}
|
||||
return self::$connection = self::$registry[$name] = new DibiConnection($config, $name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from database (doesn't destroy DibiConnection object).
|
||||
* @return void
|
||||
*/
|
||||
public static function disconnect()
|
||||
{
|
||||
self::getConnection()->disconnect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns TRUE when connection was established.
|
||||
* @return bool
|
||||
*/
|
||||
public static function isConnected()
|
||||
{
|
||||
return (self::$connection !== NULL) && self::$connection->isConnected();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve active connection.
|
||||
* @return DibiConnection
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function getConnection($name = NULL)
|
||||
{
|
||||
if ($name === NULL) {
|
||||
if (self::$connection === NULL) {
|
||||
throw new DibiException('Dibi is not connected to database.');
|
||||
}
|
||||
|
||||
return self::$connection;
|
||||
}
|
||||
|
||||
trigger_error(__METHOD__ . '(): named connections are deprecated.', E_USER_DEPRECATED);
|
||||
|
||||
if (!isset(self::$registry[$name])) {
|
||||
throw new DibiException("There is no connection named '$name'.");
|
||||
}
|
||||
|
||||
return self::$registry[$name];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets connection.
|
||||
* @param DibiConnection
|
||||
* @return DibiConnection
|
||||
*/
|
||||
public static function setConnection(DibiConnection $connection)
|
||||
{
|
||||
return self::$connection = $connection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function activate($name)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated.', E_USER_DEPRECATED);
|
||||
self::$connection = self::getConnection($name);
|
||||
}
|
||||
|
||||
|
||||
/********************* monostate for active connection ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Generates and executes SQL query - Monostate for DibiConnection::query().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiResult|int result set object (if any)
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function query($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the SQL query - Monostate for DibiConnection::nativeQuery().
|
||||
* @param string SQL statement.
|
||||
* @return DibiResult|int result set object (if any)
|
||||
*/
|
||||
public static function nativeQuery($sql)
|
||||
{
|
||||
return self::getConnection()->nativeQuery($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates and prints SQL query - Monostate for DibiConnection::test().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return bool
|
||||
*/
|
||||
public static function test($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->test($args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiRow
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetch($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetch();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes SQL query and fetch results - Monostate for DibiConnection::query() & fetchAll().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return DibiRow[]
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetchAll($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetchAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes SQL query and fetch first column - Monostate for DibiConnection::query() & fetchSingle().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return string
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetchSingle($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetchSingle();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes SQL query and fetch pairs - Monostate for DibiConnection::query() & fetchPairs().
|
||||
* @param array|mixed one or more arguments
|
||||
* @return string
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function fetchPairs($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return self::getConnection()->query($args)->fetchPairs();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows.
|
||||
* 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
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function affectedRows()
|
||||
{
|
||||
return self::getConnection()->getAffectedRows();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
|
||||
* 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
|
||||
* @return int
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function insertId($sequence=NULL)
|
||||
{
|
||||
return self::getConnection()->getInsertId($sequence);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begins a transaction - Monostate for DibiConnection::begin().
|
||||
* @param string optional savepoint name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function begin($savepoint = NULL)
|
||||
{
|
||||
self::getConnection()->begin($savepoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commits statements in a transaction - Monostate for DibiConnection::commit($savepoint = NULL).
|
||||
* @param string optional savepoint name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function commit($savepoint = NULL)
|
||||
{
|
||||
self::getConnection()->commit($savepoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rollback changes in a transaction - Monostate for DibiConnection::rollback().
|
||||
* @param string optional savepoint name
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
public static function rollback($savepoint = NULL)
|
||||
{
|
||||
self::getConnection()->rollback($savepoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a information about the current database - Monostate for DibiConnection::getDatabaseInfo().
|
||||
* @return DibiDatabaseInfo
|
||||
*/
|
||||
public static function getDatabaseInfo()
|
||||
{
|
||||
return self::getConnection()->getDatabaseInfo();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Import SQL dump from file - extreme fast!
|
||||
* @param string filename
|
||||
* @return int count of sql commands
|
||||
*/
|
||||
public static function loadFile($file)
|
||||
{
|
||||
return self::getConnection()->loadFile($file);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replacement for majority of dibi::methods() in future.
|
||||
*/
|
||||
public static function __callStatic($name, $args)
|
||||
{
|
||||
//if ($name = 'select', 'update', ...') {
|
||||
// return self::command()->$name($args);
|
||||
//}
|
||||
return call_user_func_array(array(self::getConnection(), $name), $args);
|
||||
}
|
||||
|
||||
|
||||
/********************* fluent SQL builders ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function command()
|
||||
{
|
||||
return self::getConnection()->command();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string column name
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function select($args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array(self::getConnection(), 'select'), $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string table
|
||||
* @param array
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function update($table, $args)
|
||||
{
|
||||
return self::getConnection()->update($table, $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string table
|
||||
* @param array
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function insert($table, $args)
|
||||
{
|
||||
return self::getConnection()->insert($table, $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string table
|
||||
* @return DibiFluent
|
||||
*/
|
||||
public static function delete($table)
|
||||
{
|
||||
return self::getConnection()->delete($table);
|
||||
}
|
||||
|
||||
|
||||
/********************* substitutions ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Returns substitution hashmap - Monostate for DibiConnection::getSubstitutes().
|
||||
* @return DibiHashMap
|
||||
*/
|
||||
public static function getSubstitutes()
|
||||
{
|
||||
return self::getConnection()->getSubstitutes();
|
||||
}
|
||||
|
||||
|
||||
/********************* misc tools ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Prints out a syntax highlighted version of the SQL command or DibiResult.
|
||||
* @param string|DibiResult
|
||||
* @param bool return output instead of printing it?
|
||||
* @return string
|
||||
*/
|
||||
public static function dump($sql = NULL, $return = FALSE)
|
||||
{
|
||||
ob_start();
|
||||
if ($sql instanceof DibiResult) {
|
||||
$sql->dump();
|
||||
|
||||
} else {
|
||||
if ($sql === NULL) {
|
||||
$sql = self::$sql;
|
||||
}
|
||||
|
||||
static $keywords1 = 'SELECT|(?:ON\s+DUPLICATE\s+KEY)?UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|CALL|UNION|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE|START\s+TRANSACTION|BEGIN|COMMIT|ROLLBACK(?:\s+TO\s+SAVEPOINT)?|(?:RELEASE\s+)?SAVEPOINT';
|
||||
static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|RLIKE|REGEXP|TRUE|FALSE';
|
||||
|
||||
// insert new lines
|
||||
$sql = " $sql ";
|
||||
$sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
|
||||
|
||||
// reduce spaces
|
||||
$sql = preg_replace('#[ \t]{2,}#', " ", $sql);
|
||||
|
||||
$sql = wordwrap($sql, 100);
|
||||
$sql = preg_replace("#([ \t]*\r?\n){2,}#", "\n", $sql);
|
||||
|
||||
// syntax highlight
|
||||
$highlighter = "#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is";
|
||||
if (PHP_SAPI === 'cli') {
|
||||
if (substr(getenv('TERM'), 0, 5) === 'xterm') {
|
||||
$sql = preg_replace_callback($highlighter, array('dibi', 'cliHighlightCallback'), $sql);
|
||||
}
|
||||
echo trim($sql) . "\n\n";
|
||||
|
||||
} else {
|
||||
$sql = htmlSpecialChars($sql);
|
||||
$sql = preg_replace_callback($highlighter, array('dibi', 'highlightCallback'), $sql);
|
||||
echo '<pre class="dump">', trim($sql), "</pre>\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
return ob_get_clean();
|
||||
} else {
|
||||
ob_end_flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static function highlightCallback($matches)
|
||||
{
|
||||
if (!empty($matches[1])) { // comment
|
||||
return '<em style="color:gray">' . $matches[1] . '</em>';
|
||||
|
||||
} elseif (!empty($matches[2])) { // error
|
||||
return '<strong style="color:red">' . $matches[2] . '</strong>';
|
||||
|
||||
} elseif (!empty($matches[3])) { // most important keywords
|
||||
return '<strong style="color:blue">' . $matches[3] . '</strong>';
|
||||
|
||||
} elseif (!empty($matches[4])) { // other keywords
|
||||
return '<strong style="color:green">' . $matches[4] . '</strong>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static function cliHighlightCallback($matches)
|
||||
{
|
||||
if (!empty($matches[1])) { // comment
|
||||
return "\033[1;30m" . $matches[1] . "\033[0m";
|
||||
|
||||
} elseif (!empty($matches[2])) { // error
|
||||
return "\033[1;31m" . $matches[2] . "\033[0m";
|
||||
|
||||
} elseif (!empty($matches[3])) { // most important keywords
|
||||
return "\033[1;34m" . $matches[3] . "\033[0m";
|
||||
|
||||
} elseif (!empty($matches[4])) { // other keywords
|
||||
return "\033[1;32m" . $matches[4] . "\033[0m";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -56,6 +56,9 @@ class DibiConnection extends DibiObject
|
||||
*/
|
||||
public function __construct($config, $name = NULL)
|
||||
{
|
||||
class_exists('dibi'); // ensure class dibi is loaded
|
||||
|
||||
// DSN string
|
||||
if (is_string($config)) {
|
||||
parse_str($config, $config);
|
||||
|
||||
@@ -80,10 +83,10 @@ class DibiConnection extends DibiObject
|
||||
$config['driver'] = dibi::$defaultDriver;
|
||||
}
|
||||
|
||||
$class = preg_replace(array('#\W#', '#sql#'), array('_', 'Sql'), ucfirst(strtolower($config['driver'])));
|
||||
$class = "Dibi{$class}Driver";
|
||||
if (!class_exists($class)) {
|
||||
include_once dirname(__FILE__) . "/../drivers/$class.php";
|
||||
$driver = preg_replace('#[^a-z0-9_]#', '_', strtolower($config['driver']));
|
||||
$class = "Dibi" . $driver . "Driver";
|
||||
if (!class_exists($class, FALSE)) {
|
||||
include_once dirname(__FILE__) . "/../drivers/$driver.php";
|
||||
|
||||
if (!class_exists($class, FALSE)) {
|
||||
throw new DibiException("Unable to create instance of dibi driver '$class'.");
|
||||
@@ -111,7 +114,7 @@ class DibiConnection extends DibiObject
|
||||
$this->onEvent[] = array(new DibiFirePhpLogger($filter), 'logEvent');
|
||||
}
|
||||
|
||||
if (!interface_exists('Tracy\IBarPanel') && interface_exists('Nette\Diagnostics\IBarPanel') && class_exists('DibiNettePanel')) {
|
||||
if (class_exists('DibiNettePanel', FALSE)) {
|
||||
$panel = new DibiNettePanel(isset($profilerCfg['explain']) ? $profilerCfg['explain'] : TRUE, $filter);
|
||||
$panel->register($this);
|
||||
}
|
||||
@@ -638,21 +641,14 @@ class DibiConnection extends DibiObject
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$delimiter = ';';
|
||||
$sql = '';
|
||||
while (!feof($handle)) {
|
||||
$s = rtrim(fgets($handle));
|
||||
if (substr($s, 0, 10) === 'DELIMITER ') {
|
||||
$delimiter = substr($s, 10);
|
||||
|
||||
} elseif (substr($s, -strlen($delimiter)) === $delimiter) {
|
||||
$sql .= substr($s, 0, -strlen($delimiter));
|
||||
$s = fgets($handle);
|
||||
$sql .= $s;
|
||||
if (substr(rtrim($s), -1) === ';') {
|
||||
$this->driver->query($sql);
|
||||
$sql = '';
|
||||
$count++;
|
||||
|
||||
} else {
|
||||
$sql .= $s . "\n";
|
||||
}
|
||||
}
|
||||
if (trim($sql) !== '') {
|
||||
|
@@ -481,7 +481,7 @@ class DibiColumnInfo extends DibiObject
|
||||
*/
|
||||
public function getTableName()
|
||||
{
|
||||
return isset($this->info['table']) && $this->info['table'] != NULL ? $this->info['table'] : NULL; // intentionally ==
|
||||
return isset($this->info['table']) ? $this->info['table'] : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -569,13 +569,13 @@ class DibiColumnInfo extends DibiObject
|
||||
static $patterns = array(
|
||||
'^_' => dibi::TEXT, // PostgreSQL arrays
|
||||
'BYTEA|BLOB|BIN' => dibi::BINARY,
|
||||
'TEXT|CHAR|POINT|INTERVAL' => dibi::TEXT,
|
||||
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT' => dibi::INTEGER,
|
||||
'TEXT|CHAR' => dibi::TEXT,
|
||||
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG' => dibi::INTEGER,
|
||||
'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER' => dibi::FLOAT,
|
||||
'^TIME$' => dibi::TIME,
|
||||
'TIME' => dibi::DATETIME, // DATETIME, TIMESTAMP
|
||||
'DATE' => dibi::DATE,
|
||||
'BOOL' => dibi::BOOL,
|
||||
'BOOL|BIT' => dibi::BOOL,
|
||||
);
|
||||
|
||||
foreach ($patterns as $s => $val) {
|
||||
|
@@ -18,9 +18,9 @@ class DibiDateTime extends DateTime
|
||||
public function __construct($time = 'now', DateTimeZone $timezone = NULL)
|
||||
{
|
||||
if (is_numeric($time)) {
|
||||
parent::__construct('@' . $time);
|
||||
$this->setTimeZone($timezone ? $timezone : new DateTimeZone(date_default_timezone_get()));
|
||||
} elseif ($timezone === NULL) {
|
||||
$time = date('Y-m-d H:i:s', $time);
|
||||
}
|
||||
if ($timezone === NULL) {
|
||||
parent::__construct($time);
|
||||
} else {
|
||||
parent::__construct($time, $timezone);
|
||||
@@ -42,19 +42,29 @@ class DibiDateTime extends DateTime
|
||||
}
|
||||
|
||||
|
||||
public function setTimestamp($timestamp)
|
||||
public function __sleep()
|
||||
{
|
||||
$zone = PHP_VERSION_ID === 50206 ? new DateTimeZone($this->getTimezone()->getName()) : $this->getTimezone();
|
||||
$this->__construct('@' . $timestamp);
|
||||
$this->setTimeZone($zone);
|
||||
return $this;
|
||||
$this->fix = array($this->format('Y-m-d H:i:s'), $this->getTimezone()->getName());
|
||||
return array('fix');
|
||||
}
|
||||
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->__construct($this->fix[0], new DateTimeZone($this->fix[1]));
|
||||
unset($this->fix);
|
||||
}
|
||||
|
||||
|
||||
public function getTimestamp()
|
||||
{
|
||||
$ts = $this->format('U');
|
||||
return is_float($tmp = $ts * 1) ? $ts : $tmp;
|
||||
return (int) $this->format('U');
|
||||
}
|
||||
|
||||
|
||||
public function setTimestamp($timestamp)
|
||||
{
|
||||
return $this->__construct(date('Y-m-d H:i:s', $timestamp), new DateTimeZone($this->getTimezone()->getName())); // getTimeZone() crashes in PHP 5.2.6
|
||||
}
|
||||
|
||||
|
||||
@@ -63,27 +73,4 @@ class DibiDateTime extends DateTime
|
||||
return $this->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
|
||||
public function __sleep()
|
||||
{
|
||||
$zone = $this->getTimezone()->getName();
|
||||
if ($zone[0] === '+') {
|
||||
$this->fix = array($this->format('Y-m-d H:i:sP'));
|
||||
} else {
|
||||
$this->fix = array($this->format('Y-m-d H:i:s'), $zone);
|
||||
}
|
||||
return array('fix');
|
||||
}
|
||||
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
if (isset($this->fix[1])) {
|
||||
$this->__construct($this->fix[0], new DateTimeZone($this->fix[1]));
|
||||
} else {
|
||||
$this->__construct($this->fix[0]);
|
||||
}
|
||||
unset($this->fix);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,9 +20,6 @@ class DibiFirePhpLogger extends DibiObject
|
||||
/** maximum SQL length */
|
||||
static public $maxLength = 1000;
|
||||
|
||||
/** size of json stream chunk */
|
||||
static public $streamChunkSize = 4990;
|
||||
|
||||
/** @var int */
|
||||
public $filter;
|
||||
|
||||
@@ -61,11 +58,6 @@ class DibiFirePhpLogger extends DibiObject
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->numOfQueries) {
|
||||
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-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
|
||||
}
|
||||
$this->totalTime += $event->time;
|
||||
$this->numOfQueries++;
|
||||
self::$fireTable[] = array(
|
||||
@@ -75,6 +67,10 @@ class DibiFirePhpLogger extends DibiObject
|
||||
$event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name')
|
||||
);
|
||||
|
||||
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-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
|
||||
|
||||
$payload = json_encode(array(
|
||||
array(
|
||||
'Type' => 'TABLE',
|
||||
@@ -82,7 +78,7 @@ class DibiFirePhpLogger extends DibiObject
|
||||
),
|
||||
self::$fireTable,
|
||||
));
|
||||
foreach (str_split($payload, self::$streamChunkSize) as $num => $s) {
|
||||
foreach (str_split($payload, 4990) as $num => $s) {
|
||||
$num++;
|
||||
header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index
|
||||
}
|
||||
|
@@ -24,8 +24,6 @@
|
||||
* @method DibiFluent orderBy($field)
|
||||
* @method DibiFluent limit(int $limit)
|
||||
* @method DibiFluent offset(int $offset)
|
||||
* @method DibiFluent leftJoin($table)
|
||||
* @method DibiFluent on($cond)
|
||||
*/
|
||||
class DibiFluent extends DibiObject implements IDataSource
|
||||
{
|
||||
@@ -205,10 +203,15 @@ class DibiFluent extends DibiObject implements IDataSource
|
||||
* @param string clause name
|
||||
* @return self
|
||||
*/
|
||||
public function clause($clause)
|
||||
public function clause($clause, $remove = FALSE)
|
||||
{
|
||||
$this->cursor = & $this->clauses[self::$normalizer->$clause];
|
||||
if ($this->cursor === NULL) {
|
||||
|
||||
if ($remove) { // deprecated, use removeClause
|
||||
trigger_error(__METHOD__ . '(..., TRUE) is deprecated; use removeClause() instead.', E_USER_NOTICE);
|
||||
$this->cursor = NULL;
|
||||
|
||||
} elseif ($this->cursor === NULL) {
|
||||
$this->cursor = array();
|
||||
}
|
||||
|
||||
@@ -302,14 +305,7 @@ class DibiFluent extends DibiObject implements IDataSource
|
||||
public function execute($return = NULL)
|
||||
{
|
||||
$res = $this->query($this->_export());
|
||||
switch ($return) {
|
||||
case dibi::IDENTIFIER:
|
||||
return $this->connection->getInsertId();
|
||||
case dibi::AFFECTED_ROWS:
|
||||
return $this->connection->getAffectedRows();
|
||||
default:
|
||||
return $res;
|
||||
}
|
||||
return $return === dibi::IDENTIFIER ? $this->connection->getInsertId() : $res;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -49,9 +49,6 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
/** @var string returned object class */
|
||||
private $rowClass = 'DibiRow';
|
||||
|
||||
/** @var Callback returned object factory*/
|
||||
private $rowFactory;
|
||||
|
||||
/** @var array format */
|
||||
private $formats = array();
|
||||
|
||||
@@ -138,12 +135,26 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set. Alias for getRowCount().
|
||||
* @deprecated
|
||||
*/
|
||||
final public function rowCount()
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; use count($res) or $res->getRowCount() instead.', E_USER_WARNING);
|
||||
return $this->getResultDriver()->getRowCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Required by the IteratorAggregate interface.
|
||||
* @return DibiResultIterator
|
||||
*/
|
||||
final public function getIterator()
|
||||
{
|
||||
if (func_num_args()) {
|
||||
trigger_error(__METHOD__ . ' arguments $offset & $limit have been dropped; use SQL clauses instead.', E_USER_WARNING);
|
||||
}
|
||||
return new DibiResultIterator($this);
|
||||
}
|
||||
|
||||
@@ -173,18 +184,6 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a factory to create fetched object instances. These should extend the DibiRow class.
|
||||
* @param callback
|
||||
* @return self
|
||||
*/
|
||||
public function setRowFactory($callback)
|
||||
{
|
||||
$this->rowFactory = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position, process optional type conversion.
|
||||
* and moves the internal cursor to the next position
|
||||
@@ -198,9 +197,7 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
}
|
||||
$this->fetched = TRUE;
|
||||
$this->normalize($row);
|
||||
if ($this->rowFactory) {
|
||||
return call_user_func($this->rowFactory, $row);
|
||||
} elseif ($this->rowClass) {
|
||||
if ($this->rowClass) {
|
||||
$row = new $this->rowClass($row);
|
||||
}
|
||||
return $row;
|
||||
@@ -457,7 +454,7 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
}
|
||||
|
||||
do {
|
||||
$data[ (string) $row[$key] ] = $row[$value];
|
||||
$data[ $row[$key] ] = $row[$value];
|
||||
} while ($row = $this->fetch());
|
||||
|
||||
return $data;
|
||||
@@ -500,15 +497,26 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
$row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
|
||||
|
||||
} elseif ($type === dibi::FLOAT) {
|
||||
$row[$key] = str_replace(',', '.', ltrim((string) ($tmp = (float) $value), '0')) === ltrim(rtrim(rtrim($value, '0'), '.'), '0') ? $tmp : $value;
|
||||
$row[$key] = ltrim((string) ($tmp = (float) $value), '0') === ltrim(rtrim(rtrim($value, '0'), '.'), '0') ? $tmp : $value;
|
||||
|
||||
} elseif ($type === dibi::BOOL) {
|
||||
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
|
||||
|
||||
} elseif ($type === dibi::DATE || $type === dibi::DATETIME) {
|
||||
if ((int) $value !== 0 || substr((string) $value, 0, 3) === '00:') { // '', NULL, FALSE, '0000-00-00', ...
|
||||
if ((int) $value === 0 && substr((string) $value, 0, 3) !== '00:') { // '', NULL, FALSE, '0000-00-00', ...
|
||||
|
||||
} elseif (empty($this->formats[$type])) { // return DateTime object (default)
|
||||
$row[$key] = new DibiDateTime(is_numeric($value) ? date('Y-m-d H:i:s', $value) : $value);
|
||||
|
||||
} elseif ($this->formats[$type] === 'U') { // return timestamp
|
||||
$row[$key] = is_numeric($value) ? (int) $value : strtotime($value);
|
||||
|
||||
} elseif (is_numeric($value)) { // formatted date
|
||||
$row[$key] = date($this->formats[$type], $value);
|
||||
|
||||
} else {
|
||||
$value = new DibiDateTime($value);
|
||||
$row[$key] = empty($this->formats[$type]) ? $value : $value->format($this->formats[$type]);
|
||||
$row[$key] = $value->format($this->formats[$type]);
|
||||
}
|
||||
|
||||
} elseif ($type === dibi::BINARY) {
|
||||
@@ -589,74 +597,49 @@ class DibiResult extends DibiObject implements IDataSource
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public function getColumnNames($fullNames = FALSE)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated; use $res->getInfo()->getColumnNames() instead.', E_USER_WARNING);
|
||||
return $this->getInfo()->getColumnNames($fullNames);
|
||||
}
|
||||
|
||||
|
||||
/********************* misc tools ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Displays complete result set as HTML or text table for debug purposes.
|
||||
* Displays complete result set as HTML table for debug purposes.
|
||||
* @return void
|
||||
*/
|
||||
final public function dump()
|
||||
{
|
||||
$i = 0;
|
||||
$this->seek(0);
|
||||
if (PHP_SAPI === 'cli') {
|
||||
$hasColors = (substr(getenv('TERM'), 0, 5) === 'xterm');
|
||||
$maxLen = 0;
|
||||
while ($row = $this->fetch()) {
|
||||
if ($i === 0) {
|
||||
foreach ($row as $col => $foo) {
|
||||
$len = mb_strlen($col);
|
||||
$maxLen = max($len, $maxLen);
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasColors) {
|
||||
echo "\033[1;37m#row: $i\033[0m\n";
|
||||
} else {
|
||||
echo "#row: $i\n";
|
||||
}
|
||||
|
||||
foreach ($row as $col => $val) {
|
||||
$spaces = $maxLen - mb_strlen($col) + 2;
|
||||
echo "$col" . str_repeat(" ", $spaces) . "$val\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
$i++;
|
||||
}
|
||||
|
||||
while ($row = $this->fetch()) {
|
||||
if ($i === 0) {
|
||||
echo "empty result set\n";
|
||||
}
|
||||
echo "\n";
|
||||
echo "\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n";
|
||||
|
||||
foreach ($row as $col => $foo) {
|
||||
echo "\t\t<th>" . htmlSpecialChars($col) . "</th>\n";
|
||||
}
|
||||
|
||||
echo "\t</tr>\n</thead>\n<tbody>\n";
|
||||
}
|
||||
|
||||
echo "\t<tr>\n\t\t<th>", $i, "</th>\n";
|
||||
foreach ($row as $col) {
|
||||
//if (is_object($col)) $col = $col->__toString();
|
||||
echo "\t\t<td>", htmlSpecialChars($col), "</td>\n";
|
||||
}
|
||||
echo "\t</tr>\n";
|
||||
$i++;
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
echo '<p><em>empty result set</em></p>';
|
||||
} else {
|
||||
while ($row = $this->fetch()) {
|
||||
if ($i === 0) {
|
||||
echo "\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n";
|
||||
|
||||
foreach ($row as $col => $foo) {
|
||||
echo "\t\t<th>" . htmlSpecialChars($col) . "</th>\n";
|
||||
}
|
||||
|
||||
echo "\t</tr>\n</thead>\n<tbody>\n";
|
||||
}
|
||||
|
||||
echo "\t<tr>\n\t\t<th>", $i, "</th>\n";
|
||||
foreach ($row as $col) {
|
||||
//if (is_object($col)) $col = $col->__toString();
|
||||
echo "\t\t<td>", htmlSpecialChars($col), "</td>\n";
|
||||
}
|
||||
echo "\t</tr>\n";
|
||||
$i++;
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
echo '<p><em>empty result set</em></p>';
|
||||
} else {
|
||||
echo "</tbody>\n</table>\n";
|
||||
}
|
||||
echo "</tbody>\n</table>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,12 +42,48 @@ class DibiRow implements ArrayAccess, IteratorAggregate, Countable
|
||||
if ((int) $time === 0 && substr((string) $time, 0, 3) !== '00:') { // '', NULL, FALSE, '0000-00-00', ...
|
||||
return NULL;
|
||||
}
|
||||
$time = new DibiDateTime($time);
|
||||
$time = new DibiDateTime(is_numeric($time) ? date('Y-m-d H:i:s', $time) : $time);
|
||||
}
|
||||
return $format === NULL ? $time : $time->format($format);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts value to UNIX timestamp.
|
||||
* @param string key
|
||||
* @return int
|
||||
*/
|
||||
public function asTimestamp($key)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated.', E_USER_WARNING);
|
||||
return $this->asDateTime($key, 'U');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts value to boolean.
|
||||
* @param string key
|
||||
* @return mixed
|
||||
*/
|
||||
public function asBool($key)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated.', E_USER_WARNING);
|
||||
return $this[$key];
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public function asDate($key, $format = NULL)
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated.', E_USER_WARNING);
|
||||
if ($format === NULL) {
|
||||
return $this->asTimestamp($key);
|
||||
} else {
|
||||
return $this->asDateTime($key, $format === TRUE ? NULL : $format);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************* interfaces ArrayAccess, Countable & IteratorAggregate ****************d*g**/
|
||||
|
||||
|
||||
|
@@ -51,7 +51,6 @@ final class DibiTranslator extends DibiObject
|
||||
public function __construct(DibiConnection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->identifiers = new DibiHashMap(array($this, 'delimite'));
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +62,8 @@ final class DibiTranslator extends DibiObject
|
||||
*/
|
||||
public function translate(array $args)
|
||||
{
|
||||
if (!$this->driver) {
|
||||
$this->driver = $this->connection->getDriver();
|
||||
}
|
||||
$this->identifiers = new DibiHashMap(array($this, 'delimite'));
|
||||
$this->driver = $this->connection->getDriver();
|
||||
|
||||
$args = array_values($args);
|
||||
while (count($args) === 1 && is_array($args[0])) { // implicit array expansion
|
||||
@@ -190,10 +188,6 @@ final class DibiTranslator extends DibiObject
|
||||
return "...";
|
||||
}
|
||||
|
||||
if (!$this->driver) {
|
||||
$this->driver = $this->connection->getDriver();
|
||||
}
|
||||
|
||||
// array processing (with or without modifier)
|
||||
if ($value instanceof Traversable) {
|
||||
$value = iterator_to_array($value);
|
||||
@@ -333,7 +327,7 @@ final class DibiTranslator extends DibiObject
|
||||
|
||||
// with modifier procession
|
||||
if ($modifier) {
|
||||
if ($value !== NULL && !is_scalar($value) && !$value instanceof DateTime && !$value instanceof DateTimeInterface) { // array is already processed
|
||||
if ($value !== NULL && !is_scalar($value) && !($value instanceof DateTime)) { // array is already processed
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected type ' . gettype($value) . '**';
|
||||
}
|
||||
@@ -451,7 +445,7 @@ final class DibiTranslator extends DibiObject
|
||||
} elseif ($value === NULL) {
|
||||
return 'NULL';
|
||||
|
||||
} elseif ($value instanceof DateTime || $value instanceof DateTimeInterface) {
|
||||
} elseif ($value instanceof DateTime) {
|
||||
return $this->driver->escape($value, dibi::DATETIME);
|
||||
|
||||
} elseif ($value instanceof DibiLiteral) {
|
||||
@@ -542,23 +536,17 @@ final class DibiTranslator extends DibiObject
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'lmt') { // apply limit
|
||||
$arg = $this->args[$cursor++];
|
||||
if ($arg === NULL) {
|
||||
} elseif ($this->comment) {
|
||||
return "(limit $arg)";
|
||||
} else {
|
||||
$this->limit = (int) $arg;
|
||||
if ($this->args[$cursor] !== NULL) {
|
||||
$this->limit = (int) $this->args[$cursor];
|
||||
}
|
||||
$cursor++;
|
||||
return '';
|
||||
|
||||
} elseif ($mod === 'ofs') { // apply offset
|
||||
$arg = $this->args[$cursor++];
|
||||
if ($arg === NULL) {
|
||||
} elseif ($this->comment) {
|
||||
return "(offset $arg)";
|
||||
} else {
|
||||
$this->offset = (int) $arg;
|
||||
if ($this->args[$cursor] !== NULL) {
|
||||
$this->offset = (int) $this->args[$cursor];
|
||||
}
|
||||
$cursor++;
|
||||
return '';
|
||||
|
||||
} else { // default processing
|
||||
|
1
examples/.gitignore
vendored
1
examples/.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
_test.bat
|
||||
ref
|
||||
output
|
||||
log
|
||||
|
834
examples/Nette/Debugger.php
Normal file
834
examples/Nette/Debugger.php
Normal file
File diff suppressed because one or more lines are too long
60
examples/Nette/license.txt
Normal file
60
examples/Nette/license.txt
Normal file
@@ -0,0 +1,60 @@
|
||||
Licenses
|
||||
========
|
||||
|
||||
Good news! You may use Nette Framework under the terms of either
|
||||
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
|
||||
|
||||
The BSD License is recommended for most projects. It is easy to understand and it
|
||||
places almost no restrictions on what you can do with the framework. If the GPL
|
||||
fits better to your project, you can use the framework under this license.
|
||||
|
||||
You don't have to notify anyone which license you are using. You can freely
|
||||
use Nette Framework in commercial projects as long as the copyright header
|
||||
remains intact.
|
||||
|
||||
Please be advised that the name "Nette Framework" is a protected trademark and its
|
||||
usage has some limitations. So please do not use word "Nette" in the name of your
|
||||
project or top-level domain, and choose a name that stands on its own merits.
|
||||
If your stuff is good, it will not take long to establish a reputation for yourselves.
|
||||
|
||||
|
||||
New BSD License
|
||||
---------------
|
||||
|
||||
Copyright (c) 2004, 2012 David Grudl (http://davidgrudl.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of "Nette Framework" nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
GPL licenses are very very long, so instead of including them here we offer
|
||||
you URLs with full text:
|
||||
|
||||
- GPL version 2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
- GPL version 3: http://www.gnu.org/licenses/gpl-3.0.html
|
3
examples/Nette/readme.txt
Normal file
3
examples/Nette/readme.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
This file is part of Nette Framework
|
||||
|
||||
For more information please see http://nette.org
|
@@ -4,15 +4,16 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// connects to SQlite using dibi class
|
||||
echo '<p>Connecting to Sqlite: ';
|
||||
try {
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
@@ -26,8 +27,8 @@ echo "</p>\n";
|
||||
echo '<p>Connecting to Sqlite: ';
|
||||
try {
|
||||
$connection = new DibiConnection(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
@@ -78,7 +79,7 @@ try {
|
||||
'driver' => 'odbc',
|
||||
'username' => 'root',
|
||||
'password' => '***',
|
||||
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.__DIR__.'/data/sample.mdb',
|
||||
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.dirname(__FILE__).'/data/sample.mdb',
|
||||
));
|
||||
echo 'OK';
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
@@ -2,7 +2,7 @@ body {
|
||||
font: 15px/1.5 Tahoma, Verdana, Myriad Web, Syntax, sans-serif;
|
||||
color: #333;
|
||||
background: #fff url('dibi-powered.gif') no-repeat 99% 1em;
|
||||
margin: 1.6em;
|
||||
margin: 1.6em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -41,24 +41,24 @@ table.dump th {
|
||||
}
|
||||
|
||||
/* dump() */
|
||||
pre.tracy-dump, pre.dump {
|
||||
pre.nette-dump, pre.dump {
|
||||
color: #444; background: white;
|
||||
border: 1px solid silver;
|
||||
padding: 1em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
pre.tracy-dump .php-array, pre.tracy-dump .php-object {
|
||||
pre.nette-dump .php-array, pre.nette-dump .php-object {
|
||||
color: #C22;
|
||||
}
|
||||
pre.tracy-dump .php-string {
|
||||
pre.nette-dump .php-string {
|
||||
color: #080;
|
||||
}
|
||||
pre.tracy-dump .php-int, pre.tracy-dump .php-float {
|
||||
pre.nette-dump .php-int, pre.nette-dump .php-float {
|
||||
color: #37D;
|
||||
}
|
||||
pre.tracy-dump .php-null, pre.tracy-dump .php-bool {
|
||||
pre.nette-dump .php-null, pre.nette-dump .php-bool {
|
||||
color: black;
|
||||
}
|
||||
pre.tracy-dump .php-visibility {
|
||||
pre.nette-dump .php-visibility {
|
||||
font-size: 85%; color: #999;
|
||||
}
|
||||
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
@@ -4,16 +4,14 @@
|
||||
|
||||
<?php
|
||||
|
||||
if (@!include __DIR__ . '/../vendor/autoload.php') {
|
||||
die('Install dependencies using `composer install --dev`');
|
||||
}
|
||||
|
||||
Tracy\Debugger::enable();
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
ndebug();
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
@@ -32,40 +30,38 @@ product_id | title
|
||||
// fetch a single row
|
||||
echo "<h2>fetch()</h2>\n";
|
||||
$row = dibi::fetch('SELECT title FROM products');
|
||||
Tracy\Dumper::dump($row); // Chair
|
||||
dump($row); // Chair
|
||||
|
||||
|
||||
// fetch a single value
|
||||
echo "<h2>fetchSingle()</h2>\n";
|
||||
$value = dibi::fetchSingle('SELECT title FROM products');
|
||||
Tracy\Dumper::dump($value); // Chair
|
||||
dump($value); // Chair
|
||||
|
||||
|
||||
// fetch complete result set
|
||||
echo "<h2>fetchAll()</h2>\n";
|
||||
$all = dibi::fetchAll('SELECT * FROM products');
|
||||
Tracy\Dumper::dump($all);
|
||||
dump($all);
|
||||
|
||||
|
||||
// fetch complete result set like association array
|
||||
echo "<h2>fetchAssoc('title')</h2>\n";
|
||||
$res = dibi::query('SELECT * FROM products');
|
||||
$assoc = $res->fetchAssoc('title'); // key
|
||||
Tracy\Dumper::dump($assoc);
|
||||
dump($assoc);
|
||||
|
||||
|
||||
// fetch complete result set like pairs key => value
|
||||
echo "<h2>fetchPairs('product_id', 'title')</h2>\n";
|
||||
$res = dibi::query('SELECT * FROM products');
|
||||
$pairs = $res->fetchPairs('product_id', 'title');
|
||||
Tracy\Dumper::dump($pairs);
|
||||
dump($pairs);
|
||||
|
||||
|
||||
// fetch row by row
|
||||
echo "<h2>using foreach</h2>\n";
|
||||
$res = dibi::query('SELECT * FROM products');
|
||||
foreach ($res as $n => $row) {
|
||||
Tracy\Dumper::dump($row);
|
||||
dump($row);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,16 +73,14 @@ $res = dibi::query('
|
||||
INNER JOIN customers USING (customer_id)
|
||||
');
|
||||
|
||||
echo "<h2>fetchAssoc('name|title')</h2>\n";
|
||||
$assoc = $res->fetchAssoc('name|title'); // key
|
||||
Tracy\Dumper::dump($assoc);
|
||||
echo "<h2>fetchAssoc('customers.name|products.title')</h2>\n";
|
||||
$assoc = $res->fetchAssoc('customers.name|products.title'); // key
|
||||
dump($assoc);
|
||||
|
||||
echo "<h2>fetchAssoc('name[]title')</h2>\n";
|
||||
$res = dibi::query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)');
|
||||
$assoc = $res->fetchAssoc('name[]title'); // key
|
||||
Tracy\Dumper::dump($assoc);
|
||||
echo "<h2>fetchAssoc('customers.name[]products.title')</h2>\n";
|
||||
$assoc = $res->fetchAssoc('customers.name[]products.title'); // key
|
||||
dump($assoc);
|
||||
|
||||
echo "<h2>fetchAssoc('name->title')</h2>\n";
|
||||
$res = dibi::query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)');
|
||||
$assoc = $res->fetchAssoc('name->title'); // key
|
||||
Tracy\Dumper::dump($assoc);
|
||||
echo "<h2>fetchAssoc('customers.name->products.title')</h2>\n";
|
||||
$assoc = $res->fetchAssoc('customers.name->products.title'); // key
|
||||
dump($assoc);
|
||||
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
44
examples/nette-debug-and-exceptions.php
Normal file
44
examples/nette-debug-and-exceptions.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Nette Debugger & SQL Exceptions | dibi</h1>
|
||||
|
||||
<p>Dibi can display and log exceptions via Nette Debugger, part of Nette Framework.</p>
|
||||
|
||||
<ul>
|
||||
<li>Nette Framework: http://nette.org
|
||||
</ul>
|
||||
|
||||
<?php
|
||||
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// enable Nette Debugger
|
||||
ndebug();
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
// throws error because SQL is bad
|
||||
dibi::query('SELECT * FROM customers WHERE customer_id < ?', 38);
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
// throws error because SQL is bad
|
||||
dibi::query('SELECT FROM customers WHERE customer_id < ?', 38);
|
30
examples/nette-debug-and-variables.php
Normal file
30
examples/nette-debug-and-variables.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Nette Debugger & Variables | dibi</h1>
|
||||
|
||||
<p>Dibi can dump variables via Nette Debugger, part of Nette Framework.</p>
|
||||
|
||||
<ul>
|
||||
<li>Nette Framework: http://nette.org
|
||||
</ul>
|
||||
|
||||
<?php
|
||||
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
// enable Nette Debugger
|
||||
NDebugger::enable();
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
NDebugger::barDump( dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]' );
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
@@ -52,10 +53,3 @@ dibi::test('
|
||||
%else 1 LIMIT 10 %end'
|
||||
);
|
||||
// -> SELECT * FROM customers WHERE LIMIT 10
|
||||
|
||||
|
||||
// IF()
|
||||
dibi::test('UPDATE products SET', array(
|
||||
'price' => array('IF(price_fixed, price, ?)', 123),
|
||||
));
|
||||
// -> SELECT * FROM customers WHERE LIMIT 10
|
||||
|
@@ -4,14 +4,15 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
@@ -1,21 +1,19 @@
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Result Set Data Types | dibi</h1>
|
||||
<h1>Result Set Data Types | dibi</h1>
|
||||
|
||||
<?php
|
||||
|
||||
if (@!include __DIR__ . '/../vendor/autoload.php') {
|
||||
die('Install dependencies using `composer install --dev`');
|
||||
}
|
||||
|
||||
Tracy\Debugger::enable();
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
ndebug();
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
@@ -27,20 +25,22 @@ $res->setType('customer_id', Dibi::INTEGER)
|
||||
->setFormat(dibi::DATETIME, 'Y-m-d H:i:s');
|
||||
|
||||
|
||||
Tracy\Dumper::dump( $res->fetch() );
|
||||
dump( $res->fetch() );
|
||||
// outputs:
|
||||
// DibiRow(3) {
|
||||
// customer_id => 1
|
||||
// name => "Dave Lister" (11)
|
||||
// added => "2007-03-11 17:20:03" (19)
|
||||
// object(DibiRow)#3 (3) {
|
||||
// customer_id => int(1)
|
||||
// name => string(11) "Dave Lister"
|
||||
// added => object(DateTime53) {}
|
||||
// }
|
||||
|
||||
|
||||
// using auto-detection (works well with MySQL or other strictly typed databases)
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
|
||||
Tracy\Dumper::dump( $res->fetch() );
|
||||
dump( $res->fetch() );
|
||||
// outputs:
|
||||
// DibiRow(3) {
|
||||
// customer_id => 1
|
||||
// name => "Dave Lister" (11)
|
||||
// added => "2007-03-11 17:20:03" (19)
|
||||
// object(DibiRow)#3 (3) {
|
||||
// customer_id => int(1)
|
||||
// name => string(11) "Dave Lister"
|
||||
// added => string(15) "17:20 11.3.2007"
|
||||
// }
|
||||
|
@@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Tracy & SQL Exceptions | dibi</h1>
|
||||
|
||||
<p>Dibi can display and log exceptions via <a href="http://tracy.nette.org">Tracy</a>.</p>
|
||||
|
||||
<?php
|
||||
|
||||
if (@!include __DIR__ . '/../vendor/autoload.php') {
|
||||
die('Install dependencies using `composer install --dev`');
|
||||
}
|
||||
|
||||
|
||||
// enable Tracy
|
||||
Tracy\Debugger::enable();
|
||||
|
||||
|
||||
$connection = dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
// add panel to debug bar
|
||||
$panel = new Dibi\Bridges\Tracy\Panel;
|
||||
$panel->register($connection);
|
||||
|
||||
|
||||
// throws error because SQL is bad
|
||||
dibi::query('SELECT FROM customers WHERE customer_id < ?', 38);
|
@@ -1,38 +0,0 @@
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<style> html { background: url(data/arrow.png) no-repeat bottom right; height: 100%; } </style>
|
||||
|
||||
<h1>Tracy | dibi</h1>
|
||||
|
||||
<p>Dibi can log queries and dump variables to the <a href="http://tracy.nette.org">Tracy</a>.</p>
|
||||
|
||||
<?php
|
||||
|
||||
if (@!include __DIR__ . '/../vendor/autoload.php') {
|
||||
die('Install dependencies using `composer install --dev`');
|
||||
}
|
||||
|
||||
|
||||
// enable Tracy
|
||||
Tracy\Debugger::enable();
|
||||
|
||||
|
||||
$connection = dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
// add panel to debug bar
|
||||
$panel = new Dibi\Bridges\Tracy\Panel;
|
||||
$panel->register($connection);
|
||||
|
||||
|
||||
// query will be logged
|
||||
dibi::query('SELECT 123');
|
||||
|
||||
// result set will be dumped
|
||||
Tracy\Debugger::barDump( dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]' );
|
@@ -4,15 +4,16 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
// CHANGE TO REAL PARAMETERS!
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
'formatDate' => "'Y-m-d'",
|
||||
'formatDateTime' => "'Y-m-d H-i-s'",
|
||||
));
|
||||
|
@@ -4,29 +4,27 @@
|
||||
|
||||
<?php
|
||||
|
||||
if (@!include __DIR__ . '/../vendor/autoload.php') {
|
||||
die('Install dependencies using `composer install --dev`');
|
||||
}
|
||||
|
||||
Tracy\Debugger::enable();
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
ndebug();
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
// using the "prototype" to add custom method to class DibiResult
|
||||
DibiResult::extensionMethod('fetchShuffle', function(DibiResult $obj)
|
||||
function DibiResult_prototype_fetchShuffle(DibiResult $obj)
|
||||
{
|
||||
$all = $obj->fetchAll();
|
||||
shuffle($all);
|
||||
return $all;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// fetch complete result set shuffled
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
$all = $res->fetchShuffle();
|
||||
Tracy\Dumper::dump($all);
|
||||
dump($all);
|
||||
|
@@ -4,14 +4,15 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
@@ -4,14 +4,15 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
// enable query logging to this file
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?php ob_start() // needed by FirePHP ?>
|
||||
<?php ob_start(1) // needed by FirePHP ?>
|
||||
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
'profiler' => array(
|
||||
'run' => TRUE,
|
||||
)
|
||||
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
@@ -4,12 +4,13 @@
|
||||
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../dibi/dibi.php';
|
||||
require_once 'Nette/Debugger.php';
|
||||
require_once '../dibi/dibi.php';
|
||||
|
||||
|
||||
dibi::connect(array(
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
'driver' => 'sqlite',
|
||||
'database' => 'data/sample.sdb',
|
||||
));
|
||||
|
||||
|
||||
|
55
license.md
55
license.md
@@ -1,55 +0,0 @@
|
||||
Licenses
|
||||
========
|
||||
|
||||
Good news! You may use Dibi under the terms of either the New BSD License
|
||||
or the GNU General Public License (GPL) version 2 or 3.
|
||||
|
||||
The BSD License is recommended for most projects. It is easy to understand and it
|
||||
places almost no restrictions on what you can do with the framework. If the GPL
|
||||
fits better to your project, you can use the framework under this license.
|
||||
|
||||
You don't have to notify anyone which license you are using. You can freely
|
||||
use Dibi in commercial projects as long as the copyright header
|
||||
remains intact.
|
||||
|
||||
|
||||
New BSD License
|
||||
---------------
|
||||
|
||||
Copyright (c) 2004, 2014 David Grudl (http://davidgrudl.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of "Dibi" nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
This software is provided by the copyright holders and contributors "as is" and
|
||||
any express or implied warranties, including, but not limited to, the implied
|
||||
warranties of merchantability and fitness for a particular purpose are
|
||||
disclaimed. In no event shall the copyright owner or contributors be liable for
|
||||
any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||
(including, but not limited to, procurement of substitute goods or services;
|
||||
loss of use, data, or profits; or business interruption) however caused and on
|
||||
any theory of liability, whether in contract, strict liability, or tort
|
||||
(including negligence or otherwise) arising in any way out of the use of this
|
||||
software, even if advised of the possibility of such damage.
|
||||
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
GPL licenses are very very long, so instead of including them here we offer
|
||||
you URLs with full text:
|
||||
|
||||
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
|
||||
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
|
61
license.txt
Normal file
61
license.txt
Normal file
@@ -0,0 +1,61 @@
|
||||
Licenses
|
||||
========
|
||||
|
||||
Good news! You may use Dibi under the terms of either the New BSD License
|
||||
or the GNU General Public License (GPL) version 2 or 3.
|
||||
|
||||
The BSD License is recommended for most projects. It is easy to understand and it
|
||||
places almost no restrictions on what you can do with the library. If the GPL
|
||||
fits better to your project, you can use the Dibi under this license.
|
||||
|
||||
You don't have to notify anyone which license you are using. You can freely
|
||||
use Dibi in commercial projects as long as the copyright header
|
||||
remains intact.
|
||||
|
||||
Please do not use word "Dibi" in the name of your project or top-level domain,
|
||||
and choose a name that stands on its own merits. If your stuff is good,
|
||||
it will not take long to establish a reputation for yourselves.
|
||||
|
||||
|
||||
|
||||
New BSD License
|
||||
---------------
|
||||
|
||||
Copyright (c) 2005, 2012 David Grudl (http://davidgrudl.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of "Dibi" nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
GPL licenses are very very long, so instead of including them here we offer
|
||||
you URLs with full text:
|
||||
|
||||
- GPL version 2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
- GPL version 3: http://www.gnu.org/licenses/gpl-3.0.html
|
130
readme.md
130
readme.md
@@ -1,130 +0,0 @@
|
||||
[Dibi](http://dibiphp.com) - smart database layer for PHP [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9XXL5ZJHAYQUN)
|
||||
=========================================================
|
||||
|
||||
[](https://packagist.org/packages/dibi/dibi)
|
||||
[](https://travis-ci.org/dg/dibi)
|
||||
|
||||
Database access functions in PHP are not standardised. This library
|
||||
hides the differences between them, and above all, it gives you a very handy interface.
|
||||
|
||||
The best way to install Dibi is to use a [Composer](http://getcomposer.org/download):
|
||||
|
||||
php composer.phar require dibi/dibi
|
||||
|
||||
Or you can download the latest package from http://dibiphp.com. In this
|
||||
package is also `Dibi.minified`, shrinked single-file version of whole Dibi,
|
||||
useful when you don't want to modify the library, but just use it.
|
||||
|
||||
Dibi requires PHP 5.2.0 or later. It has been tested with PHP 5.5 too.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Refer to the `examples` directory for examples. Dibi documentation is
|
||||
available on the [homepage](http://dibiphp.com).
|
||||
|
||||
Connect to database:
|
||||
|
||||
```php
|
||||
// connect to database (static way)
|
||||
dibi::connect(array(
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'username' => 'root',
|
||||
'password' => '***',
|
||||
));
|
||||
|
||||
// or object way; in all other examples use $connection-> instead of dibi::
|
||||
$connection = new DibiConnection($options);
|
||||
```
|
||||
|
||||
SELECT, INSERT, UPDATE
|
||||
|
||||
```php
|
||||
dibi::query('SELECT * FROM users WHERE id = ?', $id);
|
||||
|
||||
$arr = array(
|
||||
'name' => 'John',
|
||||
'is_admin' => TRUE,
|
||||
);
|
||||
dibi::query('INSERT INTO users', $arr);
|
||||
// INSERT INTO users (`name`, `is_admin`) VALUES ('John', 1)
|
||||
|
||||
dibi::query('UPDATE users SET', $arr, 'WHERE `id`=?', $x);
|
||||
// UPDATE users SET `name`='John', `is_admin`=1 WHERE `id` = 123
|
||||
|
||||
dibi::query('UPDATE users SET', array(
|
||||
'title' => array('SHA1(?)', 'tajneheslo'),
|
||||
));
|
||||
// UPDATE users SET 'title' = SHA1('tajneheslo')
|
||||
```
|
||||
|
||||
Getting results
|
||||
|
||||
```php
|
||||
$result = dibi::query('SELECT * FROM users');
|
||||
|
||||
$value = $result->fetchSingle(); // single value
|
||||
$all = $result->fetchAll(); // all rows
|
||||
$assoc = $result->fetchAssoc('id'); // all rows as associative array
|
||||
$pairs = $result->fetchPairs('customerID', 'name'); // all rows as key => value pairs
|
||||
|
||||
// iterating
|
||||
foreach ($result as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
```
|
||||
|
||||
Modifiers for arrays:
|
||||
|
||||
```php
|
||||
dibi::query('SELECT * FROM users WHERE %and', array(
|
||||
array('number > ?', 10),
|
||||
array('number < ?', 100),
|
||||
));
|
||||
// SELECT * FROM users WHERE (number > 10) AND (number < 100)
|
||||
```
|
||||
|
||||
<table>
|
||||
<tr><td> %and </td><td> </td><td> `[key]=val AND [key2]="val2" AND ...` </td></tr>
|
||||
<tr><td> %or </td><td> </td><td> `[key]=val OR [key2]="val2" OR ...` </td></tr>
|
||||
<tr><td> %a </td><td> assoc </td><td> `[key]=val, [key2]="val2", ...` </td></tr>
|
||||
<tr><td> %l %in </td><td> list </td><td> `(val, "val2", ...)` </td></tr>
|
||||
<tr><td> %v </td><td> values </td><td> `([key], [key2], ...) VALUES (val, "val2", ...)` </td></tr>
|
||||
<tr><td> %m </td><td> multivalues </td><td> `([key], [key2], ...) VALUES (val, "val2", ...), (val, "val2", ...), ...` </td></tr>
|
||||
<tr><td> %by </td><td> ordering </td><td> `[key] ASC, [key2] DESC ...` </td></tr>
|
||||
<tr><td> %n </td><td> identifiers </td><td> `[key], [key2] AS alias, ...` </td></tr>
|
||||
<tr><td> other </td><td> - </td><td> `val, val2, ...` </td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
Modifiers for LIKE
|
||||
|
||||
```php
|
||||
dibi::query("SELECT * FROM table WHERE name LIKE %like~", $query);
|
||||
```
|
||||
|
||||
<table>
|
||||
<tr><td> %like~ </td><td> begins with </td></tr>
|
||||
<tr><td> %~like </td><td> ends with </td></tr>
|
||||
<tr><td> %~like~ </td><td> contains </td></tr>
|
||||
</table>
|
||||
|
||||
DateTime:
|
||||
|
||||
```php
|
||||
dibi::query('UPDATE users SET', array(
|
||||
'time' => new DateTime,
|
||||
));
|
||||
// UPDATE users SET ('2008-01-01 01:08:10')
|
||||
```
|
||||
|
||||
Testing:
|
||||
|
||||
```php
|
||||
echo dibi::$sql; // last SQL query
|
||||
echo dibi::$elapsedTime;
|
||||
echo dibi::$numOfQueries;
|
||||
echo dibi::$totalTime;
|
||||
```
|
31
readme.txt
Normal file
31
readme.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Thank you for downloading Dibi!
|
||||
|
||||
Database access functions in PHP are not standardised. This is class library
|
||||
to hide the differences between the different databases access.
|
||||
|
||||
|
||||
Documentation and Examples
|
||||
--------------------------
|
||||
|
||||
Refer to the 'examples' directory for examples. Dibi documentation is
|
||||
available on the homepage:
|
||||
|
||||
http://dibiphp.com
|
||||
|
||||
|
||||
Dibi.minified
|
||||
-------------
|
||||
|
||||
This is shrinked single-file version of whole Dibi, useful when you don't
|
||||
want to modify library, but just use it.
|
||||
|
||||
This is exactly the same as normal version, just only comments and
|
||||
whitespaces are removed.
|
||||
|
||||
|
||||
-----
|
||||
For more information, visit the author's weblog (in czech language):
|
||||
http://phpfashion.com
|
4
tests/.gitignore
vendored
4
tests/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
output
|
||||
/tmp
|
||||
/test.log
|
||||
/databases.ini
|
69
tests/DibiFluent.cloning.phpt
Normal file
69
tests/DibiFluent.cloning.phpt
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test: Cloning of DibiFluent
|
||||
*
|
||||
* @author David Grudl
|
||||
* @category Dibi
|
||||
* @subpackage UnitTests
|
||||
*/
|
||||
|
||||
|
||||
require dirname(__FILE__) . '/initialize.php';
|
||||
|
||||
|
||||
|
||||
dibi::connect($config['sqlite']);
|
||||
|
||||
|
||||
$fluent = new DibiFluent(dibi::getConnection());
|
||||
$fluent->select('*')->from('table')->where('x=1');
|
||||
$dolly = clone $fluent;
|
||||
$dolly->where('y=1');
|
||||
$dolly->clause('FOO');
|
||||
|
||||
$fluent->test();
|
||||
$dolly->test();
|
||||
|
||||
|
||||
$fluent = dibi::select('id')->from('table')->where('id = %i',1);
|
||||
$dolly = clone $fluent;
|
||||
$dolly->where('cd = %i',5);
|
||||
|
||||
$fluent->test();
|
||||
$dolly->test();
|
||||
|
||||
|
||||
$fluent = dibi::select("*")->from("table");
|
||||
$dolly = clone $fluent;
|
||||
$dolly->removeClause("select")->select("count(*)");
|
||||
|
||||
$fluent->test();
|
||||
$dolly->test();
|
||||
|
||||
|
||||
|
||||
__halt_compiler() ?>
|
||||
|
||||
------EXPECT------
|
||||
SELECT *
|
||||
FROM [table]
|
||||
WHERE x=1
|
||||
|
||||
SELECT *
|
||||
FROM [table]
|
||||
WHERE x=1 AND y=1 FOO
|
||||
|
||||
SELECT [id]
|
||||
FROM [table]
|
||||
WHERE id = 1
|
||||
|
||||
SELECT [id]
|
||||
FROM [table]
|
||||
WHERE id = 1 AND cd = 5
|
||||
|
||||
SELECT *
|
||||
FROM [table]
|
||||
|
||||
SELECT count(*)
|
||||
FROM [table]
|
138
tests/NetteTest/Assert.php
Normal file
138
tests/NetteTest/Assert.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* @copyright Copyright (c) 2004 David Grudl
|
||||
* @license http://nette.org/license Nette license
|
||||
* @link http://nette.org
|
||||
* @category Nette
|
||||
* @package Nette\Test
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Asseratation test helpers.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package Nette\Test
|
||||
*/
|
||||
class Assert
|
||||
{
|
||||
|
||||
/**
|
||||
* Checks assertation.
|
||||
* @param mixed expected
|
||||
* @param mixed actual
|
||||
* @return void
|
||||
*/
|
||||
public static function same($expected, $actual)
|
||||
{
|
||||
if ($actual !== $expected) {
|
||||
self::note('Failed asserting that ' . self::dump($actual) . ' is not identical to ' . self::dump($expected));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks TRUE assertation.
|
||||
* @param mixed actual
|
||||
* @return void
|
||||
*/
|
||||
public static function true($actual)
|
||||
{
|
||||
if ($actual !== TRUE) {
|
||||
self::note('Failed asserting that ' . self::dump($actual) . ' is not TRUE');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks FALSE assertation.
|
||||
* @param mixed actual
|
||||
* @return void
|
||||
*/
|
||||
public static function false($actual)
|
||||
{
|
||||
if ($actual !== FALSE) {
|
||||
self::note('Failed asserting that ' . self::dump($actual) . ' is not FALSE');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks NULL assertation.
|
||||
* @param mixed actual
|
||||
* @return void
|
||||
*/
|
||||
public static function null($actual)
|
||||
{
|
||||
if ($actual !== NULL) {
|
||||
self::note('Failed asserting that ' . self::dump($actual) . ' is not NULL');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dumps information about a variable in readable format.
|
||||
* @param mixed variable to dump
|
||||
* @return void
|
||||
*/
|
||||
private static function dump($var)
|
||||
{
|
||||
if (is_bool($var)) {
|
||||
return $var ? 'TRUE' : 'FALSE';
|
||||
|
||||
} elseif ($var === NULL) {
|
||||
return "NULL";
|
||||
|
||||
} elseif (is_int($var)) {
|
||||
return "$var";
|
||||
|
||||
} elseif (is_float($var)) {
|
||||
return "$var";
|
||||
|
||||
} elseif (is_string($var)) {
|
||||
return var_export($var, TRUE);
|
||||
|
||||
} elseif (is_array($var)) {
|
||||
return "array(" . count($var) . ")";
|
||||
|
||||
} elseif ($var instanceof Exception) {
|
||||
return 'Exception ' . get_class($var) . ': ' . ($var->getCode() ? '#' . $var->getCode() . ' ' : '') . $var->getMessage();
|
||||
|
||||
} elseif (is_object($var)) {
|
||||
$arr = (array) $var;
|
||||
return "object(" . get_class($var) . ") (" . count($arr) . ")";
|
||||
|
||||
} elseif (is_resource($var)) {
|
||||
return "resource(" . get_resource_type($var) . ")";
|
||||
|
||||
} else {
|
||||
return "unknown type";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns message and file and line from call stack.
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
private static function note($message)
|
||||
{
|
||||
echo $message;
|
||||
$trace = debug_backtrace();
|
||||
if (isset($trace[1]['file'], $trace[1]['line'])) {
|
||||
echo ' in file ' . $trace[1]['file'] . ' on line ' . $trace[1]['line'];
|
||||
}
|
||||
echo "\n\n";
|
||||
}
|
||||
|
||||
}
|
43
tests/NetteTest/RunTests.php
Normal file
43
tests/NetteTest/RunTests.php
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
Nette Test Framework (v0.3)
|
||||
---------------------------
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/TestRunner.php';
|
||||
|
||||
/**
|
||||
* Help
|
||||
*/
|
||||
if (!isset($_SERVER['argv'][1])) { ?>
|
||||
Usage:
|
||||
php RunTests.php [options] [file or directory]
|
||||
|
||||
Options:
|
||||
-p <php> Specify PHP-CGI executable to run.
|
||||
-c <path> Look for php.ini in directory <path> or use <path> as php.ini.
|
||||
-d key=val Define INI entry 'key' with value 'val'.
|
||||
-l <path> Specify path to shared library files (LD_LIBRARY_PATH)
|
||||
-e <name> Load php environment <name>
|
||||
-s Show information about skipped tests
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute tests
|
||||
*/
|
||||
try {
|
||||
@unlink(dirname(__FILE__) . '/coverage.tmp'); // @ - file may not exist
|
||||
|
||||
$manager = new TestRunner;
|
||||
$manager->parseConfigFile();
|
||||
$manager->parseArguments();
|
||||
$res = $manager->run();
|
||||
die($res ? 0 : 1);
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo 'Error: ', $e->getMessage(), "\n";
|
||||
die(2);
|
||||
}
|
400
tests/NetteTest/TestCase.php
Normal file
400
tests/NetteTest/TestCase.php
Normal file
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* @copyright Copyright (c) 2004 David Grudl
|
||||
* @license http://nette.org/license Nette license
|
||||
* @link http://nette.org
|
||||
* @category Nette
|
||||
* @package Nette\Test
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Single test case.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package Nette\Test
|
||||
*/
|
||||
class TestCase
|
||||
{
|
||||
/** @var string test file */
|
||||
private $file;
|
||||
|
||||
/** @var array test file multiparts */
|
||||
private $sections;
|
||||
|
||||
/** @var string test output */
|
||||
private $output;
|
||||
|
||||
/** @var string output headers in raw format */
|
||||
private $headers;
|
||||
|
||||
/** @var string PHP command line */
|
||||
private $cmdLine;
|
||||
|
||||
/** @var string PHP command line */
|
||||
private $phpVersion;
|
||||
|
||||
/** @var array */
|
||||
private static $cachedPhp;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string test file name
|
||||
* @param string PHP command line
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($testFile)
|
||||
{
|
||||
$this->file = (string) $testFile;
|
||||
$this->sections = self::parseSections($this->file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Runs single test.
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// pre-skip?
|
||||
$options = $this->sections['options'];
|
||||
if (isset($options['skip'])) {
|
||||
$message = $options['skip'] ? $options['skip'] : 'No message.';
|
||||
throw new TestCaseException($message, TestCaseException::SKIPPED);
|
||||
|
||||
} elseif (isset($options['phpversion'])) {
|
||||
$operator = '>=';
|
||||
if (preg_match('#^(<=|le|<|lt|==|=|eq|!=|<>|ne|>=|ge|>|gt)#', $options['phpversion'], $matches)) {
|
||||
$options['phpversion'] = trim(substr($options['phpversion'], strlen($matches[1])));
|
||||
$operator = $matches[1];
|
||||
}
|
||||
if (version_compare($options['phpversion'], $this->phpVersion, $operator)) {
|
||||
throw new TestCaseException("Requires PHP $operator $options[phpversion].", TestCaseException::SKIPPED);
|
||||
}
|
||||
}
|
||||
|
||||
$this->execute();
|
||||
$output = $this->output;
|
||||
$headers = array_change_key_case(self::parseLines($this->headers, ':'), CASE_LOWER);
|
||||
$tests = 0;
|
||||
|
||||
// post-skip?
|
||||
if (isset($headers['x-nette-test-skip'])) {
|
||||
throw new TestCaseException($headers['x-nette-test-skip'], TestCaseException::SKIPPED);
|
||||
}
|
||||
|
||||
// compare output
|
||||
$expectedOutput = $this->getExpectedOutput();
|
||||
if ($expectedOutput !== NULL) {
|
||||
$tests++;
|
||||
$binary = (bool) preg_match('#[\x00-\x08\x0B\x0C\x0E-\x1F]#', $expectedOutput);
|
||||
if ($binary) {
|
||||
if ($expectedOutput !== $output) {
|
||||
throw new TestCaseException("Binary output doesn't match.");
|
||||
}
|
||||
} else {
|
||||
$output = self::normalize($output, isset($options['keeptrailingspaces']));
|
||||
$expectedOutput = self::normalize($expectedOutput, isset($options['keeptrailingspaces']));
|
||||
if (!$this->compare($output, $expectedOutput)) {
|
||||
throw new TestCaseException("Output doesn't match.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compare headers
|
||||
$expectedHeaders = $this->getExpectedHeaders();
|
||||
if ($expectedHeaders !== NULL) {
|
||||
$tests++;
|
||||
$expectedHeaders = self::normalize($expectedHeaders, FALSE);
|
||||
$expectedHeaders = array_change_key_case(self::parseLines($expectedHeaders, ':'), CASE_LOWER);
|
||||
foreach ($expectedHeaders as $name => $header) {
|
||||
if (!isset($headers[$name])) {
|
||||
throw new TestCaseException("Missing header '$name'.");
|
||||
|
||||
} elseif (!$this->compare($headers[$name], $header)) {
|
||||
throw new TestCaseException("Header '$name' doesn't match.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$tests) { // expecting no output
|
||||
if (trim($output) !== '') {
|
||||
throw new TestCaseException("Empty output doesn't match.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets PHP command line.
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @return TestCase provides a fluent interface
|
||||
*/
|
||||
public function setPhp($binary, $args, $environment)
|
||||
{
|
||||
if (isset(self::$cachedPhp[$binary])) {
|
||||
$this->phpVersion = self::$cachedPhp[$binary];
|
||||
|
||||
} else {
|
||||
exec($environment . escapeshellarg($binary) . ' -v', $output, $res);
|
||||
if ($res !== 0 && $res !== 255) {
|
||||
throw new Exception("Unable to execute '$binary -v'.");
|
||||
}
|
||||
|
||||
if (!preg_match('#^PHP (\S+).*cli#i', $output[0], $matches)) {
|
||||
throw new Exception("Unable to detect PHP version (output: $output[0]).");
|
||||
}
|
||||
|
||||
$this->phpVersion = self::$cachedPhp[$binary] = $matches[1];
|
||||
}
|
||||
|
||||
$this->cmdLine = $environment . escapeshellarg($binary) . $args;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute test.
|
||||
* @return array
|
||||
*/
|
||||
private function execute()
|
||||
{
|
||||
$this->headers = $this->output = NULL;
|
||||
|
||||
$tempFile = tempnam('', 'tmp');
|
||||
if (!$tempFile) {
|
||||
throw new Exception("Unable to create temporary file.");
|
||||
}
|
||||
|
||||
$command = $this->cmdLine;
|
||||
if (isset($this->sections['options']['phpini'])) {
|
||||
foreach (explode(';', $this->sections['options']['phpini']) as $item) {
|
||||
$command .= " -d " . escapeshellarg(trim($item));
|
||||
}
|
||||
}
|
||||
$command .= ' ' . escapeshellarg($this->file) . ' > ' . escapeshellarg($tempFile);
|
||||
|
||||
chdir(dirname($this->file));
|
||||
exec($command, $foo, $res);
|
||||
if ($res === 255) {
|
||||
// exit_status 255 => parse or fatal error
|
||||
|
||||
} elseif ($res !== 0) {
|
||||
throw new Exception("Unable to execute '$command'.");
|
||||
|
||||
}
|
||||
|
||||
$this->output = file_get_contents($tempFile);
|
||||
unlink($tempFile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns test file section.
|
||||
* @return string
|
||||
*/
|
||||
public function getSection($name)
|
||||
{
|
||||
return isset($this->sections[$name]) ? $this->sections[$name] : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns test name.
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->sections['options']['name'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns test output.
|
||||
* @return string
|
||||
*/
|
||||
public function getOutput()
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns output headers.
|
||||
* @return string
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns expected output.
|
||||
* @return string
|
||||
*/
|
||||
public function getExpectedOutput()
|
||||
{
|
||||
if (isset($this->sections['expect'])) {
|
||||
return $this->sections['expect'];
|
||||
|
||||
} elseif (is_file($expFile = str_replace('.phpt', '', $this->file) . '.expect')) {
|
||||
return file_get_contents($expFile);
|
||||
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns expected headers.
|
||||
* @return string
|
||||
*/
|
||||
public function getExpectedHeaders()
|
||||
{
|
||||
return $this->getSection('expectheaders');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************* helpers ****************d*g**/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Splits file into sections.
|
||||
* @param string file
|
||||
* @return array
|
||||
*/
|
||||
public static function parseSections($testFile)
|
||||
{
|
||||
$content = file_get_contents($testFile);
|
||||
$sections = array(
|
||||
'options' => array(),
|
||||
);
|
||||
|
||||
// phpDoc
|
||||
$phpDoc = preg_match('#^/\*\*(.*?)\*/#ms', $content, $matches) ? trim($matches[1]) : '';
|
||||
preg_match_all('#^\s*\*\s*@(\S+)(.*)#mi', $phpDoc, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
$sections['options'][strtolower($match[1])] = isset($match[2]) ? trim($match[2]) : TRUE;
|
||||
}
|
||||
$sections['options']['name'] = preg_match('#^\s*\*\s*TEST:(.*)#mi', $phpDoc, $matches) ? trim($matches[1]) : $testFile;
|
||||
|
||||
// file parts
|
||||
$tmp = preg_split('#^-{3,}([^\s-]+)-{1,}(?:\r?\n|$)#m', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$i = 1;
|
||||
while (isset($tmp[$i])) {
|
||||
$sections[strtolower($tmp[$i])] = $tmp[$i+1];
|
||||
$i += 2;
|
||||
}
|
||||
return $sections;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Splits HTTP headers into array.
|
||||
* @param string
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public static function parseLines($raw, $separator)
|
||||
{
|
||||
$headers = array();
|
||||
foreach (explode("\r\n", $raw) as $header) {
|
||||
$a = strpos($header, $separator);
|
||||
if ($a !== FALSE) {
|
||||
$headers[trim(substr($header, 0, $a))] = (string) trim(substr($header, $a + 1));
|
||||
}
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compares results.
|
||||
* @param string
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
public static function compare($left, $right)
|
||||
{
|
||||
$right = strtr($right, array(
|
||||
'%a%' => '[^\r\n]+', // one or more of anything except the end of line characters
|
||||
'%a?%'=> '[^\r\n]*', // zero or more of anything except the end of line characters
|
||||
'%A%' => '.+', // one or more of anything including the end of line characters
|
||||
'%A?%'=> '.*', // zero or more of anything including the end of line characters
|
||||
'%s%' => '[\t ]+', // one or more white space characters except the end of line characters
|
||||
'%s?%'=> '[\t ]*', // zero or more white space characters except the end of line characters
|
||||
'%S%' => '\S+', // one or more of characters except the white space
|
||||
'%S?%'=> '\S*', // zero or more of characters except the white space
|
||||
'%c%' => '[^\r\n]', // a single character of any sort (except the end of line)
|
||||
'%d%' => '[0-9]+', // one or more digits
|
||||
'%d?%'=> '[0-9]*', // zero or more digits
|
||||
'%i%' => '[+-]?[0-9]+', // signed integer value
|
||||
'%f%' => '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', // floating point number
|
||||
'%h%' => '[0-9a-fA-F]+',// one or more HEX digits
|
||||
'%ns%'=> '(?:[_0-9a-zA-Z\\\\]+\\\\|N)?',// PHP namespace
|
||||
'%[^' => '[^', // reg-exp
|
||||
'%[' => '[', // reg-exp
|
||||
']%' => ']+', // reg-exp
|
||||
|
||||
'.' => '\.', '\\' => '\\\\', '+' => '\+', '*' => '\*', '?' => '\?', '[' => '\[', '^' => '\^', ']' => '\]', '$' => '\$', '(' => '\(', ')' => '\)', // preg quote
|
||||
'{' => '\{', '}' => '\}', '=' => '\=', '!' => '\!', '>' => '\>', '<' => '\<', '|' => '\|', ':' => '\:', '-' => '\-', "\x00" => '\000', '#' => '\#', // preg quote
|
||||
));
|
||||
|
||||
return (bool) preg_match("#^$right$#s", $left);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes whitespace
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return string
|
||||
*/
|
||||
public static function normalize($s, $keepTrailingSpaces)
|
||||
{
|
||||
$s = str_replace("\n", PHP_EOL, str_replace("\r\n", "\n", $s)); // normalize EOL
|
||||
if (!$keepTrailingSpaces) {
|
||||
$s = preg_replace("#[\t ]+(\r?\n)#", '$1', $s); // multiline right trim
|
||||
$s = rtrim($s); // ending trim
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Single test exception.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package Nette\Test
|
||||
*/
|
||||
class TestCaseException extends Exception
|
||||
{
|
||||
const SKIPPED = 1;
|
||||
|
||||
}
|
312
tests/NetteTest/TestHelpers.php
Normal file
312
tests/NetteTest/TestHelpers.php
Normal file
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* @copyright Copyright (c) 2004 David Grudl
|
||||
* @license http://nette.org/license Nette license
|
||||
* @link http://nette.org
|
||||
* @category Nette
|
||||
* @package Nette\Test
|
||||
*/
|
||||
|
||||
require dirname(__FILE__) . '/TestCase.php';
|
||||
|
||||
|
||||
/**
|
||||
* Test helpers.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package Nette\Test
|
||||
*/
|
||||
class TestHelpers
|
||||
{
|
||||
/** @var int */
|
||||
static public $maxDepth = 5;
|
||||
|
||||
/** @var array */
|
||||
private static $sections;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Configures PHP and environment.
|
||||
* @return void
|
||||
*/
|
||||
public static function startup()
|
||||
{
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
ini_set('display_errors', TRUE);
|
||||
ini_set('html_errors', FALSE);
|
||||
ini_set('log_errors', FALSE);
|
||||
|
||||
|
||||
$_SERVER = array_intersect_key($_SERVER, array_flip(array('PHP_SELF', 'SCRIPT_NAME', 'SERVER_ADDR', 'SERVER_SOFTWARE', 'HTTP_HOST', 'DOCUMENT_ROOT', 'OS')));
|
||||
$_SERVER['REQUEST_TIME'] = 1234567890;
|
||||
$_ENV = array();
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
}
|
||||
|
||||
if (extension_loaded('xdebug')) {
|
||||
xdebug_disable();
|
||||
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
|
||||
register_shutdown_function(array(__CLASS__, 'prepareSaveCoverage'));
|
||||
}
|
||||
|
||||
set_exception_handler(array(__CLASS__, 'exceptionHandler'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Purges directory.
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
public static function purge($dir)
|
||||
{
|
||||
@mkdir($dir); // @ - directory may already exist
|
||||
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST) as $entry) {
|
||||
if ($entry->getBasename() === '.gitignore') {
|
||||
// ignore
|
||||
} elseif ($entry->isDir()) {
|
||||
rmdir($entry);
|
||||
} else {
|
||||
unlink($entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns current test section.
|
||||
* @param string
|
||||
* @param string
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getSection($file, $section)
|
||||
{
|
||||
if (!isset(self::$sections[$file])) {
|
||||
self::$sections[$file] = TestCase::parseSections($file);
|
||||
}
|
||||
|
||||
$lowerSection = strtolower($section);
|
||||
if (!isset(self::$sections[$file][$lowerSection])) {
|
||||
throw new Exception("Missing section '$section' in file '$file'.");
|
||||
}
|
||||
|
||||
if (in_array($section, array('GET', 'POST', 'SERVER'), TRUE)) {
|
||||
return TestCase::parseLines(self::$sections[$file][$lowerSection], '=');
|
||||
} else {
|
||||
return self::$sections[$file][$lowerSection];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Writes new message.
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
public static function note($message = NULL)
|
||||
{
|
||||
echo $message ? "$message\n\n" : "===\n\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dumps information about a variable in readable format.
|
||||
* @param mixed variable to dump
|
||||
* @param string
|
||||
* @return mixed variable itself or dump
|
||||
*/
|
||||
public static function dump($var, $message = NULL)
|
||||
{
|
||||
if ($message) {
|
||||
echo $message . (preg_match('#[.:?]$#', $message) ? ' ' : ': ');
|
||||
}
|
||||
|
||||
self::_dump($var, 0);
|
||||
echo "\n";
|
||||
return $var;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static function _dump(& $var, $level = 0)
|
||||
{
|
||||
static $tableUtf, $tableBin, $reBinary = '#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u';
|
||||
if ($tableUtf === NULL) {
|
||||
foreach (range("\x00", "\xFF") as $ch) {
|
||||
if (ord($ch) < 32 && strpos("\r\n\t", $ch) === FALSE) $tableUtf[$ch] = $tableBin[$ch] = '\\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT);
|
||||
elseif (ord($ch) < 127) $tableUtf[$ch] = $tableBin[$ch] = $ch;
|
||||
else { $tableUtf[$ch] = $ch; $tableBin[$ch] = '\\x' . dechex(ord($ch)); }
|
||||
}
|
||||
$tableBin["\\"] = '\\\\';
|
||||
$tableBin["\r"] = '\\r';
|
||||
$tableBin["\n"] = '\\n';
|
||||
$tableBin["\t"] = '\\t';
|
||||
$tableUtf['\\x'] = $tableBin['\\x'] = '\\\\x';
|
||||
}
|
||||
|
||||
if (is_bool($var)) {
|
||||
echo ($var ? 'TRUE' : 'FALSE') . "\n";
|
||||
|
||||
} elseif ($var === NULL) {
|
||||
echo "NULL\n";
|
||||
|
||||
} elseif (is_int($var)) {
|
||||
echo "$var\n";
|
||||
|
||||
} elseif (is_float($var)) {
|
||||
$var = (string) $var;
|
||||
if (strpos($var, '.') === FALSE) $var .= '.0';
|
||||
echo "$var\n";
|
||||
|
||||
} elseif (is_string($var)) {
|
||||
$s = strtr($var, preg_match($reBinary, $var) || preg_last_error() ? $tableBin : $tableUtf);
|
||||
echo "\"$s\"\n";
|
||||
|
||||
} elseif (is_array($var)) {
|
||||
echo "array(";
|
||||
$space = str_repeat("\t", $level);
|
||||
|
||||
static $marker;
|
||||
if ($marker === NULL) $marker = uniqid("\x00", TRUE);
|
||||
if (empty($var)) {
|
||||
|
||||
} elseif (isset($var[$marker])) {
|
||||
echo " *RECURSION* ";
|
||||
|
||||
} elseif ($level < self::$maxDepth) {
|
||||
echo "\n";
|
||||
$vector = range(0, count($var) - 1) === array_keys($var);
|
||||
$var[$marker] = 0;
|
||||
foreach ($var as $k => &$v) {
|
||||
if ($k === $marker) continue;
|
||||
if ($vector) {
|
||||
echo "$space\t";
|
||||
} else {
|
||||
$k = is_int($k) ? $k : '"' . strtr($k, preg_match($reBinary, $k) || preg_last_error() ? $tableBin : $tableUtf) . '"';
|
||||
echo "$space\t$k => ";
|
||||
}
|
||||
self::_dump($v, $level + 1);
|
||||
}
|
||||
unset($var[$marker]);
|
||||
echo "$space";
|
||||
|
||||
} else {
|
||||
echo " ... ";
|
||||
}
|
||||
echo ")\n";
|
||||
|
||||
} elseif ($var instanceof Exception) {
|
||||
echo 'Exception ', get_class($var), ': ', ($var->getCode() ? '#' . $var->getCode() . ' ' : '') . $var->getMessage(), "\n";
|
||||
|
||||
} elseif (is_object($var)) {
|
||||
$arr = (array) $var;
|
||||
echo get_class($var) . "(";
|
||||
$space = str_repeat("\t", $level);
|
||||
|
||||
static $list = array();
|
||||
if (empty($arr)) {
|
||||
|
||||
} elseif (in_array($var, $list, TRUE)) {
|
||||
echo " *RECURSION* ";
|
||||
|
||||
} elseif ($level < self::$maxDepth) {
|
||||
echo "\n";
|
||||
$list[] = $var;
|
||||
foreach ($arr as $k => &$v) {
|
||||
$m = '';
|
||||
if ($k[0] === "\x00") {
|
||||
$m = $k[1] === '*' ? ' protected' : ' private';
|
||||
$k = substr($k, strrpos($k, "\x00") + 1);
|
||||
}
|
||||
$k = strtr($k, preg_match($reBinary, $k) || preg_last_error() ? $tableBin : $tableUtf);
|
||||
echo "$space\t\"$k\"$m => ";
|
||||
echo self::_dump($v, $level + 1);
|
||||
}
|
||||
array_pop($list);
|
||||
echo "$space";
|
||||
|
||||
} else {
|
||||
echo " ... ";
|
||||
}
|
||||
echo ")\n";
|
||||
|
||||
} elseif (is_resource($var)) {
|
||||
echo get_resource_type($var) . " resource\n";
|
||||
|
||||
} else {
|
||||
echo "unknown type\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom exception handler.
|
||||
* @param Exception
|
||||
* @return void
|
||||
*/
|
||||
public static function exceptionHandler(Exception $exception)
|
||||
{
|
||||
echo 'Error: Uncaught ';
|
||||
echo $exception;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Coverage saving helper.
|
||||
* @return void
|
||||
*/
|
||||
public static function prepareSaveCoverage()
|
||||
{
|
||||
register_shutdown_function(array(__CLASS__, 'saveCoverage'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Saves information about code coverage.
|
||||
* @return void
|
||||
*/
|
||||
public static function saveCoverage()
|
||||
{
|
||||
$file = dirname(__FILE__) . '/coverage.tmp';
|
||||
$coverage = @unserialize(file_get_contents($file));
|
||||
$root = realpath(dirname(__FILE__) . '/../../Nette') . DIRECTORY_SEPARATOR;
|
||||
|
||||
foreach (xdebug_get_code_coverage() as $filename => $lines) {
|
||||
if (strncmp($root, $filename, strlen($root))) continue;
|
||||
|
||||
foreach ($lines as $num => $val) {
|
||||
if (empty($coverage[$filename][$num]) || $val > 0) {
|
||||
$coverage[$filename][$num] = $val; // -1 => untested; -2 => dead code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents($file, serialize($coverage));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Skips this test.
|
||||
* @return void
|
||||
*/
|
||||
public static function skip($message = 'No message.')
|
||||
{
|
||||
header('X-Nette-Test-Skip: '. $message);
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
230
tests/NetteTest/TestRunner.php
Normal file
230
tests/NetteTest/TestRunner.php
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Nette Framework
|
||||
*
|
||||
* @copyright Copyright (c) 2004 David Grudl
|
||||
* @license http://nette.org/license Nette license
|
||||
* @link http://nette.org
|
||||
* @category Nette
|
||||
* @package Nette\Test
|
||||
*/
|
||||
|
||||
require dirname(__FILE__) . '/TestCase.php';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test runner.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @package Nette\Test
|
||||
*/
|
||||
class TestRunner
|
||||
{
|
||||
const OUTPUT = 'output';
|
||||
const EXPECTED = 'expect';
|
||||
const HEADERS = 'headers';
|
||||
|
||||
/** @var string path to test file/directory */
|
||||
public $path;
|
||||
|
||||
/** @var string php-cgi binary */
|
||||
public $phpBinary;
|
||||
|
||||
/** @var string php-cgi command-line arguments */
|
||||
public $phpArgs;
|
||||
|
||||
/** @var string php-cgi environment variables */
|
||||
public $phpEnvironment;
|
||||
|
||||
/** @var bool display skipped tests information? */
|
||||
public $displaySkipped = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Runs all tests.
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$count = 0;
|
||||
$failed = $passed = $skipped = array();
|
||||
|
||||
if (is_file($this->path)) {
|
||||
$files = array($this->path);
|
||||
} else {
|
||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path));
|
||||
}
|
||||
|
||||
foreach ($files as $entry) {
|
||||
$entry = (string) $entry;
|
||||
$info = pathinfo($entry);
|
||||
if (!isset($info['extension']) || $info['extension'] !== 'phpt') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$count++;
|
||||
$testCase = new TestCase($entry);
|
||||
$testCase->setPhp($this->phpBinary, $this->phpArgs, $this->phpEnvironment);
|
||||
|
||||
try {
|
||||
$testCase->run();
|
||||
echo '.';
|
||||
$passed[] = array($testCase->getName(), $entry);
|
||||
|
||||
} catch (TestCaseException $e) {
|
||||
if ($e->getCode() === TestCaseException::SKIPPED) {
|
||||
echo 's';
|
||||
$skipped[] = array($testCase->getName(), $entry, $e->getMessage());
|
||||
|
||||
} else {
|
||||
echo 'F';
|
||||
$failed[] = array($testCase->getName(), $entry, $e->getMessage());
|
||||
|
||||
$this->log($entry, $testCase->getOutput(), self::OUTPUT);
|
||||
$this->log($entry, $testCase->getExpectedOutput(), self::EXPECTED);
|
||||
|
||||
if ($testCase->getExpectedHeaders() !== NULL) {
|
||||
$this->log($entry, $testCase->getHeaders(), self::OUTPUT, self::HEADERS);
|
||||
$this->log($entry, $testCase->getExpectedHeaders(), self::EXPECTED, self::HEADERS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$failedCount = count($failed);
|
||||
$skippedCount = count($skipped);
|
||||
|
||||
if ($this->displaySkipped && $skippedCount) {
|
||||
echo "\n\nSkipped:\n";
|
||||
foreach ($skipped as $i => $item) {
|
||||
list($name, $file, $message) = $item;
|
||||
echo "\n", ($i + 1), ") $name\n $message\n $file\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!$count) {
|
||||
echo "No tests found\n";
|
||||
|
||||
} elseif ($failedCount) {
|
||||
echo "\n\nFailures:\n";
|
||||
foreach ($failed as $i => $item) {
|
||||
list($name, $file, $message) = $item;
|
||||
echo "\n", ($i + 1), ") $name\n $message\n $file\n";
|
||||
}
|
||||
echo "\nFAILURES! ($count tests, $failedCount failures, $skippedCount skipped)\n";
|
||||
return FALSE;
|
||||
|
||||
} else {
|
||||
echo "\n\nOK ($count tests, $skippedCount skipped)\n";
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns output file for logging.
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
public function log($testFile, $content, $type, $section = '')
|
||||
{
|
||||
$file = dirname($testFile) . '/' . $type . '/' . basename($testFile, '.phpt') . ($section ? ".$section" : '') . '.raw';
|
||||
@mkdir(dirname($file)); // @ - directory may already exist
|
||||
file_put_contents($file, $content);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parses configuration file.
|
||||
* @return void
|
||||
*/
|
||||
public function parseConfigFile()
|
||||
{
|
||||
$configFile = dirname(__FILE__) . '/config.ini';
|
||||
if (file_exists($configFile)) {
|
||||
$this->config = parse_ini_file($configFile, TRUE);
|
||||
if ($this->config === FALSE) {
|
||||
throw new Exception('Config file parsing failed.');
|
||||
}
|
||||
foreach ($this->config as & $environment) {
|
||||
$environment += array(
|
||||
'binary' => 'php-cgi',
|
||||
'args' => '',
|
||||
'environment' => '',
|
||||
);
|
||||
// shorthand options
|
||||
if (isset($environment['php.ini'])) {
|
||||
$environment['args'] .= ' -c '. escapeshellarg($environment['php.ini']);
|
||||
}
|
||||
if (isset($environment['libraries'])) {
|
||||
$environment['environment'] .= 'LD_LIBRARY_PATH='. escapeshellarg($environment['libraries']) .' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parses command line arguments.
|
||||
* @return void
|
||||
*/
|
||||
public function parseArguments()
|
||||
{
|
||||
$this->phpBinary = 'php-cgi';
|
||||
$this->phpArgs = '';
|
||||
$this->phpEnvironment = '';
|
||||
$this->path = getcwd(); // current directory
|
||||
|
||||
$args = new ArrayIterator(array_slice(isset($_SERVER['argv']) ? $_SERVER['argv'] : array(), 1));
|
||||
foreach ($args as $arg) {
|
||||
if (!preg_match('#^[-/][a-z]$#', $arg)) {
|
||||
if ($path = realpath($arg)) {
|
||||
$this->path = $path;
|
||||
} else {
|
||||
throw new Exception("Invalid path '$arg'.");
|
||||
}
|
||||
|
||||
} else switch ($arg[1]) {
|
||||
case 'p':
|
||||
$args->next();
|
||||
$this->phpBinary = $args->current();
|
||||
break;
|
||||
case 'c':
|
||||
case 'd':
|
||||
$args->next();
|
||||
$this->phpArgs .= " -$arg[1] " . escapeshellarg($args->current());
|
||||
break;
|
||||
case 'l':
|
||||
$args->next();
|
||||
$this->phpEnvironment .= 'LD_LIBRARY_PATH='. escapeshellarg($args->current()) . ' ';
|
||||
break;
|
||||
case 'e':
|
||||
$args->next();
|
||||
$name = $args->current();
|
||||
if (!isset($this->config[$name])) {
|
||||
throw new Exception("Unknown environment name '$name'.");
|
||||
}
|
||||
$this->phpBinary = $this->config[$name]['binary'];
|
||||
$this->phpArgs = $this->config[$name]['args'];
|
||||
$this->phpEnvironment = $this->config[$name]['environment'];
|
||||
break;
|
||||
case 's':
|
||||
$this->displaySkipped = TRUE;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown option -$arg[1].");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
67
tests/config.ini
Normal file
67
tests/config.ini
Normal file
@@ -0,0 +1,67 @@
|
||||
[mysql]
|
||||
driver = mysql
|
||||
host = localhost
|
||||
username = dibi
|
||||
password = dibi
|
||||
database = dibi_test
|
||||
charset = utf8
|
||||
|
||||
[mysqli]
|
||||
driver = mysqli
|
||||
host = localhost
|
||||
username = dibi
|
||||
password = dibi
|
||||
database = dibi_test
|
||||
charset = utf8
|
||||
|
||||
[sqlite]
|
||||
driver = sqlite
|
||||
database = DIR "/data/sample.sdb"
|
||||
|
||||
[sqlite3]
|
||||
driver = sqlite3
|
||||
database = DIR "/data/sample.sdb3"
|
||||
|
||||
[odbc]
|
||||
driver = odbc
|
||||
username = dibi
|
||||
password = dibi
|
||||
dsn = "Driver={Microsoft Access Driver (*.mdb)};Dbq=" DIR "/data/sample.mdb"
|
||||
|
||||
[postgresql]
|
||||
driver = postgre
|
||||
host = localhost
|
||||
port = 5432
|
||||
username = dibi
|
||||
password = dibi
|
||||
database = dibi_test
|
||||
persistent = TRUE
|
||||
|
||||
[sqlite-pdo]
|
||||
driver = pdo
|
||||
dsn = "sqlite2::" DIR "/data/sample.sdb"
|
||||
|
||||
[mysql-pdo]
|
||||
driver = pdo
|
||||
dsn = "mysql:dbname=dibi_test;host=localhost"
|
||||
username = dibi
|
||||
password = dibi
|
||||
|
||||
[mssql]
|
||||
driver = mssql
|
||||
host = localhost
|
||||
username = dibi
|
||||
password = dibi
|
||||
|
||||
[mssql2005]
|
||||
driver = mssql2005
|
||||
host = "(local)"
|
||||
username = dibi
|
||||
password = dibi
|
||||
database = dibi_test
|
||||
|
||||
[oracle]
|
||||
driver = oracle
|
||||
username = dibi
|
||||
password = dibi
|
||||
database = dibi_test
|
BIN
tests/data/sample.mdb
Normal file
BIN
tests/data/sample.mdb
Normal file
Binary file not shown.
149
tests/data/sample.mysql
Normal file
149
tests/data/sample.mysql
Normal file
@@ -0,0 +1,149 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 2.11.1.2
|
||||
-- http://www.phpmyadmin.net
|
||||
--
|
||||
-- Po<50><6F>ta<74>: localhost
|
||||
-- Vygenerov<6F>no: Ned<65>le 02. prosince 2007, 19:49
|
||||
-- Verze MySQL: 5.0.45
|
||||
-- Verze PHP: 5.2.1
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
|
||||
|
||||
--
|
||||
-- Datab<61>ze: `dibi`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktura tabulky `customers`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `customers`;
|
||||
CREATE TABLE IF NOT EXISTS `customers` (
|
||||
`customer_id` int(11) NOT NULL auto_increment,
|
||||
`name` varchar(100) default NULL,
|
||||
PRIMARY KEY (`customer_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
|
||||
|
||||
--
|
||||
-- Vypisuji data pro tabulku `customers`
|
||||
--
|
||||
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES
|
||||
(1, 'Dave Lister'),
|
||||
(2, 'Arnold Rimmer'),
|
||||
(3, 'The Cat'),
|
||||
(4, 'Holly'),
|
||||
(5, 'Kryten'),
|
||||
(6, 'Kristine Kochanski');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktura tabulky `enumtest`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `enumtest`;
|
||||
CREATE TABLE IF NOT EXISTS `enumtest` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`test` enum('a','b','c') NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
|
||||
|
||||
--
|
||||
-- Vypisuji data pro tabulku `enumtest`
|
||||
--
|
||||
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktura tabulky `orders`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `orders`;
|
||||
CREATE TABLE IF NOT EXISTS `orders` (
|
||||
`order_id` int(11) NOT NULL,
|
||||
`customer_id` int(11) NOT NULL,
|
||||
`product_id` int(11) NOT NULL,
|
||||
`amount` float NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Vypisuji data pro tabulku `orders`
|
||||
--
|
||||
|
||||
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES
|
||||
(1, 2, 1, 7),
|
||||
(2, 2, 3, 2),
|
||||
(3, 1, 2, 3),
|
||||
(4, 6, 3, 5);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktura tabulky `products`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `products`;
|
||||
CREATE TABLE IF NOT EXISTS `products` (
|
||||
`product_id` int(11) NOT NULL auto_increment,
|
||||
`title` varchar(100) default NULL,
|
||||
PRIMARY KEY (`product_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
|
||||
|
||||
--
|
||||
-- Vypisuji data pro tabulku `products`
|
||||
--
|
||||
|
||||
INSERT INTO `products` (`product_id`, `title`) VALUES
|
||||
(1, 'Chair'),
|
||||
(2, 'Table'),
|
||||
(3, 'Computer');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktura tabulky `settest`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `settest`;
|
||||
CREATE TABLE IF NOT EXISTS `settest` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`test` set('a','b','c') NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
|
||||
|
||||
--
|
||||
-- Vypisuji data pro tabulku `settest`
|
||||
--
|
||||
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktura tabulky `where`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `where`;
|
||||
CREATE TABLE IF NOT EXISTS `where` (
|
||||
`select` int(11) NOT NULL,
|
||||
`dot.dot` int(11) NOT NULL,
|
||||
`is` int(11) NOT NULL,
|
||||
`quot'n' space` int(11) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Vypisuji data pro tabulku `where`
|
||||
--
|
||||
|
||||
INSERT INTO `where` (`select`, `dot.dot`, `is`, `quot'n' space`) VALUES
|
||||
(1, 2, 3, 4);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
|
||||
SET SQL_MODE="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";
|
||||
|
BIN
tests/data/sample.sdb
Normal file
BIN
tests/data/sample.sdb
Normal file
Binary file not shown.
BIN
tests/data/sample.sdb3
Normal file
BIN
tests/data/sample.sdb3
Normal file
Binary file not shown.
@@ -1,76 +0,0 @@
|
||||
[mysql]
|
||||
driver = mysql
|
||||
host = 127.0.0.1
|
||||
username = root
|
||||
password =
|
||||
charset = utf8
|
||||
system = mysql
|
||||
|
||||
[mysqli]
|
||||
driver = mysqli
|
||||
host = 127.0.0.1
|
||||
username = root
|
||||
password =
|
||||
charset = utf8
|
||||
system = mysql
|
||||
|
||||
[sqlite2]
|
||||
driver = sqlite
|
||||
database = :memory:
|
||||
system = sqlite
|
||||
|
||||
[sqlite3] ; default
|
||||
driver = sqlite3
|
||||
database = :memory:
|
||||
system = sqlite
|
||||
|
||||
[pgsql]
|
||||
driver = postgre
|
||||
host = 127.0.0.1
|
||||
username = postgres
|
||||
password =
|
||||
system = pgsql
|
||||
|
||||
[odbc]
|
||||
driver = odbc
|
||||
dsn = "Driver={Microsoft Access Driver (*.mdb)}Dbq=data/odbc_tmp.mdb"
|
||||
system = odbc
|
||||
|
||||
[mssql]
|
||||
driver = mssql
|
||||
host = 127.0.0.1
|
||||
username = dibi
|
||||
password =
|
||||
system = mssql
|
||||
|
||||
[mssql2005]
|
||||
driver = mssql2005
|
||||
host = (local)
|
||||
username = dibi
|
||||
password =
|
||||
system = mssql
|
||||
|
||||
[oracle]
|
||||
driver = oracle
|
||||
username = dibi
|
||||
password =
|
||||
system = oracle
|
||||
|
||||
[sqlite-pdo]
|
||||
driver = pdo
|
||||
dsn = "sqlite::memory:"
|
||||
system = sqlite
|
||||
|
||||
[mysql-pdo]
|
||||
driver = pdo
|
||||
dsn = "mysql:host=127.0.0.1"
|
||||
username = root
|
||||
password =
|
||||
system = mysql
|
||||
|
||||
[pgsql-pdo]
|
||||
driver = pdo
|
||||
dsn = "pgsql:host=127.0.0.1;dbname=dibi_test"
|
||||
username = postgres
|
||||
password =
|
||||
system = pgsql
|
@@ -1,159 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
|
||||
$ds = $conn->dataSource('SELECT * FROM products');
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM (SELECT * FROM products) t"),
|
||||
(string) $ds
|
||||
);
|
||||
|
||||
|
||||
Assert::same(3, $ds->count());
|
||||
Assert::same(3, $ds->getTotalCount());
|
||||
Assert::same(
|
||||
reformat('SELECT COUNT(*) FROM (SELECT * FROM products) t'),
|
||||
dibi::$sql
|
||||
);
|
||||
|
||||
|
||||
$ds->select('title');
|
||||
$ds->orderBy('title', dibi::DESC);
|
||||
$ds->where('title like "%a%"');
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT [title]
|
||||
FROM (SELECT * FROM products) t
|
||||
WHERE (title like '%a%')
|
||||
ORDER BY [title] DESC
|
||||
"),
|
||||
(string) $ds
|
||||
);
|
||||
|
||||
|
||||
$ds->select('product_id');
|
||||
$ds->orderBy('product_id', dibi::ASC);
|
||||
$ds->where('product_id = %i', 1);
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT [title], [product_id]
|
||||
FROM (SELECT * FROM products) t
|
||||
WHERE (title like '%a%') AND (product_id = 1)
|
||||
ORDER BY [title] DESC, [product_id] ASC
|
||||
"),
|
||||
(string) $ds
|
||||
);
|
||||
|
||||
|
||||
$ds->select(array('product_id'));
|
||||
$ds->orderBy(array('product_id' => dibi::ASC));
|
||||
$ds->where(array('product_id = 1'));
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT [product_id]
|
||||
FROM (SELECT * FROM products) t
|
||||
WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1)
|
||||
ORDER BY [product_id] ASC
|
||||
"),
|
||||
(string) $ds
|
||||
);
|
||||
|
||||
|
||||
Assert::same(1, $ds->count());
|
||||
Assert::same(3, $ds->getTotalCount());
|
||||
Assert::match(reformat("SELECT COUNT(*) FROM (
|
||||
SELECT [product_id]
|
||||
FROM (SELECT * FROM products) t
|
||||
WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1)
|
||||
ORDER BY [product_id] ASC
|
||||
) t"), dibi::$sql);
|
||||
Assert::same(1, $ds->toDataSource()->count());
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
new DibiRow(array(
|
||||
'product_id' => 1,
|
||||
)),
|
||||
), iterator_to_array($ds));
|
||||
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT [product_id]
|
||||
FROM (SELECT * FROM products) t
|
||||
WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1)
|
||||
ORDER BY [product_id] ASC
|
||||
"),
|
||||
dibi::$sql
|
||||
);
|
||||
|
||||
|
||||
$fluent = $ds->toFluent();
|
||||
Assert::same(1, $fluent->count());
|
||||
Assert::match(
|
||||
reformat("SELECT * FROM (
|
||||
SELECT [product_id]
|
||||
FROM (SELECT * FROM products) t
|
||||
WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1)
|
||||
ORDER BY [product_id] ASC
|
||||
) t"),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
|
||||
$ds = $conn->select('title')->from('products')->toDataSource();
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM (SELECT [title] FROM [products]) t"),
|
||||
(string) $ds
|
||||
);
|
||||
|
||||
Assert::equal(new DibiRow(array(
|
||||
'product_id' => 1,
|
||||
'title' => 'Chair',
|
||||
)), $conn->dataSource('SELECT * FROM products ORDER BY product_id')->fetch());
|
||||
|
||||
Assert::same(1, $conn->dataSource('SELECT * FROM products ORDER BY product_id')->fetchSingle());
|
||||
|
||||
Assert::same(
|
||||
array(1 => 'Chair', 'Table', 'Computer'),
|
||||
$conn->dataSource('SELECT * FROM products ORDER BY product_id')->fetchPairs()
|
||||
);
|
||||
|
||||
Assert::equal(array(
|
||||
1 => new DibiRow(array(
|
||||
'product_id' => 1,
|
||||
'title' => 'Chair',
|
||||
)),
|
||||
new DibiRow(array(
|
||||
'product_id' => 2,
|
||||
'title' => 'Table',
|
||||
)),
|
||||
new DibiRow(array(
|
||||
'product_id' => 3,
|
||||
'title' => 'Computer',
|
||||
)),
|
||||
), $conn->dataSource('SELECT * FROM products ORDER BY product_id')->fetchAssoc('product_id'));
|
||||
|
||||
|
||||
$ds = new DibiDataSource('products', $conn);
|
||||
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM [products]"),
|
||||
(string) $ds
|
||||
);
|
||||
|
||||
Assert::same(3, $ds->count());
|
||||
Assert::same(3, $ds->getTotalCount());
|
||||
Assert::same(reformat('SELECT COUNT(*) FROM [products]'), dibi::$sql);
|
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
|
||||
$conn->query('INSERT INTO products', array(
|
||||
'title' => 'Test product',
|
||||
));
|
||||
Assert::same(1, $conn->getAffectedRows());
|
||||
|
||||
|
||||
$conn->query('UPDATE products SET title="xxx" WHERE product_id > 100');
|
||||
Assert::same(0, $conn->getAffectedRows());
|
||||
|
||||
|
||||
$conn->query('UPDATE products SET title="xxx"');
|
||||
Assert::same(4, $conn->getAffectedRows());
|
||||
|
||||
|
||||
$conn->query('DELETE FROM orders');
|
||||
$conn->query('DELETE FROM products WHERE product_id > 100');
|
||||
Assert::same(0, $conn->getAffectedRows());
|
||||
|
||||
|
||||
$conn->query('DELETE FROM products WHERE product_id < 3');
|
||||
Assert::same(2, $conn->getAffectedRows());
|
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
test(function() use ($config) {
|
||||
$conn = new DibiConnection($config);
|
||||
Assert::true($conn->isConnected());
|
||||
|
||||
$conn->disconnect();
|
||||
Assert::false($conn->isConnected());
|
||||
});
|
||||
|
||||
|
||||
test(function() use ($config) { // lazy
|
||||
$conn = new DibiConnection($config + array('lazy' => TRUE));
|
||||
Assert::false($conn->isConnected());
|
||||
|
||||
$conn->query('SELECT 1');
|
||||
Assert::true($conn->isConnected());
|
||||
});
|
||||
|
||||
|
||||
test(function() use ($config) { // query string
|
||||
$conn = new DibiConnection(http_build_query($config, NULL, '&'));
|
||||
Assert::true($conn->isConnected());
|
||||
|
||||
Assert::null($conn->getConfig('lazy'));
|
||||
Assert::same($config['driver'], $conn->getConfig('driver'));
|
||||
Assert::type('IDibiDriver', $conn->getDriver());
|
||||
});
|
@@ -1,329 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
|
||||
function num($n)
|
||||
{
|
||||
global $config;
|
||||
if (substr(@$config['dsn'], 0, 5) === 'odbc:' || $config['driver'] === 'sqlite') {
|
||||
$n = is_float($n) ? "$n.0" : (string) $n;
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
|
||||
// fetch a single value
|
||||
$res = $conn->query('SELECT [title] FROM [products]');
|
||||
Assert::same('Chair', $res->fetchSingle());
|
||||
|
||||
|
||||
// fetch complete result set
|
||||
$res = $conn->query('SELECT * FROM [products] ORDER BY product_id');
|
||||
Assert::equal(array(
|
||||
new DibiRow(array('product_id' => num(1), 'title' => 'Chair')),
|
||||
new DibiRow(array('product_id' => num(2), 'title' => 'Table')),
|
||||
new DibiRow(array('product_id' => num(3), 'title' => 'Computer')),
|
||||
), $res->fetchAll());
|
||||
|
||||
|
||||
// fetch complete result set like pairs key => value
|
||||
$res = $conn->query('SELECT * FROM [products] ORDER BY product_id');
|
||||
Assert::same(
|
||||
array(1 => 'Chair', 'Table', 'Computer'),
|
||||
$res->fetchPairs('product_id', 'title')
|
||||
);
|
||||
|
||||
$res = $conn->query('SELECT * FROM [products] ORDER BY product_id');
|
||||
Assert::same(
|
||||
array(1 => 'Chair', 'Table', 'Computer'),
|
||||
$res->fetchPairs()
|
||||
);
|
||||
|
||||
|
||||
// fetch row by row
|
||||
$res = $conn->query('SELECT * FROM [products] ORDER BY product_id');
|
||||
Assert::equal(array(
|
||||
new DibiRow(array('product_id' => num(1), 'title' => 'Chair')),
|
||||
new DibiRow(array('product_id' => num(2), 'title' => 'Table')),
|
||||
new DibiRow(array('product_id' => num(3), 'title' => 'Computer')),
|
||||
), iterator_to_array($res));
|
||||
|
||||
|
||||
// fetch complete result set like association array
|
||||
$res = $conn->query('SELECT * FROM [products] ORDER BY product_id');
|
||||
Assert::equal(array(
|
||||
'Chair' => new DibiRow(array('product_id' => num(1), 'title' => 'Chair')),
|
||||
'Table' => new DibiRow(array('product_id' => num(2), 'title' => 'Table')),
|
||||
'Computer' => new DibiRow(array('product_id' => num(3), 'title' => 'Computer')),
|
||||
), $res->fetchAssoc('title'));
|
||||
|
||||
|
||||
|
||||
// more complex association array
|
||||
function query($conn) {
|
||||
|
||||
return $conn->query($conn->getConfig('system') === 'odbc' ? '
|
||||
SELECT products.title, customers.name, orders.amount
|
||||
FROM ([products]
|
||||
INNER JOIN [orders] ON [products.product_id] = [orders.product_id])
|
||||
INNER JOIN [customers] ON [orders.customer_id] = [customers.customer_id]
|
||||
ORDER BY orders.order_id
|
||||
' : '
|
||||
SELECT products.title AS title, customers.name AS name, orders.amount AS amount
|
||||
FROM [products]
|
||||
INNER JOIN [orders] USING ([product_id])
|
||||
INNER JOIN [customers] USING ([customer_id])
|
||||
ORDER BY orders.order_id
|
||||
');
|
||||
}
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
), query($conn)->fetchAssoc('name,title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
),
|
||||
array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
),
|
||||
), query($conn)->fetchAssoc('name,#,title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
'title' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'name' => 'Arnold Rimmer',
|
||||
'amount' => num(7.0),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
'title' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'name' => 'Dave Lister',
|
||||
'amount' => num(3.0),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
'title' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
'name' => 'Kristine Kochanski',
|
||||
'amount' => num(5.0),
|
||||
),
|
||||
), query($conn)->fetchAssoc('name,=,title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'name' => 'Arnold Rimmer',
|
||||
'amount' => num(7.0),
|
||||
)),
|
||||
'Dave Lister' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'name' => 'Dave Lister',
|
||||
'amount' => num(3.0),
|
||||
)),
|
||||
'Kristine Kochanski' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
'name' => 'Kristine Kochanski',
|
||||
'amount' => num(5.0),
|
||||
)),
|
||||
), query($conn)->fetchAssoc('name,@,title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
new DibiRow(array(
|
||||
'title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
new DibiRow(array(
|
||||
'title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
new DibiRow(array(
|
||||
'title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
), query($conn)->fetchAssoc('@,='));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
'title' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'name' => 'Arnold Rimmer',
|
||||
'amount' => num(7.0),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
'title' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'name' => 'Dave Lister',
|
||||
'amount' => num(3.0),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
'title' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
'name' => 'Kristine Kochanski',
|
||||
'amount' => num(5.0),
|
||||
),
|
||||
), query($conn)->fetchAssoc('name,=,title,@'));
|
||||
|
||||
|
||||
// old syntax
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
), query($conn)->fetchAssoc('name|title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
),
|
||||
array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
),
|
||||
), query($conn)->fetchAssoc('name[]title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'name' => 'Arnold Rimmer',
|
||||
'amount' => num(7.0),
|
||||
)),
|
||||
'Dave Lister' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'name' => 'Dave Lister',
|
||||
'amount' => num(3.0),
|
||||
)),
|
||||
'Kristine Kochanski' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
'name' => 'Kristine Kochanski',
|
||||
'amount' => num(5.0),
|
||||
)),
|
||||
), query($conn)->fetchAssoc('name->title'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => new DibiRow(array(
|
||||
'title' => array('Chair' => 'Arnold Rimmer', 'Computer' => 'Arnold Rimmer'),
|
||||
'name' => 'Arnold Rimmer',
|
||||
'amount' => num(7.0),
|
||||
)),
|
||||
'Dave Lister' => new DibiRow(array(
|
||||
'title' => array('Table' => 'Dave Lister'),
|
||||
'name' => 'Dave Lister',
|
||||
'amount' => num(3.0),
|
||||
)),
|
||||
'Kristine Kochanski' => new DibiRow(array(
|
||||
'title' => array('Computer' => 'Kristine Kochanski'),
|
||||
'name' => 'Kristine Kochanski',
|
||||
'amount' => num(5.0),
|
||||
)),
|
||||
), query($conn)->fetchAssoc('name->title=name'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
), query($conn)->fetchAssoc('[]'));
|
||||
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'name' => 'Arnold Rimmer',
|
||||
'amount' => num(7.0),
|
||||
)),
|
||||
'Dave Lister' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'name' => 'Dave Lister',
|
||||
'amount' => num(3.0),
|
||||
)),
|
||||
'Kristine Kochanski' => new DibiRow(array(
|
||||
'title' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
'name' => 'Kristine Kochanski',
|
||||
'amount' => num(5.0),
|
||||
)),
|
||||
), query($conn)->fetchAssoc('name->title->'));
|
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
// create new substitution :blog: ==> wp_
|
||||
$conn->getSubstitutes()->blog = 'wp_';
|
||||
|
||||
Assert::same(
|
||||
reformat('UPDATE wp_items SET [text]=\'Hello World\''),
|
||||
$conn->translate("UPDATE :blog:items SET [text]='Hello World'")
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('UPDATE \'wp_\' SET [text]=\'Hello World\''),
|
||||
$conn->translate("UPDATE :blog: SET [text]='Hello World'")
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('UPDATE \':blg:\' SET [text]=\'Hello World\''),
|
||||
$conn->translate("UPDATE :blg: SET [text]='Hello World'")
|
||||
);
|
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
|
||||
/*Assert::exception(function() use ($conn) {
|
||||
$conn->rollback();
|
||||
}, 'DibiException');
|
||||
|
||||
Assert::exception(function() use ($conn) {
|
||||
$conn->commit();
|
||||
}, 'DibiException');
|
||||
|
||||
$conn->begin();
|
||||
Assert::exception(function() use ($conn) {
|
||||
$conn->begin();
|
||||
}, 'DibiException');
|
||||
*/
|
||||
|
||||
|
||||
$conn->begin();
|
||||
Assert::same(3, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||
$conn->query('INSERT INTO [products]', array(
|
||||
'title' => 'Test product',
|
||||
));
|
||||
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||
$conn->rollback();
|
||||
Assert::same(3, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||
|
||||
|
||||
|
||||
|
||||
$conn->begin();
|
||||
$conn->query('INSERT INTO [products]', array(
|
||||
'title' => 'Test product',
|
||||
));
|
||||
$conn->commit();
|
||||
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
$fluent = new DibiFluent($conn);
|
||||
$fluent->select('*')->from('table')->where('x=1');
|
||||
$dolly = clone $fluent;
|
||||
$dolly->where('y=1');
|
||||
$dolly->clause('FOO');
|
||||
|
||||
Assert::same( reformat('SELECT * FROM [table] WHERE x=1'), (string) $fluent );
|
||||
Assert::same( reformat('SELECT * FROM [table] WHERE x=1 AND y=1 FOO'), (string) $dolly );
|
||||
|
||||
|
||||
$fluent = new DibiFluent($conn);
|
||||
$fluent->select('id')->from('table')->where('id = %i',1);
|
||||
$dolly = clone $fluent;
|
||||
$dolly->where('cd = %i',5);
|
||||
|
||||
Assert::same( reformat('SELECT [id] FROM [table] WHERE id = 1'), (string) $fluent );
|
||||
Assert::same( reformat('SELECT [id] FROM [table] WHERE id = 1 AND cd = 5'), (string) $dolly );
|
||||
|
||||
|
||||
$fluent = new DibiFluent($conn);
|
||||
$fluent->select("*")->from("table");
|
||||
$dolly = clone $fluent;
|
||||
$dolly->removeClause("select")->select("count(*)");
|
||||
|
||||
Assert::same( reformat('SELECT * FROM [table]'), (string) $fluent );
|
||||
Assert::same( reformat('SELECT count(*) FROM [table]'), (string) $dolly );
|
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
|
||||
$fluent = $conn->delete('table')->as('bAlias')
|
||||
->setFlag('IGNORE');
|
||||
|
||||
Assert::same(
|
||||
reformat('DELETE IGNORE FROM [table] AS [bAlias]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->removeClause('from')->from('anotherTable');
|
||||
|
||||
Assert::same(
|
||||
reformat('DELETE IGNORE FROM [anotherTable]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->using('thirdTable');
|
||||
|
||||
Assert::same(
|
||||
reformat('DELETE IGNORE FROM [anotherTable] USING [thirdTable]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->setFlag('IGNORE', FALSE);
|
||||
|
||||
Assert::same(
|
||||
reformat('DELETE FROM [anotherTable] USING [thirdTable]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->limit(10);
|
||||
|
||||
Assert::same(
|
||||
reformat('DELETE FROM [anotherTable] USING [thirdTable] LIMIT 10'),
|
||||
(string) $fluent
|
||||
);
|
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
|
||||
function num($n)
|
||||
{
|
||||
global $config;
|
||||
if (substr(@$config['dsn'], 0, 5) === 'odbc:' || $config['driver'] === 'sqlite') {
|
||||
$n = is_float($n) ? "$n.0" : (string) $n;
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
|
||||
// fetch a single value
|
||||
$res = $conn->select('title')->from('products')->orderBy('product_id');
|
||||
Assert::equal('Chair', $res->fetchSingle());
|
||||
|
||||
|
||||
// fetch complete result set
|
||||
$res = $conn->select('*')->from('products')->orderBy('product_id');
|
||||
Assert::equal(array(
|
||||
new DibiRow(array('product_id' => num(1), 'title' => 'Chair')),
|
||||
new DibiRow(array('product_id' => num(2), 'title' => 'Table')),
|
||||
new DibiRow(array('product_id' => num(3), 'title' => 'Computer')),
|
||||
), $res->fetchAll());
|
||||
|
||||
|
||||
// more complex association array
|
||||
if ($config['system'] !== 'odbc') {
|
||||
$res = $conn->select(array('products.title' => 'title', 'customers.name' => 'name'))->select('orders.amount')->as('amount')
|
||||
->from('products')
|
||||
->innerJoin('orders')->using('(product_id)')
|
||||
->innerJoin('customers')->using('([customer_id])')
|
||||
->orderBy('order_id');
|
||||
|
||||
Assert::equal(array(
|
||||
'Arnold Rimmer' => array(
|
||||
'Chair' => new DibiRow(array('title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0))),
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0))),
|
||||
),
|
||||
'Dave Lister' => array(
|
||||
'Table' => new DibiRow(array('title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0))),
|
||||
),
|
||||
'Kristine Kochanski' => array(
|
||||
'Computer' => new DibiRow(array('title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0))),
|
||||
),
|
||||
), $res->fetchAssoc('name,title'));
|
||||
}
|
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
|
||||
$arr = array(
|
||||
'title' => 'Super Product',
|
||||
'price' => 12,
|
||||
'brand' => NULL,
|
||||
);
|
||||
|
||||
$fluent = $conn->insert('table', $arr)
|
||||
->setFlag('IGNORE')->setFlag('DELAYED');
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT IGNORE DELAYED INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->setFlag('IGNORE', FALSE);
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT DELAYED INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->setFlag('HIGH_priority');
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT DELAYED HIGH_PRIORITY INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->into('anotherTable');
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT DELAYED HIGH_PRIORITY INTO [anotherTable] VALUES (\'Super Product\', 12, NULL)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->values('%l', $arr);
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT DELAYED HIGH_PRIORITY INTO [anotherTable] VALUES (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->values($arr);
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT DELAYED HIGH_PRIORITY INTO [anotherTable] VALUES (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL)'),
|
||||
(string) $fluent
|
||||
);
|
@@ -1,139 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
|
||||
$max = 10;
|
||||
$min = 5;
|
||||
|
||||
$fluent = $conn->select('*')
|
||||
->select('a')
|
||||
->select('b')->as('bAlias')
|
||||
->select(array('c', 'd', 'e'))
|
||||
->select('%n', 'd');
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->from('table')->as('tableAlias')
|
||||
->innerJoin('table1')->on('table.col = table1.col')
|
||||
->innerJoin('table2')->on('table.col = table2.col');
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [table] AS [tableAlias] INNER JOIN [table1] ON table.col = table1.col INNER JOIN [table2] ON table.col = table2.col'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->from('anotherTable');
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [table] AS [tableAlias] INNER JOIN [table1] ON table.col = table1.col INNER JOIN [table2] ON table.col = table2.col , [anotherTable]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->removeClause('from')->from('anotherTable');
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable]'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->as('anotherAlias')
|
||||
->clause('from')
|
||||
->innerJoin('table3')
|
||||
->on('table.col = table3.col');
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable] AS [anotherAlias] INNER JOIN [table3] ON table.col = table3.col'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->where('col > %i', $max)
|
||||
->or('col < %i', $min)
|
||||
->where('active = 1')
|
||||
->where('col')->in(array(1,2,3))
|
||||
->orderBy('val')->asc()
|
||||
->orderBy('[val2] DESC')
|
||||
->orderBy(array('val3' => -1));
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable] AS [anotherAlias] INNER JOIN [table3] ON table.col = table3.col WHERE col > 10 OR col < 5 AND active = 1 AND [col] IN (1, 2, 3) ORDER BY [val] ASC , [val2] DESC , [val3] DESC'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->orderBy(DibiFluent::REMOVE);
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable] AS [anotherAlias] INNER JOIN [table3] ON table.col = table3.col WHERE col > 10 OR col < 5 AND active = 1 AND [col] IN (1, 2, 3)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
|
||||
try {
|
||||
$fluent = $conn->select('*')->from('table')->fetch();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
Assert::same(
|
||||
reformat(' SELECT * FROM [table] LIMIT 1'),
|
||||
dibi::$sql
|
||||
);
|
||||
|
||||
|
||||
$fluent = $conn->select('*')
|
||||
->select(
|
||||
$conn->select('count(*)')
|
||||
->from('precteni')->as('P')
|
||||
->where('P.id_clanku', '=', 'C.id_clanku')
|
||||
)
|
||||
->from('clanky')->as('C')
|
||||
->where('id_clanku=%i', 123)
|
||||
->limit(1)
|
||||
->offset(0);
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , (SELECT count(*) FROM [precteni] AS [P] WHERE P.id_clanku = C.id_clanku) FROM [clanky] AS [C] WHERE id_clanku=123 LIMIT 1 OFFSET 0'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
|
||||
$fluent = $conn->select('*')
|
||||
->select(array('x' => 'xAlias'))
|
||||
->from('products')
|
||||
->innerJoin('orders')->using('(product_id)')
|
||||
->innerJoin('customers')->using('([customer_id])')
|
||||
->innerJoin('items')->using('(%n)', array('customer_id', 'order_id'));
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * , [x] AS [xAlias] FROM [products] INNER JOIN [orders] USING (product_id) INNER JOIN [customers] USING ([customer_id]) INNER JOIN [items] USING ([customer_id], [order_id])'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
|
||||
|
||||
$fluent = $conn->command()->select()
|
||||
->from('products')
|
||||
->select('*')
|
||||
->innerJoin('orders')->using('(product_id)');
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [products] INNER JOIN [orders] USING (product_id)'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
|
||||
$fluent = $conn->select('*')
|
||||
->from(array('me' => 't'))
|
||||
->where('col > %i', $max)
|
||||
->where(array('x' => 'a', 'b', 'c'));
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [me] AS [t] WHERE col > 10 AND ([x] = \'a\') AND (b) AND (c)'),
|
||||
(string) $fluent
|
||||
);
|
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
|
||||
$arr = array(
|
||||
'title' => 'Super Product',
|
||||
'price' => 12,
|
||||
'brand' => NULL,
|
||||
);
|
||||
|
||||
$fluent = $conn->update('table', $arr)
|
||||
->setFlag('IGNORE')->setFlag('DELAYED');
|
||||
|
||||
Assert::same(
|
||||
reformat('UPDATE IGNORE DELAYED [table] SET [title]=\'Super Product\', [price]=12, [brand]=NULL'),
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->set(array('another' => 123));
|
||||
|
||||
Assert::same(
|
||||
reformat('UPDATE IGNORE DELAYED [table] SET [title]=\'Super Product\', [price]=12, [brand]=NULL , [another]=123'),
|
||||
(string) $fluent
|
||||
);
|
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
if ($config['system'] === 'odbc') {
|
||||
Tester\Environment::skip('Not supported.');
|
||||
}
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
$info = $conn->query('
|
||||
SELECT products.product_id, orders.order_id, customers.name, products.product_id + 1 AS xxx
|
||||
FROM products
|
||||
INNER JOIN orders USING (product_id)
|
||||
INNER JOIN customers USING (customer_id)
|
||||
')->getInfo();
|
||||
|
||||
|
||||
Assert::same(
|
||||
array('product_id', 'order_id', 'name', 'xxx'),
|
||||
$info->getColumnNames()
|
||||
);
|
||||
|
||||
|
||||
if ($config['driver'] !== 'sqlite3' && $config['driver'] !== 'pdo') {
|
||||
Assert::same(
|
||||
array('products.product_id', 'orders.order_id', 'customers.name', 'xxx'),
|
||||
$info->getColumnNames(TRUE)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$columns = $info->getColumns();
|
||||
|
||||
Assert::same('product_id', $columns[0]->name);
|
||||
if ($config['driver'] !== 'sqlite3' && $config['driver'] !== 'pdo') {
|
||||
Assert::same('products', $columns[0]->tableName);
|
||||
}
|
||||
Assert::null($columns[0]->getVendorInfo('xxx'));
|
||||
if ($config['system'] !== 'sqlite') {
|
||||
Assert::same('i', $columns[0]->type);
|
||||
}
|
||||
Assert::null($columns[0]->nullable);
|
||||
|
||||
Assert::same('xxx', $columns[3]->name);
|
||||
Assert::null($columns[3]->tableName);
|
||||
if ($config['system'] !== 'sqlite') {
|
||||
Assert::same('i', $columns[0]->type);
|
||||
}
|
||||
Assert::null($columns[3]->nullable);
|
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
|
||||
|
||||
$res = $conn->query('SELECT * FROM [customers]');
|
||||
|
||||
// auto-converts this column to integer
|
||||
$res->setType('customer_id', Dibi::DATETIME, 'H:i j.n.Y');
|
||||
|
||||
Assert::equal(new DibiRow(array(
|
||||
'customer_id' => new DibiDateTime('1970-01-01 01:00:01'),
|
||||
'name' => 'Dave Lister',
|
||||
)), $res->fetch());
|
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @phpversion 5.5
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$translator = new DibiTranslator($conn);
|
||||
|
||||
$datetime = new DateTime('1978-01-23 00:00:00');
|
||||
|
||||
Assert::equal($datetime->format('U'), $translator->formatValue(new DateTime($datetime->format('c')), NULL));
|
||||
Assert::equal($datetime->format('U'), $translator->formatValue(new DateTimeImmutable($datetime->format('c')), NULL));
|
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
|
||||
// if & end
|
||||
Assert::same(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
/* WHERE ... LIKE ... */"),
|
||||
|
||||
$conn->translate('
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
%if', isset($name), 'WHERE [name] LIKE %s', 'xxx', '%end'
|
||||
));
|
||||
|
||||
|
||||
// if & else & end (last end is optional)
|
||||
Assert::same(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM [customers] /* ... */"),
|
||||
|
||||
$conn->translate('
|
||||
SELECT *
|
||||
FROM %if', TRUE, '[customers] %else [products]'
|
||||
));
|
||||
|
||||
|
||||
// if & else & (optional) end
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] > 0
|
||||
/* AND ...=...
|
||||
*/ AND [bar]=1
|
||||
"),
|
||||
|
||||
$conn->translate("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] > 0
|
||||
%if", FALSE, "AND [foo]=%i", 1, "
|
||||
%else %if", TRUE, "AND [bar]=%i", 1, "
|
||||
"));
|
||||
|
||||
|
||||
// nested condition
|
||||
Assert::match(
|
||||
reformat("
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
WHERE
|
||||
[name] LIKE 'xxx'
|
||||
/* AND ...=1 */
|
||||
/* 1 LIMIT 10 */"),
|
||||
|
||||
$conn->translate('
|
||||
SELECT *
|
||||
FROM [customers]
|
||||
WHERE
|
||||
%if', TRUE, '[name] LIKE %s', 'xxx', '
|
||||
%if', FALSE, 'AND [admin]=1 %end
|
||||
%else 1 LIMIT 10 %end'
|
||||
));
|
||||
|
||||
|
||||
// limit & offset
|
||||
Assert::same(
|
||||
'SELECT * FROM foo /* (limit 3) (offset 5) */',
|
||||
$conn->translate(
|
||||
'SELECT * FROM foo',
|
||||
'%if', FALSE,
|
||||
'%lmt', 3,
|
||||
'%ofs', 5,
|
||||
'%end'
|
||||
));
|
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM where WHERE select < 2'),
|
||||
$conn->translate('SELECT * FROM where WHERE select < 2')
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [where] WHERE where.select < 2'),
|
||||
$conn->translate('SELECT * FROM [where] WHERE where.select < 2')
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [where] WHERE [where].[select] < 2'),
|
||||
$conn->translate('SELECT * FROM [where] WHERE [where.select] < 2')
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [where] as [temp] WHERE [temp].[select] < 2'),
|
||||
$conn->translate('SELECT * FROM [where] as [temp] WHERE [temp.select] < 2')
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [where] WHERE [quot\'n\' space] > 2'),
|
||||
$conn->translate("SELECT * FROM [where] WHERE [quot'n' space] > 2")
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [where] WHERE [where].[quot\'n\' space] > 2'),
|
||||
$conn->translate("SELECT * FROM [where] WHERE [where.quot'n' space] > 2")
|
||||
);
|
@@ -1,531 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
$conn = new DibiConnection($config + array('formatDateTime' => "'Y-m-d H:i:s'", 'formatDate' => "'Y-m-d'"));
|
||||
|
||||
|
||||
// dibi detects INSERT or REPLACE command & booleans
|
||||
Assert::same(
|
||||
reformat("REPLACE INTO [products] ([title], [price]) VALUES ('Drticka', 318)"),
|
||||
$conn->translate('REPLACE INTO [products]', array(
|
||||
'title' => 'Drticka',
|
||||
'price' => 318,
|
||||
)));
|
||||
|
||||
|
||||
// multiple INSERT command
|
||||
$array = array(
|
||||
'title' => 'Super Product',
|
||||
'price' => 12,
|
||||
'brand' => NULL,
|
||||
);
|
||||
Assert::same(
|
||||
reformat('INSERT INTO [products] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL)'),
|
||||
$conn->translate("INSERT INTO [products]", $array, $array, $array)
|
||||
);
|
||||
|
||||
|
||||
// multiple INSERT command II
|
||||
$array = array(
|
||||
array('pole' => 'hodnota1', 'bit' => 1),
|
||||
array('pole' => 'hodnota2', 'bit' => 1),
|
||||
array('pole' => 'hodnota3', 'bit' => 1)
|
||||
);
|
||||
Assert::same(
|
||||
reformat('INSERT INTO [products] ([pole], [bit]) VALUES (\'hodnota1\', 1) , (\'hodnota2\', 1) , (\'hodnota3\', 1)'),
|
||||
$conn->translate("INSERT INTO [products] %ex", $array)
|
||||
);
|
||||
|
||||
|
||||
// dibi detects UPDATE command
|
||||
Assert::same(
|
||||
reformat("UPDATE [colors] SET [color]='blue', [order]=12 WHERE [id]=123"),
|
||||
$conn->translate('UPDATE [colors] SET', array(
|
||||
'color' => 'blue',
|
||||
'order' => 12,
|
||||
), "WHERE [id]=%i", 123));
|
||||
|
||||
|
||||
// IN array
|
||||
$array = array(1, 2, 3);
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [people] WHERE [id] IN ( 1, 2, 3 )'),
|
||||
$conn->translate("SELECT * FROM [people] WHERE [id] IN (", $array, ")")
|
||||
);
|
||||
|
||||
|
||||
// long numbers
|
||||
Assert::same(
|
||||
reformat('SELECT -123456789123456789123456789'),
|
||||
$conn->translate("SELECT %i", '-123456789123456789123456789')
|
||||
);
|
||||
|
||||
// long float numbers
|
||||
Assert::same(
|
||||
reformat('SELECT -.12345678912345678912345678e10'),
|
||||
$conn->translate("SELECT %f", '-.12345678912345678912345678e10')
|
||||
);
|
||||
|
||||
// hex numbers
|
||||
Assert::same(
|
||||
reformat('SELECT 17'),
|
||||
$conn->translate("SELECT %i", '0x11')
|
||||
);
|
||||
|
||||
// invalid input
|
||||
$e = Assert::exception(function() use ($conn) {
|
||||
$conn->translate("SELECT %s", (object) array(123), ', %m', 123);
|
||||
}, 'DibiException', 'SQL translate error');
|
||||
Assert::same('SELECT **Unexpected type object** , **Unknown or invalid modifier %m**', $e->getSql());
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [table] WHERE id=10 AND name=\'ahoj\''),
|
||||
$conn->translate('SELECT * FROM [table] WHERE id=%i AND name=%s', 10, 'ahoj')
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('TEST ([cond] > 2) OR ([cond2] = \'3\') OR (cond3 < RAND())'),
|
||||
$conn->translate('TEST %or', array('[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()'))
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('TEST ([cond] > 2) AND ([cond2] = \'3\') AND (cond3 < RAND())'),
|
||||
$conn->translate('TEST %and', array('[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()'))
|
||||
);
|
||||
|
||||
//
|
||||
$where = array();
|
||||
$where[] = '[age] > 20';
|
||||
$where[] = '[email] IS NOT NULL';
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [table] WHERE ([age] > 20) AND ([email] IS NOT NULL)'),
|
||||
$conn->translate('SELECT * FROM [table] WHERE %and', $where)
|
||||
);
|
||||
|
||||
|
||||
$where = array();
|
||||
$where['age'] = NULL;
|
||||
$where['email'] = 'ahoj';
|
||||
$where['id%l'] = array(10, 20, 30);
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [table] WHERE ([age] IS NULL) AND ([email] = \'ahoj\') AND ([id] IN (10, 20, 30))'),
|
||||
$conn->translate('SELECT * FROM [table] WHERE %and', $where)
|
||||
);
|
||||
|
||||
|
||||
$where = array();
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [table] WHERE 1=1'),
|
||||
$conn->translate('SELECT * FROM [table] WHERE %and', $where)
|
||||
);
|
||||
|
||||
|
||||
// ORDER BY array
|
||||
$order = array(
|
||||
'field1' => 'asc',
|
||||
'field2' => 'desc',
|
||||
'field3' => 1,
|
||||
'field4' => -1,
|
||||
'field5' => TRUE,
|
||||
'field6' => FALSE,
|
||||
);
|
||||
Assert::same(
|
||||
reformat("SELECT * FROM [people] ORDER BY [field1] ASC, [field2] DESC, [field3] ASC, [field4] DESC, [field5] ASC, [field6] DESC"),
|
||||
$conn->translate("SELECT * FROM [people] ORDER BY %by", $order)
|
||||
);
|
||||
|
||||
|
||||
// with limit = 2
|
||||
Assert::same(
|
||||
reformat(array(
|
||||
'odbc' => 'SELECT TOP 2 * FROM (SELECT * FROM [products] ) t',
|
||||
'SELECT * FROM [products] LIMIT 2',
|
||||
)),
|
||||
$conn->translate('SELECT * FROM [products] %lmt', 2)
|
||||
);
|
||||
|
||||
if ($config['system'] === 'odbc') {
|
||||
Assert::exception(function() use ($conn) {
|
||||
$conn->translate('SELECT * FROM [products] %lmt %ofs', 2, 1);
|
||||
}, 'DibiException');
|
||||
} else {
|
||||
// with limit = 2, offset = 1
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [products] LIMIT 2 OFFSET 1'),
|
||||
$conn->translate('SELECT * FROM [products] %lmt %ofs', 2, 1)
|
||||
);
|
||||
|
||||
// with offset = 50
|
||||
Assert::same(
|
||||
reformat(array(
|
||||
'mysql' => 'SELECT * FROM `products` LIMIT 18446744073709551615 OFFSET 50',
|
||||
'pgsql' => 'SELECT * FROM "products" OFFSET 50',
|
||||
'SELECT * FROM [products] LIMIT -1 OFFSET 50',
|
||||
)),
|
||||
$conn->translate('SELECT * FROM [products] %ofs', 50)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat(array(
|
||||
'odbc' => 'INSERT INTO test ([a2], [a4], [b1], [b2], [b3], [b4], [b5], [b6], [b7], [b8], [b9]) VALUES (#09/26/1212 00:00:00#, #12/31/1969 22:13:20#, #09/26/1212#, #09/26/1212 00:00:00#, #12/31/1969#, #12/31/1969 22:13:20#, #09/26/1212 00:00:00#, #09/26/1212#, #09/26/1212 00:00:00#, NULL, NULL)',
|
||||
"INSERT INTO test ([a2], [a4], [b1], [b2], [b3], [b4], [b5], [b6], [b7], [b8], [b9]) VALUES ('1212-09-26 00:00:00', '1969-12-31 22:13:20', '1212-09-26', '1212-09-26 00:00:00', '1969-12-31', '1969-12-31 22:13:20', '1212-09-26 00:00:00', '1212-09-26', '1212-09-26 00:00:00', NULL, NULL)",
|
||||
)),
|
||||
$conn->translate("INSERT INTO test", array(
|
||||
'a2' => new DibiDateTime('1212-09-26'),
|
||||
'a4' => new DibiDateTime(-10000),
|
||||
'b1%d' => '1212-09-26',
|
||||
'b2%t' => '1212-09-26',
|
||||
'b3%d' => -10000,
|
||||
'b4%t' => -10000,
|
||||
'b5' => new DateTime('1212-09-26'),
|
||||
'b6%d' => new DateTime('1212-09-26'),
|
||||
'b7%t' => new DateTime('1212-09-26'),
|
||||
'b8%d' => NULL,
|
||||
'b9%t' => NULL,
|
||||
)));
|
||||
|
||||
|
||||
|
||||
// like
|
||||
$args = array(
|
||||
"SELECT * FROM products WHERE (title LIKE %like~ AND title LIKE %~like) OR title LIKE %~like~",
|
||||
'C',
|
||||
'r',
|
||||
"a\n%_\\'\""
|
||||
);
|
||||
|
||||
if ($config['system'] === 'pgsql') {
|
||||
$conn->query('SET escape_string_warning = off'); // do not log warnings
|
||||
|
||||
$conn->query('SET standard_conforming_strings = off');
|
||||
Assert::same(
|
||||
"SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\\\%\\\\_\\\\\\\\''\"%'",
|
||||
$conn->translate($args[0], $args[1], $args[2], $args[3])
|
||||
);
|
||||
|
||||
$conn->query('SET standard_conforming_strings = on');
|
||||
Assert::same(
|
||||
"SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\%\\_\\\\''\"%'",
|
||||
$conn->translate($args[0], $args[1], $args[2], $args[3])
|
||||
);
|
||||
|
||||
} elseif ($config['driver'] !== 'sqlite') { // sqlite2
|
||||
Assert::same(
|
||||
reformat(array(
|
||||
'sqlite' => "SELECT * FROM products WHERE (title LIKE 'C%' ESCAPE '\\' AND title LIKE '%r' ESCAPE '\\') OR title LIKE '%a\n\\%\\_\\\\''\"%' ESCAPE '\\'",
|
||||
'odbc' => "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n[%][_]\\''\"%'",
|
||||
"SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\\n\\%\\_\\\\\\\\\'\"%'",
|
||||
)),
|
||||
$conn->translate($args[0], $args[1], $args[2], $args[3])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$e = Assert::exception(function() use ($conn) {
|
||||
$conn->translate("SELECT '");
|
||||
}, 'DibiException', 'SQL translate error');
|
||||
Assert::same('SELECT **Alone quote**', $e->getSql());
|
||||
|
||||
Assert::match(
|
||||
reformat(array(
|
||||
'mysql' => "SELECT DISTINCT HIGH_PRIORITY SQL_BUFFER_RESULT
|
||||
CONCAT(last_name, ', ', first_name) AS full_name
|
||||
GROUP BY `user`
|
||||
HAVING MAX(salary) > %i 123
|
||||
INTO OUTFILE '/tmp/result\'.txt'
|
||||
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\\\"'
|
||||
LINES TERMINATED BY '\\\\n'
|
||||
",
|
||||
"SELECT DISTINCT HIGH_PRIORITY SQL_BUFFER_RESULT
|
||||
CONCAT(last_name, ', ', first_name) AS full_name
|
||||
GROUP BY [user]
|
||||
HAVING MAX(salary) > %i 123
|
||||
INTO OUTFILE '/tmp/result''.txt'
|
||||
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'
|
||||
LINES TERMINATED BY '\\n'
|
||||
"
|
||||
)),
|
||||
$conn->translate('%sql', "SELECT DISTINCT HIGH_PRIORITY SQL_BUFFER_RESULT
|
||||
CONCAT(last_name, \", \", first_name) AS full_name
|
||||
GROUP BY [user]
|
||||
HAVING MAX(salary) > %i", 123, "
|
||||
INTO OUTFILE '/tmp/result''.txt'
|
||||
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'
|
||||
LINES TERMINATED BY '\\n'
|
||||
")
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$array1 = array(1, 2, 3);
|
||||
$array2 = array('one', 'two', 'three');
|
||||
$array3 = array(
|
||||
'col1' => 'one',
|
||||
'col2' => 'two',
|
||||
'col3' => 'three',
|
||||
);
|
||||
$array4 = array(
|
||||
'a' => 12,
|
||||
'b' => NULL,
|
||||
'c' => new DibiDateTime('12.3.2007'),
|
||||
'd' => 'any string',
|
||||
);
|
||||
|
||||
$array5 = array('RAND()', '[col1] > [col2]');
|
||||
|
||||
|
||||
Assert::match(
|
||||
reformat(array(
|
||||
'mysql' => "SELECT *
|
||||
FROM `db`.`table`
|
||||
WHERE (`test`.`a` LIKE '1995-03-01'
|
||||
OR `b1` IN ( 1, 2, 3 )
|
||||
OR `b2` IN ('1', '2', '3' )
|
||||
OR `b3` IN ( )
|
||||
OR `b4` IN ( 'one', 'two', 'three' )
|
||||
OR `b5` IN (`col1` AS `one`, `col2` AS `two`, `col3` AS `three` )
|
||||
OR `b6` IN ('one', 'two', 'three')
|
||||
OR `b7` IN (NULL)
|
||||
OR `b8` IN (RAND() `col1` > `col2` )
|
||||
OR `b9` IN ( )
|
||||
AND `c` = 'embedded \' string'
|
||||
OR `d`=10
|
||||
OR `e`=NULL
|
||||
OR `true`= 1
|
||||
OR `false`= 0
|
||||
OR `str_null`=NULL
|
||||
OR `str_not_null`='hello'
|
||||
LIMIT 10",
|
||||
'pgsql' => 'SELECT *
|
||||
FROM "db"."table"
|
||||
WHERE ("test"."a" LIKE \'1995-03-01\'
|
||||
OR "b1" IN ( 1, 2, 3 )
|
||||
OR "b2" IN (\'1\', \'2\', \'3\' )
|
||||
OR "b3" IN ( )
|
||||
OR "b4" IN ( \'one\', \'two\', \'three\' )
|
||||
OR "b5" IN ("col1" AS "one", "col2" AS "two", "col3" AS "three" )
|
||||
OR "b6" IN (\'one\', \'two\', \'three\')
|
||||
OR "b7" IN (NULL)
|
||||
OR "b8" IN (RAND() "col1" > "col2" )
|
||||
OR "b9" IN ( )
|
||||
AND "c" = \'embedded \'\' string\'
|
||||
OR "d"=10
|
||||
OR "e"=NULL
|
||||
OR "true"= TRUE
|
||||
OR "false"= FALSE
|
||||
OR "str_null"=NULL
|
||||
OR "str_not_null"=\'hello\'
|
||||
LIMIT 10',
|
||||
'odbc' => "SELECT *
|
||||
FROM [db].[table]
|
||||
WHERE ([test].[a] LIKE #03/01/1995#
|
||||
OR [b1] IN ( 1, 2, 3 )
|
||||
OR [b2] IN ('1', '2', '3' )
|
||||
OR [b3] IN ( )
|
||||
OR [b4] IN ( 'one', 'two', 'three' )
|
||||
OR [b5] IN ([col1] AS [one], [col2] AS [two], [col3] AS [three] )
|
||||
OR [b6] IN ('one', 'two', 'three')
|
||||
OR [b7] IN (NULL)
|
||||
OR [b8] IN (RAND() [col1] > [col2] )
|
||||
OR [b9] IN ( )
|
||||
AND [c] = 'embedded '' string'
|
||||
OR [d]=10
|
||||
OR [e]=NULL
|
||||
OR [true]= 1
|
||||
OR [false]= 0
|
||||
OR [str_null]=NULL
|
||||
OR [str_not_null]='hello'
|
||||
LIMIT 10",
|
||||
"SELECT *
|
||||
FROM [db].[table]
|
||||
WHERE ([test].[a] LIKE '1995-03-01'
|
||||
OR [b1] IN ( 1, 2, 3 )
|
||||
OR [b2] IN ('1', '2', '3' )
|
||||
OR [b3] IN ( )
|
||||
OR [b4] IN ( 'one', 'two', 'three' )
|
||||
OR [b5] IN ([col1] AS [one], [col2] AS [two], [col3] AS [three] )
|
||||
OR [b6] IN ('one', 'two', 'three')
|
||||
OR [b7] IN (NULL)
|
||||
OR [b8] IN (RAND() [col1] > [col2] )
|
||||
OR [b9] IN ( )
|
||||
AND [c] = 'embedded '' string'
|
||||
OR [d]=10
|
||||
OR [e]=NULL
|
||||
OR [true]= 1
|
||||
OR [false]= 0
|
||||
OR [str_null]=NULL
|
||||
OR [str_not_null]='hello'
|
||||
LIMIT 10",
|
||||
)),
|
||||
|
||||
$conn->translate("SELECT *
|
||||
FROM [db.table]
|
||||
WHERE ([test.a] LIKE %d", '1995-03-01', "
|
||||
OR [b1] IN (", $array1, ")
|
||||
OR [b2] IN (%s", $array1, ")
|
||||
OR [b3] IN (%s", array(), ")
|
||||
OR [b4] IN (", $array2, ")
|
||||
OR [b5] IN (%n", $array3, ")
|
||||
OR [b6] IN %l", $array3, "
|
||||
OR [b7] IN %in", array(), "
|
||||
OR [b8] IN (%sql", $array5, ")
|
||||
OR [b9] IN (", array(), ")
|
||||
AND [c] = 'embedded '' string'
|
||||
OR [d]=%i", 10.3, "
|
||||
OR [e]=%i", NULL, "
|
||||
OR [true]=", TRUE, "
|
||||
OR [false]=", FALSE, "
|
||||
OR [str_null]=%sn", '', "
|
||||
OR [str_not_null]=%sn", 'hello', "
|
||||
LIMIT 10")
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('TEST [cond] > 2 [cond2] = \'3\' cond3 < RAND() 123'),
|
||||
$conn->translate('TEST %ex', array('[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()'), 123)
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('TEST ([cond] > 2) OR ([cond2] > 3) OR ([cond3] = 10 + 1)'),
|
||||
$conn->translate('TEST %or', array('`cond` > 2', array('[cond2] > %i', '3'), 'cond3%sql' => array('10 + 1')))
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('TEST ([cond] = 2) OR ([cond3] = RAND())'),
|
||||
$conn->translate('TEST %or', array('cond' => 2, 'cond3%sql' => 'RAND()'))
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('TEST ([cond1] 3) OR ([cond2] RAND()) OR ([cond3] LIKE \'string\')'),
|
||||
$conn->translate('TEST %or', array('cond1%ex' => 3, 'cond2%ex' => 'RAND()', 'cond3%ex' => array('LIKE %s', 'string')))
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat(array(
|
||||
'odbc' => 'SELECT TOP 10 * FROM (SELECT * FROM [test] WHERE [id] LIKE \'%d%t\' ) t',
|
||||
'SELECT * FROM [test] WHERE [id] LIKE \'%d%t\' LIMIT 10',
|
||||
)),
|
||||
$conn->translate("SELECT * FROM [test] WHERE %n LIKE '%d%t' %lmt", 'id', 10)
|
||||
);
|
||||
|
||||
|
||||
$where = array(
|
||||
'tablename.column' => 1,
|
||||
);
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM [tablename] WHERE ([tablename].[column] = 1)'),
|
||||
$conn->translate('SELECT * FROM [tablename] WHERE %and', $where)
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT FROM ... '),
|
||||
$conn->translate('SELECT FROM ... %lmt', NULL)
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT \'%i\''),
|
||||
$conn->translate("SELECT '%i'")
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT \'%i\''),
|
||||
$conn->translate('SELECT "%i"')
|
||||
);
|
||||
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT INTO [products] ([product_id], [title]) VALUES (1, SHA1(\'Test product\')) , (1, SHA1(\'Test product\'))'),
|
||||
$conn->translate('INSERT INTO [products]', array(
|
||||
'product_id' => 1,
|
||||
'title' => array('SHA1(%s)', 'Test product'),
|
||||
), array(
|
||||
'product_id' => 1,
|
||||
'title' => array('SHA1(%s)', 'Test product'),
|
||||
))
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('UPDATE [products] [product_id]=1, [title]=SHA1(\'Test product\')'),
|
||||
$conn->translate('UPDATE [products]', array(
|
||||
'product_id' => 1,
|
||||
'title' => array('SHA1(%s)', 'Test product'),
|
||||
))
|
||||
);
|
||||
|
||||
|
||||
$e = Assert::exception(function() use ($conn) {
|
||||
$array6 = array(
|
||||
'id' => array(1, 2, 3, 4),
|
||||
'text' => array('ahoj', 'jak', 'se', array('SUM(%i)', '5')),
|
||||
'num%i' => array('1', ''),
|
||||
);
|
||||
$conn->translate('INSERT INTO test %m', $array6);
|
||||
}, 'DibiException', 'SQL translate error');
|
||||
Assert::same('INSERT INTO test **Multi-insert array "num%i" is different.**', $e->getSql());
|
||||
|
||||
$array6 = array(
|
||||
'id' => array(1, 2, 3, 4),
|
||||
'text' => array('ahoj', 'jak', 'se', array('SUM(%i)', '5')),
|
||||
'num%i' => array('1', '', 10.3, 1),
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT INTO test ([id], [text], [num]) VALUES (1, \'ahoj\', 1), (2, \'jak\', 0), (3, \'se\', 10), (4, SUM(5), 1)'),
|
||||
$conn->translate('INSERT INTO test %m', $array6)
|
||||
);
|
||||
|
||||
|
||||
$by = array (
|
||||
array('funkce(nazev_pole) ASC'),
|
||||
'jine_pole' => 'DESC'
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('SELECT * FROM table ORDER BY funkce(nazev_pole) ASC, [jine_pole] DESC'),
|
||||
$conn->translate("SELECT * FROM table ORDER BY %by", $by)
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT INTO [test].*'),
|
||||
$conn->translate('INSERT INTO [test.*]')
|
||||
);
|
||||
|
||||
Assert::same(
|
||||
reformat('INSERT INTO 0'),
|
||||
$conn->translate('INSERT INTO %f', 'ahoj')
|
||||
);
|
||||
|
||||
|
||||
setLocale(LC_ALL, 'czech');
|
||||
|
||||
Assert::same(
|
||||
reformat("UPDATE [colors] SET [color]='blue', [price]=-12.4, [spec]=-9E-005, [spec2]=1000, [spec3]=10000, [spec4]=10000 WHERE [price]=123.5"),
|
||||
|
||||
$conn->translate("UPDATE [colors] SET", array(
|
||||
'color' => 'blue',
|
||||
'price' => -12.4,
|
||||
'spec%f' => '-9E-005',
|
||||
'spec2%f' => 1000.00,
|
||||
'spec3%i' => 10000,
|
||||
'spec4' => 10000,
|
||||
), "WHERE [price]=%f", 123.5)
|
||||
);
|
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @dataProvider ../databases.ini
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
if ($config['system'] !== 'pgsql') {
|
||||
Tester\Environment::skip("Not supported system '$config[system]'.");
|
||||
}
|
||||
|
||||
|
||||
$tests = function($conn) {
|
||||
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A_B')->fetchSingle());
|
||||
Assert::true( $conn->query("SELECT 'AA_BB' LIKE %~like~", 'A_B')->fetchSingle());
|
||||
|
||||
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A%B')->fetchSingle());
|
||||
Assert::true( $conn->query("SELECT 'AA%BB' LIKE %~like~", 'A%B')->fetchSingle());
|
||||
|
||||
Assert::same('AA\\BB', $conn->query("SELECT 'AA\\BB'")->fetchSingle());
|
||||
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A\\B')->fetchSingle());
|
||||
Assert::true( $conn->query("SELECT 'AA\\BB' LIKE %~like~", 'A\\B')->fetchSingle());
|
||||
};
|
||||
|
||||
$conn = new DibiConnection($config);
|
||||
$conn->query('SET escape_string_warning = off'); // do not log warnings
|
||||
|
||||
$conn->query('SET standard_conforming_strings = on');
|
||||
$tests($conn);
|
||||
$conn->query('SET standard_conforming_strings = off');
|
||||
$tests($conn);
|
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
// The Nette Tester command-line runner can be
|
||||
// invoked through the command: ../../vendor/bin/tester .
|
||||
|
||||
if (@!include __DIR__ . '/../../vendor/autoload.php') {
|
||||
echo 'Install Nette Tester using `composer update --dev`';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// configure environment
|
||||
Tester\Environment::setup();
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
|
||||
// load connection
|
||||
try {
|
||||
$config = Tester\Environment::loadData();
|
||||
} catch (Exception $e) {
|
||||
$config = parse_ini_file(__DIR__ . '/../databases.ini', TRUE);
|
||||
$config = $config['sqlite3'];
|
||||
}
|
||||
|
||||
|
||||
// lock
|
||||
define('TEMP_DIR', __DIR__ . '/../tmp');
|
||||
@mkdir(TEMP_DIR); // @ - directory may already exist
|
||||
Tester\Environment::lock($config['system'], TEMP_DIR);
|
||||
|
||||
|
||||
// ODBC
|
||||
if ($config['system'] === 'odbc') {
|
||||
copy(__DIR__ . '/data/odbc.mdb', TEMP_DIR . '/odbc.mdb');
|
||||
$config['dsn'] = str_replace('data/odbc.mdb', TEMP_DIR . '/odbc.mdb', $config['dsn']);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
new DibiConnection($config);
|
||||
} catch (DibiNotSupportedException $e) {
|
||||
Tester\Environment::skip($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
function test(\Closure $function)
|
||||
{
|
||||
$function();
|
||||
}
|
||||
|
||||
|
||||
/** Replaces [] with driver-specific quotes */
|
||||
function reformat($s)
|
||||
{
|
||||
global $config;
|
||||
if (is_array($s)) {
|
||||
if (isset($s[$config['system']])) {
|
||||
return $s[$config['system']];
|
||||
}
|
||||
$s = $s[0];
|
||||
}
|
||||
if ($config['system'] === 'mysql') {
|
||||
return strtr($s, '[]', '``');
|
||||
} elseif ($config['system'] === 'pgsql') {
|
||||
return strtr($s, '[]', '""');
|
||||
} elseif ($config['system'] === 'odbc' || $config['system'] === 'sqlite') {
|
||||
return $s;
|
||||
} else {
|
||||
trigger_error("Unsupported driver $config[system]", E_USER_WARNING);
|
||||
}
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
/*!40102 SET storage_engine = InnoDB */;
|
||||
|
||||
DROP DATABASE IF EXISTS dibi_test;
|
||||
CREATE DATABASE dibi_test;
|
||||
USE dibi_test;
|
||||
|
||||
DROP TABLE IF EXISTS `products`;
|
||||
CREATE TABLE `products` (
|
||||
`product_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (`product_id`),
|
||||
KEY `title` (`title`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `products` (`product_id`, `title`) VALUES
|
||||
(1, 'Chair'),
|
||||
(3, 'Computer'),
|
||||
(2, 'Table');
|
||||
|
||||
DROP TABLE IF EXISTS `customers`;
|
||||
CREATE TABLE `customers` (
|
||||
`customer_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (`customer_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES
|
||||
(1, 'Dave Lister'),
|
||||
(2, 'Arnold Rimmer'),
|
||||
(3, 'The Cat'),
|
||||
(4, 'Holly'),
|
||||
(5, 'Kryten'),
|
||||
(6, 'Kristine Kochanski');
|
||||
|
||||
DROP TABLE IF EXISTS `orders`;
|
||||
CREATE TABLE `orders` (
|
||||
`order_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`customer_id` int(11) NOT NULL,
|
||||
`product_id` int(11) NOT NULL,
|
||||
`amount` float NOT NULL,
|
||||
PRIMARY KEY (`order_id`),
|
||||
KEY `customer_id` (`customer_id`),
|
||||
KEY `product_id` (`product_id`),
|
||||
CONSTRAINT `orders_ibfk_4` FOREIGN KEY (`product_id`) REFERENCES `products` (`product_id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `orders_ibfk_3` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES
|
||||
(1, 2, 1, 7),
|
||||
(2, 2, 3, 2),
|
||||
(3, 1, 2, 3),
|
||||
(4, 6, 3, 5);
|
Binary file not shown.
@@ -1,32 +0,0 @@
|
||||
CREATE TABLE products (
|
||||
product_id COUNTER,
|
||||
title TEXT(50)
|
||||
);
|
||||
|
||||
INSERT INTO products (product_id, title) VALUES (1, 'Chair');
|
||||
INSERT INTO products (product_id, title) VALUES (2, 'Table');
|
||||
INSERT INTO products (product_id, title) VALUES (3, 'Computer');
|
||||
|
||||
CREATE TABLE [customers] (
|
||||
[customer_id] COUNTER,
|
||||
[name] TEXT(50)
|
||||
);
|
||||
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES (1, 'Dave Lister');
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES (2, 'Arnold Rimmer');
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES (3, 'The Cat');
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES (4, 'Holly');
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES (5, 'Kryten');
|
||||
INSERT INTO `customers` (`customer_id`, `name`) VALUES (6, 'Kristine Kochanski');
|
||||
|
||||
CREATE TABLE [orders] (
|
||||
[order_id] INTEGER,
|
||||
[customer_id] INTEGER,
|
||||
[product_id] INTEGER,
|
||||
[amount] FLOAT
|
||||
);
|
||||
|
||||
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (1, 2, 1, 7);
|
||||
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (2, 2, 3, 2);
|
||||
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (3, 1, 2, 3);
|
||||
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (4, 6, 3, 5);
|
@@ -1,52 +0,0 @@
|
||||
SET client_encoding = 'UTF8';
|
||||
DROP SCHEMA IF EXISTS public CASCADE;
|
||||
CREATE SCHEMA public;
|
||||
|
||||
CREATE TABLE products (
|
||||
product_id serial NOT NULL,
|
||||
title varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (product_id)
|
||||
);
|
||||
|
||||
INSERT INTO products (product_id, title) VALUES
|
||||
(1, 'Chair'),
|
||||
(2, 'Table'),
|
||||
(3, 'Computer');
|
||||
SELECT setval('products_product_id_seq', 3, TRUE);
|
||||
|
||||
CREATE INDEX title ON products USING btree (title);
|
||||
|
||||
CREATE TABLE customers (
|
||||
customer_id serial NOT NULL,
|
||||
name varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (customer_id)
|
||||
);
|
||||
|
||||
INSERT INTO customers (customer_id, name) VALUES
|
||||
(1, 'Dave Lister'),
|
||||
(2, 'Arnold Rimmer'),
|
||||
(3, 'The Cat'),
|
||||
(4, 'Holly'),
|
||||
(5, 'Kryten'),
|
||||
(6, 'Kristine Kochanski');
|
||||
SELECT setval('customers_customer_id_seq', 6, TRUE);
|
||||
|
||||
CREATE TABLE orders (
|
||||
order_id serial NOT NULL,
|
||||
customer_id integer NOT NULL,
|
||||
product_id integer NOT NULL,
|
||||
amount real NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO orders (order_id, customer_id, product_id, amount) VALUES
|
||||
(1, 2, 1, 7),
|
||||
(2, 2, 3, 2),
|
||||
(3, 1, 2, 3),
|
||||
(4, 6, 3, 5);
|
||||
SELECT setval('orders_order_id_seq', 4, TRUE);
|
||||
|
||||
ALTER TABLE ONLY orders
|
||||
ADD CONSTRAINT orders_customer_id_fkey FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ON UPDATE CASCADE ON DELETE RESTRICT;
|
||||
|
||||
ALTER TABLE ONLY orders
|
||||
ADD CONSTRAINT orders_product_id_fkey FOREIGN KEY (product_id) REFERENCES products(product_id) ON UPDATE CASCADE ON DELETE RESTRICT;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user