1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-31 09:41:43 +02:00

Compare commits

..

37 Commits
v2.2 ... v2.3.1

Author SHA1 Message Date
David Grudl
a3e5ac86f7 Released version 2.3.1 2015-02-25 15:22:04 +01:00
David Grudl
89d7148b04 removed version.txt 2015-02-25 15:21:48 +01:00
David Grudl
38aa393dc3 dibi: named connections are allowed [Closes #161]
Partially reverts commit a923ce7ecb.
2015-02-25 15:13:52 +01:00
David Grudl
84f9a6fdd8 Merge pull request #164 from bckp/patch-2
Added support for MsSQL2012 ( allow offset )
2015-02-20 12:11:02 +01:00
Radovan Kepák
eb64adeb05 Dibi: Dump now recognize MsSql2012 offset as keyword
Now $connection->test send proper highlighted code
2015-02-20 09:09:37 +01:00
Radovan Kepák
3779a5034a DibiPdoDriver: added support for MsSql2012 Offset
Since MsSql2012 allow using of OFFSET, I added this option to the driver for PDO. Driver will automaticly recognize this is proper version and use the new offset.
2015-02-20 09:04:43 +01:00
David Grudl
090bb2f182 Merge pull request #163 from bckp/patch-1
Tracy\Panel: added vector icon
2015-02-20 00:19:37 +01:00
Radovan Kepák
056c0702a1 Tracy\Panel: added vector icon 2015-02-20 00:16:05 +01:00
David Grudl
020b15c0e2 added contributing.md
inspiration https://github.com/necolas/issue-guidelines
2015-01-27 14:51:42 +01:00
David Grudl
5970db58aa Released version 2.3.0 2015-01-25 17:24:28 +01:00
David Grudl
5ea37c9894 Merge pull request #160 from milo/pull-pglike
Fix DibiPostgreDriver::escapeLike()
2015-01-23 17:26:05 +01:00
Miloslav Hůla
2892e3eae3 Postgre: added test for matching by %like 2015-01-23 09:29:58 +01:00
Miloslav Hůla
91e2d76a0a Postgre: fixed %like escaping [Closes #159] 2015-01-23 09:13:05 +01:00
David Grudl
97b50bd243 Dibi: $defaultDriver changed to mysqli [Closes #156] 2015-01-13 15:45:17 +01:00
David Grudl
97d4c8c35f Released 2.3.0-RC1 2015-01-13 15:35:18 +01:00
David Grudl
f7fd9104e9 removed bridge for Nette 2.0 (BC break) 2015-01-13 15:35:18 +01:00
David Grudl
a923ce7ecb dibi: named connections and activate() are deprecated (BC break) 2015-01-13 15:31:03 +01:00
David Grudl
9a95edf003 Merge pull request #149 from JirkaChadima/oracle-schema
Oracle: adds support for login schema option
2015-01-13 05:25:33 +01:00
MartyIX
23efb97b0c DibiFluent: add leftJoin and on to phpdoc. 2015-01-13 05:24:23 +01:00
Ondrej Brablc
3b96dc7012 DibiFirePhpLogger: save some header operations for sites with hundreds of sql queries. 2015-01-13 05:22:45 +01:00
Ondrej Brablc
39be00e08b DibiFirePhpLogger: Allow user defined size of json stream chunks [Closes #148] 2015-01-13 05:22:34 +01:00
Martin Hradil
d6826d62ed DibiTranslator: respect %if blocks for %lmt and %ofs as well [Closes #145][Closes #87] 2015-01-13 05:14:42 +01:00
Petr BAGR Smrkovský
9189d56c05 DibiResult: float detection locale fix [Closes #154] 2015-01-13 04:40:36 +01:00
David Grudl
26b167fe13 DibiMySqliDriver.php: fixes for HHVM 2015-01-12 11:01:46 +01:00
David Grudl
100f978b9b DibiPdoDriver: missing driver throws DibiNotSupportedException exception 2015-01-12 11:01:12 +01:00
David Grudl
8395abb04f added new tests 2015-01-12 10:41:07 +01:00
David Grudl
f5f4f786f1 tests: improved testing environment 2015-01-12 10:41:06 +01:00
David Grudl
59da4bd66a DibiDatabaseInfo: no table is returned as NULL 2015-01-12 08:58:28 +01:00
David Grudl
50782c037c DibiSqliteReflector: fixed detection of autoincrement 2015-01-12 08:58:27 +01:00
David Grudl
ddbf8c779e DibiOdbcDriver: compatible applyLimit 2015-01-12 04:45:30 +01:00
David Grudl
e2fe4d122e DibiPdoDriver: improved and fixed escaping 2015-01-12 04:45:30 +01:00
David Grudl
2082357f0c * .travis: added code checker 2015-01-10 19:11:30 +01:00
David Grudl
c11a97294a examples: improved Tracy examples 2015-01-10 19:07:29 +01:00
Ing. Andrej Poliak
4f315a0d74 DibiPostgreDriver: added support for pg_ping [Closes #144] 2015-01-10 18:41:56 +01:00
David Grudl
34deb6c04f Merge pull request #158 from paranoiq/patch-1
dump: added bunch of reserved words
2015-01-05 12:49:25 +01:00
Vlasta Neubauer
31122c1969 dump: added bunch of reserved words 2015-01-05 12:40:41 +01:00
Jirka Chadima
4e99d7821c Oracle: adds support for login schema option 2014-10-21 17:01:59 +02:00
96 changed files with 2752 additions and 471 deletions

2
.gitattributes vendored
View File

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

30
.travis.yml Normal file
View File

@@ -0,0 +1,30 @@
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

@@ -7,19 +7,25 @@
"authors": [
{
"name": "David Grudl",
"homepage": "https://davidgrudl.com"
"homepage": "http://davidgrudl.com"
}
],
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"tracy/tracy": "~2.2"
"tracy/tracy": "~2.2",
"nette/tester": "~1.3"
},
"replace": {
"dg/dibi": "self.version"
},
"autoload": {
"classmap": ["dibi/"]
},
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
}
}

27
contributing.md Normal file
View File

@@ -0,0 +1,27 @@
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,55 +0,0 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*
* For the full copyright and license information, please view
* the file license.txt that was distributed with this source code.
*/
/**
* Dibi extension for Nette Framework 2.0. Creates 'connection' service.
*
* @author David Grudl
* @package dibi\nette
* @phpversion 5.3
*/
class DibiNette20Extension extends Nette\Config\CompilerExtension
{
public function loadConfiguration()
{
$container = $this->getContainerBuilder();
$config = $this->getConfig();
$useProfiler = isset($config['profiler'])
? $config['profiler']
: !$container->parameters['productionMode'];
unset($config['profiler']);
if (isset($config['flags'])) {
$flags = 0;
foreach ((array) $config['flags'] as $flag) {
$flags |= constant($flag);
}
$config['flags'] = $flags;
}
$connection = $container->addDefinition($this->prefix('connection'))
->setClass('DibiConnection', array($config));
if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel'))
->setClass('DibiNettePanel')
->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

@@ -1,17 +0,0 @@
# 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

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

View File

@@ -2,13 +2,10 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
if (interface_exists('Nette\Diagnostics\IBarPanel')) {
class_alias('Nette\Diagnostics\IBarPanel', 'IBarPanel');
}
use Nette\Diagnostics\Debugger;
/**
@@ -17,7 +14,7 @@ if (interface_exists('Nette\Diagnostics\IBarPanel')) {
* @author David Grudl
* @package dibi\nette
*/
class DibiNettePanel extends DibiObject implements IBarPanel
class DibiNettePanel extends DibiObject implements Nette\Diagnostics\IBarPanel
{
/** @var int maximum SQL length */
static public $maxLength = 1000;
@@ -41,24 +38,9 @@ class DibiNettePanel extends DibiObject implements IBarPanel
public function register(DibiConnection $connection)
{
if (is_callable('Nette\Diagnostics\Debugger::enable') && !class_exists('NDebugger')) {
class_alias('Nette\Diagnostics\Debugger', 'NDebugger'); // PHP 5.2 code compatibility
}
if (is_callable('NDebugger::enable') && 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');
}
Debugger::getBar()->addPanel($this);
Debugger::getBlueScreen()->addPanel(array(__CLASS__, 'renderException'));
$connection->onEvent[] = array($this, 'logEvent');
}
@@ -124,8 +106,7 @@ class DibiNettePanel extends DibiObject implements IBarPanel
$event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN' : 'EXPLAIN');
$explain = dibi::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
} catch (DibiException $e) {
}
} catch (DibiException $e) {}
list($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime) = $backup;
}

View File

@@ -2,13 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
namespace Dibi\Bridges\Nette;
use dibi;
use Nette;
use dibi,
Nette;
/**

View File

@@ -2,18 +2,18 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
namespace Dibi\Bridges\Tracy;
use dibi;
use Tracy;
use dibi,
Tracy;
/**
* Dibi panel for Tracy.
* @package dibi\nette
*
* @author David Grudl
*/
class Panel extends \DibiObject implements Tracy\IBarPanel
@@ -81,13 +81,14 @@ class Panel extends \DibiObject implements Tracy\IBarPanel
public function getTab()
{
$totalTime = 0;
$count = count($this->events);
foreach ($this->events as $event) {
$totalTime += $event->time;
}
return '<span title="dibi"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC" />'
. count($this->events) . ' queries'
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></span>';
}
@@ -108,8 +109,7 @@ class Panel extends \DibiObject implements Tracy\IBarPanel
$event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN' : 'EXPLAIN');
$explain = dibi::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
} catch (\DibiException $e) {
}
} catch (\DibiException $e) {}
list($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime) = $backup;
}

View File

@@ -3,7 +3,7 @@
/**
* dibi - smart database abstraction layer (http://dibiphp.com)
*
* Copyright (c) 2005, 2012 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005, 2012 David Grudl (http://davidgrudl.com)
*/
@@ -33,7 +33,3 @@ require_once dirname(__FILE__) . '/libs/DibiDatabaseInfo.php';
require_once dirname(__FILE__) . '/libs/DibiEvent.php';
require_once dirname(__FILE__) . '/libs/DibiFileLogger.php';
require_once dirname(__FILE__) . '/libs/DibiFirePhpLogger.php';
if (interface_exists('Nette\Diagnostics\IBarPanel') || interface_exists('IBarPanel')) {
require_once dirname(__FILE__) . '/bridges/Nette-2.1/DibiNettePanel.php';
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -88,6 +88,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
throw new DibiDriverException(ibase_errmsg(), ibase_errcode());
}
}
}
@@ -348,7 +349,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
*/
public function getRowCount()
{
throw new DibiNotSupportedException('Firebird/Interbase do not support returning number of rows in result set.');
throw new DibiNotSupportedException("Firebird/Interbase do not support returning number of rows in result set.");
}
@@ -378,13 +379,13 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
public function seek($row)
{
throw new DibiNotSupportedException('Firebird/Interbase do not support seek in result set.');
throw new DibiNotSupportedException("Firebird/Interbase do not support seek in result set.");
}
@@ -401,7 +402,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
/**
* Returns the result set resource.
* @return mysqli_result
* @return resource
*/
public function getResultResource()
{
@@ -655,7 +656,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
END AS TRIGGER_ENABLED
FROM RDB\$TRIGGERS
WHERE RDB\$SYSTEM_FLAG = 0"
. ($table === NULL ? ';' : " AND RDB\$RELATION_NAME = UPPER('$table');")
. ($table === NULL ? ";" : " AND RDB\$RELATION_NAME = UPPER('$table');")
);
$triggers = array();
while ($row = $res->fetch(TRUE)) {
@@ -682,7 +683,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
$q = "SELECT TRIM(RDB\$TRIGGER_NAME)
FROM RDB\$TRIGGERS
WHERE RDB\$SYSTEM_FLAG = 0";
$q .= $table === NULL ? ';' : " AND RDB\$RELATION_NAME = UPPER('$table')";
$q .= $table === NULL ? ";" : " AND RDB\$RELATION_NAME = UPPER('$table')";
$res = $this->query($q);
$triggers = array();

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -17,7 +17,7 @@ require_once dirname(__FILE__) . '/DibiMsSql2005Reflector.php';
* - username (or user)
* - password (or pass)
* - database => the database name to select
* - options (array) => connection options {@link https://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx}
* - options (array) => connection options {@link http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx}
* - charset => character encoding to set (default is UTF-8)
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
@@ -226,7 +226,7 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
return "'" . str_replace("'", "''", $value) . "'";
case dibi::IDENTIFIER:
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
// @see http://msdn.microsoft.com/en-us/library/ms176027.aspx
return '[' . str_replace(']', ']]', $value) . ']';
case dibi::BOOL:
@@ -327,8 +327,8 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -104,7 +104,7 @@ class DibiMsSql2005Reflector extends DibiObject implements IDibiReflector
{
$keyUsagesRes = $this->driver->query("SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = {$this->driver->escape($table, dibi::TEXT)}");
$keyUsages = array();
while ($row = $keyUsagesRes->fetch(TRUE)) {
while( $row = $keyUsagesRes->fetch(TRUE) ) {
$keyUsages[$row['CONSTRAINT_NAME']][(int) $row['ORDINAL_POSITION'] - 1] = $row['COLUMN_NAME'];
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
require_once dirname(__FILE__) . '/DibiMsSqlReflector.php';
@@ -211,7 +211,7 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
return "'" . str_replace("'", "''", $value) . "'";
case dibi::IDENTIFIER:
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
// @see http://msdn.microsoft.com/en-us/library/ms176027.aspx
return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']';
case dibi::BOOL:
@@ -363,4 +363,5 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
return is_resource($this->resultSet) ? $this->resultSet : NULL;
}
}

View File

@@ -3,7 +3,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005, 2010 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
*
* @package dibi\drivers
*/
@@ -34,10 +34,10 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
*/
public function getTables()
{
$res = $this->driver->query('
$res = $this->driver->query("
SELECT TABLE_NAME, TABLE_TYPE
FROM INFORMATION_SCHEMA.TABLES
');
");
$tables = array();
while ($row = $res->fetch(FALSE)) {
$tables[] = array(
@@ -52,12 +52,12 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
/**
* Returns count of rows in a table
* @param string
* @return int
* @return integer
*/
public function getTableCount($table, $fallback = TRUE)
public function getTableCount($table, $fallback=true)
{
if (empty($table)) {
return FALSE;
return false;
}
$result = $this->driver->query("
SELECT MAX(rowcnt)
@@ -71,7 +71,7 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
$row = $this->driver->query("SELECT COUNT(*) FROM {$this->driver->escape($table, dibi::IDENTIFIER)}")->fetch(FALSE);
$count = intval($row[0]);
} else {
$count = FALSE;
$count = false;
}
} else {
$count = intval($row[0]);
@@ -96,16 +96,16 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
");
$columns = array();
while ($row = $res->fetch(TRUE)) {
$size = FALSE;
$size = false;
$type = strtoupper($row['DATA_TYPE']);
$size_cols = array(
'DATETIME' => 'DATETIME_PRECISION',
'DECIMAL' => 'NUMERIC_PRECISION',
'CHAR' => 'CHARACTER_MAXIMUM_LENGTH',
'NCHAR' => 'CHARACTER_OCTET_LENGTH',
'NVARCHAR' => 'CHARACTER_OCTET_LENGTH',
'VARCHAR' => 'CHARACTER_OCTET_LENGTH',
'DATETIME'=>'DATETIME_PRECISION',
'DECIMAL'=>'NUMERIC_PRECISION',
'CHAR'=>'CHARACTER_MAXIMUM_LENGTH',
'NCHAR'=>'CHARACTER_OCTET_LENGTH',
'NVARCHAR'=>'CHARACTER_OCTET_LENGTH',
'VARCHAR'=>'CHARACTER_OCTET_LENGTH'
);
if (isset($size_cols[$type])) {
@@ -122,7 +122,7 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
'unsigned' => NULL,
'nullable' => $row['IS_NULLABLE'] === 'YES',
'default' => $row['COLUMN_DEFAULT'],
'autoincrement' => FALSE,
'autoincrement' => false,
'vendor' => $row,
);
}
@@ -161,8 +161,8 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
if (!isset($indexes[$index_name])) {
$indexes[$index_name] = array();
$indexes[$index_name]['name'] = $index_name;
$indexes[$index_name]['unique'] = (bool) $row['is_unique'];
$indexes[$index_name]['primary'] = (bool) $row['is_primary_key'];
$indexes[$index_name]['unique'] = (bool)$row['is_unique'];
$indexes[$index_name]['primary'] = (bool)$row['is_primary_key'];
$indexes[$index_name]['columns'] = array();
}
$indexes[$index_name]['columns'][] = $row['column_name'];
@@ -203,8 +203,8 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
$keys[$key_name]['local'] = array($row['column_name']); // local columns
$keys[$key_name]['table'] = $row['reference_table_name']; // referenced table
$keys[$key_name]['foreign'] = array($row['reference_column_name']); // referenced columns
$keys[$key_name]['onDelete'] = FALSE;
$keys[$key_name]['onUpdate'] = FALSE;
$keys[$key_name]['onDelete'] = false;
$keys[$key_name]['onUpdate'] = false;
} else {
$keys[$key_name]['local'][] = $row['column_name']; // local columns
$keys[$key_name]['foreign'][] = $row['reference_column_name']; // referenced columns

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -406,8 +406,8 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
public function seek($row)

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -36,7 +36,7 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
");*/
$res = $this->driver->query('SHOW FULL TABLES');
$res = $this->driver->query("SHOW FULL TABLES");
$tables = array();
while ($row = $res->fetch(FALSE)) {
$tables[] = array(
@@ -138,9 +138,9 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
$keyName = $row['CONSTRAINT_NAME'];
$foreignKeys[$keyName]['name'] = $keyName;
$foreignKeys[$keyName]['local'] = explode(',', $row['COLUMNS']);
$foreignKeys[$keyName]['local'] = explode(",", $row['COLUMNS']);
$foreignKeys[$keyName]['table'] = $row['REFERENCED_TABLE_NAME'];
$foreignKeys[$keyName]['foreign'] = explode(',', $row['REFERENCED_COLUMNS']);
$foreignKeys[$keyName]['foreign'] = explode(",", $row['REFERENCED_COLUMNS']);
$foreignKeys[$keyName]['onDelete'] = $row['DELETE_RULE'];
$foreignKeys[$keyName]['onUpdate'] = $row['UPDATE_RULE'];
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -79,7 +79,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
'timezone' => date('P'),
'username' => ini_get('mysqli.default_user'),
'password' => ini_get('mysqli.default_pw'),
'socket' => ini_get('mysqli.default_socket'),
'socket' => (string) ini_get('mysqli.default_socket'),
'port' => NULL,
);
if (!isset($config['host'])) {
@@ -389,8 +389,8 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
public function seek($row)
@@ -420,9 +420,10 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
public function getResultColumns()
{
static $types;
if (empty($types)) {
if ($types === NULL) {
$consts = get_defined_constants(TRUE);
foreach ($consts['mysqli'] as $key => $value) {
$types = array();
foreach (isset($consts['mysqli']) ? $consts['mysqli'] : array() as $key => $value) {
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
$types[$value] = substr($key, 12);
}
@@ -438,7 +439,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
'name' => $row['name'],
'table' => $row['orgtable'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'nativetype' => $types[$row['type']],
'nativetype' => isset($types[$row['type']]) ? $types[$row['type']] : $row['type'],
'vendor' => $row,
);
}
@@ -453,7 +454,7 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDri
public function getResultResource()
{
$this->autoFree = FALSE;
return $this->resultSet === NULL || $this->resultSet->type === NULL ? NULL : $this->resultSet;
return $this->resultSet;
}
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -290,7 +290,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
{
// offset support is missing
if ($limit >= 0) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
}
if ($offset) {
@@ -339,9 +339,7 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
}
$count = odbc_num_fields($set);
$cols = array();
for ($i = 1; $i <= $count; $i++) {
$cols[] = odbc_result($set, $i);
}
for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i);
return $cols;
}
}
@@ -349,8 +347,8 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{
@@ -380,10 +378,10 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDrive
$columns = array();
for ($i = 1; $i <= $count; $i++) {
$columns[] = array(
'name' => odbc_field_name($this->resultSet, $i),
'table' => NULL,
'fullname' => odbc_field_name($this->resultSet, $i),
'nativetype' => odbc_field_type($this->resultSet, $i),
'name' => odbc_field_name($this->resultSet, $i),
'table' => NULL,
'fullname' => odbc_field_name($this->resultSet, $i),
'nativetype'=> odbc_field_type($this->resultSet, $i),
);
}
return $columns;

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -14,6 +14,7 @@
* - username (or user)
* - password (or pass)
* - charset => character encoding to set
* - schema => alters session schema
* - formatDate => how to format date in SQL (@see date)
* - formatDateTime => how to format datetime in SQL (@see date)
* - resource (resource) => existing connection resource
@@ -75,6 +76,10 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
$err = oci_error();
throw new DibiDriverException($err['message'], $err['code']);
}
if (isset($config['schema'])) {
$this->query('ALTER SESSION SET CURRENT_SCHEMA=' . $config['schema']);
}
}
@@ -331,8 +336,8 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -38,6 +38,9 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
/** @var string */
private $driverName;
/** @var string */
private $serverVersion;
/**
* @throws DibiNotSupportedException
@@ -64,19 +67,18 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
if ($config['resource'] instanceof PDO) {
$this->connection = $config['resource'];
} else {
try {
} else try {
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
} catch (PDOException $e) {
throw new DibiDriverException($e->getMessage(), $e->getCode());
}
}
if (!$this->connection) {
throw new DibiDriverException('Connecting error.');
} 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());
}
$this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);
$this->serverVersion = $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION);
}
@@ -246,10 +248,12 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
{
switch ($type) {
case dibi::TEXT:
return $this->connection->quote($value, PDO::PARAM_STR);
case dibi::BINARY:
return $this->connection->quote($value, PDO::PARAM_LOB);
if ($this->driverName === 'odbc') {
return "'" . str_replace("'", "''", $value) . "'";
} else {
return $this->connection->quote($value, $type === dibi::TEXT ? PDO::PARAM_STR : PDO::PARAM_LOB);
}
case dibi::IDENTIFIER:
switch ($this->driverName) {
@@ -276,14 +280,22 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
}
case dibi::BOOL:
return $this->connection->quote($value, PDO::PARAM_BOOL);
if ($this->driverName === 'pgsql') {
return $value ? 'TRUE' : 'FALSE';
} else {
return $value ? 1 : 0;
}
case dibi::DATE:
case dibi::DATETIME:
if (!$value instanceof DateTime && !$value instanceof DateTimeInterface) {
$value = new DibiDateTime($value);
}
return $value->format($type === dibi::DATETIME ? "'Y-m-d H:i:s'" : "'Y-m-d'");
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:
throw new InvalidArgumentException('Unsupported type.');
@@ -299,7 +311,36 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
*/
public function escapeLike($value, $pos)
{
throw new DibiNotImplementedException;
switch ($this->driverName) {
case 'mysql':
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_");
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
case 'oci':
$value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\\%_");
$value = str_replace("'", "''", $value);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
case 'pgsql':
$bs = substr($this->connection->quote('\\', PDO::PARAM_STR), 1, -1); // standard_conforming_strings = on/off
$value = substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1);
$value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\'));
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
case 'sqlite':
case 'sqlite2':
$value = addcslashes(substr($this->connection->quote($value, PDO::PARAM_STR), 1, -1), '%_\\');
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'";
case 'odbc':
case 'mssql':
case 'sqlsrv':
$value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]'));
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
default:
throw new DibiNotImplementedException;
}
}
@@ -359,10 +400,19 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
}
break;
case 'odbc':
case 'dblib':
case 'mssql':
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) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
break;
@@ -402,7 +452,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return boolean TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -113,6 +113,16 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
}
/**
* Pings database.
* @return boolean
*/
public function ping()
{
return pg_ping($this->connection);
}
/**
* Executes the SQL query.
* @param string SQL statement.
@@ -154,7 +164,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
{
if ($sequence === NULL) {
// PostgreSQL 8.1 is needed
$res = $this->query('SELECT LASTVAL()');
$res = $this->query("SELECT LASTVAL()");
} else {
$res = $this->query("SELECT CURRVAL('$sequence')");
}
@@ -376,7 +386,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return boolean TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{
@@ -454,14 +464,14 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
table_schema = ANY (current_schemas(false))";
if ($version >= 9.3) {
$query .= '
$query .= "
UNION ALL
SELECT
matviewname, 1
FROM
pg_matviews
WHERE
schemaname = ANY (current_schemas(false))';
schemaname = ANY (current_schemas(false))";
}
$res = $this->query($query);

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -66,12 +66,11 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
if (isset($config['resource']) && $config['resource'] instanceof SQLite3) {
$this->connection = $config['resource'];
} else {
try {
$this->connection = new SQLite3($config['database']);
} catch (Exception $e) {
throw new DibiDriverException($e->getMessage(), $e->getCode());
}
} else try {
$this->connection = new SQLite3($config['database']);
} catch (Exception $e) {
throw new DibiDriverException($e->getMessage(), $e->getCode());
}
$this->dbcharset = empty($config['dbcharset']) ? 'UTF-8' : $config['dbcharset'];
@@ -83,7 +82,7 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
// enable foreign keys support (defaultly disabled; if disabled then foreign key constraints are not enforced)
$version = SQLite3::version();
if ($version['versionNumber'] >= '3006019') {
$this->query('PRAGMA foreign_keys = ON');
$this->query("PRAGMA foreign_keys = ON");
}
}
@@ -337,8 +336,8 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiNotSupportedException
*/
public function seek($row)
@@ -369,7 +368,7 @@ class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDr
static $types = array(SQLITE3_INTEGER => 'int', SQLITE3_FLOAT => 'float', SQLITE3_TEXT => 'text', SQLITE3_BLOB => 'blob', SQLITE3_NULL => 'null');
for ($i = 0; $i < $count; $i++) {
$columns[] = array(
'name' => $this->resultSet->columnName($i),
'name' => $this->resultSet->columnName($i),
'table' => NULL,
'fullname' => $this->resultSet->columnName($i),
'nativetype' => $types[$this->resultSet->columnType($i)],

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -332,8 +332,8 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver, IDibiResultDri
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
public function seek($row)
@@ -367,7 +367,7 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver, IDibiResultDri
$name = str_replace(array('[', ']'), '', sqlite_field_name($this->resultSet, $i));
$pair = explode('.', $name);
$columns[] = array(
'name' => isset($pair[1]) ? $pair[1] : $pair[0],
'name' => isset($pair[1]) ? $pair[1] : $pair[0],
'table' => isset($pair[1]) ? $pair[0] : NULL,
'fullname' => $name,
'nativetype' => NULL,

View File

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

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -29,18 +29,18 @@ class dibi
AFFECTED_ROWS = 'a';
/** @deprecated */
const FIELD_TEXT = self::TEXT,
FIELD_BINARY = self::BINARY,
FIELD_BOOL = self::BOOL,
FIELD_INTEGER = self::INTEGER,
FIELD_FLOAT = self::FLOAT,
FIELD_DATE = self::DATE,
FIELD_DATETIME = self::DATETIME,
FIELD_TIME = self::TIME;
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.2.5',
REVISION = 'released on 2015-10-26';
const VERSION = '2.3.1',
REVISION = 'released on 2015-02-25';
/** sorting order */
const ASC = 'ASC',
@@ -68,7 +68,7 @@ class dibi
public static $numOfQueries = 0;
/** @var string Default dibi driver */
public static $defaultDriver = 'mysql';
public static $defaultDriver = 'mysqli';
/**
@@ -76,7 +76,7 @@ class dibi
*/
final public function __construct()
{
throw new LogicException('Cannot instantiate static class ' . get_class($this));
throw new LogicException("Cannot instantiate static class " . get_class($this));
}
@@ -152,13 +152,11 @@ class dibi
/**
* Change active connection.
* @param string connection registy name
* @return void
* @throws DibiException
* @deprecated
*/
public static function activate($name)
{
trigger_error(__METHOD__ . '() is deprecated.', E_USER_DEPRECATED);
self::$connection = self::getConnection($name);
}
@@ -296,7 +294,7 @@ class dibi
* @return int
* @throws DibiException
*/
public static function getInsertId($sequence = NULL)
public static function getInsertId($sequence=NULL)
{
return self::getConnection()->getInsertId($sequence);
}
@@ -308,7 +306,7 @@ class dibi
* @return int
* @throws DibiException
*/
public static function insertId($sequence = NULL)
public static function insertId($sequence=NULL)
{
return self::getConnection()->getInsertId($sequence);
}
@@ -471,7 +469,7 @@ class dibi
$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 $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
@@ -479,7 +477,7 @@ class dibi
$sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
// reduce spaces
$sql = preg_replace('#[ \t]{2,}#', ' ', $sql);
$sql = preg_replace('#[ \t]{2,}#', " ", $sql);
$sql = wordwrap($sql, 100);
$sql = preg_replace("#([ \t]*\r?\n){2,}#", "\n", $sql);

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -12,12 +12,16 @@
* @author David Grudl
* @package dibi
*
* @property-read bool $connected
* @property-read mixed $config
* @property-read IDibiDriver $driver
* @property-read int $affectedRows
* @property-read int $insertId
* @property-read DibiDatabaseInfo $databaseInfo
*/
class DibiConnection extends DibiObject
{
/** @var array of function (DibiEvent $event); Occurs after query is executed */
/** @var array of function(DibiEvent $event); Occurs after query is executed */
public $onEvent;
/** @var array Current connection configuration */
@@ -107,7 +111,7 @@ class DibiConnection extends DibiObject
$this->onEvent[] = array(new DibiFirePhpLogger($filter), 'logEvent');
}
if (!interface_exists('Tracy\IBarPanel') && (interface_exists('Nette\Diagnostics\IBarPanel') || interface_exists('IBarPanel'))) {
if (!interface_exists('Tracy\IBarPanel') && interface_exists('Nette\Diagnostics\IBarPanel') && class_exists('DibiNettePanel')) {
$panel = new DibiNettePanel(isset($profilerCfg['explain']) ? $profilerCfg['explain'] : TRUE, $filter);
$panel->register($this);
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -11,6 +11,11 @@
*
* @author David Grudl
* @package dibi
*
* @property-read DibiConnection $connection
* @property-read DibiResult $result
* @property-read DibiResultIterator $iterator
* @property-read int $totalCount
*/
class DibiDataSource extends DibiObject implements IDataSource
{

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -481,7 +481,7 @@ class DibiColumnInfo extends DibiObject
*/
public function getTableName()
{
return isset($this->info['table']) ? $this->info['table'] : NULL;
return isset($this->info['table']) && $this->info['table'] != NULL ? $this->info['table'] : NULL; // intentionally ==
}

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -117,8 +117,8 @@ class DibiDriverException extends DibiException
* @author David Grudl
* @package dibi
*/
class DibiPcreException extends Exception
{
class DibiPcreException extends Exception {
public function __construct($message = '%msg.')
{
static $messages = array(

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -58,7 +58,7 @@ class DibiFileLogger extends DibiObject
);
} else {
fwrite($handle,
'OK: ' . $event->sql
"OK: " . $event->sql
. ($event->count ? ";\n-- rows: " . $event->count : '')
. "\n-- takes: " . sprintf('%0.3f ms', $event->time * 1000)
. "\n-- source: " . implode(':', $event->source)

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -20,6 +20,9 @@ class DibiFirePhpLogger extends DibiObject
/** maximum SQL length */
static public $maxLength = 1000;
/** size of json stream chunk */
static public $streamChunkSize = 4990;
/** @var int */
public $filter;
@@ -58,19 +61,20 @@ class DibiFirePhpLogger extends DibiObject
return;
}
if (!$this->numOfQueries) {
header('X-Wf-Protocol-dibi: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
header('X-Wf-dibi-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');
header('X-Wf-dibi-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
}
$this->totalTime += $event->time;
$this->numOfQueries++;
self::$fireTable[] = array(
sprintf('%0.3f', $event->time * 1000),
strlen($event->sql) > self::$maxLength ? substr($event->sql, 0, self::$maxLength) . '...' : $event->sql,
$event->result instanceof Exception ? 'ERROR' : (string) $event->count,
$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(
array(
'Type' => 'TABLE',
@@ -78,7 +82,7 @@ class DibiFirePhpLogger extends DibiObject
),
self::$fireTable,
));
foreach (str_split($payload, 4990) as $num => $s) {
foreach (str_split($payload, self::$streamChunkSize) as $num => $s) {
$num++;
header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -12,6 +12,9 @@
* @author David Grudl
* @package dibi
*
* @property-read string $command
* @property-read DibiConnection $connection
* @property-read DibiResultIterator $iterator
* @method DibiFluent select($field)
* @method DibiFluent distinct()
* @method DibiFluent from($table)
@@ -188,7 +191,6 @@ class DibiFluent extends DibiObject implements IDataSource
foreach ($args as $arg) {
if ($arg instanceof self) {
$this->cursor[] = '%SQL';
$arg = "($arg)";
}
$this->cursor[] = $arg;
@@ -317,7 +319,7 @@ class DibiFluent extends DibiObject implements IDataSource
*/
public function fetch()
{
if ($this->command === 'SELECT' && !$this->clauses['LIMIT'] && !$this->clauses['OFFSET']) {
if ($this->command === 'SELECT') {
return $this->query($this->_export(NULL, array('%lmt', 1)))->fetch();
} else {
return $this->query($this->_export())->fetch();
@@ -331,7 +333,7 @@ class DibiFluent extends DibiObject implements IDataSource
*/
public function fetchSingle()
{
if ($this->command === 'SELECT' && !$this->clauses['LIMIT'] && !$this->clauses['OFFSET']) {
if ($this->command === 'SELECT') {
return $this->query($this->_export(NULL, array('%lmt', 1)))->fetchSingle();
} else {
return $this->query($this->_export())->fetchSingle();
@@ -403,7 +405,7 @@ class DibiFluent extends DibiObject implements IDataSource
public function count()
{
return (int) $this->query(array(
'SELECT COUNT(*) FROM (%ex', $this->_export(), ') [data]',
'SELECT COUNT(*) FROM (%ex', $this->_export(), ') AS [data]'
))->fetchSingle();
}

View File

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

View File

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

View File

@@ -2,14 +2,14 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
/**
* DibiObject is the ultimate ancestor of all instantiable classes.
*
* DibiObject is copy of Nette\Object from Nette Framework (https://nette.org).
* DibiObject is copy of Nette\Object from Nette Framework (http://nette.org).
*
* It defines some handful methods and enhances object core of PHP:
* - access to undeclared members throws exceptions
@@ -39,7 +39,7 @@
* Adding method to class (i.e. to all instances) works similar to JavaScript
* prototype property. The syntax for adding a new method is:
* <code>
* MyClass::extensionMethod('newMethod', function (MyClass $obj, $arg, ...) { ... });
* MyClass::extensionMethod('newMethod', function(MyClass $obj, $arg, ...) { ... });
* $obj = new MyClass;
* $obj->newMethod($x);
* </code>
@@ -209,8 +209,8 @@ abstract class DibiObject
}
// property getter support
$uname = ucfirst($name);
$m = 'get' . $uname;
$name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
$m = 'get' . $name;
if (self::hasAccessor($class, $m)) {
// ampersands:
// - uses & __get() because declaration should be forward compatible (e.g. with Nette\Web\Html)
@@ -219,12 +219,13 @@ abstract class DibiObject
return $val;
}
$m = 'is' . $uname;
$m = 'is' . $name;
if (self::hasAccessor($class, $m)) {
$val = $this->$m();
return $val;
}
$name = func_get_arg(0);
throw new LogicException("Cannot read an undeclared property $class::\$$name.");
}
@@ -245,18 +246,20 @@ abstract class DibiObject
}
// property setter support
$uname = ucfirst($name);
if (self::hasAccessor($class, 'get' . $uname) || self::hasAccessor($class, 'is' . $uname)) {
$name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
if (self::hasAccessor($class, 'get' . $name) || self::hasAccessor($class, 'is' . $name)) {
$m = 'set' . $name;
if (self::hasAccessor($class, $m)) {
$this->$m($value);
return;
} else {
$name = func_get_arg(0);
throw new LogicException("Cannot assign to a read-only property $class::\$$name.");
}
}
$name = func_get_arg(0);
throw new LogicException("Cannot assign to an undeclared property $class::\$$name.");
}
@@ -268,7 +271,8 @@ abstract class DibiObject
*/
public function __isset($name)
{
return $name !== '' && self::hasAccessor(get_class($this), 'get' . ucfirst($name));
$name[0] = $name[0] & "\xDF";
return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name);
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -25,7 +25,12 @@
* @author David Grudl
* @package dibi
*
* @property-read mixed $resource
* @property-read IDibiResultDriver $driver
* @property-read int $rowCount
* @property-read DibiResultIterator $iterator
* @property string $rowClass
* @property-read DibiResultInfo $info
*/
class DibiResult extends DibiObject implements IDataSource
{
@@ -104,7 +109,7 @@ class DibiResult extends DibiObject implements IDataSource
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
final public function seek($row)
@@ -183,7 +188,7 @@ class DibiResult extends DibiObject implements IDataSource
/**
* Fetches the row at current position, process optional type conversion.
* and moves the internal cursor to the next position
* @return DibiRow|FALSE array on success, FALSE if no next record
* @return DibiRow|FALSE array on success, FALSE if no next record
*/
final public function fetch()
{
@@ -204,7 +209,7 @@ class DibiResult extends DibiObject implements IDataSource
/**
* Like fetch(), but returns only first field.
* @return mixed value on success, FALSE if no next record
* @return mixed value on success, FALSE if no next record
*/
final public function fetchSingle()
{
@@ -298,16 +303,16 @@ class DibiResult extends DibiObject implements IDataSource
$x = & $x[];
} elseif ($as === '=') { // "value" node
$x = $row->{$assoc[$i + 1]};
$x = $row->{$assoc[$i+1]};
continue 2;
} elseif ($as === '->') { // "object" node
if ($x === NULL) {
$x = clone $row;
$x = & $x->{$assoc[$i + 1]};
$x = & $x->{$assoc[$i+1]};
$x = NULL; // prepare child node
} else {
$x = & $x->{$assoc[$i + 1]};
$x = & $x->{$assoc[$i+1]};
}
} elseif ($as !== '|') { // associative-array node
@@ -364,21 +369,22 @@ class DibiResult extends DibiObject implements IDataSource
} elseif ($as === '=') { // "record" node
if ($x === NULL) {
$x = $row->toArray();
$x = & $x[ $assoc[$i + 1] ];
$x = & $x[ $assoc[$i+1] ];
$x = NULL; // prepare child node
} else {
$x = & $x[ $assoc[$i + 1] ];
$x = & $x[ $assoc[$i+1] ];
}
} elseif ($as === '@') { // "object" node
if ($x === NULL) {
$x = clone $row;
$x = & $x->{$assoc[$i + 1]};
$x = & $x->{$assoc[$i+1]};
$x = NULL; // prepare child node
} else {
$x = & $x->{$assoc[$i + 1]};
$x = & $x->{$assoc[$i+1]};
}
} else { // associative-array node
$x = & $x[$row->$as];
}
@@ -418,7 +424,7 @@ class DibiResult extends DibiObject implements IDataSource
if ($value === NULL) {
if ($key !== NULL) {
throw new InvalidArgumentException('Either none or both columns must be specified.');
throw new InvalidArgumentException("Either none or both columns must be specified.");
}
// autodetect
@@ -472,8 +478,7 @@ class DibiResult extends DibiObject implements IDataSource
foreach ($this->getResultDriver()->getResultColumns() as $col) {
$this->types[$col['name']] = $cache->{$col['nativetype']};
}
} catch (DibiNotSupportedException $e) {
}
} catch (DibiNotSupportedException $e) {}
}
@@ -492,22 +497,10 @@ class DibiResult extends DibiObject implements IDataSource
if ($value === FALSE || $type === dibi::TEXT) {
} elseif ($type === dibi::INTEGER) {
$row[$key] = is_float($tmp = $value * 1)
? (is_string($value) ? $value : (int) $value)
: $tmp;
$row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
} elseif ($type === dibi::FLOAT) {
$value = ltrim($value, '0');
$p = strpos($value, '.');
if ($p !== FALSE) {
$value = rtrim(rtrim($value, '0'), '.');
}
if ($value === '' || $value[0] === '.') {
$value = '0' . $value;
}
$row[$key] = $value === str_replace(',', '.', (string) ($float = (float) $value))
? $float
: $value;
$row[$key] = str_replace(',', '.', ltrim((string) ($tmp = (float) $value), '0')) === ltrim(rtrim(rtrim($value, '0'), '.'), '0') ? $tmp : $value;
} elseif ($type === dibi::BOOL) {
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
@@ -626,7 +619,7 @@ class DibiResult extends DibiObject implements IDataSource
foreach ($row as $col => $val) {
$spaces = $maxLen - mb_strlen($col) + 2;
echo "$col" . str_repeat(' ', $spaces) . "$val\n";
echo "$col" . str_repeat(" ", $spaces) . "$val\n";
}
echo "\n";

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
*/
@@ -160,7 +160,7 @@ final class DibiTranslator extends DibiObject
if ($comment) {
$sql[] = '*/';
$sql[] = "*/";
}
$sql = implode(' ', $sql);
@@ -187,7 +187,7 @@ final class DibiTranslator extends DibiObject
public function formatValue($value, $modifier)
{
if ($this->comment) {
return '...';
return "...";
}
if (!$this->driver) {
@@ -489,7 +489,7 @@ final class DibiTranslator extends DibiObject
if ($cursor >= count($this->args)) {
$this->hasError = TRUE;
return '**Extra placeholder**';
return "**Extra placeholder**";
}
$cursor++;
@@ -512,7 +512,7 @@ final class DibiTranslator extends DibiObject
// open comment
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return '/*';
return "/*";
}
return '';
@@ -520,11 +520,11 @@ final class DibiTranslator extends DibiObject
if ($this->ifLevelStart === $this->ifLevel) {
$this->ifLevelStart = 0;
$this->comment = FALSE;
return '*/';
return "*/";
} elseif (!$this->comment) {
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return '/*';
return "/*";
}
} elseif ($mod === 'end') {
@@ -533,7 +533,7 @@ final class DibiTranslator extends DibiObject
// close comment
$this->ifLevelStart = 0;
$this->comment = FALSE;
return '*/';
return "*/";
}
return '';
@@ -542,17 +542,23 @@ final class DibiTranslator extends DibiObject
return '';
} elseif ($mod === 'lmt') { // apply limit
if ($this->args[$cursor] !== NULL) {
$this->limit = (int) $this->args[$cursor];
$arg = $this->args[$cursor++];
if ($arg === NULL) {
} elseif ($this->comment) {
return "(limit $arg)";
} else {
$this->limit = (int) $arg;
}
$cursor++;
return '';
} elseif ($mod === 'ofs') { // apply offset
if ($this->args[$cursor] !== NULL) {
$this->offset = (int) $this->args[$cursor];
$arg = $this->args[$cursor++];
if ($arg === NULL) {
} elseif ($this->comment) {
return "(offset $arg)";
} else {
$this->offset = (int) $arg;
}
$cursor++;
return '';
} else { // default processing
@@ -572,10 +578,10 @@ final class DibiTranslator extends DibiObject
return $this->identifiers->{$matches[2]};
} elseif ($matches[3]) { // SQL strings: '...'
return $this->driver->escape(str_replace("''", "'", $matches[4]), dibi::TEXT);
return $this->driver->escape( str_replace("''", "'", $matches[4]), dibi::TEXT);
} elseif ($matches[5]) { // SQL strings: "..."
return $this->driver->escape(str_replace('""', '"', $matches[6]), dibi::TEXT);
return $this->driver->escape( str_replace('""', '"', $matches[6]), dibi::TEXT);
} elseif ($matches[7]) { // string quote
$this->hasError = TRUE;
@@ -588,7 +594,7 @@ final class DibiTranslator extends DibiObject
return $matches[9] == '' ? $this->formatValue($m, FALSE) : $m . $matches[9]; // value or identifier
}
throw new Exception('this should be never executed');
die('this should be never executed');
}

View File

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

View File

@@ -11,10 +11,11 @@ require __DIR__ . '/../dibi/dibi.php';
echo '<p>Connecting to Sqlite: ';
try {
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -25,10 +26,11 @@ echo "</p>\n";
echo '<p>Connecting to Sqlite: ';
try {
$connection = new DibiConnection(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -40,6 +42,7 @@ echo '<p>Connecting to MySQL: ';
try {
dibi::connect('driver=mysql&host=localhost&username=root&password=xxx&database=test&charset=cp1250');
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -50,17 +53,18 @@ echo "</p>\n";
echo '<p>Connecting to MySQLi: ';
try {
dibi::connect(array(
'driver' => 'mysqli',
'host' => 'localhost',
'driver' => 'mysqli',
'host' => 'localhost',
'username' => 'root',
'password' => 'xxx',
'database' => 'dibi',
'options' => array(
MYSQLI_OPT_CONNECT_TIMEOUT => 30,
'options' => array(
MYSQLI_OPT_CONNECT_TIMEOUT => 30
),
'flags' => MYSQLI_CLIENT_COMPRESS,
'flags' => MYSQLI_CLIENT_COMPRESS,
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -71,12 +75,13 @@ echo "</p>\n";
echo '<p>Connecting to ODBC: ';
try {
dibi::connect(array(
'driver' => 'odbc',
'driver' => 'odbc',
'username' => 'root',
'password' => '***',
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.__DIR__.'/data/sample.mdb',
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.__DIR__.'/data/sample.mdb',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -87,11 +92,12 @@ echo "</p>\n";
echo '<p>Connecting to PostgreSql: ';
try {
dibi::connect(array(
'driver' => 'postgre',
'string' => 'host=localhost port=5432 dbname=mary',
'driver' => 'postgre',
'string' => 'host=localhost port=5432 dbname=mary',
'persistent' => TRUE,
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -102,10 +108,11 @@ echo "</p>\n";
echo '<p>Connecting to Sqlite via PDO: ';
try {
dibi::connect(array(
'driver' => 'pdo',
'dsn' => 'sqlite2::memory:',
'driver' => 'pdo',
'dsn' => 'sqlite2::memory:',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -116,12 +123,13 @@ echo "</p>\n";
echo '<p>Connecting to MS SQL: ';
try {
dibi::connect(array(
'driver' => 'mssql',
'host' => 'localhost',
'driver' => 'mssql',
'host' => 'localhost',
'username' => 'root',
'password' => 'xxx',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -132,13 +140,14 @@ echo "</p>\n";
echo '<p>Connecting to MS SQL 2005: ';
try {
dibi::connect(array(
'driver' => 'mssql2005',
'host' => '(local)',
'driver' => 'mssql2005',
'host' => '(local)',
'username' => 'Administrator',
'password' => 'xxx',
'database' => 'main',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
@@ -149,12 +158,13 @@ echo "</p>\n";
echo '<p>Connecting to Oracle: ';
try {
dibi::connect(array(
'driver' => 'oracle',
'driver' => 'oracle',
'username' => 'root',
'password' => 'xxx',
'database' => 'db',
));
echo 'OK';
} catch (DibiException $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
@@ -37,7 +37,7 @@ foreach ($table->getColumns() as $column) {
echo "</ul>\n";
echo 'Indexes';
echo "Indexes";
echo "<ul>\n";
foreach ($table->getIndexes() as $index) {
echo "<li>{$index->name} " . ($index->primary ? 'primary ' : '') . ($index->unique ? 'unique' : '') . ' (';

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));

View File

@@ -12,7 +12,7 @@ Tracy\Debugger::enable();
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
@@ -32,13 +32,13 @@ dibi::test('
// if & else & (optional) end
dibi::test('
dibi::test("
SELECT *
FROM people
WHERE id > 0
%if', ($foo > 0), 'AND foo=?', $foo, '
%else %if', ($bar > 0), 'AND bar=?', $bar, '
');
%if", ($foo > 0), "AND foo=?", $foo, "
%else %if", ($bar > 0), "AND bar=?", $bar, "
");
// -> SELECT * FROM people WHERE id > 0 AND bar=2

View File

@@ -10,7 +10,7 @@ date_default_timezone_set('Europe/Prague');
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
@@ -45,26 +45,26 @@ $array = array(
'brand' => NULL,
'created' => new DateTime,
);
dibi::test('INSERT INTO products', $array, $array, $array);
dibi::test("INSERT INTO products", $array, $array, $array);
// -> INSERT INTO products ([title], [price], [brand], [created]) VALUES ('Super Product', ...) , (...) , (...)
// dibi detects UPDATE command
dibi::test('
UPDATE colors SET', array(
dibi::test("
UPDATE colors SET", array(
'color' => 'blue',
'order' => 12,
), '
WHERE id=?', 123);
), "
WHERE id=?", 123);
// -> UPDATE colors SET [color]='blue', [order]=12 WHERE id=123
// modifier applied to array
$array = array(1, 2, 3);
dibi::test('
dibi::test("
SELECT *
FROM people
WHERE id IN (?)', $array
WHERE id IN (?)", $array
);
// -> SELECT * FROM people WHERE id IN ( 1, 2, 3 )
@@ -74,11 +74,11 @@ $order = array(
'field1' => 'asc',
'field2' => 'desc',
);
dibi::test('
dibi::test("
SELECT *
FROM people
ORDER BY %by', $order, '
');
ORDER BY %by", $order, "
");
// -> SELECT * FROM people ORDER BY [field1] ASC, [field2] DESC

View File

@@ -14,7 +14,7 @@ date_default_timezone_set('Europe/Prague');
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
@@ -27,7 +27,7 @@ $res->setType('customer_id', Dibi::INTEGER)
->setFormat(dibi::DATETIME, 'Y-m-d H:i:s');
Tracy\Dumper::dump($res->fetch());
Tracy\Dumper::dump( $res->fetch() );
// outputs:
// DibiRow(3) {
// customer_id => 1
@@ -38,7 +38,7 @@ Tracy\Dumper::dump($res->fetch());
// using auto-detection (works well with MySQL or other strictly typed databases)
$res = dibi::query('SELECT * FROM [customers]');
Tracy\Dumper::dump($res->fetch());
Tracy\Dumper::dump( $res->fetch() );
// outputs:
// DibiRow(3) {
// customer_id => 1

View File

@@ -2,7 +2,7 @@
<h1>Tracy & SQL Exceptions | dibi</h1>
<p>Dibi can display and log exceptions via <a href="https://tracy.nette.org">Tracy</a>.</p>
<p>Dibi can display and log exceptions via <a href="http://tracy.nette.org">Tracy</a>.</p>
<?php
@@ -16,11 +16,11 @@ Tracy\Debugger::enable();
$connection = dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
),
)
));

View File

@@ -4,7 +4,7 @@
<h1>Tracy | dibi</h1>
<p>Dibi can log queries and dump variables to the <a href="https://tracy.nette.org">Tracy</a>.</p>
<p>Dibi can log queries and dump variables to the <a href="http://tracy.nette.org">Tracy</a>.</p>
<?php
@@ -18,11 +18,11 @@ Tracy\Debugger::enable();
$connection = dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
),
)
));
@@ -35,4 +35,4 @@ $panel->register($connection);
dibi::query('SELECT 123');
// result set will be dumped
Tracy\Debugger::barDump(dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]');
Tracy\Debugger::barDump( dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]' );

View File

@@ -11,7 +11,7 @@ date_default_timezone_set('Europe/Prague');
// CHANGE TO REAL PARAMETERS!
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'formatDate' => "'Y-m-d'",
'formatDateTime' => "'Y-m-d H-i-s'",
@@ -19,10 +19,10 @@ dibi::connect(array(
// generate and dump SQL
dibi::test('
INSERT INTO [mytable]', array(
'id' => 123,
'date' => new DateTime('12.3.2007'),
dibi::test("
INSERT INTO [mytable]", array(
'id' => 123,
'date' => new DateTime('12.3.2007'),
'stamp' => new DateTime('23.1.2007 10:23'),
)
);

View File

@@ -12,13 +12,14 @@ Tracy\Debugger::enable();
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
// using the "prototype" to add custom method to class DibiResult
DibiResult::extensionMethod('fetchShuffle', function (DibiResult $obj) {
DibiResult::extensionMethod('fetchShuffle', function(DibiResult $obj)
{
$all = $obj->fetchAll();
shuffle($all);
return $all;

View File

@@ -10,15 +10,15 @@ date_default_timezone_set('Europe/Prague');
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
$id = 10;
$record = array(
'title' => 'Super product',
'price' => 318,
'title' => 'Super product',
'price' => 318,
'active' => TRUE,
);

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));

View File

@@ -10,7 +10,7 @@ date_default_timezone_set('Europe/Prague');
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
// enable query logging to this file
'profiler' => array(
@@ -26,12 +26,13 @@ try {
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < ?', 5);
$res = dibi::query('SELECT FROM [customers] WHERE [customer_id] < ?', 38);
} catch (DibiException $e) {
echo '<p>', get_class($e), ': ', $e->getMessage(), '</p>';
}
// outputs a log file
echo '<h2>File data/log.sql:</h2>';
echo "<h2>File data/log.sql:</h2>";
echo '<pre>', file_get_contents('data/log.sql'), '</pre>';

View File

@@ -10,16 +10,16 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
),
)
));
// execute some queries...
for ($i = 0; $i < 20; $i++) {
for ($i=0; $i<20; $i++) {
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < ?', $i);
}

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
@@ -16,7 +16,7 @@ dibi::connect(array(
// create new substitution :blog: ==> wp_
dibi::getSubstitutes()->blog = 'wp_';
dibi::test('SELECT * FROM [:blog:items]');
dibi::test("SELECT * FROM [:blog:items]");
// -> SELECT * FROM [wp_items]

View File

@@ -8,7 +8,7 @@ require __DIR__ . '/../dibi/dibi.php';
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));

View File

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

View File

@@ -1,12 +1,13 @@
[Dibi](http://dibiphp.com) - smart database layer for PHP [![Buy me a coffee](https://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 [![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)
=========================================================
[![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
hides the differences between them, and above all, it gives you a very handy interface.
The best way to install Dibi is to use a [Composer](https://getcomposer.org/download):
The best way to install Dibi is to use a [Composer](http://getcomposer.org/download):
php composer.phar require dibi/dibi

4
tests/.gitignore vendored Normal file
View File

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

View File

@@ -0,0 +1,76 @@
[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

159
tests/dibi/DataSource.phpt Normal file
View File

@@ -0,0 +1,159 @@
<?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

@@ -0,0 +1,35 @@
<?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

@@ -0,0 +1,37 @@
<?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

@@ -0,0 +1,329 @@
<?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

@@ -0,0 +1,26 @@
<?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

@@ -0,0 +1,48 @@
<?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

@@ -0,0 +1,35 @@
<?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

@@ -0,0 +1,45 @@
<?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

@@ -0,0 +1,59 @@
<?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

@@ -0,0 +1,58 @@
<?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

@@ -0,0 +1,139 @@
<?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

@@ -0,0 +1,30 @@
<?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,70 +0,0 @@
<?php
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
class TestClass extends DibiObject
{
public function getBar()
{
return 123;
}
public function isFoo()
{
return 456;
}
}
// calling
Assert::exception(function () {
$obj = new TestClass;
$obj->undeclared();
}, 'LogicException', 'Call to undefined method TestClass::undeclared().');
Assert::exception(function () {
TestClass::undeclared();
}, 'LogicException', 'Call to undefined static method TestClass::undeclared().');
// writing
Assert::exception(function () {
$obj = new TestClass;
$obj->undeclared = 'value';
}, 'LogicException', 'Cannot assign to an undeclared property TestClass::$undeclared.');
// property getter
$obj = new TestClass;
Assert::true(isset($obj->bar));
Assert::same(123, $obj->bar);
Assert::false(isset($obj->foo));
Assert::same(456, $obj->foo);
// reading
Assert::exception(function () {
$obj = new TestClass;
$val = $obj->undeclared;
}, 'LogicException', 'Cannot read an undeclared property TestClass::$undeclared.');
// unset/isset
Assert::exception(function () {
$obj = new TestClass;
unset($obj->undeclared);
}, 'LogicException', 'Cannot unset the property TestClass::$undeclared.');
Assert::false(isset($obj->undeclared));
// extension method
TestClass::extensionMethod('join', $func = function (TestClass $that, $separator) {
return $that->foo . $separator . $that->bar;
});
$obj = new TestClass;
Assert::same('456*123', $obj->join('*'));

View File

@@ -0,0 +1,57 @@
<?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

@@ -0,0 +1,18 @@
<?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

@@ -0,0 +1,17 @@
<?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

@@ -0,0 +1,88 @@
<?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

@@ -0,0 +1,47 @@
<?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

@@ -0,0 +1,531 @@
<?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

@@ -0,0 +1,80 @@
<?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);

View File

@@ -0,0 +1,34 @@
<?php
/**
* @dataProvider ../databases.ini
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
if ($config['system'] !== 'pgsql') {
Tester\Environment::skip("Not supported system '$config[system]'.");
}
$tests = function($conn) {
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A_B')->fetchSingle());
Assert::true( $conn->query("SELECT 'AA_BB' LIKE %~like~", 'A_B')->fetchSingle());
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A%B')->fetchSingle());
Assert::true( $conn->query("SELECT 'AA%BB' LIKE %~like~", 'A%B')->fetchSingle());
Assert::same('AA\\BB', $conn->query("SELECT 'AA\\BB'")->fetchSingle());
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A\\B')->fetchSingle());
Assert::true( $conn->query("SELECT 'AA\\BB' LIKE %~like~", 'A\\B')->fetchSingle());
};
$conn = new DibiConnection($config);
$conn->query('SET escape_string_warning = off'); // do not log warnings
$conn->query('SET standard_conforming_strings = on');
$tests($conn);
$conn->query('SET standard_conforming_strings = off');
$tests($conn);

71
tests/dibi/bootstrap.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
// The Nette Tester command-line runner can be
// invoked through the command: ../../vendor/bin/tester .
if (@!include __DIR__ . '/../../vendor/autoload.php') {
echo 'Install Nette Tester using `composer update --dev`';
exit(1);
}
// configure environment
Tester\Environment::setup();
date_default_timezone_set('Europe/Prague');
// load connection
try {
$config = Tester\Environment::loadData();
} catch (Exception $e) {
$config = parse_ini_file(__DIR__ . '/../databases.ini', TRUE);
$config = $config['sqlite3'];
}
// lock
define('TEMP_DIR', __DIR__ . '/../tmp');
@mkdir(TEMP_DIR); // @ - directory may already exist
Tester\Environment::lock($config['system'], TEMP_DIR);
// ODBC
if ($config['system'] === 'odbc') {
copy(__DIR__ . '/data/odbc.mdb', TEMP_DIR . '/odbc.mdb');
$config['dsn'] = str_replace('data/odbc.mdb', TEMP_DIR . '/odbc.mdb', $config['dsn']);
}
try {
new DibiConnection($config);
} catch (DibiNotSupportedException $e) {
Tester\Environment::skip($e->getMessage());
}
function test(\Closure $function)
{
$function();
}
/** Replaces [] with driver-specific quotes */
function reformat($s)
{
global $config;
if (is_array($s)) {
if (isset($s[$config['system']])) {
return $s[$config['system']];
}
$s = $s[0];
}
if ($config['system'] === 'mysql') {
return strtr($s, '[]', '``');
} elseif ($config['system'] === 'pgsql') {
return strtr($s, '[]', '""');
} elseif ($config['system'] === 'odbc' || $config['system'] === 'sqlite') {
return $s;
} else {
trigger_error("Unsupported driver $config[system]", E_USER_WARNING);
}
}

52
tests/dibi/data/mysql.sql Normal file
View File

@@ -0,0 +1,52 @@
/*!40102 SET storage_engine = InnoDB */;
DROP DATABASE IF EXISTS dibi_test;
CREATE DATABASE dibi_test;
USE dibi_test;
DROP TABLE IF EXISTS `products`;
CREATE TABLE `products` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) DEFAULT NULL,
PRIMARY KEY (`product_id`),
KEY `title` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `products` (`product_id`, `title`) VALUES
(1, 'Chair'),
(3, 'Computer'),
(2, 'Table');
DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers` (
`customer_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `customers` (`customer_id`, `name`) VALUES
(1, 'Dave Lister'),
(2, 'Arnold Rimmer'),
(3, 'The Cat'),
(4, 'Holly'),
(5, 'Kryten'),
(6, 'Kristine Kochanski');
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`order_id` int(11) NOT NULL AUTO_INCREMENT,
`customer_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`amount` float NOT NULL,
PRIMARY KEY (`order_id`),
KEY `customer_id` (`customer_id`),
KEY `product_id` (`product_id`),
CONSTRAINT `orders_ibfk_4` FOREIGN KEY (`product_id`) REFERENCES `products` (`product_id`) ON UPDATE CASCADE,
CONSTRAINT `orders_ibfk_3` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES
(1, 2, 1, 7),
(2, 2, 3, 2),
(3, 1, 2, 3),
(4, 6, 3, 5);

BIN
tests/dibi/data/odbc.mdb Normal file

Binary file not shown.

32
tests/dibi/data/odbc.sql Normal file
View File

@@ -0,0 +1,32 @@
CREATE TABLE products (
product_id COUNTER,
title TEXT(50)
);
INSERT INTO products (product_id, title) VALUES (1, 'Chair');
INSERT INTO products (product_id, title) VALUES (2, 'Table');
INSERT INTO products (product_id, title) VALUES (3, 'Computer');
CREATE TABLE [customers] (
[customer_id] COUNTER,
[name] TEXT(50)
);
INSERT INTO `customers` (`customer_id`, `name`) VALUES (1, 'Dave Lister');
INSERT INTO `customers` (`customer_id`, `name`) VALUES (2, 'Arnold Rimmer');
INSERT INTO `customers` (`customer_id`, `name`) VALUES (3, 'The Cat');
INSERT INTO `customers` (`customer_id`, `name`) VALUES (4, 'Holly');
INSERT INTO `customers` (`customer_id`, `name`) VALUES (5, 'Kryten');
INSERT INTO `customers` (`customer_id`, `name`) VALUES (6, 'Kristine Kochanski');
CREATE TABLE [orders] (
[order_id] INTEGER,
[customer_id] INTEGER,
[product_id] INTEGER,
[amount] FLOAT
);
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (1, 2, 1, 7);
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (2, 2, 3, 2);
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (3, 1, 2, 3);
INSERT INTO `orders` (`order_id`, `customer_id`, `product_id`, `amount`) VALUES (4, 6, 3, 5);

52
tests/dibi/data/pgsql.sql Normal file
View File

@@ -0,0 +1,52 @@
SET client_encoding = 'UTF8';
DROP SCHEMA IF EXISTS public CASCADE;
CREATE SCHEMA public;
CREATE TABLE products (
product_id serial NOT NULL,
title varchar(100) DEFAULT NULL,
PRIMARY KEY (product_id)
);
INSERT INTO products (product_id, title) VALUES
(1, 'Chair'),
(2, 'Table'),
(3, 'Computer');
SELECT setval('products_product_id_seq', 3, TRUE);
CREATE INDEX title ON products USING btree (title);
CREATE TABLE customers (
customer_id serial NOT NULL,
name varchar(100) DEFAULT NULL,
PRIMARY KEY (customer_id)
);
INSERT INTO customers (customer_id, name) VALUES
(1, 'Dave Lister'),
(2, 'Arnold Rimmer'),
(3, 'The Cat'),
(4, 'Holly'),
(5, 'Kryten'),
(6, 'Kristine Kochanski');
SELECT setval('customers_customer_id_seq', 6, TRUE);
CREATE TABLE orders (
order_id serial NOT NULL,
customer_id integer NOT NULL,
product_id integer NOT NULL,
amount real NOT NULL
);
INSERT INTO orders (order_id, customer_id, product_id, amount) VALUES
(1, 2, 1, 7),
(2, 2, 3, 2),
(3, 1, 2, 3),
(4, 6, 3, 5);
SELECT setval('orders_order_id_seq', 4, TRUE);
ALTER TABLE ONLY orders
ADD CONSTRAINT orders_customer_id_fkey FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE ONLY orders
ADD CONSTRAINT orders_product_id_fkey FOREIGN KEY (product_id) REFERENCES products(product_id) ON UPDATE CASCADE ON DELETE RESTRICT;

View File

@@ -0,0 +1,34 @@
CREATE TABLE [products] (
[product_id] INTEGER NOT NULL PRIMARY KEY,
[title] VARCHAR(100) NULL
);
CREATE INDEX "title" ON "products" ("title");
INSERT INTO "products" ("product_id", "title") VALUES (1, 'Chair');
INSERT INTO "products" ("product_id", "title") VALUES (2, 'Table');
INSERT INTO "products" ("product_id", "title") VALUES (3, 'Computer');
CREATE TABLE [customers] (
[customer_id] INTEGER PRIMARY KEY NOT NULL,
[name] VARCHAR(100) NULL
);
INSERT INTO "customers" ("customer_id", "name") VALUES (1, 'Dave Lister');
INSERT INTO "customers" ("customer_id", "name") VALUES (2, 'Arnold Rimmer');
INSERT INTO "customers" ("customer_id", "name") VALUES (3, 'The Cat');
INSERT INTO "customers" ("customer_id", "name") VALUES (4, 'Holly');
INSERT INTO "customers" ("customer_id", "name") VALUES (5, 'Kryten');
INSERT INTO "customers" ("customer_id", "name") VALUES (6, 'Kristine Kochanski');
CREATE TABLE [orders] (
[order_id] INTEGER NOT NULL PRIMARY KEY,
[customer_id] INTEGER NOT NULL,
[product_id] INTEGER NOT NULL,
[amount] FLOAT NOT NULL
);
INSERT INTO "orders" ("order_id", "customer_id", "product_id", "amount") VALUES (1, 2, 1, '7.0');
INSERT INTO "orders" ("order_id", "customer_id", "product_id", "amount") VALUES (2, 2, 3, '2.0');
INSERT INTO "orders" ("order_id", "customer_id", "product_id", "amount") VALUES (3, 1, 2, '3.0');
INSERT INTO "orders" ("order_id", "customer_id", "product_id", "amount") VALUES (4, 6, 3, '5.0');

75
tests/dibi/meta.phpt Normal file
View File

@@ -0,0 +1,75 @@
<?php
/**
* @dataProvider ../databases.ini
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
if ($config['system'] === 'odbc' || $config['driver'] === 'pdo') {
Tester\Environment::skip('Not supported.');
}
$conn = new DibiConnection($config);
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
$meta = $conn->getDatabaseInfo();
Assert::same(3, count($meta->getTables()));
$names = $meta->getTableNames();
sort($names);
Assert::equal(array('customers', 'orders', 'products'), $names);
Assert::false($meta->hasTable('xxxx'));
$table = $meta->getTable('products');
Assert::same('products', $table->name);
Assert::false($table->isView());
Assert::same(2, count($table->getColumns()));
Assert::false($table->hasColumn('xxxx'));
Assert::true($table->hasColumn('product_id'));
Assert::true($table->hasColumn('Product_id'));
Assert::same('product_id', $table->getColumn('Product_id')->name);
$column = $table->getColumn('product_id');
Assert::same('product_id', $column->name);
Assert::same('products', $column->table->name);
Assert::same('i', $column->type);
Assert::type('string', $column->nativeType);
Assert::false($column->nullable);
Assert::true($column->autoIncrement);
$column = $table->getColumn('title');
Assert::same('title', $column->name);
Assert::same('products', $column->table->name);
Assert::same('s', $column->type);
Assert::type('string', $column->nativeType);
Assert::same(100, $column->size);
Assert::true($column->nullable);
Assert::false($column->autoIncrement);
//Assert::null($column->default);
$indexes = $table->getIndexes();
$index = reset($indexes);
if ($config['system'] !== 'sqlite') {
Assert::same(2, count($indexes));
Assert::true($index->primary);
Assert::true($index->unique);
Assert::same(1, count($index->getColumns()));
Assert::same('product_id', $index->columns[0]->name);
$index = next($indexes);
}
Assert::same('title', $index->name);
Assert::false($index->primary);
Assert::false($index->unique);
Assert::same(1, count($index->getColumns()));
Assert::same('title', $index->columns[0]->name);

2
tests/php-unix.ini Normal file
View File

@@ -0,0 +1,2 @@
[PHP]
;extension_dir = "./ext"

18
tests/php-win.ini Normal file
View File

@@ -0,0 +1,18 @@
[PHP]
extension_dir = "./ext"
;extension=php_mssql.dll
extension=php_mysql.dll
extension=php_mysqli.dll
;extension=php_oci8.dll
;extension=php_oci8_11g.dll
;extension=php_pdo_firebird.dll
;extension=php_pdo_mssql.dll
extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
extension=php_pdo_odbc.dll
extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
extension=php_pgsql.dll
extension=php_sqlite.dll
extension=php_sqlite3.dll
;extension=php_sqlsrv_ts.dll