1
0
mirror of https://github.com/dg/dibi.git synced 2025-09-02 02:22:33 +02:00

Compare commits

..

8 Commits

Author SHA1 Message Date
David Grudl
2c3fe68c6c Released version 2.1.1 2013-10-16 21:39:29 +02:00
Jan Tvrdik
008371f3e7 composer.json: fix compatibility with dg/dibi requirements 2013-10-16 21:37:29 +02:00
David Grudl
105327f8e6 typos 2013-10-16 21:37:29 +02:00
David Grudl
d04eb76abb typos & whitespace 2013-10-16 21:37:26 +02:00
David Grudl
0b49f7da94 added examples to readme.md 2013-10-16 21:37:11 +02:00
Rossler Jan
0884cd4007 DibiResult: fixed illegal offset type in fetchPairs. 2013-10-16 21:34:09 +02:00
Miloslav Hůla
acc6ecb0d2 DibiResult: fixed normalization of time when begins by 00: 2013-10-16 21:34:08 +02:00
Jáchym Toušek
b21d592e07 Fixed usage of deprecated parameter 2013-10-16 21:34:08 +02:00
111 changed files with 2391 additions and 3606 deletions

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
tests/ export-ignore

View File

@@ -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

View File

@@ -1,31 +1,22 @@
{ {
"name": "dibi/dibi", "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"], "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"], "license": ["BSD-3", "GPLv2", "GPLv3"],
"authors": [ "authors": [
{ {
"name": "David Grudl", "name": "David Grudl",
"homepage": "http://davidgrudl.com" "homepage": "http://davidgrudl.com"
} }
], ],
"require": {
"php": ">=5.2.0"
},
"require-dev": { "require-dev": {
"tracy/tracy": "~2.2", "nette/tester": "@dev"
"nette/tester": "~1.3"
}, },
"replace": { "replace": {
"dg/dibi": "self.version" "dg/dibi": "self.version"
}, },
"autoload": { "autoload": {
"classmap": ["dibi/"] "classmap": ["dibi/"]
},
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
} }
} }

View File

@@ -1,27 +0,0 @@
How to contribute & use the issue tracker
=========================================
The issue tracker is the preferred channel for bug reports, features requests
and submitting pull requests, but please respect the following restrictions:
* Please **do not** use the issue tracker for personal support requests (use
[dibi forum](http://forum.dibiphp.com) or [Stack Overflow](http://stackoverflow.com)).
* Please **do not** derail or troll issues. Keep the discussion on topic and
respect the opinions of others.
* Use the GitHub **issue search** — check if the issue has already been
reported.
A good **bug report** shouldn't leave others needing to chase you up for more
information. Please try to be as detailed as possible in your report.
**Feature requests** are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the project's developers of the merits of this feature.
We welcome **pull requests**. If you'd like to contribute, please take a moment
to [read the guidelines](http://nette.org/en/contributing) in order to make
the contribution process easy and effective for everyone involved.
Thanks!

View File

@@ -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

View File

@@ -2,22 +2,22 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
namespace Dibi\Bridges\Nette;
use dibi,
Nette;
/** /**
* Dibi extension for Nette Framework 2.2. Creates 'connection' & 'panel' services. * Dibi extension for Nette Framework 2.0. Creates 'connection' service.
* *
* @author David Grudl * @author David Grudl
* @package dibi\nette * @package dibi\nette
* @phpversion 5.3
*/ */
class DibiExtension22 extends Nette\DI\CompilerExtension class DibiNette20Extension extends Nette\Config\CompilerExtension
{ {
public function loadConfiguration() public function loadConfiguration()
@@ -27,7 +27,7 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
$useProfiler = isset($config['profiler']) $useProfiler = isset($config['profiler'])
? $config['profiler'] ? $config['profiler']
: class_exists('Tracy\Debugger') && $container->parameters['debugMode']; : !$container->parameters['productionMode'];
unset($config['profiler']); unset($config['profiler']);
@@ -40,13 +40,15 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
} }
$connection = $container->addDefinition($this->prefix('connection')) $connection = $container->addDefinition($this->prefix('connection'))
->setClass('DibiConnection', array($config)) ->setClass('DibiConnection', array($config));
->setAutowired(isset($config['autowired']) ? $config['autowired'] : TRUE);
if ($useProfiler) { if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel')) $panel = $container->addDefinition($this->prefix('panel'))
->setClass('Dibi\Bridges\Tracy\Panel'); ->setClass('DibiNettePanel')
$connection->addSetup(array($panel, 'register'), array($connection)); ->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array('@self'))
->addSetup('Nette\Diagnostics\Debugger::$blueScreen->addPanel(?)', array('DibiNettePanel::renderException'));
$connection->addSetup('$service->onEvent[] = ?', array(array($panel, 'logEvent')));
} }
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -36,8 +40,7 @@ class DibiNette21Extension extends Nette\DI\CompilerExtension
} }
$connection = $container->addDefinition($this->prefix('connection')) $connection = $container->addDefinition($this->prefix('connection'))
->setClass('DibiConnection', array($config)) ->setClass('DibiConnection', array($config));
->setAutowired(isset($config['autowired']) ? $config['autowired'] : TRUE);
if ($useProfiler) { if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel')) $panel = $container->addDefinition($this->prefix('panel'))

View File

@@ -2,10 +2,17 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
use Nette\Diagnostics\Debugger;
if (interface_exists('Nette\Diagnostics\IBarPanel')) {
class_alias('Nette\Diagnostics\IBarPanel', 'IBarPanel');
}
/** /**
@@ -14,7 +21,7 @@ use Nette\Diagnostics\Debugger;
* @author David Grudl * @author David Grudl
* @package dibi\nette * @package dibi\nette
*/ */
class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel class DibiNettePanel extends DibiObject implements IBarPanel
{ {
/** @var int maximum SQL length */ /** @var int maximum SQL length */
static public $maxLength = 1000; static public $maxLength = 1000;
@@ -38,9 +45,24 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
public function register(DibiConnection $connection) public function register(DibiConnection $connection)
{ {
Debugger::getBar()->addPanel($this); if (is_callable('Nette\Diagnostics\Debugger::enable') && !class_exists('NDebugger')) {
Debugger::getBlueScreen()->addPanel(array(__CLASS__, 'renderException')); class_alias('Nette\Diagnostics\Debugger', 'NDebugger'); // PHP 5.2 code compatibility
$connection->onEvent[] = array($this, 'logEvent'); }
if (is_callable('NDebugger::enable') && is_callable('NDebugger::getBlueScreen')) { // Nette Framework 2.1
NDebugger::getBar()->addPanel($this);
NDebugger::getBlueScreen()->addPanel(array(__CLASS__, 'renderException'));
$connection->onEvent[] = array($this, 'logEvent');
} elseif (is_callable('NDebugger::enable')) { // Nette Framework 2.0 (for PHP 5.3 or PHP 5.2 prefixed)
NDebugger::$bar && NDebugger::$bar->addPanel($this);
NDebugger::$blueScreen && NDebugger::$blueScreen->addPanel(array(__CLASS__, 'renderException'), __CLASS__);
$connection->onEvent[] = array($this, 'logEvent');
} elseif (is_callable('Debugger::enable') && !is_callable('Debugger::getBlueScreen')) { // Nette Framework 2.0 for PHP 5.2 non-prefixed
Debugger::$bar && Debugger::$bar->addPanel($this);
Debugger::$blueScreen && Debugger::$blueScreen->addPanel(array(__CLASS__, 'renderException'), __CLASS__);
$connection->onEvent[] = array($this, 'logEvent');
}
} }
@@ -84,7 +106,7 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
} }
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" />' 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' . count($this->events) . ' queries'
. ($totalTime ? sprintf(' / %0.1f ms', $totalTime * 1000) : '') . ($totalTime ? ' / ' . sprintf('%0.1f', $totalTime * 1000) . 'ms' : '')
. '</span>'; . '</span>';
} }
@@ -104,7 +126,7 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
try { try {
$backup = array($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime); $backup = array($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime);
$event->connection->onEvent = NULL; $event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN'); $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); $explain = dibi::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
} catch (DibiException $e) {} } catch (DibiException $e) {}
list($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime) = $backup; list($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime) = $backup;
@@ -136,7 +158,7 @@ class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
'<style> #nette-debug td.nette-DibiProfiler-sql { background: white !important } '<style> #nette-debug td.nette-DibiProfiler-sql { background: white !important }
#nette-debug .nette-DibiProfiler-source { color: #999 !important } #nette-debug .nette-DibiProfiler-source { color: #999 !important }
#nette-debug nette-DibiProfiler tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style> #nette-debug nette-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> <h1>Queries: ' . count($this->events) . ($totalTime === NULL ? '' : ', time: ' . sprintf('%0.3f', $totalTime * 1000) . ' ms') . '</h1>
<div class="nette-inner nette-DibiProfiler"> <div class="nette-inner nette-DibiProfiler">
<table> <table>
<tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . ' <tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . '

