1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-30 01:09:50 +02:00

Compare commits

...

99 Commits

Author SHA1 Message Date
David Grudl
fc6ef0b121 Released version 2.3.5 2015-12-16 15:14:32 +01:00
Jan Langer
96188d2edc Helpers::detectType resolves tinyint as integer
# Conflicts:
#	src/Dibi/Helpers.php
2015-12-16 15:14:32 +01:00
Michal Kočárek
f392728e0c PdoDriver: unset remaining references to PDO to allow disconnection 2015-12-16 15:14:31 +01:00
David Grudl
c14dd863b6 uses https 2015-12-16 15:09:30 +01:00
David Grudl
7812e74602 tests: improved 2015-11-26 12:27:37 +01:00
Petr Soukup
f457504037 DibiFluent: added missing annotations [Closes #191] 2015-11-06 23:11:56 +01:00
David Grudl
50324fd815 typo 2015-11-06 23:11:12 +01:00
David Grudl
8f8fd040ff tests: fixes 2015-11-04 17:29:05 +01:00
David Grudl
120f0946e0 tests: improved ini quering 2015-11-04 17:29:05 +01:00
David Grudl
fef3eccc61 tests: added missing items to databases.sample.ini & etc 2015-11-04 17:29:04 +01:00
David Grudl
411862d5d8 DibiFluent: fixed combination of modifier and inner fluent [Closes #192] 2015-11-02 14:49:08 +01:00
David Grudl
84f3a5ddef DibiResultInfo: fixed case insensitivity 2015-11-02 11:45:27 +01:00
David Grudl
47ef875c73 Released version 2.3.4 2015-10-26 19:31:39 +01:00
David Grudl
63c644a860 DibiFluent::fetch() uses limit only when there is no LIMIT & OFFSET (fixes 20f2093 on MSSQL) 2015-10-26 19:31:08 +01:00
David Grudl
1c3ef5f5cf DibiFluent: prevents doubled processing 2015-10-26 19:26:07 +01:00
Pavel Zelezny
9100f94b8f DibiConnection: option 'driver' can contain driver instance or class name [Closes #153] 2015-10-26 19:26:06 +01:00
David Grudl
e339eff00f tests: improved sql dumps, renamed pgsql -> postgre 2015-10-26 14:32:48 +01:00
David Grudl
48adcec6dc added DibiSqlsrvDriver as alias for DibiMsSql2005Driver 2015-10-26 14:28:55 +01:00
David Grudl
389026d697 DibiTranslator: removed die() 2015-10-23 17:20:15 +02:00
David Grudl
8f0d0fb115 Released version 2.3.3 2015-10-22 02:44:33 +02:00
David Grudl
965570c067 removed unused code 2015-10-22 02:43:57 +02:00
David Grudl
4ae4f49c21 Result: fixed normalization of float when ends with "0" [Closes #189] 2015-10-13 15:13:59 +02:00
David Grudl
5b9ffe14ba Result: normalize converts FALSE 2015-10-13 15:13:59 +02:00
castamir
2d9358e4f7 DibiFluent::fetch(): fixed limit clause duplication [Closes #188][Closes #186][Closes #185] 2015-10-09 11:41:12 +02:00
David Grudl
e3748420f5 DibiFluent: removed keyword AS from SQL [Closes #172] 2015-10-09 00:17:10 +02:00
David Grudl
d708ac2aeb tests: added new, typo 2015-10-06 15:39:37 +02:00
David Grudl
806ee1ccd1 DibiObject: fixed compatibility with PHP 7 2015-10-06 15:35:55 +02:00
David Grudl
0ec544043f removed rarely used @property 2015-10-06 12:10:22 +02:00
David Grudl
6dcdd68d6d removed @author 2015-10-06 12:10:21 +02:00
David Grudl
9ad502887b used https 2015-10-06 12:10:20 +02:00
David Grudl
f06425b9a0 travis: migrating to container-based infrastructure 2015-07-23 18:54:35 +02:00
David Grudl
ca99b0b822 improved coding style 2015-06-19 15:00:23 +02:00
David Grudl
462ef6934b readme.md: added badges 2015-06-15 15:14:45 +02:00
Jan Tvrdik
84c85bc536 travis: run tests on PHP 7 2015-06-15 15:14:44 +02:00
David Grudl
d3151f7c65 DibiTranslator: deprecated support for hex number in strings '0xFF' (BC break)
related to PHP7 and https://wiki.php.net/rfc/remove_hex_support_in_numeric_strings
2015-06-15 14:57:38 +02:00
David Grudl
66afffcddc DibiTranslator: small refactoring 2015-06-15 14:42:48 +02:00
David Grudl
7762da1bbb Released version 2.3.2 2015-04-18 16:26:53 +02:00
David Grudl
6f6a63881a Merge pull request #176 from milo/pull-oracle
Oracle fixes
2015-04-17 15:47:00 +02:00
Miloslav Hůla
999f51a7bd OracleDriver: cast type NUMBER(p, 0) as an INTEGER
In many cases, Oracle returns integers as a NUMBER(8,0). Type NUMBER is casted to (float) which is unnecessary in this case.
2015-04-17 15:22:45 +02:00
Miloslav Hůla
64b3d0c6f4 Tracy panels: Oracle uses EXPLAIN PLAN FOR
Warning 'ORA-00905: missing keyword' is emmited otherwise.
2015-04-17 15:21:21 +02:00
Miloslav Hůla
06440ab6dc OracleDriver: shut-up oci_execute()
The oci_execute() emits warnings e.g. on denied permissions when EXPLAIN.
2015-04-17 15:17:14 +02:00
David Grudl
b341b66d43 Merge pull request #175 from milo/pull-autowired
Nette extensions: added 'autowired' configuration
2015-04-16 16:47:39 +02:00
Miloslav Hůla
aac83ba849 Nette extensions: added 'autowired' configuration 2015-04-16 15:01:00 +02:00
David Grudl
2de32b66e1 Merge pull request #174 from baasha/baasha-patch-1
DibiPdoDriver::escape() added support for dblib
2015-03-27 00:05:09 +01:00
baasha
1829366fc9 DibiPdoDriver::escape() added support for dblib
Fixed escaping for linux version of mssql driver - dblib.
2015-03-26 23:47:06 +01:00
Radovan Kepák
94f34a2a33 DibiPdoDriver: added support for version specified in options
If driver do not support ATTR_SERVER_VERSION (like dblib) fallback to the version from config, or set null as we do not know what is the driver version.

I belive this is better solution then add some creazy switch with queries for all possible versions on all drivers, and becouse it is faster to pass variable then run query asking about version.
2015-03-12 15:11:04 +01:00
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
David Grudl
f534c15f0e Merge pull request #155 from JirkaChadima/dbliblimitsupport
MSSQL: Adds limit support for PDO dblib driver on unix
2014-11-04 23:47:23 +01:00
Jirka Chadima
985f59a2b2 MSSQL: Adds limit support for PDO dblib driver on unix 2014-11-04 11:43:05 +01:00
David Grudl
6fc99254ab Merge pull request #152 from zeleznypa/master
Oracle does not support any brackets around table name
2014-10-26 14:01:41 +01:00
Pavel Zelezny
dc688f3ee7 Oracle use double quotes for escaping 2014-10-26 13:56:34 +01:00
Jirka Chadima
4e99d7821c Oracle: adds support for login schema option 2014-10-21 17:01:59 +02:00
David Grudl
cde5af7cbe Merge pull request #142 from JanRossler/multi-search-path
PostgreSQL: fixed identifier escaping in reflection.
2014-07-16 17:46:08 +02:00
Rossler Jan
7c35e49a1c PostgreSQL: fixed identifier escaping in reflection. 2014-07-16 14:06:14 +02:00
David Grudl
6b08cf0711 Merge pull request #140 from JanRossler/multi-search-path
PostgreSQL: fixed search path resolution in table and column reflection.
2014-07-16 11:46:38 +02:00
David Grudl
4b0ebc76b0 Merge pull request #141 from JanRossler/php52
DibiDateTime: Restored php 5.2 support.
2014-07-15 12:46:42 +02:00
Rossler Jan
5993ea8aaf DibiDateTime: Restored php 5.2 support. 2014-07-15 12:39:51 +02:00
Rossler Jan
f89a2310cc PostgreSQL: fixed search path resolution in table and column reflection. 2014-07-07 01:51:56 +02:00
David Grudl
a118c2cf96 Released version 2.2.2 2014-06-30 17:08:04 +02:00
castamir
9b0e64220b Tracy loaded from composer instead of a local copy [Closes #139] 2014-06-30 14:52:44 +02:00
David Grudl
1c386d5582 typos 2014-06-30 14:52:43 +02:00
David Grudl
c9944b3886 Partially reverts "DibiTranslator: object is initialized in constructor", fixes lazy connection [Closes #138]
This reverts commit 0071b80938.
2014-06-24 21:40:54 +02:00
David Grudl
d0fd009dda readme.md: buy me a coffee 2014-06-13 17:54:46 +02:00
David Grudl
c32251357d fixed bug 'interface IBarPanel not found' [Closes #137] 2014-06-11 16:16:32 +02:00
111 changed files with 3256 additions and 942 deletions

View File

@@ -4,18 +4,35 @@ php:
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
allow_failures:
- php: 7.0
- php: hhvm
script: vendor/bin/tester tests -s -c tests/php-unix.ini
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
- composer install --no-interaction --dev --prefer-source
# Install Nette Tester & Code Checker
- travis_retry composer install --no-interaction
- travis_retry composer create-project nette/code-checker code-checker ~2.5 --no-interaction
# Create databases.ini
- cp ./tests/databases.sample.ini ./tests/databases.ini
# Create Postgre database
- psql -c 'CREATE DATABASE dibi_test' -U postgres
sudo: false
cache:
directories:
- $HOME/.composer/cache

View File

@@ -2,19 +2,20 @@
"name": "dibi/dibi",
"description": "Dibi is Database Abstraction Library for PHP",
"keywords": ["database", "dbal", "mysql", "postgresql", "sqlite", "mssql", "oracle", "access", "pdo", "odbc"],
"homepage": "http://dibiphp.com",
"homepage": "https://dibiphp.com",
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
"authors": [
{
"name": "David Grudl",
"homepage": "http://davidgrudl.com"
"homepage": "https://davidgrudl.com"
}
],
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"nette/tester": "~1.1"
"tracy/tracy": "~2.2",
"nette/tester": "~1.3"
},
"replace": {
"dg/dibi": "self.version"
@@ -24,7 +25,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"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](https://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](https://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 (http://davidgrudl.com)
*
* For the full copyright and license information, please view
* the file license.txt that was distributed with this source code.
*/
/**
* Dibi extension for Nette Framework 2.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,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* Dibi extension for Nette Framework 2.1. Creates 'connection' service.
*
* @author David Grudl
* @package dibi\nette
* @phpversion 5.3
*/
@@ -36,7 +35,8 @@ class DibiNette21Extension extends Nette\DI\CompilerExtension
}
$connection = $container->addDefinition($this->prefix('connection'))
->setClass('DibiConnection', array($config));
->setClass('DibiConnection', array($config))
->setAutowired(isset($config['autowired']) ? $config['autowired'] : TRUE);
if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel'))

View File

@@ -2,22 +2,18 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
if (interface_exists('Nette\Diagnostics\IBarPanel')) {
class_alias('Nette\Diagnostics\IBarPanel', 'IBarPanel');
}
use Nette\Diagnostics\Debugger;
/**
* Dibi panel for Nette\Diagnostics.
*
* @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 +37,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');
}
@@ -122,9 +103,10 @@ class DibiNettePanel extends DibiObject implements IBarPanel
try {
$backup = array($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime);
$event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN' : 'EXPLAIN');
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN');
$explain = dibi::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
} catch (DibiException $e) {}
} catch (DibiException $e) {
}
list($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime) = $backup;
}

View File

@@ -2,19 +2,18 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi\Bridges\Nette;
use dibi,
Nette;
use dibi;
use Nette;
/**
* Dibi extension for Nette Framework 2.2. Creates 'connection' & 'panel' services.
*
* @author David Grudl
* @package dibi\nette
*/
class DibiExtension22 extends Nette\DI\CompilerExtension
@@ -40,7 +39,8 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
}
$connection = $container->addDefinition($this->prefix('connection'))
->setClass('DibiConnection', array($config));
->setClass('DibiConnection', array($config))
->setAutowired(isset($config['autowired']) ? $config['autowired'] : TRUE);
if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel'))

View File

@@ -2,19 +2,18 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi\Bridges\Tracy;
use dibi,
Tracy;
use dibi;
use Tracy;
/**
* Dibi panel for Tracy.
*
* @author David Grudl
* @package dibi\nette
*/
class Panel extends \DibiObject implements Tracy\IBarPanel
{
@@ -81,13 +80,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>';
}
@@ -106,9 +106,10 @@ class Panel extends \DibiObject implements Tracy\IBarPanel
try {
$backup = array($event->connection->onEvent, dibi::$numOfQueries, dibi::$totalTime);
$event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN' : 'EXPLAIN');
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN');
$explain = dibi::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
} catch (\DibiException $e) {}
} 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 (http://davidgrudl.com)
* Copyright (c) 2005, 2012 David Grudl (https://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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -18,7 +18,6 @@
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author Tomáš Kraina, Roman Sklenář
* @package dibi\drivers
*/
class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultDriver, IDibiReflector
@@ -88,7 +87,6 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
throw new DibiDriverException(ibase_errmsg(), ibase_errcode());
}
}
}
@@ -349,7 +347,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.');
}
@@ -379,13 +377,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool 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.');
}
@@ -402,7 +400,7 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
/**
* Returns the result set resource.
* @return mysqli_result
* @return resource
*/
public function getResultResource()
{
@@ -656,7 +654,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)) {
@@ -683,7 +681,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();
@@ -808,8 +806,6 @@ class DibiFirebirdDriver extends DibiObject implements IDibiDriver, IDibiResultD
/**
* Database procedure exception.
*
* @author Roman Sklenář
* @copyright Copyright (c) 2010
* @package dibi\drivers
*/
class DibiProcedureException extends DibiException

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -17,12 +17,11 @@ require_once dirname(__FILE__) . '/DibiMsSql2005Reflector.php';
* - username (or user)
* - password (or pass)
* - database => the database name to select
* - options (array) => connection options {@link http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx}
* - options (array) => connection options {@link https://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
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResultDriver
@@ -226,7 +225,7 @@ class DibiMsSql2005Driver extends DibiObject implements IDibiDriver, IDibiResult
return "'" . str_replace("'", "''", $value) . "'";
case dibi::IDENTIFIER:
// @see http://msdn.microsoft.com/en-us/library/ms176027.aspx
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
return '[' . str_replace(']', ']]', $value) . ']';
case dibi::BOOL:
@@ -327,8 +326,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* The dibi reflector for MSSQL2005 databases.
*
* @author Daniel Kouba
* @package dibi\drivers
* @internal
*/
@@ -104,7 +103,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
require_once dirname(__FILE__) . '/DibiMsSqlReflector.php';
@@ -19,7 +19,6 @@ require_once dirname(__FILE__) . '/DibiMsSqlReflector.php';
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
@@ -211,7 +210,7 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
return "'" . str_replace("'", "''", $value) . "'";
case dibi::IDENTIFIER:
// @see http://msdn.microsoft.com/en-us/library/ms176027.aspx
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']';
case dibi::BOOL:
@@ -363,5 +362,4 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriv
return is_resource($this->resultSet) ? $this->resultSet : NULL;
}
}

View File

@@ -2,17 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
*
* Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
*
* @package dibi\drivers
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* The dibi reflector for MsSQL databases.
*
* @author Steven Bredenberg
* @package dibi\drivers
* @internal
*/
@@ -34,10 +30,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 +48,12 @@ class DibiMsSqlReflector extends DibiObject implements IDibiReflector
/**
* Returns count of rows in a table
* @param string
* @return integer
* @return int
*/
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 +67,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 +92,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 +118,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 +157,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 +199,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -27,7 +27,6 @@ require_once dirname(__FILE__) . '/DibiMySqlReflector.php';
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiMySqlDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
@@ -406,8 +405,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
public function seek($row)

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* The dibi reflector for MySQL databases.
*
* @author David Grudl
* @package dibi\drivers
* @internal
*/
@@ -31,12 +30,7 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
*/
public function getTables()
{
/*$this->query("
SELECT TABLE_NAME as name, TABLE_TYPE = 'VIEW' as view
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(
@@ -55,12 +49,6 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
*/
public function getColumns($table)
{
/*$table = $this->escape($table, dibi::TEXT);
$this->query("
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = $table AND TABLE_SCHEMA = DATABASE()
");*/
$res = $this->driver->query("SHOW FULL COLUMNS FROM {$this->driver->escape($table, dibi::IDENTIFIER)}");
$columns = array();
while ($row = $res->fetch(TRUE)) {
@@ -88,13 +76,6 @@ class DibiMySqlReflector extends DibiObject implements IDibiReflector
*/
public function getIndexes($table)
{
/*$table = $this->escape($table, dibi::TEXT);
$this->query("
SELECT *
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME = $table AND TABLE_SCHEMA = DATABASE()
AND REFERENCED_COLUMN_NAME IS NULL
");*/
$res = $this->driver->query("SHOW INDEX FROM {$this->driver->escape($table, dibi::IDENTIFIER)}");
$indexes = array();
while ($row = $res->fetch(TRUE)) {
@@ -138,9 +119,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -28,7 +28,6 @@ require_once dirname(__FILE__) . '/DibiMySqlReflector.php';
* - resource (mysqli) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiMySqliDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
@@ -79,7 +78,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 +388,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
public function seek($row)
@@ -420,9 +419,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 +438,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 +453,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -17,7 +17,6 @@
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiOdbcDriver extends DibiObject implements IDibiDriver, IDibiResultDriver, IDibiReflector
@@ -290,7 +289,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,7 +338,9 @@ 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;
}
}
@@ -347,8 +348,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{
@@ -378,10 +379,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -14,13 +14,13 @@
* - username (or user)
* - password (or pass)
* - charset => character encoding to set
* - schema => alters session schema
* - formatDate => how to format date in SQL (@see date)
* - formatDateTime => how to format datetime in SQL (@see date)
* - resource (resource) => existing connection resource
* - persistent => Creates persistent connections with oci_pconnect instead of oci_new_connect
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDriver, IDibiReflector
@@ -75,6 +75,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']);
}
}
@@ -98,7 +102,7 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
{
$res = oci_parse($this->connection, $sql);
if ($res) {
oci_execute($res, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
@oci_execute($res, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
$err = oci_error($res);
if ($err) {
throw new DibiDriverException($err['message'], $err['code'], $sql);
@@ -331,8 +335,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{
@@ -360,11 +364,12 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver, IDibiResultDri
$count = oci_num_fields($this->resultSet);
$columns = array();
for ($i = 1; $i <= $count; $i++) {
$type = oci_field_type($this->resultSet, $i);
$columns[] = array(
'name' => oci_field_name($this->resultSet, $i),
'table' => NULL,
'fullname' => oci_field_name($this->resultSet, $i),
'nativetype'=> oci_field_type($this->resultSet, $i),
'nativetype' => $type === 'NUMBER' && oci_field_scale($this->resultSet, $i) === 0 ? 'INTEGER' : $type,
);
}
return $columns;

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -19,9 +19,9 @@ require_once dirname(__FILE__) . '/DibiSqliteReflector.php';
* - password (or pass)
* - options (array) => driver specific options {@see PDO::__construct}
* - resource (PDO) => existing connection
* - version
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
@@ -38,6 +38,9 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
/** @var string */
private $driverName;
/** @var string */
private $serverVersion;
/**
* @throws DibiNotSupportedException
@@ -63,19 +66,22 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
if ($config['resource'] instanceof PDO) {
$this->connection = $config['resource'];
} 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.');
unset($config['resource'], $config['pdo']);
} else {
try {
$this->connection = new PDO($config['dsn'], $config['username'], $config['password'], $config['options']);
} catch (PDOException $e) {
if ($e->getMessage() === 'could not find driver') {
throw new DibiNotSupportedException('PHP extension for PDO is not loaded.');
}
throw new DibiDriverException($e->getMessage(), $e->getCode());
}
}
$this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);
$this->serverVersion = isset($config['version'])
? $config['version']
: @$this->connection->getAttribute(PDO::ATTR_SERVER_VERSION); // @ - may be not supported
}
@@ -99,7 +105,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
{
// must detect if SQL returns result set or num of affected rows
$cmd = strtoupper(substr(ltrim($sql), 0, 6));
static $list = array('UPDATE'=>1, 'DELETE'=>1, 'INSERT'=>1, 'REPLAC'=>1);
static $list = array('UPDATE' => 1, 'DELETE' => 1, 'INSERT' => 1, 'REPLAC' => 1);
$this->affectedRows = FALSE;
if (isset($list[$cmd])) {
@@ -245,16 +251,19 @@ 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) {
case 'mysql':
return '`' . str_replace('`', '``', $value) . '`';
case 'oci':
case 'pgsql':
return '"' . str_replace('"', '""', $value) . '"';
@@ -263,10 +272,10 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
return '[' . strtr($value, '[]', ' ') . ']';
case 'odbc':
case 'oci': // TODO: not tested
case 'mssql':
return '[' . str_replace(array('[', ']'), array('[[', ']]'), $value) . ']';
case 'dblib':
case 'sqlsrv':
return '[' . str_replace(']', ']]', $value) . ']';
@@ -275,14 +284,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.');
@@ -298,7 +315,37 @@ 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 'dblib':
case 'sqlsrv':
$value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]'));
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
default:
throw new DibiNotImplementedException;
}
}
@@ -358,9 +405,19 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
}
break;
case 'odbc':
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;
@@ -399,8 +456,8 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool 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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -18,7 +18,6 @@
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDriver, IDibiReflector
@@ -67,7 +66,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
$string = '';
DibiConnection::alias($config, 'user', 'username');
DibiConnection::alias($config, 'dbname', 'database');
foreach (array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service') as $key) {
foreach (array('host', 'hostaddr', 'port', 'dbname', 'user', 'password', 'connect_timeout', 'options', 'sslmode', 'service') as $key) {
if (isset($config[$key])) {
$string .= $key . '=' . $config[$key] . ' ';
}
@@ -113,6 +112,16 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
}
/**
* Pings database.
* @return bool
*/
public function ping()
{
return pg_ping($this->connection);
}
/**
* Executes the SQL query.
* @param string SQL statement.
@@ -154,7 +163,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')");
}
@@ -300,8 +309,9 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/
public function escapeLike($value, $pos)
{
$bs = pg_escape_string($this->connection, '\\'); // standard_conforming_strings = on/off
$value = pg_escape_string($this->connection, $value);
$value = strtr($value, array( '%' => '\\\\%', '_' => '\\\\_'));
$value = strtr($value, array('%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\'));
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
}
@@ -374,8 +384,8 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
*/
public function seek($row)
{
@@ -404,9 +414,9 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
$columns = array();
for ($i = 0; $i < $count; $i++) {
$row = array(
'name' => pg_field_name($this->resultSet, $i),
'table' => pg_field_table($this->resultSet, $i),
'nativetype'=> pg_field_type($this->resultSet, $i),
'name' => pg_field_name($this->resultSet, $i),
'table' => pg_field_table($this->resultSet, $i),
'nativetype' => pg_field_type($this->resultSet, $i),
);
$row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'];
$columns[] = $row;
@@ -450,17 +460,17 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
FROM
information_schema.tables
WHERE
table_schema = current_schema()";
table_schema = ANY (current_schemas(false))";
if ($version >= 9.3) {
$query .= "
$query .= '
UNION ALL
SELECT
matviewname, 1
FROM
pg_matviews
WHERE
schemaname = current_schema()";
schemaname = ANY (current_schemas(false))';
}
$res = $this->query($query);
@@ -476,20 +486,22 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/
public function getColumns($table)
{
$_table = $this->escape($table, dibi::TEXT);
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT);
$res = $this->query("
SELECT indkey
FROM pg_class
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
WHERE pg_class.relname = $_table
WHERE pg_class.oid = $_table::regclass
");
$primary = (int) pg_fetch_object($res->resultSet)->indkey;
$res = $this->query("
SELECT *
FROM information_schema.columns
WHERE table_name = $_table AND table_schema = current_schema()
ORDER BY ordinal_position
FROM information_schema.columns c
JOIN pg_class ON pg_class.relname = c.table_name
JOIN pg_namespace nsp ON nsp.oid = pg_class.relnamespace AND nsp.nspname = c.table_schema
WHERE pg_class.oid = $_table::regclass
ORDER BY c.ordinal_position
");
if (!$res->getRowCount()) {
@@ -541,11 +553,18 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/
public function getIndexes($table)
{
$_table = $this->escape($table, dibi::TEXT);
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT);
$res = $this->query("
SELECT ordinal_position, column_name
FROM information_schema.columns
WHERE table_name = $_table AND table_schema = current_schema()
SELECT
a.attnum AS ordinal_position,
a.attname AS column_name
FROM
pg_attribute a
JOIN pg_class cls ON a.attrelid = cls.oid
WHERE
a.attrelid = $_table::regclass
AND a.attnum > 0
AND NOT a.attisdropped
ORDER BY ordinal_position
");
@@ -559,7 +578,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
FROM pg_class
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid
INNER JOIN pg_class as pg_class2 on pg_class2.oid = pg_index.indexrelid
WHERE pg_class.relname = $_table
WHERE pg_class.oid = $_table::regclass
");
$indexes = array();
@@ -582,7 +601,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver, IDibiResultDr
*/
public function getForeignKeys($table)
{
$_table = $this->escape($table, dibi::TEXT);
$_table = $this->escape($this->escape($table, dibi::IDENTIFIER), dibi::TEXT);
$res = $this->query("
SELECT

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -21,7 +21,6 @@ require_once dirname(__FILE__) . '/DibiSqliteReflector.php';
* - resource (SQLite3) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see DibiConnection options
*
* @author David Grudl
* @package dibi\drivers
*/
class DibiSqlite3Driver extends DibiObject implements IDibiDriver, IDibiResultDriver
@@ -66,11 +65,12 @@ 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'];
@@ -82,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');
}
}
@@ -336,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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @throws DibiNotSupportedException
*/
public function seek($row)
@@ -368,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://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 boolean TRUE on success, FALSE if unable to seek to specified record
* @param int the 0-based cursor pos to seek to
* @return bool 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,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* The dibi reflector for SQLite database.
*
* @author David Grudl
* @package dibi\drivers
* @internal
*/
@@ -52,17 +51,10 @@ class DibiSqliteReflector extends DibiObject implements IDibiReflector
*/
public function getColumns($table)
{
$meta = $this->driver->query("
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = {$this->driver->escape($table, dibi::TEXT)}
UNION ALL
SELECT sql FROM sqlite_temp_master WHERE type = 'table' AND name = {$this->driver->escape($table, dibi::TEXT)}
")->fetch(TRUE);
$res = $this->driver->query("PRAGMA table_info({$this->driver->escape($table, dibi::IDENTIFIER)})");
$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 +64,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

@@ -0,0 +1,14 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
require_once dirname(__FILE__) . '/DibiMsSql2005Driver.php';
class DibiSqlsrvDriver extends DibiMsSql2005Driver
{
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -10,7 +10,6 @@
* This class is static container class for creating DB objects and
* store connections info.
*
* @author David Grudl
* @package dibi
*/
class dibi
@@ -29,18 +28,18 @@ class dibi
AFFECTED_ROWS = 'a';
/** @deprecated */
const FIELD_TEXT = dibi::TEXT,
FIELD_BINARY = dibi::BINARY,
FIELD_BOOL = dibi::BOOL,
FIELD_INTEGER = dibi::INTEGER,
FIELD_FLOAT = dibi::FLOAT,
FIELD_DATE = dibi::DATE,
FIELD_DATETIME = dibi::DATETIME,
FIELD_TIME = dibi::TIME;
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;
/** version */
const VERSION = '2.2.0',
REVISION = 'released on 2014-06-02';
const VERSION = '2.3.5',
REVISION = 'released on 2015-12-16';
/** sorting order */
const ASC = 'ASC',
@@ -68,7 +67,7 @@ class dibi
public static $numOfQueries = 0;
/** @var string Default dibi driver */
public static $defaultDriver = 'mysql';
public static $defaultDriver = 'mysqli';
/**
@@ -76,7 +75,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 +151,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 +293,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 +305,7 @@ class dibi
* @return int
* @throws DibiException
*/
public static function insertId($sequence=NULL)
public static function insertId($sequence = NULL)
{
return self::getConnection()->getInsertId($sequence);
}
@@ -371,18 +368,6 @@ class dibi
}
/**
* Replacement for majority of dibi::methods() in future.
*/
public static function __callStatic($name, $args)
{
//if ($name = 'select', 'update', ...') {
// return self::command()->$name($args);
//}
return call_user_func_array(array(self::getConnection(), $name), $args);
}
/********************* fluent SQL builders ****************d*g**/
@@ -471,7 +456,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 +464,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,26 +2,21 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* dibi connection.
*
* @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 */
@@ -80,19 +75,26 @@ class DibiConnection extends DibiObject
$config['driver'] = dibi::$defaultDriver;
}
$class = preg_replace(array('#\W#', '#sql#'), array('_', 'Sql'), ucfirst(strtolower($config['driver'])));
$class = "Dibi{$class}Driver";
if (!class_exists($class)) {
include_once dirname(__FILE__) . "/../drivers/$class.php";
if ($config['driver'] instanceof IDibiDriver) {
$this->driver = $config['driver'];
$config['driver'] = get_class($this->driver);
} elseif (PHP_VERSION_ID >= 50307 && is_subclass_of($config['driver'], 'IDibiDriver')) {
$this->driver = new $config['driver'];
} else {
$class = preg_replace(array('#\W#', '#sql#'), array('_', 'Sql'), ucfirst(strtolower($config['driver'])));
$class = "Dibi{$class}Driver";
if (!class_exists($class)) {
include_once dirname(__FILE__) . "/../drivers/$class.php";
if (!class_exists($class, FALSE)) {
throw new DibiException("Unable to create instance of dibi driver '$class'.");
if (!class_exists($class, FALSE)) {
throw new DibiException("Unable to create instance of dibi driver '$class'.");
}
}
$this->driver = new $class;
}
$config['name'] = $name;
$this->config = $config;
$this->driver = new $class;
$this->translator = new DibiTranslator($this);
// profiler
@@ -111,7 +113,7 @@ class DibiConnection extends DibiObject
$this->onEvent[] = array(new DibiFirePhpLogger($filter), 'logEvent');
}
if (class_exists('DibiNettePanel') && !interface_exists('Tracy\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,20 +2,14 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* Default implementation of IDataSource for dibi.
*
* @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,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* Reflection metadata class for a database.
*
* @author David Grudl
* @package dibi\reflection
*
* @property-read string $name
@@ -115,7 +114,6 @@ class DibiDatabaseInfo extends DibiObject
/**
* Reflection metadata class for a database table.
*
* @author David Grudl
* @package dibi\reflection
*
* @property-read string $name
@@ -307,7 +305,6 @@ class DibiTableInfo extends DibiObject
/**
* Reflection metadata class for a result set.
*
* @author David Grudl
* @package dibi\reflection
*
* @property-read array $columns
@@ -393,7 +390,7 @@ class DibiResultInfo extends DibiObject
$this->columns = array();
$reflector = $this->driver instanceof IDibiReflector ? $this->driver : NULL;
foreach ($this->driver->getResultColumns() as $info) {
$this->columns[] = $this->names[$info['name']] = new DibiColumnInfo($reflector, $info);
$this->columns[] = $this->names[strtolower($info['name'])] = new DibiColumnInfo($reflector, $info);
}
}
}
@@ -404,7 +401,6 @@ class DibiResultInfo extends DibiObject
/**
* Reflection metadata class for a table or result set column.
*
* @author David Grudl
* @package dibi\reflection
*
* @property-read string $name
@@ -481,7 +477,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 ==
}
@@ -570,7 +566,7 @@ class DibiColumnInfo extends DibiObject
'^_' => dibi::TEXT, // PostgreSQL arrays
'BYTEA|BLOB|BIN' => dibi::BINARY,
'TEXT|CHAR|POINT|INTERVAL' => dibi::TEXT,
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT' => dibi::INTEGER,
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT|^TINY$' => dibi::INTEGER,
'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER' => dibi::FLOAT,
'^TIME$' => dibi::TIME,
'TIME' => dibi::DATETIME, // DATETIME, TIMESTAMP
@@ -604,7 +600,6 @@ class DibiColumnInfo extends DibiObject
/**
* Reflection metadata class for a foreign key.
*
* @author David Grudl
* @package dibi\reflection
* @todo
*
@@ -650,7 +645,6 @@ class DibiForeignKeyInfo extends DibiObject
/**
* Reflection metadata class for a index or primary key.
*
* @author David Grudl
* @package dibi\reflection
*
* @property-read string $name

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* DateTime with serialization and timestamp support for PHP 5.2.
*
* @author David Grudl
* @package dibi
*/
class DibiDateTime extends DateTime
@@ -44,7 +43,7 @@ class DibiDateTime extends DateTime
public function setTimestamp($timestamp)
{
$zone = PHP_VERSION_ID === 50206 ? new \DateTimeZone($this->getTimezone()->getName()) : $this->getTimezone();
$zone = PHP_VERSION_ID === 50206 ? new DateTimeZone($this->getTimezone()->getName()) : $this->getTimezone();
$this->__construct('@' . $timestamp);
$this->setTimeZone($zone);
return $this;

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* Profiler & logger event.
*
* @author David Grudl
* @package dibi
*/
class DibiEvent

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* dibi common exception.
*
* @author David Grudl
* @package dibi
*/
class DibiException extends Exception
@@ -54,7 +53,6 @@ class DibiException extends Exception
/**
* database server exception.
*
* @author David Grudl
* @package dibi
*/
class DibiDriverException extends DibiException
@@ -114,11 +112,10 @@ class DibiDriverException extends DibiException
/**
* PCRE exception.
*
* @author David Grudl
* @package dibi
*/
class DibiPcreException extends Exception {
class DibiPcreException extends Exception
{
public function __construct($message = '%msg.')
{
static $messages = array(

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* dibi file logger.
*
* @author David Grudl
* @package dibi
*/
class DibiFileLogger extends DibiObject
@@ -58,7 +57,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,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* dibi FirePHP logger.
*
* @author David Grudl
* @package dibi
*/
class DibiFirePhpLogger extends DibiObject
@@ -20,6 +19,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 +60,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 +81,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,28 +2,29 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* dibi SQL builder via fluent interfaces. EXPERIMENTAL!
*
* @author David Grudl
* @package dibi
*
* @property-read string $command
* @property-read DibiConnection $connection
* @property-read DibiResultIterator $iterator
* @method DibiFluent select($field)
* @method DibiFluent select(...$field)
* @method DibiFluent distinct()
* @method DibiFluent from($table)
* @method DibiFluent where($cond)
* @method DibiFluent groupBy($field)
* @method DibiFluent having($cond)
* @method DibiFluent orderBy($field)
* @method DibiFluent where(...$cond)
* @method DibiFluent groupBy(...$field)
* @method DibiFluent having(...$cond)
* @method DibiFluent orderBy(...$field)
* @method DibiFluent limit(int $limit)
* @method DibiFluent offset(int $offset)
* @method DibiFluent join(...$table)
* @method DibiFluent leftJoin(...$table)
* @method DibiFluent innerJoin(...$table)
* @method DibiFluent rightJoin(...$table)
* @method DibiFluent outerJoin(...$table)
* @method DibiFluent on(...$cond)
* @method DibiFluent using(...$cond)
*/
class DibiFluent extends DibiObject implements IDataSource
{
@@ -177,7 +178,10 @@ class DibiFluent extends DibiObject implements IDataSource
} elseif (is_string($arg) && preg_match('#^[a-z:_][a-z0-9_.:]*\z#i', $arg)) { // identifier
$args = array('%n', $arg);
} elseif (is_array($arg) || ($arg instanceof Traversable && !$arg instanceof self)) { // any array
} elseif ($arg instanceof self) {
$args = array('%SQL', $arg);
} elseif (is_array($arg) || $arg instanceof Traversable) { // any array
if (isset(self::$modifiers[$clause])) {
$args = array(self::$modifiers[$clause], $arg);
@@ -317,7 +321,7 @@ class DibiFluent extends DibiObject implements IDataSource
*/
public function fetch()
{
if ($this->command === 'SELECT') {
if ($this->command === 'SELECT' && !$this->clauses['LIMIT'] && !$this->clauses['OFFSET']) {
return $this->query($this->_export(NULL, array('%lmt', 1)))->fetch();
} else {
return $this->query($this->_export())->fetch();
@@ -331,7 +335,7 @@ class DibiFluent extends DibiObject implements IDataSource
*/
public function fetchSingle()
{
if ($this->command === 'SELECT') {
if ($this->command === 'SELECT' && !$this->clauses['LIMIT'] && !$this->clauses['OFFSET']) {
return $this->query($this->_export(NULL, array('%lmt', 1)))->fetchSingle();
} else {
return $this->query($this->_export())->fetchSingle();
@@ -403,7 +407,7 @@ class DibiFluent extends DibiObject implements IDataSource
public function count()
{
return (int) $this->query(array(
'SELECT COUNT(*) FROM (%ex', $this->_export(), ') AS [data]'
'SELECT COUNT(*) FROM (%ex', $this->_export(), ') [data]',
))->fetchSingle();
}

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* Lazy cached storage.
*
* @author David Grudl
* @package dibi
* @internal
*/
@@ -45,7 +44,6 @@ abstract class DibiHashMapBase
/**
* Lazy cached storage.
*
* @author David Grudl
* @internal
*/
final class DibiHashMap extends DibiHashMapBase

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* SQL literal value.
*
* @author David Grudl
* @package dibi
*/
class DibiLiteral extends DibiObject

View File

@@ -2,14 +2,14 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* DibiObject is the ultimate ancestor of all instantiable classes.
*
* DibiObject is copy of Nette\Object from Nette Framework (http://nette.org).
* DibiObject is copy of Nette\Object from Nette Framework (https://nette.org).
*
* It defines some handful methods and enhances object core of PHP:
* - access to undeclared members throws exceptions
@@ -39,12 +39,11 @@
* 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>
*
* @author David Grudl
* @package dibi
*/
abstract class DibiObject
@@ -209,8 +208,8 @@ abstract class DibiObject
}
// property getter support
$name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
$m = 'get' . $name;
$uname = ucfirst($name);
$m = 'get' . $uname;
if (self::hasAccessor($class, $m)) {
// ampersands:
// - uses & __get() because declaration should be forward compatible (e.g. with Nette\Web\Html)
@@ -219,13 +218,12 @@ abstract class DibiObject
return $val;
}
$m = 'is' . $name;
$m = 'is' . $uname;
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.");
}
@@ -246,20 +244,18 @@ abstract class DibiObject
}
// property setter support
$name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
if (self::hasAccessor($class, 'get' . $name) || self::hasAccessor($class, 'is' . $name)) {
$uname = ucfirst($name);
if (self::hasAccessor($class, 'get' . $uname) || self::hasAccessor($class, 'is' . $uname)) {
$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.");
}
@@ -271,8 +267,7 @@ abstract class DibiObject
*/
public function __isset($name)
{
$name[0] = $name[0] & "\xDF";
return $name !== '' && self::hasAccessor(get_class($this), 'get' . $name);
return $name !== '' && self::hasAccessor(get_class($this), 'get' . ucfirst($name));
}

View File

@@ -2,7 +2,7 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -22,15 +22,9 @@
* unset($result);
* </code>
*
* @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
{
@@ -109,7 +103,7 @@ class DibiResult extends DibiObject implements IDataSource
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
final public function seek($row)
@@ -188,7 +182,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()
{
@@ -209,7 +203,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()
{
@@ -259,7 +253,7 @@ class DibiResult extends DibiObject implements IDataSource
* - associative descriptor: col1|col2->col3=col4
* builds a tree: $tree[$val1][$val2]->col3[$val3] = val4
* @param string associative descriptor
* @return DibiRow
* @return array
* @throws InvalidArgumentException
*/
final public function fetchAssoc($assoc)
@@ -303,16 +297,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
@@ -369,22 +363,21 @@ 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];
}
@@ -424,7 +417,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
@@ -478,7 +471,8 @@ 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) {
}
}
@@ -494,13 +488,23 @@ class DibiResult extends DibiObject implements IDataSource
continue;
}
$value = $row[$key];
if ($value === FALSE || $type === dibi::TEXT) {
if ($type === dibi::TEXT) {
} elseif ($type === dibi::INTEGER) {
$row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
} elseif ($type === dibi::FLOAT) {
$row[$key] = ltrim((string) ($tmp = (float) $value), '0') === ltrim(rtrim(rtrim($value, '0'), '.'), '0') ? $tmp : $value;
$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;
} elseif ($type === dibi::BOOL) {
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
@@ -619,7 +623,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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -18,7 +18,6 @@
* unset($result);
* </code>
*
* @author David Grudl
* @package dibi
*/
class DibiResultIterator implements Iterator, Countable

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* Result set single row.
*
* @author David Grudl
* @package dibi
*/
class DibiRow implements ArrayAccess, IteratorAggregate, Countable

View File

@@ -2,14 +2,13 @@
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
/**
* dibi SQL translator.
*
* @author David Grudl
* @package dibi
*/
final class DibiTranslator extends DibiObject
@@ -51,7 +50,6 @@ final class DibiTranslator extends DibiObject
public function __construct(DibiConnection $connection)
{
$this->connection = $connection;
$this->driver = $connection->getDriver();
$this->identifiers = new DibiHashMap(array($this, 'delimite'));
}
@@ -64,6 +62,10 @@ final class DibiTranslator extends DibiObject
*/
public function translate(array $args)
{
if (!$this->driver) {
$this->driver = $this->connection->getDriver();
}
$args = array_values($args);
while (count($args) === 1 && is_array($args[0])) { // implicit array expansion
$args = array_values($args[0]);
@@ -157,7 +159,7 @@ final class DibiTranslator extends DibiObject
if ($comment) {
$sql[] = "*/";
$sql[] = '*/';
}
$sql = implode(' ', $sql);
@@ -184,7 +186,11 @@ final class DibiTranslator extends DibiObject
public function formatValue($value, $modifier)
{
if ($this->comment) {
return "...";
return '...';
}
if (!$this->driver) {
$this->driver = $this->connection->getDriver();
}
// array processing (with or without modifier)
@@ -209,7 +215,7 @@ final class DibiTranslator extends DibiObject
$v = $this->formatValue($v, FALSE);
$vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
} elseif ($pair[1] === 'ex') { // TODO: this will be removed
} elseif ($pair[1] === 'ex') {
$vx[] = $k . $this->formatValue($v, 'ex');
} else {
@@ -350,19 +356,24 @@ final class DibiTranslator extends DibiObject
case 'i': // signed int
case 'u': // unsigned int, ignored
// support for long numbers - keep them unchanged
if (is_string($value) && preg_match('#[+-]?\d++(e\d+)?\z#A', $value)) {
return $value;
if ($value === NULL) {
return 'NULL';
} elseif (is_string($value) && preg_match('#[+-]?\d++(?:e\d+)?\z#A', $value)) {
return $value; // support for long numbers - keep them unchanged
} elseif (is_string($value) && substr($value, 1, 1) === 'x' && is_numeric($value)) {
trigger_error('Support for hex strings has been deprecated.', E_USER_DEPRECATED);
return (string) hexdec($value);
} else {
return $value === NULL ? 'NULL' : (string) (int) ($value + 0);
return (string) (int) $value;
}
case 'f': // float
// support for extreme numbers - keep them unchanged
if (is_string($value) && is_numeric($value) && strpos($value, 'x') === FALSE) {
return $value; // something like -9E-005 is accepted by SQL, HEX values are not
if ($value === NULL) {
return 'NULL';
} elseif (is_string($value) && is_numeric($value) && substr($value, 1, 1) !== 'x') {
return $value; // support for extreme numbers - keep them unchanged
} else {
return $value === NULL ? 'NULL' : rtrim(rtrim(number_format($value + 0, 10, '.', ''), '0'), '.');
return rtrim(rtrim(number_format($value + 0, 10, '.', ''), '0'), '.');
}
case 'd': // date
@@ -482,7 +493,7 @@ final class DibiTranslator extends DibiObject
if ($cursor >= count($this->args)) {
$this->hasError = TRUE;
return "**Extra placeholder**";
return '**Extra placeholder**';
}
$cursor++;
@@ -505,7 +516,7 @@ final class DibiTranslator extends DibiObject
// open comment
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return "/*";
return '/*';
}
return '';
@@ -513,11 +524,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') {
@@ -526,7 +537,7 @@ final class DibiTranslator extends DibiObject
// close comment
$this->ifLevelStart = 0;
$this->comment = FALSE;
return "*/";
return '*/';
}
return '';
@@ -535,17 +546,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
@@ -565,10 +582,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;
@@ -581,7 +598,7 @@ final class DibiTranslator extends DibiObject
return $matches[9] == '' ? $this->formatValue($m, FALSE) : $m . $matches[9]; // value or identifier
}
die('this should be never executed');
throw new Exception('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 (http://davidgrudl.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -184,7 +184,6 @@ interface IDibiResultDriver
/**
* dibi driver reflection.
*
* @author David Grudl
* @package dibi
*/
interface IDibiReflector

2
examples/.gitignore vendored
View File

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

View File

@@ -1,63 +0,0 @@
Tracy - PHP debugger, see http://tracy.nette.org
Licenses
========
Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.
You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.
Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.
New BSD License
---------------
Copyright (c) 2004, 2012 David Grudl (http://davidgrudl.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of "Nette Framework" nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
GNU General Public License
--------------------------
GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:
- GPL version 2: http://www.gnu.org/licenses/gpl-2.0.html
- GPL version 3: http://www.gnu.org/licenses/gpl-3.0.html

Binary file not shown.

View File

@@ -11,11 +11,10 @@ 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";
}
@@ -26,11 +25,10 @@ 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";
}
@@ -42,7 +40,6 @@ 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";
}
@@ -53,18 +50,17 @@ 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";
}
@@ -75,13 +71,12 @@ 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";
}
@@ -92,12 +87,11 @@ 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";
}
@@ -108,11 +102,10 @@ 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";
}
@@ -123,13 +116,12 @@ 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";
}
@@ -140,14 +132,13 @@ 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";
}
@@ -158,13 +149,12 @@ 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";
}

Binary file not shown.

View File

@@ -2,7 +2,7 @@ body {
font: 15px/1.5 Tahoma, Verdana, Myriad Web, Syntax, sans-serif;
color: #333;
background: #fff url('dibi-powered.gif') no-repeat 99% 1em;
margin: 1.6em;
margin: 1.6em;
padding: 0;
}

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

@@ -4,14 +4,15 @@
<?php
require __DIR__ . '/Tracy/tracy.phar';
require __DIR__ . '/../dibi/dibi.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install dependencies using `composer install --dev`');
}
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

@@ -4,8 +4,9 @@
<?php
require __DIR__ . '/Tracy/tracy.phar';
require __DIR__ . '/../dibi/dibi.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install dependencies using `composer install --dev`');
}
Tracy\Debugger::enable();
@@ -13,7 +14,7 @@ date_default_timezone_set('Europe/Prague');
dibi::connect(array(
'driver' => 'sqlite3',
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
));
@@ -26,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
@@ -37,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,41 +2,31 @@
<h1>Tracy & SQL Exceptions | dibi</h1>
<p>Dibi can display and log exceptions via Tracy, part of Nette Framework.</p>
<ul>
<li>Tracy Debugger: http://tracy.nette.org
</ul>
<p>Dibi can display and log exceptions via <a href="https://tracy.nette.org">Tracy</a>.</p>
<?php
require __DIR__ . '/Tracy/tracy.phar';
require __DIR__ . '/../dibi/dibi.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install dependencies using `composer install --dev`');
}
// enable Tracy
Tracy\Debugger::enable();
dibi::connect(array(
'driver' => 'sqlite3',
$connection = dibi::connect(array(
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
)
),
));
// throws error because SQL is bad
dibi::query('SELECT * FROM customers WHERE customer_id < ?', 38);
dibi::connect(array(
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
)
));
// add panel to debug bar
$panel = new Dibi\Bridges\Tracy\Panel;
$panel->register($connection);
// throws error because SQL is bad

View File

@@ -1,31 +0,0 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<style> html { background: url(data/arrow.png) no-repeat bottom right; height: 100%; } </style>
<h1>Tracy & Variables | dibi</h1>
<p>Dibi can dump variables via Tracy, part of Nette Framework.</p>
<ul>
<li>Tracy Debugger: http://tracy.nette.org
</ul>
<?php
require __DIR__ . '/Tracy/tracy.phar';
require __DIR__ . '/../dibi/dibi.php';
Tracy\Debugger::enable();
dibi::connect(array(
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
)
));
Tracy\Debugger::barDump( dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]' );

38
examples/tracy.php Normal file
View File

@@ -0,0 +1,38 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<style> html { background: url(data/arrow.png) no-repeat bottom right; height: 100%; } </style>
<h1>Tracy | dibi</h1>
<p>Dibi can log queries and dump variables to the <a href="https://tracy.nette.org">Tracy</a>.</p>
<?php
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install dependencies using `composer install --dev`');
}
// enable Tracy
Tracy\Debugger::enable();
$connection = dibi::connect(array(
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => array(
'run' => TRUE,
),
));
// add panel to debug bar
$panel = new Dibi\Bridges\Tracy\Panel;
$panel->register($connection);
// query will be logged
dibi::query('SELECT 123');
// result set will be dumped
Tracy\Debugger::barDump(dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]');

View File

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

@@ -4,21 +4,21 @@
<?php
require __DIR__ . '/Tracy/tracy.phar';
require __DIR__ . '/../dibi/dibi.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install dependencies using `composer install --dev`');
}
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,13 +26,12 @@ 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 (http://davidgrudl.com)
Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,17 +1,19 @@
[Dibi](http://dibiphp.com) - smart database layer for PHP
[Dibi](https://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)
=========================================================
[![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)
[![Latest Stable Version](https://poser.pugx.org/dibi/dibi/v/stable)](https://github.com/dg/dibi/releases)
[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/dg/dibi/blob/master/license.md)
Database access functions in PHP are not standardised. This library
hides the differences between them, and above all, it gives you a very handy interface.
The best way to install Dibi is to use a [Composer](http://getcomposer.org/download):
The best way to install Dibi is to use a [Composer](https://getcomposer.org/download):
php composer.phar require dibi/dibi
Or you can download the latest package from http://dibiphp.com. In this
Or you can download the latest package from https://dibiphp.com. In this
package is also `Dibi.minified`, shrinked single-file version of whole Dibi,
useful when you don't want to modify the library, but just use it.
@@ -22,7 +24,7 @@ Examples
--------
Refer to the `examples` directory for examples. Dibi documentation is
available on the [homepage](http://dibiphp.com).
available on the [homepage](https://dibiphp.com).
Connect to database:

6
tests/.gitignore vendored
View File

@@ -1,4 +1,4 @@
/*/output
/coverage.dat
/test.log
output
/tmp
/test.log
/databases.ini

104
tests/databases.sample.ini Normal file
View File

@@ -0,0 +1,104 @@
[sqlite] ; default
driver = sqlite3
database = :memory:
system = sqlite
[sqlite 2]
driver = sqlite
database = :memory:
system = sqlite
[sqlite pdo]
driver = pdo
dsn = "sqlite::memory:"
system = sqlite
[mysql]
driver = mysql
host = 127.0.0.1
username = root
password =
charset = utf8
system = mysql
[mysql improved]
driver = mysqli
host = 127.0.0.1
username = root
password =
charset = utf8
system = mysql
[mysql pdo]
driver = pdo
dsn = "mysql:host=127.0.0.1"
username = root
password =
system = mysql
[postgre]
driver = postgre
host = 127.0.0.1
username = postgres
password =
system = postgre
[postgre pdo]
driver = pdo
dsn = "pgsql:host=127.0.0.1;dbname=dibi_test"
username = postgres
password =
system = postgre
[odbc]
driver = odbc
dsn = "Driver={Microsoft Access Driver (*.mdb)};Dbq=data/odbc.mdb"
system = odbc
[odbc pdo]
driver = pdo
dsn = "odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=data/odbc.mdb"
username =
password =
system = odbc
[mssql]
driver = mssql
host = 127.0.0.1
username = dibi
password =
system = sqlsrv
[sqlsrv]
driver = mssql2005
host = (local)
username = dibi
password =
system = sqlsrv
[sqlsrv pdo]
driver = pdo
dsn = "sqlsrv:Server=127.0.0.1"
username = dibi
password =
system = sqlsrv
[oracle]
driver = oracle
username = dibi
password =
system = oracle
[oracle pdo]
driver = pdo
dsn = "oci:dbname=dibi"
username = dibi
password =
system = oracle
[firebird]
driver = firebird
database = database.fdb
username = dibi
password =
system = firebird

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,319 @@
<?php
/**
* @dataProvider ../databases.ini
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$conn = new DibiConnection($config);
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
// 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,56 @@
<?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 [val]=1'),
$conn->translate('UPDATE :blog:items SET [val]=1')
);
Assert::same(
reformat('UPDATE [wp_items] SET [val]=1'),
$conn->translate('UPDATE [:blog:items] SET [val]=1')
);
Assert::same(
reformat("UPDATE 'wp_' SET [val]=1"),
$conn->translate('UPDATE :blog: SET [val]=1')
);
Assert::same(
reformat("UPDATE ':blg:' SET [val]=1"),
$conn->translate('UPDATE :blg: SET [val]=1')
);
Assert::same(
reformat("UPDATE table SET [text]=':blog:a'"),
$conn->translate("UPDATE table SET [text]=':blog:a'")
);
// create new substitution :: (empty) ==> my_
$conn->getSubstitutes()->{''} = 'my_';
Assert::same(
reformat('UPDATE my_table SET [val]=1'),
$conn->translate('UPDATE ::table SET [val]=1')
);
// create substitutions using fallback callback
$conn->getSubstitutes()->setCallback(function ($expr) {
return '_' . $expr . '_';
});
Assert::same(
reformat('UPDATE _account_user SET [val]=1'),
$conn->translate('UPDATE :account:user SET [val]=1')
);

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

@@ -1,40 +1,35 @@
<?php
/**
* Test: Cloning of DibiFluent
*
* @author David Grudl
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
dibi::connect($config['sqlite3']);
$conn = new DibiConnection($config);
$fluent = new DibiFluent(dibi::getConnection());
$fluent = new DibiFluent($conn);
$fluent->select('*')->from('table')->where('x=1');
$dolly = clone $fluent;
$dolly->where('y=1');
$dolly->clause('FOO');
Assert::same( 'SELECT * FROM [table] WHERE x=1', (string) $fluent );
Assert::same( 'SELECT * FROM [table] WHERE x=1 AND y=1 FOO', (string) $dolly );
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 = dibi::select('id')->from('table')->where('id = %i',1);
$fluent = new DibiFluent($conn);
$fluent->select('id')->from('table')->where('id = %i', 1);
$dolly = clone $fluent;
$dolly->where('cd = %i',5);
$dolly->where('cd = %i', 5);
Assert::same( 'SELECT [id] FROM [table] WHERE id = 1', (string) $fluent );
Assert::same( 'SELECT [id] FROM [table] WHERE id = 1 AND cd = 5', (string) $dolly );
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 = dibi::select("*")->from("table");
$fluent = new DibiFluent($conn);
$fluent->select('*')->from('table');
$dolly = clone $fluent;
$dolly->removeClause("select")->select("count(*)");
$dolly->removeClause('select')->select('count(*)');
Assert::same( 'SELECT * FROM [table]', (string) $fluent );
Assert::same( 'SELECT count(*) FROM [table]', (string) $dolly );
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,98 @@
<?php
/**
* @dataProvider? ../databases.ini mysql
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$conn = new DibiConnection($config);
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
// fetch & limit
$fluent = $conn->select('*')
->from('customers')
->limit(1)
->offset(3)
->orderBy('customer_id');
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'),
(string) $fluent
);
$fluent->fetch();
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'),
dibi::$sql
);
$fluent->fetchSingle();
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'),
dibi::$sql
);
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'),
(string) $fluent
);
$fluent->limit(0);
$fluent->fetch();
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 0 OFFSET 3'),
dibi::$sql
);
$fluent->fetchSingle();
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 0 OFFSET 3'),
dibi::$sql
);
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 0 OFFSET 3'),
(string) $fluent
);
$fluent->removeClause('limit');
try {
$fluent->fetch();
} catch (DibiException $e) {
}
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] OFFSET 3'),
dibi::$sql
);
try {
$fluent->fetchSingle();
} catch (DibiException $e) {
}
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] OFFSET 3'),
dibi::$sql
);
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id] OFFSET 3'),
(string) $fluent
);
$fluent->removeClause('offset');
$fluent->fetch();
Assert::same(
reformat(' SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1'),
dibi::$sql
);
$fluent->fetchSingle();
Assert::same(
reformat(' SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1'),
dibi::$sql
);
Assert::same(
reformat('SELECT * FROM [customers] ORDER BY [customer_id]'),
(string) $fluent
);

View File

@@ -0,0 +1,49 @@
<?php
/**
* @dataProvider ../databases.ini
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$conn = new DibiConnection($config);
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
// 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,142 @@
<?php
/**
* @dataProvider ../databases.ini
*/
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
);
$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
);
$fluent = $conn->select('*')->from('abc')
->where('x IN (%SQL)', $conn->select('id')->from('xyz'));
Assert::same(
reformat('SELECT * FROM [abc] WHERE x IN ((SELECT [id] FROM [xyz]))'),
(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

@@ -0,0 +1,70 @@
<?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,56 @@
<?php
/**
* @dataProvider ../databases.ini !=odbc
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$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);
Assert::same('xXx', $info->getColumn('xxx')->getName());
Assert::same('xXx', $info->getColumn('xXx')->getName());

View File

@@ -0,0 +1,130 @@
<?php
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
class MockResult extends DibiResult
{
function __construct()
{}
function test($row)
{
$normalize = new ReflectionMethod('DibiResult', 'normalize');
$normalize->setAccessible(TRUE);
$normalize->invokeArgs($this, array(& $row));
return $row;
}
}
test(function () {
$result = new MockResult;
$result->setType('col', dibi::BOOL);
Assert::same(array('col' => NULL), $result->test(array('col' => NULL)));
Assert::same(array('col' => TRUE), $result->test(array('col' => TRUE)));
Assert::same(array('col' => FALSE), $result->test(array('col' => FALSE)));
Assert::same(array('col' => FALSE), $result->test(array('col' => '')));
Assert::same(array('col' => FALSE), $result->test(array('col' => '0')));
Assert::same(array('col' => TRUE), $result->test(array('col' => '1')));
Assert::same(array('col' => TRUE), $result->test(array('col' => 't')));
Assert::same(array('col' => FALSE), $result->test(array('col' => 'f')));
Assert::same(array('col' => TRUE), $result->test(array('col' => 'T')));
Assert::same(array('col' => FALSE), $result->test(array('col' => 'F')));
Assert::same(array('col' => FALSE), $result->test(array('col' => 0)));
Assert::same(array('col' => FALSE), $result->test(array('col' => 0.0)));
Assert::same(array('col' => TRUE), $result->test(array('col' => 1)));
Assert::same(array('col' => TRUE), $result->test(array('col' => 1.0)));
});
test(function () {
$result = new MockResult;
$result->setType('col', dibi::TEXT); // means TEXT or UNKNOWN
Assert::same(array('col' => NULL), $result->test(array('col' => NULL)));
Assert::same(array('col' => TRUE), $result->test(array('col' => TRUE)));
Assert::same(array('col' => FALSE), $result->test(array('col' => FALSE)));
Assert::same(array('col' => ''), $result->test(array('col' => '')));
Assert::same(array('col' => '0'), $result->test(array('col' => '0')));
Assert::same(array('col' => '1'), $result->test(array('col' => '1')));
Assert::same(array('col' => 0), $result->test(array('col' => 0)));
Assert::same(array('col' => 1), $result->test(array('col' => 1)));
});
test(function () {
$result = new MockResult;
$result->setType('col', dibi::FLOAT);
Assert::same(array('col' => NULL), $result->test(array('col' => NULL)));
Assert::same(array('col' => 1.0), $result->test(array('col' => TRUE)));
Assert::same(array('col' => 0.0), $result->test(array('col' => FALSE)));
Assert::same(array('col' => 0.0), $result->test(array('col' => '')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '0')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '1')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '.0')));
Assert::same(array('col' => 0.1), $result->test(array('col' => '.1')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '0.0')));
Assert::same(array('col' => 0.1), $result->test(array('col' => '0.1')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '0.000')));
Assert::same(array('col' => 0.1), $result->test(array('col' => '0.100')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '1.0')));
Assert::same(array('col' => 1.1), $result->test(array('col' => '1.1')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '1.000')));
Assert::same(array('col' => 1.1), $result->test(array('col' => '1.100')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '001.000')));
Assert::same(array('col' => 1.1), $result->test(array('col' => '001.100')));
Assert::same(array('col' => 10.0), $result->test(array('col' => '10')));
Assert::same(array('col' => 11.0), $result->test(array('col' => '11')));
Assert::same(array('col' => 10.0), $result->test(array('col' => '0010')));
Assert::same(array('col' => 11.0), $result->test(array('col' => '0011')));
Assert::same(array('col' => '0.00000000000000000001'), $result->test(array('col' => '0.00000000000000000001')));
Assert::same(array('col' => '12345678901234567890'), $result->test(array('col' => '12345678901234567890')));
Assert::same(array('col' => '12345678901234567890'), $result->test(array('col' => '012345678901234567890')));
Assert::same(array('col' => '12345678901234567890'), $result->test(array('col' => '12345678901234567890.000')));
Assert::same(array('col' => '12345678901234567890.1'), $result->test(array('col' => '012345678901234567890.100')));
Assert::same(array('col' => 0.0), $result->test(array('col' => 0)));
Assert::same(array('col' => 0.0), $result->test(array('col' => 0.0)));
Assert::same(array('col' => 1.0), $result->test(array('col' => 1)));
Assert::same(array('col' => 1.0), $result->test(array('col' => 1.0)));
setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');
Assert::same(array('col' => 0.0), $result->test(array('col' => '')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '0')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '1')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '.0')));
Assert::same(array('col' => 0.1), $result->test(array('col' => '.1')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '0.0')));
Assert::same(array('col' => 0.1), $result->test(array('col' => '0.1')));
Assert::same(array('col' => 0.0), $result->test(array('col' => '0.000')));
Assert::same(array('col' => 0.1), $result->test(array('col' => '0.100')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '1.0')));
Assert::same(array('col' => 1.1), $result->test(array('col' => '1.1')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '1.000')));
Assert::same(array('col' => 1.1), $result->test(array('col' => '1.100')));
Assert::same(array('col' => 1.0), $result->test(array('col' => '001.000')));
Assert::same(array('col' => 1.1), $result->test(array('col' => '001.100')));
Assert::same(array('col' => 10.0), $result->test(array('col' => '10')));
Assert::same(array('col' => 11.0), $result->test(array('col' => '11')));
Assert::same(array('col' => 10.0), $result->test(array('col' => '0010')));
Assert::same(array('col' => 11.0), $result->test(array('col' => '0011')));
Assert::same(array('col' => '0.00000000000000000001'), $result->test(array('col' => '0.00000000000000000001')));
Assert::same(array('col' => '12345678901234567890'), $result->test(array('col' => '12345678901234567890')));
Assert::same(array('col' => '12345678901234567890'), $result->test(array('col' => '012345678901234567890')));
Assert::same(array('col' => '12345678901234567890'), $result->test(array('col' => '12345678901234567890.000')));
Assert::same(array('col' => '12345678901234567890.1'), $result->test(array('col' => '012345678901234567890.100')));
Assert::same(array('col' => 0.0), $result->test(array('col' => 0)));
Assert::same(array('col' => 0.0), $result->test(array('col' => 0.0)));
Assert::same(array('col' => 1.0), $result->test(array('col' => 1)));
Assert::same(array('col' => 1.0), $result->test(array('col' => 1.0)));
setlocale(LC_NUMERIC, 'C');
});

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

42
tests/dibi/DibiRow.phpt Normal file
View File

@@ -0,0 +1,42 @@
<?php
/**
* @dataProvider ../databases.ini
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$conn = new DibiConnection($config);
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
$row = $conn->fetch('SELECT * FROM [products] ORDER BY product_id');
// existing
Assert::same('Chair', $row->title);
Assert::true(isset($row->title));
Assert::same('Chair', $row['title']);
Assert::true(isset($row['title']));
// missing
Assert::error(function () use ($row) {
$x = $row->missing;
}, E_NOTICE, 'Undefined property: DibiRow::$missing');
Assert::error(function () use ($row) {
$x = $row['missing'];
}, E_NOTICE, 'Undefined property: DibiRow::$missing');
Assert::false(isset($row->missing));
Assert::false(isset($row['missing']));
// to array
Assert::same(array('product_id' => num(1), 'title' => 'Chair'), iterator_to_array($row));
Assert::same(array('product_id' => num(1), 'title' => 'Chair'), $row->toArray());
// counting
Assert::same(2, count($row));

View File

@@ -1,9 +1,6 @@
<?php
/**
* Test: DateTimeInterface of DibiTranslator
*
* @author Patrik Votoček
* @phpversion 5.5
*/
@@ -11,11 +8,8 @@ use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$connection = new DibiConnection(array(
'driver' => 'sqlite3',
'database' => ':memory:',
));
$translator = new DibiTranslator($connection);
$conn = new DibiConnection($config);
$translator = new DibiTranslator($conn);
$datetime = new DateTime('1978-01-23 00:00:00');

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,524 @@
<?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')
);
// 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',
'postgre' => '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'] === 'postgre') {
$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",
'postgre' => '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,76 @@
<?php
/**
* @dataProvider? ../databases.ini sqlsrv
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$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,30 @@
<?php
/**
* @dataProvider? ../databases.ini postgre
*/
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$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);

View File

@@ -14,5 +14,68 @@ Tester\Environment::setup();
date_default_timezone_set('Europe/Prague');
// load connections
$config = require __DIR__ . '/config.php';
// load connection
try {
$config = Tester\Environment::loadData();
} catch (Exception $e) {
$config = parse_ini_file(__DIR__ . '/../databases.ini', TRUE);
$config = reset($config);
}
// 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'] === 'postgre') {
return strtr($s, '[]', '""');
} elseif (in_array($config['system'], array('odbc', 'sqlite', 'sqlsrv'))) {
return $s;
} else {
trigger_error("Unsupported driver $config[system]", E_USER_WARNING);
}
}
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;
}

View File

@@ -1,77 +0,0 @@
<?php
return array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'username' => 'root',
'password' => 'xxx',
'charset' => 'utf8',
),
'mysqli' => array(
'driver' => 'mysqli',
'host' => 'localhost',
'username' => 'dibi',
'password' => 'dibi',
'charset' => 'utf8',
),
'sqlite' => array(
'driver' => 'sqlite',
'database' => dirname(__FILE__) . '/data/sample.sdb',
),
'sqlite3' => array(
'driver' => 'sqlite3',
'database' => dirname(__FILE__) . '/data/sample.sdb3',
),
'odbc' => array(
'driver' => 'odbc',
'username' => 'dibi',
'password' => 'dibi',
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq=' . dirname(__FILE__) . '/data/sample.mdb',
),
'postgresql' => array(
'driver' => 'postgre',
'host' => 'localhost',
'port' => '5432',
'username' => 'dibi',
'password' => 'dibi',
'persistent' => '1',
),
'sqlite-pdo' => array(
'driver' => 'pdo',
'dsn' => 'sqlite2::' . dirname(__FILE__) . '/data/sample.sdb',
),
'mysql-pdo' => array(
'driver' => 'pdo',
'dsn' => 'mysql:host=localhost',
'username' => 'dibi',
'password' => 'dibi',
),
'mssql' => array(
'driver' => 'mssql',
'host' => 'localhost',
'username' => 'dibi',
'password' => 'dibi',
),
'mssql2005' => array(
'driver' => 'mssql2005',
'host' => '(local)',
'username' => 'dibi',
'password' => 'dibi',
),
'oracle' => array(
'driver' => 'oracle',
'username' => 'dibi',
'password' => 'dibi',
),
);

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) NOT 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) NOT 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.

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