View File

@@ -0,0 +1,17 @@
# Requires Nette Framework 2.0 for PHP 5.3
#
# In bootstrap.php append these lines after line $configurator = new Nette\Config\Configurator;
#
# $configurator->onCompile[] = function($configurator, $compiler) {
# $compiler->addExtension('dibi', new DibiNette20Extension);
# };
#
# This will create service named 'dibi.connection'.
common:
dibi:
host: localhost
username: root
password: ***
database: foo
lazy: TRUE

View File

@@ -1,146 +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;
$count = count($this->events);
foreach ($this->events as $event) {
$totalTime += $event->time;
}
return '<span title="dibi"><svg viewBox="0 0 2048 2048" style="vertical-align: bottom; width:1.23em; height:1.55em"><path fill="' . ( $count ? '#b079d6' : '#aaa') . '" d="M1024 896q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0 768q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-384q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-1152q208 0 385 34.5t280 93.5 103 128v128q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-128q0-69 103-128t280-93.5 385-34.5z"/></svg><span class="tracy-label">'
. $count . ' queries'
. ($totalTime ? sprintf(' / %0.1f ms', $totalTime * 1000) : '')
. '</span></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 FOR' : '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&nbsp;ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . '
</table>
</div>';
}
}

View File

@@ -4,6 +4,9 @@
* dibi - smart database abstraction layer (http://dibiphp.com) * dibi - smart database abstraction layer (http://dibiphp.com)
* *
* Copyright (c) 2005, 2012 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2012 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.
*/ */
@@ -14,9 +17,10 @@ if (version_compare(PHP_VERSION, '5.2.0', '<')) {
throw new Exception('dibi needs PHP 5.2.0 or newer.'); throw new Exception('dibi needs PHP 5.2.0 or newer.');
} }
@set_magic_quotes_runtime(FALSE); // intentionally @
require_once dirname(__FILE__) . '/libs/interfaces.php'; 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/DibiDateTime.php';
require_once dirname(__FILE__) . '/libs/DibiObject.php'; require_once dirname(__FILE__) . '/libs/DibiObject.php';
require_once dirname(__FILE__) . '/libs/DibiLiteral.php'; require_once dirname(__FILE__) . '/libs/DibiLiteral.php';
@@ -33,3 +37,598 @@ require_once dirname(__FILE__) . '/libs/DibiDatabaseInfo.php';
require_once dirname(__FILE__) . '/libs/DibiEvent.php'; require_once dirname(__FILE__) . '/libs/DibiEvent.php';
require_once dirname(__FILE__) . '/libs/DibiFileLogger.php'; require_once dirname(__FILE__) . '/libs/DibiFileLogger.php';
require_once dirname(__FILE__) . '/libs/DibiFirePhpLogger.php'; require_once dirname(__FILE__) . '/libs/DibiFirePhpLogger.php';
if (interface_exists('Nette\Diagnostics\IBarPanel') || interface_exists('IBarPanel')) {
require_once dirname(__FILE__) . '/bridges/Nette/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.1.1',
REVISION = '$WCREV$ released on $WCDATE$';
/** 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 array of 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 DateTime object instead.', E_USER_WARNING);
return new DibiDateTime($time);
}
/**
* @deprecated
*/
public static function date($date = NULL)
{
trigger_error(__METHOD__ . '() is deprecated; create DateTime 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);
// 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";
}
}
}

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -277,11 +281,10 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
@@ -402,7 +405,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
/** /**
* Returns the result set resource. * Returns the result set resource.
* @return resource * @return mysqli_result
*/ */
public function getResultResource() public function getResultResource()
{ {

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -233,11 +237,10 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
require_once dirname(__FILE__) . '/DibiMsSqlReflector.php'; require_once dirname(__FILE__) . '/DibiMsSqlReflector.php';
@@ -218,11 +222,10 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');

View File

@@ -5,6 +5,9 @@
* *
* Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com) * Copyright (c) 2005, 2010 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.
*
* @package dibi\drivers * @package dibi\drivers
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -312,11 +316,10 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -111,40 +115,10 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
* Returns metadata for all foreign keys in a table. * Returns metadata for all foreign keys in a table.
* @param string * @param string
* @return array * @return array
* @throws DibiNotSupportedException
*/ */
public function getForeignKeys($table) 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); throw new DibiNotImplementedException;
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);
} }
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -79,7 +83,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
'timezone' => date('P'), 'timezone' => date('P'),
'username' => ini_get('mysqli.default_user'), 'username' => ini_get('mysqli.default_user'),
'password' => ini_get('mysqli.default_pw'), 'password' => ini_get('mysqli.default_pw'),
'socket' => (string) ini_get('mysqli.default_socket'), 'socket' => ini_get('mysqli.default_socket'),
'port' => NULL, 'port' => NULL,
); );
if (!isset($config['host'])) { if (!isset($config['host'])) {
@@ -115,7 +119,12 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
} }
if (isset($config['charset'])) { 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]'"); $this->query("SET NAMES '$config[charset]'");
} }
} }
@@ -295,11 +304,10 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
@@ -420,10 +428,9 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
public function getResultColumns() public function getResultColumns()
{ {
static $types; static $types;
if ($types === NULL) { if (empty($types)) {
$consts = get_defined_constants(TRUE); $consts = get_defined_constants(TRUE);
$types = array(); foreach ($consts['mysqli'] as $key => $value) {
foreach (isset($consts['mysqli']) ? $consts['mysqli'] : array() as $key => $value) {
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) { if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
$types[$value] = substr($key, 12); $types[$value] = substr($key, 12);
} }
@@ -439,7 +446,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
'name' => $row['name'], 'name' => $row['name'],
'table' => $row['orgtable'], 'table' => $row['orgtable'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'], '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, 'vendor' => $row,
); );
} }
@@ -454,7 +461,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
public function getResultResource() public function getResultResource()
{ {
$this->autoFree = FALSE; $this->autoFree = FALSE;
return $this->resultSet; return @$this->resultSet->type === NULL ? NULL : $this->resultSet;
} }
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -241,11 +245,10 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("#m/d/Y#") : date("#m/d/Y#", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("#m/d/Y H:i:s#") : date("#m/d/Y H:i:s#", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "#m/d/Y H:i:s#" : "#m/d/Y#");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
@@ -290,7 +293,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
{ {
// offset support is missing // offset support is missing
if ($limit >= 0) { if ($limit >= 0) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t'; $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
} }
if ($offset) { if ($offset) {

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -14,7 +18,6 @@
* - username (or user) * - username (or user)
* - password (or pass) * - password (or pass)
* - charset => character encoding to set * - charset => character encoding to set
* - schema => alters session schema
* - formatDate => how to format date in SQL (@see date) * - formatDate => how to format date in SQL (@see date)
* - formatDateTime => how to format datetime in SQL (@see date) * - formatDateTime => how to format datetime in SQL (@see date)
* - resource (resource) => existing connection resource * - resource (resource) => existing connection resource
@@ -76,10 +79,6 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
$err = oci_error(); $err = oci_error();
throw new DibiDriverException($err['message'], $err['code']); throw new DibiDriverException($err['message'], $err['code']);
} }
if (isset($config['schema'])) {
$this->query('ALTER SESSION SET CURRENT_SCHEMA=' . $config['schema']);
}
} }
@@ -103,7 +102,7 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
{ {
$res = oci_parse($this->connection, $sql); $res = oci_parse($this->connection, $sql);
if ($res) { if ($res) {
@oci_execute($res, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); oci_execute($res, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
$err = oci_error($res); $err = oci_error($res);
if ($err) { if ($err) {
throw new DibiDriverException($err['message'], $err['code'], $sql); throw new DibiDriverException($err['message'], $err['code'], $sql);
@@ -240,11 +239,10 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? $this->fmtDateTime : $this->fmtDate);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
@@ -365,12 +363,11 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
$count = oci_num_fields($this->resultSet); $count = oci_num_fields($this->resultSet);
$columns = array(); $columns = array();
for ($i = 1; $i <= $count; $i++) { for ($i = 1; $i <= $count; $i++) {
$type = oci_field_type($this->resultSet, $i);
$columns[] = array( $columns[] = array(
'name' => oci_field_name($this->resultSet, $i), 'name' => oci_field_name($this->resultSet, $i),
'table' => NULL, 'table' => NULL,
'fullname' => oci_field_name($this->resultSet, $i), 'fullname' => oci_field_name($this->resultSet, $i),
'nativetype' => $type === 'NUMBER' && oci_field_scale($this->resultSet, $i) === 0 ? 'INTEGER' : $type, 'nativetype'=> oci_field_type($this->resultSet, $i),
); );
} }
return $columns; return $columns;

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -19,7 +23,6 @@ require_once dirname(__FILE__) . '/DibiSqliteReflector.php';
* - password (or pass) * - password (or pass)
* - options (array) => driver specific options {@see PDO::__construct} * - options (array) => driver specific options {@see PDO::__construct}
* - resource (PDO) => existing connection * - resource (PDO) => existing connection
* - version
* - lazy, profiler, result, substitutes, ... => see DibiConnection options * - lazy, profiler, result, substitutes, ... => see DibiConnection options
* *
* @author David Grudl * @author David Grudl
@@ -39,9 +42,6 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
/** @var string */ /** @var string */
private $driverName; private $driverName;
/** @var string */
private $serverVersion;
/** /**
* @throws DibiNotSupportedException * @throws DibiNotSupportedException
@@ -72,16 +72,14 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']); $this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
} catch (PDOException $e) { } catch (PDOException $e) {
if ($e->getMessage() === 'could not find driver') {
throw new DibiNotSupportedException("PHP extension for PDO is not loaded.");
}
throw new DibiDriverException($e->getMessage(), $e->getCode()); throw new DibiDriverException($e->getMessage(), $e->getCode());
} }
if (!$this->connection) {
throw new DibiDriverException('Connecting error.');
}
$this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME); $this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);
$this->serverVersion = isset($config['version'])
? $config['version']
: @$this->connection->getAttribute(PDO::ATTR_SERVER_VERSION); // @ - may be not supported
} }
@@ -251,19 +249,16 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
{ {
switch ($type) { switch ($type) {
case dibi::TEXT: case dibi::TEXT:
return $this->connection->quote($value, PDO::PARAM_STR);
case dibi::BINARY: case dibi::BINARY:
if ($this->driverName === 'odbc') { return $this->connection->quote($value, PDO::PARAM_LOB);
return "'" . str_replace("'", "''", $value) . "'";
} else {
return $this->connection->quote($value, $type === dibi::TEXT ? PDO::PARAM_STR : PDO::PARAM_LOB);
}
case dibi::IDENTIFIER: case dibi::IDENTIFIER:
switch ($this->driverName) { switch ($this->driverName) {
case 'mysql': case 'mysql':
return '`' . str_replace('`', '``', $value) . '`'; return '`' . str_replace('`', '``', $value) . '`';
case 'oci':
case 'pgsql': case 'pgsql':
return '"' . str_replace('"', '""', $value) . '"'; return '"' . str_replace('"', '""', $value) . '"';
@@ -272,10 +267,10 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
return '[' . strtr($value, '[]', ' ') . ']'; return '[' . strtr($value, '[]', ' ') . ']';
case 'odbc': case 'odbc':
case 'oci': // TODO: not tested
case 'mssql': case 'mssql':
return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']'; return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']';
case 'dblib':
case 'sqlsrv': case 'sqlsrv':
return '[' . str_replace(']', ']]', $value) . ']'; return '[' . str_replace(']', ']]', $value) . ']';
@@ -284,22 +279,13 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
} }
case dibi::BOOL: case dibi::BOOL:
if ($this->driverName === 'pgsql') { return $this->connection->quote($value, PDO::PARAM_BOOL);
return $value ? 'TRUE' : 'FALSE';
} else {
return $value ? 1 : 0;
}
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$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'");
}
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
@@ -315,37 +301,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
*/ */
public function escapeLike($value, $pos) public function escapeLike($value, $pos)
{ {
switch ($this->driverName) { throw new DibiNotImplementedException;
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 'dblib':
case 'sqlsrv':
$value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]'));
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
default:
throw new DibiNotImplementedException;
}
} }
@@ -405,19 +361,9 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
} }
break; break;
case 'odbc':
case 'mssql': case 'mssql':
case 'sqlsrv': case 'sqlsrv':
case 'dblib':
if (version_compare($this->serverVersion, '11.0') >= 0) {
if ($offset >= 0 || $limit >= 0) {
$sql .= ' OFFSET ' . (int) $offset . ' ROWS'
. ($limit > 0 ? ' FETCH NEXT ' . (int) $limit . ' ROWS ONLY' : '');
}
break;
}
// intentionally break omitted
case 'odbc':
if ($offset < 1) { if ($offset < 1) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t'; $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
break; break;

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -35,6 +39,9 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
/** @var int|FALSE Affected rows */ /** @var int|FALSE Affected rows */
private $affectedRows = FALSE; private $affectedRows = FALSE;
/** @var bool Escape method */
private $escMethod = FALSE;
/** /**
* @throws DibiNotSupportedException * @throws DibiNotSupportedException
@@ -100,6 +107,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
if (isset($config['schema'])) { if (isset($config['schema'])) {
$this->query('SET search_path TO "' . $config['schema'] . '"'); $this->query('SET search_path TO "' . $config['schema'] . '"');
} }
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
} }
@@ -113,16 +122,6 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
} }
/**
* Pings database.
* @return boolean
*/
public function ping()
{
return pg_ping($this->connection);
}
/** /**
* Executes the SQL query. * Executes the SQL query.
* @param string SQL statement. * @param string SQL statement.
@@ -271,16 +270,24 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
{ {
switch ($type) { switch ($type) {
case dibi::TEXT: case dibi::TEXT:
if (!is_resource($this->connection)) { if ($this->escMethod) {
throw new DibiException('Lost connection to server.'); 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: case dibi::BINARY:
if (!is_resource($this->connection)) { if ($this->escMethod) {
throw new DibiException('Lost connection to server.'); 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: case dibi::IDENTIFIER:
// @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS // @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
@@ -290,11 +297,10 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
return $value ? 'TRUE' : 'FALSE'; return $value ? 'TRUE' : 'FALSE';
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format("'Y-m-d'") : date("'Y-m-d'", $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');
@@ -310,9 +316,13 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/ */
public function escapeLike($value, $pos) public function escapeLike($value, $pos)
{ {
$bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off if ($this->escMethod) {
$value = pg_escape_string($this->connection, $value); $value = pg_escape_string($this->connection, $value);
$value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\')); } else {
$value = pg_escape_string($value);
}
$value = strtr($value, array( '%' => '\\\\%', '_' => '\\\\_'));
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
} }
@@ -411,12 +421,13 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/ */
public function getResultColumns() public function getResultColumns()
{ {
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
$count = pg_num_fields($this->resultSet); $count = pg_num_fields($this->resultSet);
$columns = array(); $columns = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
$row = array( $row = array(
'name' => pg_field_name($this->resultSet, $i), '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), 'nativetype'=> pg_field_type($this->resultSet, $i),
); );
$row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name']; $row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'];
@@ -451,7 +462,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
throw new DibiDriverException('Reflection requires PostgreSQL 7.4 and newer.'); throw new DibiDriverException('Reflection requires PostgreSQL 7.4 and newer.');
} }
$query = " $res = $this->query("
SELECT SELECT
table_name AS name, table_name AS name,
CASE table_type CASE table_type
@@ -461,20 +472,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
FROM FROM
information_schema.tables information_schema.tables
WHERE WHERE
table_schema = ANY (current_schemas(false))"; table_schema = current_schema()
");
if ($version >= 9.3) {
$query .= "
UNION ALL
SELECT
matviewname, 1
FROM
pg_matviews
WHERE
schemaname = ANY (current_schemas(false))";
}
$res = $this->query($query);
$tables = pg_fetch_all($res->resultSet); $tables = pg_fetch_all($res->resultSet);
return $tables ? $tables : array(); return $tables ? $tables : array();
} }
@@ -487,48 +486,21 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/ */
public function getColumns($table) public function getColumns($table)
{ {
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT); $_table = $this->escape($table, dibi::TEXT);
$res = $this->query(" $res = $this->query("
SELECT indkey SELECT indkey
FROM pg_class FROM pg_class
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid AND pg_index.indisprimary 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; $primary = (int) pg_fetch_object($res->resultSet)->indkey;
$res = $this->query(" $res = $this->query("
SELECT * SELECT *
FROM information_schema.columns c FROM information_schema.columns
JOIN pg_class ON pg_class.relname = c.table_name WHERE table_name = $_table AND table_schema = current_schema()
JOIN pg_namespace nsp ON nsp.oid = pg_class.relnamespace AND nsp.nspname = c.table_schema ORDER BY ordinal_position
WHERE pg_class.oid = $_table::regclass
ORDER BY c.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(); $columns = array();
while ($row = $res->fetch(TRUE)) { while ($row = $res->fetch(TRUE)) {
$size = (int) max($row['character_maximum_length'], $row['numeric_precision']); $size = (int) max($row['character_maximum_length'], $row['numeric_precision']);
@@ -536,8 +508,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
'name' => $row['column_name'], 'name' => $row['column_name'],
'table' => $table, 'table' => $table,
'nativetype' => strtoupper($row['udt_name']), 'nativetype' => strtoupper($row['udt_name']),
'size' => $size > 0 ? $size : NULL, 'size' => $size ? $size : NULL,
'nullable' => $row['is_nullable'] === 'YES' || $row['is_nullable'] === 't', 'nullable' => $row['is_nullable'] === 'YES',
'default' => $row['column_default'], 'default' => $row['column_default'],
'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'], 0, 7) === 'nextval', 'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'], 0, 7) === 'nextval',
'vendor' => $row, 'vendor' => $row,
@@ -554,18 +526,11 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/ */
public function getIndexes($table) public function getIndexes($table)
{ {
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT); $_table = $this->escape($table, dibi::TEXT);
$res = $this->query(" $res = $this->query("
SELECT SELECT ordinal_position, column_name
a.attnum AS ordinal_position, FROM information_schema.columns
a.attname AS column_name WHERE table_name = $_table AND table_schema = current_schema()
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
ORDER BY ordinal_position ORDER BY ordinal_position
"); ");
@@ -579,7 +544,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
FROM pg_class FROM pg_class
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid 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 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(); $indexes = array();
@@ -602,7 +567,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/ */
public function getForeignKeys($table) public function getForeignKeys($table)
{ {
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT); $_table = $this->escape($table, dibi::TEXT);
$res = $this->query(" $res = $this->query("
SELECT SELECT

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -234,11 +238,10 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? $this->fmtDateTime : $this->fmtDate);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -239,11 +243,10 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver, IDibiResultDri
return $value ? 1 : 0; return $value ? 1 : 0;
case dibi::DATE: case dibi::DATE:
return $value instanceof DateTime ? $value->format($this->fmtDate) : date($this->fmtDate, $value);
case dibi::DATETIME: case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) { return $value instanceof DateTime ? $value->format($this->fmtDateTime) : date($this->fmtDateTime, $value);
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? $this->fmtDateTime : $this->fmtDate);
default: default:
throw new InvalidArgumentException('Unsupported type.'); throw new InvalidArgumentException('Unsupported type.');

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -62,6 +66,7 @@ class DibiSqliteReflector extends DibiObject implements IDibiReflector
$columns = array(); $columns = array();
while ($row = $res->fetch(TRUE)) { while ($row = $res->fetch(TRUE)) {
$column = $row['name']; $column = $row['name'];
$pattern = "/(\"$column\"|\[$column\]|$column)\\s+[^,]+\\s+PRIMARY\\s+KEY\\s+AUTOINCREMENT/Ui";
$type = explode('(', $row['type']); $type = explode('(', $row['type']);
$columns[] = array( $columns[] = array(
'name' => $column, 'name' => $column,
@@ -71,7 +76,7 @@ class DibiSqliteReflector extends DibiObject implements IDibiReflector
'size' => isset($type[1]) ? (int) $type[1] : NULL, 'size' => isset($type[1]) ? (int) $type[1] : NULL,
'nullable' => $row['notnull'] == '0', 'nullable' => $row['notnull'] == '0',
'default' => $row['dflt_value'], 'default' => $row['dflt_value'],
'autoincrement' => $row['pk'] && $type[0] === 'INTEGER', 'autoincrement' => (bool) preg_match($pattern, $meta['sql']),
'vendor' => $row, 'vendor' => $row,
); );
} }

View File

@@ -1,541 +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.2',
REVISION = 'released on 2015-04-18';
/** 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
* @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;
}
/**
* @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|FETCH\s+NEXT|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";
}
}
}

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -56,6 +60,9 @@ class DibiConnection extends DibiObject
*/ */
public function __construct($config, $name = NULL) public function __construct($config, $name = NULL)
{ {
class_exists('dibi'); // ensure class dibi is loaded
// DSN string
if (is_string($config)) { if (is_string($config)) {
parse_str($config, $config); parse_str($config, $config);
@@ -82,7 +89,7 @@ class DibiConnection extends DibiObject
$class = preg_replace(array('#\W#', '#sql#'), array('_', 'Sql'), ucfirst(strtolower($config['driver']))); $class = preg_replace(array('#\W#', '#sql#'), array('_', 'Sql'), ucfirst(strtolower($config['driver'])));
$class = "Dibi{$class}Driver"; $class = "Dibi{$class}Driver";
if (!class_exists($class)) { if (!class_exists($class, FALSE)) {
include_once dirname(__FILE__) . "/../drivers/$class.php"; include_once dirname(__FILE__) . "/../drivers/$class.php";
if (!class_exists($class, FALSE)) { if (!class_exists($class, FALSE)) {
@@ -111,7 +118,7 @@ class DibiConnection extends DibiObject
$this->onEvent[] = array(new DibiFirePhpLogger($filter), 'logEvent'); $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 = new DibiNettePanel(isset($profilerCfg['explain']) ? $profilerCfg['explain'] : TRUE, $filter);
$panel->register($this); $panel->register($this);
} }
@@ -583,7 +590,7 @@ class DibiConnection extends DibiObject
/** /**
* Executes SQL query and fetch results - shortcut for query() & fetchAll(). * Executes SQL query and fetch results - shortcut for query() & fetchAll().
* @param array|mixed one or more arguments * @param array|mixed one or more arguments
* @return DibiRow[] * @return array of DibiRow
* @throws DibiException * @throws DibiException
*/ */
public function fetchAll($args) public function fetchAll($args)
@@ -638,21 +645,14 @@ class DibiConnection extends DibiObject
} }
$count = 0; $count = 0;
$delimiter = ';';
$sql = ''; $sql = '';
while (!feof($handle)) { while (!feof($handle)) {
$s = rtrim(fgets($handle)); $s = fgets($handle);
if (substr($s, 0, 10) === 'DELIMITER ') { $sql .= $s;
$delimiter = substr($s, 10); if (substr(rtrim($s), -1) === ';') {
} elseif (substr($s, -strlen($delimiter)) === $delimiter) {
$sql .= substr($s, 0, -strlen($delimiter));
$this->driver->query($sql); $this->driver->query($sql);
$sql = ''; $sql = '';
$count++; $count++;
} else {
$sql .= $s . "\n";
} }
} }
if (trim($sql) !== '') { if (trim($sql) !== '') {

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -45,7 +49,7 @@ class DibiDatabaseInfo extends DibiObject
/** /**
* @return DibiTableInfo[] * @return array of DibiTableInfo
*/ */
public function getTables() public function getTables()
{ {
@@ -55,7 +59,7 @@ class DibiDatabaseInfo extends DibiObject
/** /**
* @return string[] * @return array of string
*/ */
public function getTableNames() public function getTableNames()
{ {
@@ -177,7 +181,7 @@ class DibiTableInfo extends DibiObject
/** /**
* @return DibiColumnInfo[] * @return array of DibiColumnInfo
*/ */
public function getColumns() public function getColumns()
{ {
@@ -187,7 +191,7 @@ class DibiTableInfo extends DibiObject
/** /**
* @return string[] * @return array of string
*/ */
public function getColumnNames() public function getColumnNames()
{ {
@@ -229,7 +233,7 @@ class DibiTableInfo extends DibiObject
/** /**
* @return DibiForeignKeyInfo[] * @return array of DibiForeignKeyInfo
*/ */
public function getForeignKeys() public function getForeignKeys()
{ {
@@ -239,7 +243,7 @@ class DibiTableInfo extends DibiObject
/** /**
* @return DibiIndexInfo[] * @return array of DibiIndexInfo
*/ */
public function getIndexes() public function getIndexes()
{ {
@@ -332,7 +336,7 @@ class DibiResultInfo extends DibiObject
/** /**
* @return DibiColumnInfo[] * @return array of DibiColumnInfo
*/ */
public function getColumns() public function getColumns()
{ {
@@ -343,7 +347,7 @@ class DibiResultInfo extends DibiObject
/** /**
* @param bool * @param bool
* @return string[] * @return array of string
*/ */
public function getColumnNames($fullNames = FALSE) public function getColumnNames($fullNames = FALSE)
{ {
@@ -481,7 +485,7 @@ class DibiColumnInfo extends DibiObject
*/ */
public function getTableName() 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;
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -18,9 +22,9 @@ class DibiDateTime extends DateTime
public function __construct($time = 'now', DateTimeZone $timezone = NULL) public function __construct($time = 'now', DateTimeZone $timezone = NULL)
{ {
if (is_numeric($time)) { if (is_numeric($time)) {
parent::__construct('@' . $time); $time = date('Y-m-d H:i:s', $time);
$this->setTimeZone($timezone ? $timezone : new DateTimeZone(date_default_timezone_get())); }
} elseif ($timezone === NULL) { if ($timezone === NULL) {
parent::__construct($time); parent::__construct($time);
} else { } else {
parent::__construct($time, $timezone); parent::__construct($time, $timezone);
@@ -42,19 +46,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->fix = array($this->format('Y-m-d H:i:s'), $this->getTimezone()->getName());
$this->__construct('@' . $timestamp); return array('fix');
$this->setTimeZone($zone); }
return $this;
public function __wakeup()
{
$this->__construct($this->fix[0], new DateTimeZone($this->fix[1]));
unset($this->fix);
} }
public function getTimestamp() public function getTimestamp()
{ {
$ts = $this->format('U'); return (int) $this->format('U');
return is_float($tmp = $ts * 1) ? $ts : $tmp; }
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 +77,4 @@ class DibiDateTime extends DateTime
return $this->format('Y-m-d H:i:s'); 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);
}
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -60,7 +64,7 @@ class DibiFileLogger extends DibiObject
fwrite($handle, fwrite($handle,
"OK: " . $event->sql "OK: " . $event->sql
. ($event->count ? ";\n-- rows: " . $event->count : '') . ($event->count ? ";\n-- rows: " . $event->count : '')
. "\n-- takes: " . sprintf('%0.3f ms', $event->time * 1000) . "\n-- takes: " . sprintf('%0.3f', $event->time * 1000) . ' ms'
. "\n-- source: " . implode(':', $event->source) . "\n-- source: " . implode(':', $event->source)
. "\n-- driver: " . $event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name') . "\n-- driver: " . $event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name')
. "\n-- " . date('Y-m-d H:i:s') . "\n-- " . date('Y-m-d H:i:s')

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -20,9 +24,6 @@ class DibiFirePhpLogger extends DibiObject
/** maximum SQL length */ /** maximum SQL length */
static public $maxLength = 1000; static public $maxLength = 1000;
/** size of json stream chunk */
static public $streamChunkSize = 4990;
/** @var int */ /** @var int */
public $filter; public $filter;
@@ -61,11 +62,6 @@ class DibiFirePhpLogger extends DibiObject
return; 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->totalTime += $event->time;
$this->numOfQueries++; $this->numOfQueries++;
self::$fireTable[] = array( self::$fireTable[] = array(
@@ -75,6 +71,10 @@ class DibiFirePhpLogger extends DibiObject
$event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name') $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( $payload = json_encode(array(
array( array(
'Type' => 'TABLE', 'Type' => 'TABLE',
@@ -82,7 +82,7 @@ class DibiFirePhpLogger extends DibiObject
), ),
self::$fireTable, self::$fireTable,
)); ));
foreach (str_split($payload, self::$streamChunkSize) as $num => $s) { foreach (str_split($payload, 4990) as $num => $s) {
$num++; $num++;
header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -24,8 +28,6 @@
* @method DibiFluent orderBy($field) * @method DibiFluent orderBy($field)
* @method DibiFluent limit(int $limit) * @method DibiFluent limit(int $limit)
* @method DibiFluent offset(int $offset) * @method DibiFluent offset(int $offset)
* @method DibiFluent leftJoin($table)
* @method DibiFluent on($cond)
*/ */
class DibiFluent extends DibiObject implements IDataSource class DibiFluent extends DibiObject implements IDataSource
{ {
@@ -205,10 +207,15 @@ class DibiFluent extends DibiObject implements IDataSource
* @param string clause name * @param string clause name
* @return self * @return self
*/ */
public function clause($clause) public function clause($clause, $remove = FALSE)
{ {
$this->cursor = & $this->clauses[self::$normalizer->$clause]; $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(); $this->cursor = array();
} }
@@ -302,14 +309,7 @@ class DibiFluent extends DibiObject implements IDataSource
public function execute($return = NULL) public function execute($return = NULL)
{ {
$res = $this->query($this->_export()); $res = $this->query($this->_export());
switch ($return) { return $return === dibi::IDENTIFIER ? $this->connection->getInsertId() : $res;
case dibi::IDENTIFIER:
return $this->connection->getInsertId();
case dibi::AFFECTED_ROWS:
return $this->connection->getAffectedRows();
default:
return $res;
}
} }

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -10,7 +14,6 @@
* SQL literal value. * SQL literal value.
* *
* @author David Grudl * @author David Grudl
* @package dibi
*/ */
class DibiLiteral extends DibiObject class DibiLiteral extends DibiObject
{ {

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -138,12 +142,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. * Required by the IteratorAggregate interface.
* @return DibiResultIterator * @return DibiResultIterator
*/ */
final public function getIterator() 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); return new DibiResultIterator($this);
} }
@@ -227,7 +245,7 @@ class DibiResult extends DibiObject implements IDataSource
* Fetches all records from table. * Fetches all records from table.
* @param int offset * @param int offset
* @param int limit * @param int limit
* @return DibiRow[] * @return array of DibiRow
*/ */
final public function fetchAll($offset = NULL, $limit = NULL) final public function fetchAll($offset = NULL, $limit = NULL)
{ {
@@ -500,15 +518,26 @@ class DibiResult extends DibiObject implements IDataSource
$row[$key] = is_float($tmp = $value * 1) ? $value : $tmp; $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
} elseif ($type === dibi::FLOAT) { } elseif ($type === dibi::FLOAT) {
$row[$key] = str_replace(',', '.', ltrim((string) ($tmp = (float) $value), '0')) === ltrim(rtrim(rtrim($value, '0'), '.'), '0') ? $tmp : $value; $row[$key] = (string) ($tmp = (float) $value) === rtrim(rtrim($value, '0'), '.') ? $tmp : $value;
} elseif ($type === dibi::BOOL) { } elseif ($type === dibi::BOOL) {
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F'; $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
} elseif ($type === dibi::DATE || $type === dibi::DATETIME) { } 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); $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) { } elseif ($type === dibi::BINARY) {
@@ -589,6 +618,14 @@ 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**/ /********************* misc tools ****************d*g**/

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -39,15 +43,54 @@ class DibiRow implements ArrayAccess, IteratorAggregate, Countable
{ {
$time = $this[$key]; $time = $this[$key];
if (!$time instanceof DibiDateTime) { if (!$time instanceof DibiDateTime) {
if ((int) $time === 0 && substr((string) $time, 0, 3) !== '00:') { // '', NULL, FALSE, '0000-00-00', ... if ((int) $time === 0) { // '', NULL, FALSE, '0000-00-00', ...
return NULL; 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); 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);
$time = $this[$key];
return (int) $time === 0 // '', NULL, FALSE, '0000-00-00', ...
? NULL
: (is_numeric($time) ? (int) $time : strtotime($time));
}
/**
* 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**/ /********************* interfaces ArrayAccess, Countable & IteratorAggregate ****************d*g**/

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */
@@ -51,7 +55,6 @@ final class DibiTranslator extends DibiObject
public function __construct(DibiConnection $connection) public function __construct(DibiConnection $connection)
{ {
$this->connection = $connection; $this->connection = $connection;
$this->identifiers = new DibiHashMap(array($this, 'delimite'));
} }
@@ -63,9 +66,8 @@ final class DibiTranslator extends DibiObject
*/ */
public function translate(array $args) public function translate(array $args)
{ {
if (!$this->driver) { $this->identifiers = new DibiHashMap(array($this, 'delimite'));
$this->driver = $this->connection->getDriver(); $this->driver = $this->connection->getDriver();
}
$args = array_values($args); $args = array_values($args);
while (count($args) === 1 && is_array($args[0])) { // implicit array expansion while (count($args) === 1 && is_array($args[0])) { // implicit array expansion
@@ -190,10 +192,6 @@ final class DibiTranslator extends DibiObject
return "..."; return "...";
} }
if (!$this->driver) {
$this->driver = $this->connection->getDriver();
}
// array processing (with or without modifier) // array processing (with or without modifier)
if ($value instanceof Traversable) { if ($value instanceof Traversable) {
$value = iterator_to_array($value); $value = iterator_to_array($value);
@@ -333,7 +331,7 @@ final class DibiTranslator extends DibiObject
// with modifier procession // with modifier procession
if ($modifier) { 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; $this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**'; return '**Unexpected type ' . gettype($value) . '**';
} }
@@ -451,7 +449,7 @@ final class DibiTranslator extends DibiObject
} elseif ($value === NULL) { } elseif ($value === NULL) {
return 'NULL'; return 'NULL';
} elseif ($value instanceof DateTime || $value instanceof DateTimeInterface) { } elseif ($value instanceof DateTime) {
return $this->driver->escape($value, dibi::DATETIME); return $this->driver->escape($value, dibi::DATETIME);
} elseif ($value instanceof DibiLiteral) { } elseif ($value instanceof DibiLiteral) {
@@ -542,23 +540,17 @@ final class DibiTranslator extends DibiObject
return ''; return '';
} elseif ($mod === 'lmt') { // apply limit } elseif ($mod === 'lmt') { // apply limit
$arg = $this->args[$cursor++]; if ($this->args[$cursor] !== NULL) {
if ($arg === NULL) { $this->limit = (int) $this->args[$cursor];
} elseif ($this->comment) {
return "(limit $arg)";
} else {
$this->limit = (int) $arg;
} }
$cursor++;
return ''; return '';
} elseif ($mod === 'ofs') { // apply offset } elseif ($mod === 'ofs') { // apply offset
$arg = $this->args[$cursor++]; if ($this->args[$cursor] !== NULL) {
if ($arg === NULL) { $this->offset = (int) $this->args[$cursor];
} elseif ($this->comment) {
return "(offset $arg)";
} else {
$this->offset = (int) $arg;
} }
$cursor++;
return ''; return '';
} else { // default processing } else { // default processing

View File

@@ -2,7 +2,11 @@
/** /**
* This file is part of the "dibi" - smart database abstraction layer. * This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (http://davidgrudl.com) * 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.
*/ */

1
examples/.gitignore vendored
View File

@@ -1,4 +1,3 @@
_test.bat _test.bat
ref ref
output output
log

834
examples/Nette/Debugger.php Normal file

File diff suppressed because one or more lines are too long

View 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

View File

@@ -0,0 +1,3 @@
This file is part of Nette Framework
For more information please see http://nette.org

View File

@@ -4,15 +4,16 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
// connects to SQlite using dibi class // connects to SQlite using dibi class
echo '<p>Connecting to Sqlite: '; echo '<p>Connecting to Sqlite: ';
try { try {
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));
echo 'OK'; echo 'OK';
@@ -26,8 +27,8 @@ echo "</p>\n";
echo '<p>Connecting to Sqlite: '; echo '<p>Connecting to Sqlite: ';
try { try {
$connection = new DibiConnection(array( $connection = new DibiConnection(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));
echo 'OK'; echo 'OK';
@@ -78,7 +79,7 @@ try {
'driver' => 'odbc', 'driver' => 'odbc',
'username' => 'root', 'username' => 'root',
'password' => '***', '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'; echo 'OK';

View File

@@ -2,7 +2,7 @@ body {
font: 15px/1.5 Tahoma, Verdana, Myriad Web, Syntax, sans-serif; font: 15px/1.5 Tahoma, Verdana, Myriad Web, Syntax, sans-serif;
color: #333; color: #333;
background: #fff url('dibi-powered.gif') no-repeat 99% 1em; background: #fff url('dibi-powered.gif') no-repeat 99% 1em;
margin: 1.6em; margin: 1.6em;
padding: 0; padding: 0;
} }
@@ -41,24 +41,24 @@ table.dump th {
} }
/* dump() */ /* dump() */
pre.tracy-dump, pre.dump { pre.nette-dump, pre.dump {
color: #444; background: white; color: #444; background: white;
border: 1px solid silver; border: 1px solid silver;
padding: 1em; padding: 1em;
margin: 1em 0; 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; color: #C22;
} }
pre.tracy-dump .php-string { pre.nette-dump .php-string {
color: #080; color: #080;
} }
pre.tracy-dump .php-int, pre.tracy-dump .php-float { pre.nette-dump .php-int, pre.nette-dump .php-float {
color: #37D; color: #37D;
} }
pre.tracy-dump .php-null, pre.tracy-dump .php-bool { pre.nette-dump .php-null, pre.nette-dump .php-bool {
color: black; color: black;
} }
pre.tracy-dump .php-visibility { pre.nette-dump .php-visibility {
font-size: 85%; color: #999; font-size: 85%; color: #999;
} }

View File

@@ -4,12 +4,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View File

@@ -4,12 +4,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View File

@@ -4,16 +4,14 @@
<?php <?php
if (@!include __DIR__ . '/../vendor/autoload.php') { require dirname(__FILE__) . '/Nette/Debugger.php';
die('Install dependencies using `composer install --dev`'); require dirname(__FILE__) . '/../dibi/dibi.php';
}
Tracy\Debugger::enable();
ndebug();
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));
@@ -32,40 +30,38 @@ product_id | title
// fetch a single row // fetch a single row
echo "<h2>fetch()</h2>\n"; echo "<h2>fetch()</h2>\n";
$row = dibi::fetch('SELECT title FROM products'); $row = dibi::fetch('SELECT title FROM products');
Tracy\Dumper::dump($row); // Chair dump($row); // Chair
// fetch a single value // fetch a single value
echo "<h2>fetchSingle()</h2>\n"; echo "<h2>fetchSingle()</h2>\n";
$value = dibi::fetchSingle('SELECT title FROM products'); $value = dibi::fetchSingle('SELECT title FROM products');
Tracy\Dumper::dump($value); // Chair dump($value); // Chair
// fetch complete result set // fetch complete result set
echo "<h2>fetchAll()</h2>\n"; echo "<h2>fetchAll()</h2>\n";
$all = dibi::fetchAll('SELECT * FROM products'); $all = dibi::fetchAll('SELECT * FROM products');
Tracy\Dumper::dump($all); dump($all);
// fetch complete result set like association array // fetch complete result set like association array
echo "<h2>fetchAssoc('title')</h2>\n"; echo "<h2>fetchAssoc('title')</h2>\n";
$res = dibi::query('SELECT * FROM products'); $res = dibi::query('SELECT * FROM products');
$assoc = $res->fetchAssoc('title'); // key $assoc = $res->fetchAssoc('title'); // key
Tracy\Dumper::dump($assoc); dump($assoc);
// fetch complete result set like pairs key => value // fetch complete result set like pairs key => value
echo "<h2>fetchPairs('product_id', 'title')</h2>\n"; echo "<h2>fetchPairs('product_id', 'title')</h2>\n";
$res = dibi::query('SELECT * FROM products');
$pairs = $res->fetchPairs('product_id', 'title'); $pairs = $res->fetchPairs('product_id', 'title');
Tracy\Dumper::dump($pairs); dump($pairs);
// fetch row by row // fetch row by row
echo "<h2>using foreach</h2>\n"; echo "<h2>using foreach</h2>\n";
$res = dibi::query('SELECT * FROM products');
foreach ($res as $n => $row) { foreach ($res as $n => $row) {
Tracy\Dumper::dump($row); dump($row);
} }
@@ -77,16 +73,14 @@ $res = dibi::query('
INNER JOIN customers USING (customer_id) INNER JOIN customers USING (customer_id)
'); ');
echo "<h2>fetchAssoc('name|title')</h2>\n"; echo "<h2>fetchAssoc('customers.name|products.title')</h2>\n";
$assoc = $res->fetchAssoc('name|title'); // key $assoc = $res->fetchAssoc('customers.name|products.title'); // key
Tracy\Dumper::dump($assoc); dump($assoc);
echo "<h2>fetchAssoc('name[]title')</h2>\n"; echo "<h2>fetchAssoc('customers.name[]products.title')</h2>\n";
$res = dibi::query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)'); $assoc = $res->fetchAssoc('customers.name[]products.title'); // key
$assoc = $res->fetchAssoc('name[]title'); // key dump($assoc);
Tracy\Dumper::dump($assoc);
echo "<h2>fetchAssoc('name->title')</h2>\n"; echo "<h2>fetchAssoc('customers.name->products.title')</h2>\n";
$res = dibi::query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)'); $assoc = $res->fetchAssoc('customers.name->products.title'); // key
$assoc = $res->fetchAssoc('name->title'); // key dump($assoc);
Tracy\Dumper::dump($assoc);

View File

@@ -4,12 +4,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View 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 dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../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);

View File

@@ -0,0 +1,32 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<style> html { background: url(data/arrow.png) no-repeat bottom right; height: 100%; } </style>
<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 dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../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]' );

View File

@@ -4,7 +4,8 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(

View File

@@ -4,7 +4,8 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
date_default_timezone_set('Europe/Prague'); date_default_timezone_set('Europe/Prague');

View File

@@ -1,21 +1,19 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css"> <!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Result Set Data Types | dibi</h1> <h1>Result Set Data Types | dibi</h1>
<?php <?php
if (@!include __DIR__ . '/../vendor/autoload.php') { require dirname(__FILE__) . '/Nette/Debugger.php';
die('Install dependencies using `composer install --dev`'); require dirname(__FILE__) . '/../dibi/dibi.php';
}
Tracy\Debugger::enable();
ndebug();
date_default_timezone_set('Europe/Prague'); date_default_timezone_set('Europe/Prague');
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));
@@ -27,7 +25,7 @@ $res->setType('customer_id', Dibi::INTEGER)
->setFormat(dibi::DATETIME, 'Y-m-d H:i:s'); ->setFormat(dibi::DATETIME, 'Y-m-d H:i:s');
Tracy\Dumper::dump( $res->fetch() ); dump( $res->fetch() );
// outputs: // outputs:
// DibiRow(3) { // DibiRow(3) {
// customer_id => 1 // customer_id => 1
@@ -38,7 +36,7 @@ Tracy\Dumper::dump( $res->fetch() );
// using auto-detection (works well with MySQL or other strictly typed databases) // using auto-detection (works well with MySQL or other strictly typed databases)
$res = dibi::query('SELECT * FROM [customers]'); $res = dibi::query('SELECT * FROM [customers]');
Tracy\Dumper::dump( $res->fetch() ); dump( $res->fetch() );
// outputs: // outputs:
// DibiRow(3) { // DibiRow(3) {
// customer_id => 1 // customer_id => 1

View File

@@ -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);

View File

@@ -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]' );

View File

@@ -4,15 +4,16 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
date_default_timezone_set('Europe/Prague'); date_default_timezone_set('Europe/Prague');
// CHANGE TO REAL PARAMETERS! // CHANGE TO REAL PARAMETERS!
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
'formatDate' => "'Y-m-d'", 'formatDate' => "'Y-m-d'",
'formatDateTime' => "'Y-m-d H-i-s'", 'formatDateTime' => "'Y-m-d H-i-s'",
)); ));

View File

@@ -4,29 +4,27 @@
<?php <?php
if (@!include __DIR__ . '/../vendor/autoload.php') { require dirname(__FILE__) . '/Nette/Debugger.php';
die('Install dependencies using `composer install --dev`'); require dirname(__FILE__) . '/../dibi/dibi.php';
}
Tracy\Debugger::enable();
ndebug();
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));
// using the "prototype" to add custom method to class DibiResult // 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(); $all = $obj->fetchAll();
shuffle($all); shuffle($all);
return $all; return $all;
}); }
// fetch complete result set shuffled // fetch complete result set shuffled
$res = dibi::query('SELECT * FROM [customers]'); $res = dibi::query('SELECT * FROM [customers]');
$all = $res->fetchShuffle(); $all = $res->fetchShuffle();
Tracy\Dumper::dump($all); dump($all);

View File

@@ -4,14 +4,15 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
date_default_timezone_set('Europe/Prague'); date_default_timezone_set('Europe/Prague');
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View File

@@ -4,12 +4,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View File

@@ -4,14 +4,15 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
date_default_timezone_set('Europe/Prague'); date_default_timezone_set('Europe/Prague');
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
// enable query logging to this file // enable query logging to this file
'profiler' => array( 'profiler' => array(
'run' => TRUE, 'run' => TRUE,

View File

@@ -6,12 +6,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
'profiler' => array( 'profiler' => array(
'run' => TRUE, 'run' => TRUE,
) )

View File

@@ -4,12 +4,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View File

@@ -4,12 +4,13 @@
<?php <?php
require __DIR__ . '/../dibi/dibi.php'; require dirname(__FILE__) . '/Nette/Debugger.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
dibi::connect(array( dibi::connect(array(
'driver' => 'sqlite3', 'driver' => 'sqlite',
'database' => 'data/sample.s3db', 'database' => 'data/sample.sdb',
)); ));

View File

@@ -16,7 +16,7 @@ remains intact.
New BSD License New BSD License
--------------- ---------------
Copyright (c) 2004, 2014 David Grudl (http://davidgrudl.com) Copyright (c) 2004, 2013 David Grudl (http://davidgrudl.com)
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,19 +1,16 @@
[Dibi](http://dibiphp.com) - smart database layer for PHP [![Buy me a coffee](http://files.nette.org/images/coffee1s.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9XXL5ZJHAYQUN) [Dibi](http://dibiphp.com) - smart database layer for PHP
========================================================= =========================================================
[![Downloads this Month](https://img.shields.io/packagist/dm/dibi/dibi.svg)](https://packagist.org/packages/dibi/dibi)
[![Build Status](https://travis-ci.org/dg/dibi.svg?branch=master)](https://travis-ci.org/dg/dibi)
Database access functions in PHP are not standardised. This library 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. hides the differences between them, a above all, it gives you a very handy interface.
The best way to install Dibi is to use a [Composer](http://getcomposer.org/download): The best way how to install Dibi is to use a [Composer](http://getcomposer.org/download):
php composer.phar require dibi/dibi php composer.phar require dibi/dibi
Or you can download the latest package from http://dibiphp.com. In this Or you can download a latest package from http://dibiphp.com. In this
package is also `Dibi.minified`, shrinked single-file version of whole Dibi, 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. useful when you don't want to modify library, but just use it.
Dibi requires PHP 5.2.0 or later. It has been tested with PHP 5.5 too. Dibi requires PHP 5.2.0 or later. It has been tested with PHP 5.5 too.
@@ -127,4 +124,3 @@ echo dibi::$sql; // last SQL query
echo dibi::$elapsedTime; echo dibi::$elapsedTime;
echo dibi::$numOfQueries; echo dibi::$numOfQueries;
echo dibi::$totalTime; echo dibi::$totalTime;
```

4
tests/.gitignore vendored
View File

@@ -1,4 +0,0 @@
output
/tmp
/test.log
/databases.ini

View File

@@ -0,0 +1,40 @@
<?php
/**
* Test: Cloning of DibiFluent
*
* @author David Grudl
*/
require dirname(__FILE__) . '/bootstrap.php';
dibi::connect($config['sqlite3']);
$fluent = new DibiFluent(dibi::getConnection());
$fluent->select('*')->from('table')->where('x=1');
$dolly = clone $fluent;
$dolly->where('y=1');
$dolly->clause('FOO');
Assert::same( 'SELECT * FROM [table] WHERE x=1', (string) $fluent );
Assert::same( 'SELECT * FROM [table] WHERE x=1 AND y=1 FOO', (string) $dolly );
$fluent = dibi::select('id')->from('table')->where('id = %i',1);
$dolly = clone $fluent;
$dolly->where('cd = %i',5);
Assert::same( 'SELECT [id] FROM [table] WHERE id = 1', (string) $fluent );
Assert::same( 'SELECT [id] FROM [table] WHERE id = 1 AND cd = 5', (string) $dolly );
$fluent = dibi::select("*")->from("table");
$dolly = clone $fluent;
$dolly->removeClause("select")->select("count(*)");
Assert::same( 'SELECT * FROM [table]', (string) $fluent );
Assert::same( 'SELECT count(*) FROM [table]', (string) $dolly );

18
tests/bootstrap.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
/**
* Test initialization and helpers.
*
* @author David Grudl
* @package Nette\Test
*/
require dirname(__FILE__) . '/../vendor/nette/tester/Tester/bootstrap.php';
require dirname(__FILE__) . '/../dibi/dibi.php';
date_default_timezone_set('Europe/Prague');
class_alias('Tester\Assert', 'Assert');
// load connections
define('DIR', dirname(__FILE__));
$config = parse_ini_file(dirname(__FILE__) . '/config.ini', TRUE);

67
tests/config.ini Normal file
View 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

Binary file not shown.

149
tests/data/sample.mysql Normal file
View 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

Binary file not shown.

BIN
tests/data/sample.sdb3 Normal file

Binary file not shown.

View File

@@ -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

View File

@@ -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);

View File

@@ -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());

View File

@@ -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());
});

View File

@@ -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->'));

View File

@@ -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'")
);

View File

@@ -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());

View File

@@ -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 );

View File

@@ -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
);

View File

@@ -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'));
}

View File

@@ -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
);

View File

@@ -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
);

View File

@@ -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
);

View File

@@ -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);

View File

@@ -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());

View File

@@ -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));

View File

@@ -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'
));

View File

@@ -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")
);

View File

@@ -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)
);

View File

@@ -1,80 +0,0 @@
<?php
/**
* @dataProvider ../databases.ini
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
if ($config['system'] !== 'mssql' || $config['driver'] !== 'pdo') {
Tester\Environment::skip("Not supported system '$config[system]'.");
}
$tests = function($conn){
$version = $conn->getDriver()->getResource()->getAttribute(PDO::ATTR_SERVER_VERSION);
// MsSQL2012+
if(version_compare($version, '11.0') >= 0) {
// Limit and offset
Assert::same(
'SELECT 1 OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY',
$conn->translate('SELECT 1 %ofs %lmt', 10, 10)
);
// Limit only
Assert::same(
'SELECT 1 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY',
$conn->translate('SELECT 1 %lmt', 10)
);
// Offset only
Assert::same(
'SELECT 1 OFFSET 10 ROWS',
$conn->translate('SELECT 1 %ofs', 10)
);
// Offset invalid
Assert::same(
'SELECT 1',
$conn->translate('SELECT 1 %ofs', -10)
);
// Limit invalid
Assert::same(
'SELECT 1',
$conn->translate('SELECT 1 %lmt', -10)
);
// Limit invalid, offset valid
Assert::same(
'SELECT 1',
$conn->translate('SELECT 1 %ofs %lmt', 10, -10)
);
// Limit valid, offset invalid
Assert::same(
'SELECT 1',
$conn->translate('SELECT 1 %ofs %lmt', -10, 10)
);
} else {
Assert::same(
'SELECT TOP 1 * FROM (SELECT 1) t',
$conn->translate('SELECT 1 %lmt', 1)
);
Assert::same(
'SELECT 1',
$conn->translate('SELECT 1 %lmt', -10)
);
Assert::exception(
$conn->translate('SELECT 1 %ofs %lmt', 10, 10),
'DibiNotSupportedException'
);
}
};
$conn = new DibiConnection($config);
$tests($conn);

Some files were not shown because too many files have changed in this diff Show More