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

Compare commits

...

84 Commits

Author SHA1 Message Date
David Grudl
906e1f2407 Released version 3.2.3 2018-09-17 13:47:10 +02:00
David Grudl
6a4f77b684 test: fix for PHP 7.3 2018-09-17 13:36:50 +02:00
Jan Kuchař
689597a237 PdoDriver: check for misconfigured PDO connections resource (#294) 2018-09-17 13:36:50 +02:00
David Grudl
a8ed2a34e5 travis: uses NCS 2 2018-09-13 03:28:20 +02:00
David Grudl
c8e5f5c8d1 loader: added missing classes [Closes #310] 2018-08-22 15:38:20 +02:00
David Grudl
4bfd314225 OdbcDriver: added option 'microseconds' 2018-08-09 22:54:00 +02:00
David Grudl
2b4ea9abe7 updated donation links 2018-06-22 11:48:18 +02:00
Miroslav Koula
3711b1739f DibiExtension: compatibility with Nette DI 3.x (#297)
Nette DI 3.x require $container->setFactory() usage except of $container->setClass()
2018-06-19 11:56:01 +02:00
David Grudl
45d7e0b365 cs 2018-06-13 15:39:54 +02:00
Josef Drábek
7d07db1f12 PdoDriver::getInsertId() fixed 2018-06-13 11:49:27 +02:00
Jan Endel
34bdd5f267 typo
for example fluent:

$dibiConnection->select(‘id’)
    ->from(‘users’);

will not pass static analysis although is completely valid code.
2018-06-13 11:48:28 +02:00
David Grudl
5a7543a5a6 Released version 3.2.2 2018-05-10 21:55:12 +02:00
David Grudl
2848c965f9 Result: added getColumnCount() 2018-05-10 21:55:12 +02:00
David Grudl
3660f26e03 improved phpDoc, capitalized Dibi 2018-05-10 21:54:30 +02:00
David Grudl
f474abfeda type improvements 2018-05-02 10:49:01 +02:00
David Grudl
809386edf8 added dibi::stripMicroseconds 2018-04-19 13:04:47 +02:00
David Grudl
1909c98e6d Sqlite3Driver: for SQLite 3 is not needed to strip [] from column names 2018-04-19 13:04:47 +02:00
David Grudl
8985c71276 refactoring 2018-04-19 13:04:39 +02:00
David Grudl
0d5fd9d65b type fixes 2018-04-17 13:09:27 +02:00
David Grudl
4049ea4717 examples: dibi:: replaced with $dibi-> 2018-04-17 13:09:27 +02:00
David Grudl
cec699af0f Released version 3.2.1 2018-04-14 20:49:54 +02:00
David Grudl
59a4cc2fe0 Revert "loader: uses only Composer's autoloader"
This reverts commit 5c806ea517.
2018-04-14 20:49:14 +02:00
David Grudl
985f09417e Translator: improved Expression usage 2018-04-14 20:49:14 +02:00
David Grudl
729d133d70 PdoDriver: improved detection of query result [Closes #279] 2018-03-28 18:04:35 +02:00
David Grudl
759c63bca0 appveyor: improved 2018-03-23 17:53:22 +01:00
David Grudl
f9fc7e330d examples: added notice when vendor/autoload.php not found 2018-03-23 11:57:59 +01:00
jahudka
dbca915bfe Firebird: fix datetime precision (#277) (#273) 2018-03-18 10:49:20 +01:00
Miloslav Hůla
1bae6eae08 tests: connection removed from bootstrap 2018-03-09 15:09:48 +01:00
David Grudl
34b7e22d40 readme.md: static -> object 2018-03-09 15:09:48 +01:00
David Grudl
369f5ee7d6 readme: updated installation and requirements 2018-03-09 15:09:48 +01:00
David Grudl
2d74bb3da0 examples: uses composer autoload 2018-03-09 14:50:36 +01:00
David Grudl
a5422a65c9 loader: old class names triggers E_USER_DEPRECATED, removed preloading (BC break) 2018-03-09 14:44:06 +01:00
David Grudl
5c806ea517 loader: uses only Composer's autoloader
# Conflicts:
#	src/loader.php
2018-03-09 14:38:18 +01:00
David Grudl
ecafed6246 opened 3.2-dev 2018-03-09 14:37:31 +01:00
David Grudl
504b7725c7 Released version 3.1.1 2018-03-09 13:00:25 +01:00
David Grudl
822405b478 appveyor: PHP is downloaded using cURL
"03/mar/2018: We've upgraded the server bandwidth. This is however still not sufficient to handle all empty user agent connections. Please update the user agent in your scripts accordingly or contact us so we can discuss it."
2018-03-08 13:52:54 +01:00
David Grudl
43d3b57a8d Microsoft SQL Server and MSSQL support for microseconds fix cont. 2018-02-25 16:59:37 +01:00
hubipe
4f0566ece7 Microsoft SQL Server and MSSQL support for microseconds fix (#249) 2018-02-25 16:59:36 +01:00
Korney Czukowski
67521084d9 Previous exception can now be passed to Dibi\Exception constructor (#276) 2018-02-16 14:12:33 +01:00
David Grudl
22ac601502 loader: fixed missing class 'dibi.php' 2018-02-15 11:53:57 +01:00
Petr Bugyík
b740b70f18 drivers: changed self:: to static:: 2018-02-14 13:05:35 +01:00
David Grudl
44fc3f4553 coding style 2018-02-11 22:47:22 +01:00
David Grudl
fa35c0cf7d Released version 3.1.0 2017-09-25 17:57:54 +02:00
David Grudl
8a25700c8c travis: fixed PHP versions 2017-09-25 17:57:45 +02:00
David Grudl
1352437e08 added Dibi\Expression [Closes #264] 2017-09-25 17:57:45 +02:00
David Grudl
f0d08a990c whitespace 2017-09-21 14:22:22 +02:00
David Grudl
4472fb3a3d Translator: fixed %dt with DateTimeInterface object [Closes #263] 2017-09-21 14:04:30 +02:00
Miloslav Hůla
d4b87490a1 Fluent: fixed phpDoc, query() may return Result|int 2017-09-07 21:26:43 +02:00
Miloslav Hůla
9486b65b84 OdbcDriver, OracleDriver, SqlsrvDriver, Sqlite3Driver: query() returns ResultSet only when contains columns 2017-09-07 21:26:43 +02:00
David Grudl
f47ad15af0 MySqliDriver: removed deprecated stuff 2017-09-07 21:26:43 +02:00
David Grudl
6c147f2ea5 Connection, dibi: deprecated insertId() & affectedRows() 2017-09-07 21:26:43 +02:00
David Grudl
0af64b5f9b Revert "loader: uses only Composer's autoloader"
This reverts commit 53475ba05a.
2017-07-26 15:02:03 +02:00
David Grudl
03c6eeeb16 Revert "examples: uses composer autoload"
This reverts commit 6a4cc4f36f.
2017-07-26 15:01:44 +02:00
David Grudl
ad3a9c50f9 travis: use stages 2017-07-24 17:04:29 +02:00
David Grudl
d31f2e3dd4 Translator: %i %f throws exception when value is not numeric (BC break) 2017-07-22 00:41:39 +02:00
David Grudl
3253a5b092 support for 64bit numbers on 32bit platform [Closes #253] (BC break)
throws exception when given argument is not a number
2017-07-22 00:41:35 +02:00
David Grudl
be3a0aa57d __toString() returns always string 2017-07-22 00:40:33 +02:00
David Grudl
6a4cc4f36f examples: uses composer autoload 2017-07-21 22:46:09 +02:00
David Grudl
1815b214ee travis: tested using Nette Coding Standard 2017-07-21 22:46:09 +02:00
David Grudl
4f75637b63 coding style: fixes in code 2017-07-21 22:46:09 +02:00
David Grudl
ebf0be1fd0 coding style: TRUE/FALSE/NULL -> true/false/null 2017-07-21 22:33:41 +02:00
David Grudl
b439ee9df1 coding style: fixed spaces & use statements order 2017-07-21 22:25:33 +02:00
David Grudl
e45a86d58c Released version 3.1.0 2017-06-10 03:08:16 +02:00
David Grudl
e891bdd862 DibiExtension22: added $debugMode to constructor 2017-06-10 03:08:16 +02:00
David Grudl
8dc5567bdd Helpers::loadFromFile added $onProgress 2017-06-10 03:08:16 +02:00
David Grudl
e3bfac2316 Helpers::loadFromFile improved 2017-06-10 03:08:16 +02:00
David Grudl
53475ba05a loader: uses only Composer's autoloader 2017-06-10 03:08:14 +02:00
David Grudl
c219726914 removed bridges for Nette < 2.2 2017-06-10 03:06:01 +02:00
hubipe
ed0cb63df0 Support for microseconds (#246) 2017-06-10 03:06:01 +02:00
Aleš Culek
1ab69f3576 OracleDriver: added 'nativeDate' option, formatDate & formatDateTime are deprecated (#232) 2017-06-10 03:06:01 +02:00
David Grudl
70f29f6857 removed folder /dibi 2017-06-10 03:06:01 +02:00
David Grudl
d365077319 opened 3.1-dev 2017-06-10 03:05:55 +02:00
David Grudl
0e5d951dfb Released version 3.0.8 2017-06-10 03:05:18 +02:00
David Grudl
126422ad7e strict fixes 2017-06-10 03:05:18 +02:00
David Grudl
277f52c928 appveyor: is unable to start MSSQL 2012 & 2014 together 2017-06-10 02:58:47 +02:00
David Grudl
80ac569621 fixed phpDoc 2017-06-10 02:58:47 +02:00
David Grudl
d9628f933d coding style: removed space after reference & 2017-06-10 02:58:47 +02:00
David Grudl
f7009f3e0c Tracy\Panel: better typography 2017-06-10 02:58:47 +02:00
Jiří Trávníček
36d30c1fcf Dibi\Bridges\Tracy\Panel: host added to tracy panel [closes #250] (#251) 2017-06-10 02:58:44 +02:00
David Grudl
ae6c8756b6 Tracy\Panel: one panel is used per connection 2017-06-10 02:58:06 +02:00
David Grudl
6b2c996b16 Tracy\Panel: dump() may fails
related: https://forum.nette.org/cs/26790-error-dibi-bridges-tracy-panel-oracle
917971992f (commitcomment-18444224)
2017-06-09 12:12:07 +02:00
David Grudl
718c617764 travis: removed HHVM 2017-06-09 12:12:07 +02:00
David Grudl
6194152e67 examples: tracy is loaded before output [Closes #248] 2017-06-09 12:12:07 +02:00
David Grudl
d39603e23d updated .gitattributes 2017-06-09 12:12:07 +02:00
95 changed files with 2044 additions and 1713 deletions

1
.gitattributes vendored
View File

@@ -2,4 +2,5 @@
.gitignore export-ignore
.github export-ignore
.travis.yml export-ignore
appveyor.yml export-ignore
tests/ export-ignore

View File

@@ -5,25 +5,11 @@ php:
- 5.6
- 7.0
- 7.1
- hhvm
- 7.2
matrix:
allow_failures:
- php: hhvm
script:
- vendor/bin/tester tests -s -p php -c tests/php-unix.ini $COVERAGE
- php temp/code-checker/src/code-checker.php --short-arrays
after_failure:
# Print *.actual content
- for i in $(find tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done
before_script:
# Install Nette Tester & Code Checker
- travis_retry composer install --no-interaction
- travis_retry composer create-project nette/code-checker temp/code-checker ~2.5 --no-interaction
- if [ $TRAVIS_PHP_VERSION == "7.0" ]; then COVERAGE="-p phpdbg --coverage ./coverage.xml --coverage-src ./src"; fi
before_install:
# turn off XDebug
- phpenv config-rm xdebug.ini || return 0
# Create databases.ini
- cp ./tests/databases.travis.ini ./tests/databases.ini
@@ -31,16 +17,49 @@ before_script:
# Create Postgre database
- psql -c 'CREATE DATABASE dibi_test' -U postgres
after_script:
# Report Code Coverage
- >
if [ "$COVERAGE" != "" ]; then
wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar
&& php coveralls.phar --verbose --config tests/.coveralls.yml
|| true; fi
install:
- travis_retry composer install --no-progress --prefer-dist
script:
- vendor/bin/tester tests -s
after_failure:
# Print *.actual content
- for i in $(find tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done
jobs:
include:
- stage: Code Standard Checker
php: 7.1
install:
# Install Nette Code Checker
- travis_retry composer create-project nette/code-checker temp/code-checker ^3 --no-progress
# Install Nette Coding Standard
- travis_retry composer create-project nette/coding-standard temp/coding-standard ^2 --no-progress
script:
- php temp/code-checker/code-checker
- php temp/coding-standard/ecs check src tests examples --config temp/coding-standard/coding-standard-php56.yml
- stage: Code Coverage
php: 7.1
script:
- vendor/bin/tester -p phpdbg tests -s --coverage ./coverage.xml --coverage-src ./src
after_script:
- wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar
- php coveralls.phar --verbose --config tests/.coveralls.yml
allow_failures:
- php: 7.2
- stage: Code Coverage
sudo: false
cache:
directories:
- $HOME/.composer/cache
notifications:
email: false

View File

@@ -8,7 +8,7 @@ clone_folder: c:\projects\dibi
services:
- mssql2012sp1
- mssql2014
# - mssql2014
- mysql
init:
@@ -20,8 +20,8 @@ install:
- IF EXIST c:\php5 (SET PHP=0) ELSE (SET PHP=1)
- IF %PHP%==1 mkdir c:\php5
- IF %PHP%==1 cd c:\php5
- IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.6.14-Win32-VC11-x86.zip
- IF %PHP%==1 7z x php-5.6.14-Win32-VC11-x86.zip >nul
- IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-5.6.14-Win32-VC11-x86.zip --output php.zip
- IF %PHP%==1 7z x php.zip >nul
- IF %PHP%==1 echo extension_dir=ext >> php.ini
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini
- IF %PHP%==1 appveyor DownloadFile https://files.nette.org/misc/php-sqlsrv.zip
@@ -34,8 +34,8 @@ install:
- IF EXIST c:\php7 (SET PHP=0) ELSE (SET PHP=1)
- IF %PHP%==1 mkdir c:\php7
- IF %PHP%==1 cd c:\php7
- IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-7.0.3-Win32-VC14-x86.zip
- IF %PHP%==1 7z x php-7.0.3-Win32-VC14-x86.zip >nul
- IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-7.0.3-Win32-VC14-x86.zip --output php.zip
- IF %PHP%==1 7z x php.zip >nul
- IF %PHP%==1 echo extension_dir=ext >> php.ini
- IF %PHP%==1 appveyor DownloadFile https://files.nette.org/misc/php-sqlsrv.zip
- IF %PHP%==1 7z x php-sqlsrv.zip >nul
@@ -56,4 +56,4 @@ test_script:
on_failure:
# Print *.actual content
- type tests\dibi\output\*.actual
- for /r %%x in (*.actual) do ( type "%%x" )

View File

@@ -26,7 +26,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
"dev-master": "3.2-dev"
}
}
}

View File

@@ -1,3 +0,0 @@
<?php
trigger_error('Dibi was moved to /src/loader.php', E_USER_WARNING);
require __DIR__ . '/../src/loader.php';

View File

@@ -1,13 +1,15 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Connecting to Databases | dibi</h1>
<h1>Connecting to Databases | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
// connects to SQlite using dibi class
// connects to SQlite using Dibi class
echo '<p>Connecting to Sqlite: ';
try {
dibi::connect([
@@ -74,7 +76,7 @@ try {
'driver' => 'odbc',
'username' => 'root',
'password' => '***',
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq='.__DIR__.'/data/sample.mdb',
'dsn' => 'Driver={Microsoft Access Driver (*.mdb)};Dbq=' . __DIR__ . '/data/sample.mdb',
]);
echo 'OK';
} catch (Dibi\Exception $e) {
@@ -89,7 +91,7 @@ try {
dibi::connect([
'driver' => 'postgre',
'string' => 'host=localhost port=5432 dbname=mary',
'persistent' => TRUE,
'persistent' => true,
]);
echo 'OK';
} catch (Dibi\Exception $e) {

View File

@@ -1,20 +1,22 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Database Reflection | dibi</h1>
<h1>Database Reflection | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
// retrieve database reflection
$database = dibi::getDatabaseInfo();
$database = $dibi->getDatabaseInfo();
echo "<h2>Database '{$database->getName()}'</h2>\n";
echo "<ul>\n";

View File

@@ -1,19 +1,21 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Dumping SQL and Result Set | dibi</h1>
<h1>Dumping SQL and Result Set | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
$res = dibi::query('
$res = $dibi->query('
SELECT * FROM products
INNER JOIN orders USING (product_id)
INNER JOIN customers USING (customer_id)

View File

@@ -1,7 +1,3 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Fetching Examples | dibi</h1>
<?php
if (@!include __DIR__ . '/../vendor/autoload.php') {
@@ -10,8 +6,14 @@ if (@!include __DIR__ . '/../vendor/autoload.php') {
Tracy\Debugger::enable();
?>
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
dibi::connect([
<h1>Fetching Examples | Dibi</h1>
<?php
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
@@ -31,46 +33,46 @@ product_id | title
// fetch a single row
echo "<h2>fetch()</h2>\n";
$row = dibi::fetch('SELECT title FROM products');
$row = $dibi->fetch('SELECT title FROM products');
Tracy\Dumper::dump($row); // Chair
// fetch a single value
echo "<h2>fetchSingle()</h2>\n";
$value = dibi::fetchSingle('SELECT title FROM products');
$value = $dibi->fetchSingle('SELECT title FROM products');
Tracy\Dumper::dump($value); // Chair
// fetch complete result set
echo "<h2>fetchAll()</h2>\n";
$all = dibi::fetchAll('SELECT * FROM products');
$all = $dibi->fetchAll('SELECT * FROM products');
Tracy\Dumper::dump($all);
// fetch complete result set like association array
echo "<h2>fetchAssoc('title')</h2>\n";
$res = dibi::query('SELECT * FROM products');
$res = $dibi->query('SELECT * FROM products');
$assoc = $res->fetchAssoc('title'); // key
Tracy\Dumper::dump($assoc);
// fetch complete result set like pairs key => value
echo "<h2>fetchPairs('product_id', 'title')</h2>\n";
$res = dibi::query('SELECT * FROM products');
$res = $dibi->query('SELECT * FROM products');
$pairs = $res->fetchPairs('product_id', 'title');
Tracy\Dumper::dump($pairs);
// fetch row by row
echo "<h2>using foreach</h2>\n";
$res = dibi::query('SELECT * FROM products');
$res = $dibi->query('SELECT * FROM products');
foreach ($res as $n => $row) {
Tracy\Dumper::dump($row);
}
// more complex association array
$res = dibi::query('
$res = $dibi->query('
SELECT *
FROM products
INNER JOIN orders USING (product_id)
@@ -82,11 +84,11 @@ $assoc = $res->fetchAssoc('name|title'); // key
Tracy\Dumper::dump($assoc);
echo "<h2>fetchAssoc('name[]title')</h2>\n";
$res = dibi::query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)');
$res = $dibi->query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)');
$assoc = $res->fetchAssoc('name[]title'); // key
Tracy\Dumper::dump($assoc);
echo "<h2>fetchAssoc('name->title')</h2>\n";
$res = dibi::query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)');
$res = $dibi->query('SELECT * FROM products INNER JOIN orders USING (product_id) INNER JOIN customers USING (customer_id)');
$assoc = $res->fetchAssoc('name->title'); // key
Tracy\Dumper::dump($assoc);

View File

@@ -1,18 +1,20 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Importing SQL Dump from File | dibi</h1>
<h1>Importing SQL Dump from File | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
$count = dibi::loadFile('compress.zlib://data/sample.dump.sql.gz');
$count = $dibi->loadFile('compress.zlib://data/sample.dump.sql.gz');
echo 'Number of SQL commands:', $count;

View File

@@ -1,29 +1,31 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Query Language & Conditions | dibi</h1>
<h1>Query Language & Conditions | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
// some variables
$cond1 = TRUE;
$cond2 = FALSE;
$cond1 = true;
$cond2 = false;
$foo = -1;
$bar = 2;
// conditional variable
$name = $cond1 ? 'K%' : NULL;
$name = $cond1 ? 'K%' : null;
// if & end
dibi::test('
$dibi->test('
SELECT *
FROM customers
%if', isset($name), 'WHERE name LIKE ?', $name, '%end'
@@ -32,7 +34,7 @@ dibi::test('
// if & else & (optional) end
dibi::test('
$dibi->test('
SELECT *
FROM people
WHERE id > 0
@@ -43,7 +45,7 @@ dibi::test('
// nested condition
dibi::test('
$dibi->test('
SELECT *
FROM customers
WHERE
@@ -55,7 +57,7 @@ dibi::test('
// IF()
dibi::test('UPDATE products SET', [
'price' => ['IF(price_fixed, price, ?)', 123],
$dibi->test('UPDATE products SET', [
'price' => $dibi->expression('IF(price_fixed, price, ?)', 123),
]);
// -> SELECT * FROM customers WHERE LIMIT 10

View File

@@ -1,15 +1,17 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Query Language Basic Examples | dibi</h1>
<h1>Query Language Basic Examples | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
date_default_timezone_set('Europe/Prague');
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
@@ -19,7 +21,7 @@ dibi::connect([
$ipMask = '192.168.%';
$timestamp = mktime(0, 0, 0, 10, 13, 1997);
dibi::test('
$dibi->test('
SELECT COUNT(*) as [count]
FROM [comments]
WHERE [ip] LIKE ?', $ipMask, '
@@ -29,11 +31,11 @@ dibi::test('
// dibi detects INSERT or REPLACE command
dibi::test('
$dibi->test('
REPLACE INTO products', [
'title' => 'Super product',
'price' => 318,
'active' => TRUE,
'active' => true,
]);
// -> REPLACE INTO products ([title], [price], [active]) VALUES ('Super product', 318, 1)
@@ -42,15 +44,15 @@ dibi::test('
$array = [
'title' => 'Super Product',
'price' => 12,
'brand' => NULL,
'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('
$dibi->test('
UPDATE colors SET', [
'color' => 'blue',
'order' => 12,
@@ -61,7 +63,7 @@ dibi::test('
// modifier applied to array
$array = [1, 2, 3];
dibi::test('
$dibi->test('
SELECT *
FROM people
WHERE id IN (?)', $array
@@ -74,7 +76,7 @@ $order = [
'field1' => 'asc',
'field2' => 'desc',
];
dibi::test('
$dibi->test('
SELECT *
FROM people
ORDER BY %by', $order, '
@@ -83,5 +85,5 @@ dibi::test('
// indentifiers and strings syntax mix
dibi::test('UPDATE [table] SET `item` = "5 1/4"" diskette"');
$dibi->test('UPDATE [table] SET `item` = "5 1/4"" diskette"');
// -> UPDATE [table] SET [item] = '5 1/4" diskette'

View File

@@ -1,7 +1,3 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Result Set Data Types | dibi</h1>
<?php
use Dibi\Type;
@@ -14,15 +10,21 @@ Tracy\Debugger::enable();
date_default_timezone_set('Europe/Prague');
?>
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
dibi::connect([
<h1>Result Set Data Types | Dibi</h1>
<?php
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
// using manual hints
$res = dibi::query('SELECT * FROM [customers]');
$res = $dibi->query('SELECT * FROM [customers]');
$res->setType('customer_id', Type::INTEGER)
->setType('added', Type::DATETIME)
@@ -38,7 +40,7 @@ Tracy\Dumper::dump($res->fetch());
// using auto-detection (works well with MySQL or other strictly typed databases)
$res = dibi::query('SELECT * FROM [customers]');
$res = $dibi->query('SELECT * FROM [customers]');
Tracy\Dumper::dump($res->fetch());
// outputs:

View File

@@ -1,9 +1,3 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Tracy & SQL Exceptions | dibi</h1>
<p>Dibi can display and log exceptions via <a href="https://tracy.nette.org">Tracy</a>.</p>
<?php
if (@!include __DIR__ . '/../vendor/autoload.php') {
@@ -15,19 +9,25 @@ if (@!include __DIR__ . '/../vendor/autoload.php') {
Tracy\Debugger::enable();
$connection = dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => [
'run' => TRUE,
'run' => true,
],
]);
// add panel to debug bar
$panel = new Dibi\Bridges\Tracy\Panel;
$panel->register($connection);
$panel->register($dibi);
// throws error because SQL is bad
dibi::query('SELECT FROM customers WHERE customer_id < ?', 38);
$dibi->query('SELECT FROM customers WHERE customer_id < ?', 38);
?><!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Tracy & SQL Exceptions | dibi</h1>
<p>Dibi can display and log exceptions via <a href="https://tracy.nette.org">Tracy</a>.</p>

View File

@@ -1,11 +1,3 @@
<!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') {
@@ -17,22 +9,32 @@ if (@!include __DIR__ . '/../vendor/autoload.php') {
Tracy\Debugger::enable();
$connection = dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => [
'run' => TRUE,
'run' => true,
],
]);
// add panel to debug bar
$panel = new Dibi\Bridges\Tracy\Panel;
$panel->register($connection);
$panel->register($dibi);
// query will be logged
dibi::query('SELECT 123');
$dibi->query('SELECT 123');
// result set will be dumped
Tracy\Debugger::barDump(dibi::fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]');
Tracy\Debugger::barDump($dibi->fetchAll('SELECT * FROM customers WHERE customer_id < ?', 38), '[customers]');
?>
<!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>

View File

@@ -1,16 +1,18 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using DateTime | dibi</h1>
<h1>Using DateTime | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
date_default_timezone_set('Europe/Prague');
// CHANGE TO REAL PARAMETERS!
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'formatDate' => "'Y-m-d'",
@@ -19,7 +21,7 @@ dibi::connect([
// generate and dump SQL
dibi::test('
$dibi->test('
INSERT INTO [mytable]', [
'id' => 123,
'date' => new DateTime('12.3.2007'),

View File

@@ -1,7 +1,3 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Extension Methods | dibi</h1>
<?php
if (@!include __DIR__ . '/../vendor/autoload.php') {
@@ -10,8 +6,14 @@ if (@!include __DIR__ . '/../vendor/autoload.php') {
Tracy\Debugger::enable();
?>
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
dibi::connect([
<h1>Using Extension Methods | Dibi</h1>
<?php
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
@@ -26,6 +28,6 @@ Dibi\Result::extensionMethod('fetchShuffle', function (Dibi\Result $obj) {
// fetch complete result set shuffled
$res = dibi::query('SELECT * FROM [customers]');
$res = $dibi->query('SELECT * FROM [customers]');
$all = $res->fetchShuffle();
Tracy\Dumper::dump($all);

View File

@@ -1,15 +1,17 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Fluent Syntax | dibi</h1>
<h1>Using Fluent Syntax | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
date_default_timezone_set('Europe/Prague');
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
@@ -19,11 +21,11 @@ $id = 10;
$record = [
'title' => 'Super product',
'price' => 318,
'active' => TRUE,
'active' => true,
];
// SELECT ...
dibi::select('product_id')->as('id')
$dibi->select('product_id')->as('id')
->select('title')
->from('products')
->innerJoin('orders')->using('(product_id)')
@@ -35,35 +37,35 @@ dibi::select('product_id')->as('id')
// SELECT ...
echo dibi::select('title')->as('id')
echo $dibi->select('title')->as('id')
->from('products')
->fetchSingle();
// -> Chair (as result of query: SELECT [title] AS [id] FROM [products])
// INSERT ...
dibi::insert('products', $record)
$dibi->insert('products', $record)
->setFlag('IGNORE')
->test();
// -> INSERT IGNORE INTO [products] ([title], [price], [active]) VALUES ('Super product', 318, 1)
// UPDATE ...
dibi::update('products', $record)
$dibi->update('products', $record)
->where('product_id = ?', $id)
->test();
// -> UPDATE [products] SET [title]='Super product', [price]=318, [active]=1 WHERE product_id = 10
// DELETE ...
dibi::delete('products')
$dibi->delete('products')
->where('product_id = ?', $id)
->test();
// -> DELETE FROM [products] WHERE product_id = 10
// custom commands
dibi::command()
$dibi->command()
->update('products')
->where('product_id = ?', $id)
->set($record)
@@ -71,7 +73,7 @@ dibi::command()
// -> UPDATE [products] SET [title]='Super product', [price]=318, [active]=1 WHERE product_id = 10
dibi::command()
$dibi->command()
->truncate('products')
->test();
// -> TRUNCATE [products]

View File

@@ -1,28 +1,30 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Limit & Offset | dibi</h1>
<h1>Using Limit & Offset | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
// no limit
dibi::test('SELECT * FROM [products]');
$dibi->test('SELECT * FROM [products]');
// -> SELECT * FROM [products]
// with limit = 2
dibi::test('SELECT * FROM [products] %lmt', 2);
$dibi->test('SELECT * FROM [products] %lmt', 2);
// -> SELECT * FROM [products] LIMIT 2
// with limit = 2, offset = 1
dibi::test('SELECT * FROM [products] %lmt %ofs', 2, 1);
$dibi->test('SELECT * FROM [products] %lmt %ofs', 2, 1);
// -> SELECT * FROM [products] LIMIT 2 OFFSET 1

View File

@@ -1,31 +1,33 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Logger | dibi</h1>
<h1>Using Logger | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
date_default_timezone_set('Europe/Prague');
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
// enable query logging to this file
'profiler' => [
'run' => TRUE,
'run' => true,
'file' => 'data/log.sql',
],
]);
try {
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] = ?', 1);
$res = $dibi->query('SELECT * FROM [customers] WHERE [customer_id] = ?', 1);
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < ?', 5);
$res = $dibi->query('SELECT * FROM [customers] WHERE [customer_id] < ?', 5);
$res = dibi::query('SELECT FROM [customers] WHERE [customer_id] < ?', 38);
$res = $dibi->query('SELECT FROM [customers] WHERE [customer_id] < ?', 38);
} catch (Dibi\Exception $e) {
echo '<p>', get_class($e), ': ', $e->getMessage(), '</p>';
}

View File

@@ -2,25 +2,27 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Profiler | dibi</h1>
<h1>Using Profiler | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
'profiler' => [
'run' => TRUE,
'run' => true,
],
]);
// execute some queries...
for ($i = 0; $i < 20; $i++) {
$res = dibi::query('SELECT * FROM [customers] WHERE [customer_id] < ?', $i);
$res = $dibi->query('SELECT * FROM [customers] WHERE [customer_id] < ?', $i);
}
// display output

View File

@@ -1,29 +1,31 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Substitutions | dibi</h1>
<h1>Using Substitutions | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
// create new substitution :blog: ==> wp_
dibi::getSubstitutes()->blog = 'wp_';
$dibi->getSubstitutes()->blog = 'wp_';
dibi::test('SELECT * FROM [:blog:items]');
$dibi->test('SELECT * FROM [:blog:items]');
// -> SELECT * FROM [wp_items]
// create new substitution :: (empty) ==> my_
dibi::getSubstitutes()->{''} = 'my_';
$dibi->getSubstitutes()->{''} = 'my_';
dibi::test("UPDATE ::table SET [text]='Hello World'");
$dibi->test("UPDATE ::table SET [text]='Hello World'");
// -> UPDATE my_table SET [text]='Hello World'
@@ -38,14 +40,15 @@ function substFallBack($expr)
}
}
// define callback
dibi::getSubstitutes()->setCallback('substFallBack');
$dibi->getSubstitutes()->setCallback('substFallBack');
// define substitutes as constants
define('SUBST_ACCOUNT', 'eshop_');
define('SUBST_ACTIVE', 7);
dibi::test("
$dibi->test("
UPDATE :account:user
SET name='John Doe', status=:active:
WHERE id=", 7

View File

@@ -1,34 +1,36 @@
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
<h1>Using Transactions | dibi</h1>
<h1>Using Transactions | Dibi</h1>
<?php
require __DIR__ . '/../src/loader.php';
if (@!include __DIR__ . '/../vendor/autoload.php') {
die('Install packages using `composer install`');
}
dibi::connect([
$dibi = new Dibi\Connection([
'driver' => 'sqlite3',
'database' => 'data/sample.s3db',
]);
echo "<h2>Before</h2>\n";
dibi::query('SELECT * FROM [products]')->dump();
$dibi->query('SELECT * FROM [products]')->dump();
// -> 3 rows
dibi::begin();
dibi::query('INSERT INTO [products]', [
$dibi->begin();
$dibi->query('INSERT INTO [products]', [
'title' => 'Test product',
]);
echo "<h2>After INSERT</h2>\n";
dibi::query('SELECT * FROM [products]')->dump();
$dibi->query('SELECT * FROM [products]')->dump();
dibi::rollback(); // or dibi::commit();
$dibi->rollback(); // or $dibi->commit();
echo "<h2>After rollback</h2>\n";
dibi::query('SELECT * FROM [products]')->dump();
$dibi->query('SELECT * FROM [products]')->dump();
// -> 3 rows again

View File

@@ -1,4 +1,4 @@
[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)
[Dibi](https://dibiphp.com) - smart database layer for PHP [![Buy me a coffee](https://files.nette.org/images/coffee1s.png)](https://nette.org/make-donation?to=dibi)
=========================================================
[![Downloads this Month](https://img.shields.io/packagist/dm/dibi/dibi.svg)](https://packagist.org/packages/dibi/dibi)
@@ -7,22 +7,30 @@
[![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)
Introduction
------------
Database access functions in PHP are not standardised. This library
hides the differences between them, and above all, it gives you a very handy interface.
The best way to install Dibi is to use a [Composer](https://getcomposer.org/download):
php composer.phar require dibi/dibi
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.
Dibi requires PHP 5.4.4 or later. It has been tested with PHP 7 too.
If you like Dibi, **[please make a donation now](https://nette.org/make-donation?to=dibi)**. Thank you!
Examples
--------
Installation
------------
The recommended way to install Dibi is via Composer (alternatively you can [download package](https://github.com/dg/dibi/releases)):
```bash
composer require dibi/dibi
```
The Dibi 3.x requires PHP version 5.4.4 and supports PHP up to 7.2.
Usage
-----
Refer to the `examples` directory for examples. Dibi documentation is
available on the [homepage](https://dibiphp.com).
@@ -30,34 +38,34 @@ available on the [homepage](https://dibiphp.com).
Connect to database:
```php
// connect to database (static way)
dibi::connect([
'driver' => 'mysql',
$dibi = new Dibi\Connection([
'driver' => 'mysqli',
'host' => 'localhost',
'username' => 'root',
'password' => '***',
]);
// or object way; in all other examples use $connection-> instead of dibi::
$connection = new DibiConnection($options);
// or static way; in all other examples use dibi:: instead of $dibi->
dibi::connect($options);
```
SELECT, INSERT, UPDATE
```php
dibi::query('SELECT * FROM users WHERE id = ?', $id);
$dibi->query('SELECT * FROM users WHERE id = ?', $id);
$arr = [
'name' => 'John',
'is_admin' => TRUE,
'is_admin' => true,
];
dibi::query('INSERT INTO users', $arr);
$dibi->query('INSERT INTO users', $arr);
// INSERT INTO users (`name`, `is_admin`) VALUES ('John', 1)
dibi::query('UPDATE users SET', $arr, 'WHERE `id`=?', $x);
$dibi->query('UPDATE users SET', $arr, 'WHERE `id`=?', $x);
// UPDATE users SET `name`='John', `is_admin`=1 WHERE `id` = 123
dibi::query('UPDATE users SET', [
$dibi->query('UPDATE users SET', [
'title' => array('SHA1(?)', 'tajneheslo'),
]);
// UPDATE users SET 'title' = SHA1('tajneheslo')
@@ -66,7 +74,7 @@ dibi::query('UPDATE users SET', [
Getting results
```php
$result = dibi::query('SELECT * FROM users');
$result = $dibi->query('SELECT * FROM users');
$value = $result->fetchSingle(); // single value
$all = $result->fetchAll(); // all rows
@@ -82,7 +90,7 @@ foreach ($result as $n => $row) {
Modifiers for arrays:
```php
dibi::query('SELECT * FROM users WHERE %and', [
$dibi->query('SELECT * FROM users WHERE %and', [
array('number > ?', 10),
array('number < ?', 100),
]);
@@ -105,7 +113,7 @@ dibi::query('SELECT * FROM users WHERE %and', [
Modifiers for LIKE
```php
dibi::query("SELECT * FROM table WHERE name LIKE %like~", $query);
$dibi->query("SELECT * FROM table WHERE name LIKE %like~", $query);
```
<table>
@@ -117,7 +125,7 @@ dibi::query("SELECT * FROM table WHERE name LIKE %like~", $query);
DateTime:
```php
dibi::query('UPDATE users SET', [
$dibi->query('UPDATE users SET', [
'time' => new DateTime,
]);
// UPDATE users SET ('2008-01-01 01:08:10')

View File

@@ -1,52 +0,0 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi\Bridges\Nette;
use Nette;
/**
* Dibi extension for Nette Framework 2.1. Creates 'connection' service.
*/
class DibiExtension21 extends Nette\DI\CompilerExtension
{
public function loadConfiguration()
{
$container = $this->getContainerBuilder();
$config = $this->getConfig();
$useProfiler = isset($config['profiler'])
? $config['profiler']
: $container->parameters['debugMode'];
unset($config['profiler']);
if (isset($config['flags'])) {
$flags = 0;
foreach ((array) $config['flags'] as $flag) {
$flags |= constant($flag);
}
$config['flags'] = $flags;
}
$connection = $container->addDefinition($this->prefix('connection'))
->setClass('Dibi\Connection', [$config])
->setAutowired(isset($config['autowired']) ? $config['autowired'] : TRUE);
if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel'))
->setClass('Dibi\Bridges\Nette\Panel')
->addSetup('Nette\Diagnostics\Debugger::getBar()->addPanel(?)', ['@self'])
->addSetup('Nette\Diagnostics\Debugger::getBlueScreen()->addPanel(?)', ['Dibi\Bridges\Nette\Panel::renderException']);
$connection->addSetup('$service->onEvent[] = ?', [[$panel, 'logEvent']]);
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -16,15 +16,28 @@ use Nette;
*/
class DibiExtension22 extends Nette\DI\CompilerExtension
{
/** @var bool */
private $debugMode;
public function __construct($debugMode = null)
{
$this->debugMode = $debugMode;
}
public function loadConfiguration()
{
$container = $this->getContainerBuilder();
$config = $this->getConfig();
if ($this->debugMode === null) {
$this->debugMode = $container->parameters['debugMode'];
}
$useProfiler = isset($config['profiler'])
? $config['profiler']
: class_exists('Tracy\Debugger') && $container->parameters['debugMode'];
: class_exists('Tracy\Debugger') && $this->debugMode;
unset($config['profiler']);
@@ -37,8 +50,8 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
}
$connection = $container->addDefinition($this->prefix('connection'))
->setClass('Dibi\Connection', [$config])
->setAutowired(isset($config['autowired']) ? $config['autowired'] : TRUE);
->setFactory('Dibi\Connection', [$config])
->setAutowired(isset($config['autowired']) ? $config['autowired'] : true);
if (class_exists('Tracy\Debugger')) {
$connection->addSetup(
@@ -48,12 +61,11 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
}
if ($useProfiler) {
$panel = $container->addDefinition($this->prefix('panel'))
->setClass('Dibi\Bridges\Tracy\Panel', [
isset($config['explain']) ? $config['explain'] : TRUE,
isset($config['filter']) && $config['filter'] === FALSE ? Dibi\Event::ALL : Dibi\Event::QUERY,
->setFactory('Dibi\Bridges\Tracy\Panel', [
isset($config['explain']) ? $config['explain'] : true,
isset($config['filter']) && $config['filter'] === false ? Dibi\Event::ALL : Dibi\Event::QUERY,
]);
$connection->addSetup([$panel, 'register'], [$connection]);
}
}
}

View File

@@ -1,153 +0,0 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi\Bridges\Nette;
use Dibi;
use Dibi\Event;
use Dibi\Helpers;
use Nette;
use Nette\Diagnostics\Debugger;
/**
* Dibi panel for Nette\Diagnostics.
*/
class Panel implements Nette\Diagnostics\IBarPanel
{
use Dibi\Strict;
/** @var int maximum SQL length */
public static $maxLength = 1000;
/** @var bool explain queries? */
public $explain;
/** @var int */
public $filter;
/** @var array */
private $events = [];
public function __construct($explain = TRUE, $filter = NULL)
{
$this->filter = $filter ? (int) $filter : Event::QUERY;
$this->explain = $explain;
}
public function register(Dibi\Connection $connection)
{
Debugger::getBar()->addPanel($this);
Debugger::getBlueScreen()->addPanel([__CLASS__, 'renderException']);
$connection->onEvent[] = [$this, 'logEvent'];
}
/**
* After event notification.
* @return void
*/
public function logEvent(Event $event)
{
if (($event->type & $this->filter) === 0) {
return;
}
$this->events[] = $event;
}
/**
* Returns blue-screen custom tab.
* @return mixed
*/
public static function renderException($e)
{
if ($e instanceof Dibi\Exception && $e->getSql()) {
return [
'tab' => 'SQL',
'panel' => Helpers::dump($e->getSql(), TRUE),
];
}
}
/**
* Returns HTML code for custom tab. (Nette\Diagnostics\IBarPanel)
* @return mixed
*/
public function getTab()
{
$totalTime = 0;
foreach ($this->events as $event) {
$totalTime += $event->time;
}
return '<span title="dibi"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC" />'
. count($this->events) . ' queries'
. ($totalTime ? sprintf(' / %0.1f ms', $totalTime * 1000) : '')
. '</span>';
}
/**
* Returns HTML code for custom panel. (Nette\Diagnostics\IBarPanel)
* @return mixed
*/
public function getPanel()
{
$totalTime = $s = NULL;
$h = 'htmlSpecialChars';
foreach ($this->events as $event) {
$totalTime += $event->time;
$explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS()
if ($this->explain && $event->type === Event::SELECT) {
try {
$backup = [$event->connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime];
$event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN');
$explain = Helpers::dump($event->connection->nativeQuery("$cmd $event->sql"), TRUE);
} catch (Dibi\Exception $e) {
}
list($event->connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime) = $backup;
}
$s .= '<tr><td>' . sprintf('%0.3f', $event->time * 1000);
if ($explain) {
static $counter;
$counter++;
$s .= "<br /><a href='#nette-debug-DibiProfiler-row-$counter' class='nette-toggler nette-toggle-collapsed' rel='#nette-debug-DibiProfiler-row-$counter'>explain</a>";
}
$s .= '</td><td class="nette-DibiProfiler-sql">' . Helpers::dump(strlen($event->sql) > self::$maxLength ? substr($event->sql, 0, self::$maxLength) . '...' : $event->sql, TRUE);
if ($explain) {
$s .= "<div id='nette-debug-DibiProfiler-row-$counter' class='nette-collapsed'>{$explain}</div>";
}
if ($event->source) {
$helpers = 'Nette\Diagnostics\Helpers';
if (!class_exists($helpers)) {
$helpers = class_exists('NDebugHelpers') ? 'NDebugHelpers' : 'DebugHelpers';
}
$s .= call_user_func([$helpers, 'editorLink'], $event->source[0], $event->source[1])->class('nette-DibiProfiler-source');
}
$s .= "</td><td>{$event->count}</td><td>{$h($event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name'))}</td></tr>";
}
return empty($this->events) ? '' :
'<style> #nette-debug td.nette-DibiProfiler-sql { background: white !important }
#nette-debug .nette-DibiProfiler-source { color: #999 !important }
#nette-debug nette-DibiProfiler tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style>
<h1>Queries: ' . count($this->events) . ($totalTime === NULL ? '' : sprintf(', time: %0.3f ms', $totalTime * 1000)) . '</h1>
<div class="nette-inner nette-DibiProfiler">
<table>
<tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . '
</table>
</div>';
}
}

View File

@@ -1,5 +1,5 @@
# This will create service named 'dibi.connection'.
# Requires Nette Framework 2.2
# Requires Nette Framework 2.2 or later
extensions:
dibi: Dibi\Bridges\Nette\DibiExtension22
@@ -9,4 +9,4 @@ dibi:
username: root
password: ***
database: foo
lazy: TRUE
lazy: true

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -23,7 +23,7 @@ class Panel implements Tracy\IBarPanel
/** @var int maximum SQL length */
public static $maxLength = 1000;
/** @var bool explain queries? */
/** @var bool|string explain queries? */
public $explain;
/** @var int */
@@ -33,7 +33,7 @@ class Panel implements Tracy\IBarPanel
private $events = [];
public function __construct($explain = TRUE, $filter = NULL)
public function __construct($explain = true, $filter = null)
{
$this->filter = $filter ? (int) $filter : Event::QUERY;
$this->explain = $explain;
@@ -63,14 +63,14 @@ class Panel implements Tracy\IBarPanel
/**
* Returns blue-screen custom tab.
* @return mixed
* @return array|null
*/
public static function renderException($e)
{
if ($e instanceof Dibi\Exception && $e->getSql()) {
return [
'tab' => 'SQL',
'panel' => Helpers::dump($e->getSql(), TRUE),
'panel' => Helpers::dump($e->getSql(), true),
];
}
}
@@ -78,7 +78,7 @@ class Panel implements Tracy\IBarPanel
/**
* Returns HTML code for custom tab. (Tracy\IBarPanel)
* @return mixed
* @return string
*/
public function getTab()
{
@@ -88,42 +88,46 @@ class Panel implements Tracy\IBarPanel
$totalTime += $event->time;
}
return '<span title="dibi"><svg viewBox="0 0 2048 2048" style="vertical-align: bottom; width:1.23em; height:1.55em"><path fill="' . ($count ? '#b079d6' : '#aaa') . '" d="M1024 896q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0 768q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-384q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-1152q208 0 385 34.5t280 93.5 103 128v128q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-128q0-69 103-128t280-93.5 385-34.5z"/></svg><span class="tracy-label">'
. $count . ' queries'
. ($totalTime ? sprintf(' / %0.1f ms', $totalTime * 1000) : '')
. $count . ' queries'
. ($totalTime ? ' / ' . number_format($totalTime * 1000, 1, '.', '') . 'ms' : '')
. '</span></span>';
}
/**
* Returns HTML code for custom panel. (Tracy\IBarPanel)
* @return mixed
* @return string|null
*/
public function getPanel()
{
$totalTime = $s = NULL;
$h = 'htmlSpecialChars';
if (!$this->events) {
return null;
}
$totalTime = $s = null;
foreach ($this->events as $event) {
$totalTime += $event->time;
$explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS()
$connection = $event->connection;
$explain = null; // EXPLAIN is called here to work SELECT FOUND_ROWS()
if ($this->explain && $event->type === Event::SELECT) {
$backup = [$connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime];
$connection->onEvent = null;
$cmd = is_string($this->explain) ? $this->explain : ($connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN');
try {
$backup = [$event->connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime];
$event->connection->onEvent = NULL;
$cmd = is_string($this->explain) ? $this->explain : ($event->connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN');
$explain = Helpers::dump(@$event->connection->nativeQuery("$cmd $event->sql"), TRUE);
$explain = @Helpers::dump($connection->nativeQuery("$cmd $event->sql"), true);
} catch (Dibi\Exception $e) {
}
list($event->connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime) = $backup;
list($connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime) = $backup;
}
$s .= '<tr><td>' . sprintf('%0.3f', $event->time * 1000);
$s .= '<tr><td>' . number_format($event->time * 1000, 3, '.', '');
if ($explain) {
static $counter;
$counter++;
$s .= "<br /><a href='#tracy-debug-DibiProfiler-row-$counter' class='tracy-toggle tracy-collapsed' rel='#tracy-debug-DibiProfiler-row-$counter'>explain</a>";
}
$s .= '</td><td class="tracy-DibiProfiler-sql">' . Helpers::dump(strlen($event->sql) > self::$maxLength ? substr($event->sql, 0, self::$maxLength) . '...' : $event->sql, TRUE);
$s .= '</td><td class="tracy-DibiProfiler-sql">' . Helpers::dump(strlen($event->sql) > self::$maxLength ? substr($event->sql, 0, self::$maxLength) . '...' : $event->sql, true);
if ($explain) {
$s .= "<div id='tracy-debug-DibiProfiler-row-$counter' class='tracy-collapsed'>{$explain}</div>";
}
@@ -131,19 +135,20 @@ class Panel implements Tracy\IBarPanel
$s .= Tracy\Helpers::editorLink($event->source[0], $event->source[1]);//->class('tracy-DibiProfiler-source');
}
$s .= "</td><td>{$event->count}</td><td>{$h($event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name'))}</td></tr>";
$s .= "</td><td>{$event->count}</td></tr>";
}
return empty($this->events) ? '' :
'<style> #tracy-debug td.tracy-DibiProfiler-sql { background: white !important }
return '<style> #tracy-debug td.tracy-DibiProfiler-sql { background: white !important }
#tracy-debug .tracy-DibiProfiler-source { color: #999 !important }
#tracy-debug tracy-DibiProfiler tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style>
<h1>Queries: ' . count($this->events) . ($totalTime === NULL ? '' : sprintf(', time: %0.3f ms', $totalTime * 1000)) . '</h1>
<h1>Queries: ' . count($this->events)
. ($totalTime === null ? '' : ', time: ' . number_format($totalTime * 1000, 1, '.', '') . 'ms') . ', '
. htmlspecialchars($connection->getConfig('driver') . ($connection->getConfig('name') ? '/' . $connection->getConfig('name') : '')
. ($connection->getConfig('host') ? '@' . $connection->getConfig('host') : '')) . '</h1>
<div class="tracy-inner tracy-DibiProfiler">
<table>
<tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . '
<tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th></tr>' . $s . '
</table>
</div>';
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Traversable;
/**
* dibi connection.
* Dibi connection.
*
* @property-read int $affectedRows
* @property-read int $insertId
@@ -29,11 +29,11 @@ class Connection
/** @var Driver */
private $driver;
/** @var Translator */
/** @var Translator|null */
private $translator;
/** @var bool Is connected? */
private $connected = FALSE;
private $connected = false;
/** @var HashMap Substitutes for identifiers */
private $substitutes;
@@ -41,19 +41,18 @@ class Connection
/**
* Connection options: (see driver-specific options too)
* - lazy (bool) => if TRUE, connection will be established only when required
* - lazy (bool) => if true, connection will be established only when required
* - result (array) => result set options
* - formatDateTime => date-time format (if empty, DateTime objects will be returned)
* - profiler (array or bool)
* - run (bool) => enable profiler?
* - file => file to log
* - substitutes (array) => map of driver specific substitutes (under development)
* @param mixed connection parameters
* @param string connection name
* @throws Exception
*/
public function __construct($config, $name = NULL)
public function __construct($config, $name = null)
{
if (is_string($config)) {
parse_str($config, $config);
@@ -97,7 +96,7 @@ class Connection
$this->config = $config;
// profiler
$profilerCfg = & $config['profiler'];
$profilerCfg = &$config['profiler'];
if (is_scalar($profilerCfg)) {
$profilerCfg = ['run' => (bool) $profilerCfg];
}
@@ -111,11 +110,6 @@ class Connection
if (Loggers\FirePhpLogger::isAvailable()) {
$this->onEvent[] = [new Loggers\FirePhpLogger($filter), 'logEvent'];
}
if (!interface_exists('Tracy\IBarPanel') && interface_exists('Nette\Diagnostics\IBarPanel') && class_exists('Dibi\Bridges\Nette\Panel')) {
$panel = new Bridges\Nette\Panel(isset($profilerCfg['explain']) ? $profilerCfg['explain'] : TRUE, $filter);
$panel->register($this);
}
}
$this->substitutes = new HashMap(function ($expr) { return ":$expr:"; });
@@ -137,8 +131,9 @@ class Connection
*/
public function __destruct()
{
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
$this->connected && $this->driver->getResource() && $this->disconnect();
if ($this->connected && $this->driver->getResource()) {
$this->disconnect();
}
}
@@ -148,14 +143,18 @@ class Connection
*/
final public function connect()
{
$event = $this->onEvent ? new Event($this, Event::CONNECT) : NULL;
$event = $this->onEvent ? new Event($this, Event::CONNECT) : null;
try {
$this->driver->connect($this->config);
$this->connected = TRUE;
$event && $this->onEvent($event->done());
$this->connected = true;
if ($event) {
$this->onEvent($event->done());
}
} catch (Exception $e) {
$event && $this->onEvent($event->done($e));
if ($event) {
$this->onEvent($event->done($e));
}
throw $e;
}
}
@@ -168,12 +167,12 @@ class Connection
final public function disconnect()
{
$this->driver->disconnect();
$this->connected = FALSE;
$this->connected = false;
}
/**
* Returns TRUE when connection was established.
* Returns true when connection was established.
* @return bool
*/
final public function isConnected()
@@ -189,9 +188,9 @@ class Connection
* @param mixed default value to use if key not found
* @return mixed
*/
final public function getConfig($key = NULL, $default = NULL)
final public function getConfig($key = null, $default = null)
{
if ($key === NULL) {
if ($key === null) {
return $this->config;
} elseif (isset($this->config[$key])) {
@@ -204,7 +203,7 @@ class Connection
/** @deprecated */
public static function alias(& $config, $key, $alias)
public static function alias(&$config, $key, $alias)
{
trigger_error(__METHOD__ . '() is deprecated, use Helpers::alias().', E_USER_DEPRECATED);
Helpers::alias($config, $key, $alias);
@@ -217,7 +216,9 @@ class Connection
*/
final public function getDriver()
{
$this->connected || $this->connect();
if (!$this->connected) {
$this->connect();
}
return $this->driver;
}
@@ -225,7 +226,7 @@ class Connection
/**
* Generates (translates) and executes SQL query.
* @param array|mixed one or more arguments
* @return Result|int result set object (if any)
* @return Result|int result set or number of affected rows
* @throws Exception
*/
final public function query($args)
@@ -258,7 +259,7 @@ class Connection
$args = func_get_args();
try {
Helpers::dump($this->translateArgs($args));
return TRUE;
return true;
} catch (Exception $e) {
if ($e->getSql()) {
@@ -266,7 +267,7 @@ class Connection
} else {
echo get_class($e) . ': ' . $e->getMessage() . (PHP_SAPI === 'cli' ? "\n" : '<br>');
}
return FALSE;
return false;
}
}
@@ -291,7 +292,9 @@ class Connection
*/
protected function translateArgs($args)
{
$this->connected || $this->connect();
if (!$this->connected) {
$this->connect();
}
if (!$this->translator) {
$this->translator = new Translator($this);
}
@@ -303,20 +306,24 @@ class Connection
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Result|int result set object (if any)
* @return Result|int result set or number of affected rows
* @throws Exception
*/
final public function nativeQuery($sql)
{
$this->connected || $this->connect();
if (!$this->connected) {
$this->connect();
}
\dibi::$sql = $sql;
$event = $this->onEvent ? new Event($this, Event::QUERY, $sql) : NULL;
$event = $this->onEvent ? new Event($this, Event::QUERY, $sql) : null;
try {
$res = $this->driver->query($sql);
} catch (Exception $e) {
$event && $this->onEvent($event->done($e));
if ($event) {
$this->onEvent($event->done($e));
}
throw $e;
}
@@ -326,7 +333,9 @@ class Connection
$res = $this->driver->getAffectedRows();
}
$event && $this->onEvent($event->done($res));
if ($event) {
$this->onEvent($event->done($res));
}
return $res;
}
@@ -338,7 +347,9 @@ class Connection
*/
public function getAffectedRows()
{
$this->connected || $this->connect();
if (!$this->connected) {
$this->connect();
}
$rows = $this->driver->getAffectedRows();
if (!is_int($rows) || $rows < 0) {
throw new Exception('Cannot retrieve number of affected rows.');
@@ -348,12 +359,11 @@ class Connection
/**
* Gets the number of affected rows. Alias for getAffectedRows().
* @return int number of rows
* @throws Exception
* @deprecated
*/
public function affectedRows()
{
trigger_error(__METHOD__ . '() is deprecated, use getAffectedRows()', E_USER_DEPRECATED);
return $this->getAffectedRows();
}
@@ -364,25 +374,25 @@ class Connection
* @return int
* @throws Exception
*/
public function getInsertId($sequence = NULL)
public function getInsertId($sequence = null)
{
$this->connected || $this->connect();
if (!$this->connected) {
$this->connect();
}
$id = $this->driver->getInsertId($sequence);
if ($id < 1) {
throw new Exception('Cannot retrieve last generated ID.');
}
return (int) $id;
return Helpers::intVal($id);
}
/**
* Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
* @param string optional sequence name
* @return int
* @throws Exception
* @deprecated
*/
public function insertId($sequence = NULL)
public function insertId($sequence = null)
{
trigger_error(__METHOD__ . '() is deprecated, use getInsertId()', E_USER_DEPRECATED);
return $this->getInsertId($sequence);
}
@@ -392,16 +402,22 @@ class Connection
* @param string optional savepoint name
* @return void
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->connected || $this->connect();
$event = $this->onEvent ? new Event($this, Event::BEGIN, $savepoint) : NULL;
if (!$this->connected) {
$this->connect();
}
$event = $this->onEvent ? new Event($this, Event::BEGIN, $savepoint) : null;
try {
$this->driver->begin($savepoint);
$event && $this->onEvent($event->done());
if ($event) {
$this->onEvent($event->done());
}
} catch (Exception $e) {
$event && $this->onEvent($event->done($e));
if ($event) {
$this->onEvent($event->done($e));
}
throw $e;
}
}
@@ -412,16 +428,22 @@ class Connection
* @param string optional savepoint name
* @return void
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
$this->connected || $this->connect();
$event = $this->onEvent ? new Event($this, Event::COMMIT, $savepoint) : NULL;
if (!$this->connected) {
$this->connect();
}
$event = $this->onEvent ? new Event($this, Event::COMMIT, $savepoint) : null;
try {
$this->driver->commit($savepoint);
$event && $this->onEvent($event->done());
if ($event) {
$this->onEvent($event->done());
}
} catch (Exception $e) {
$event && $this->onEvent($event->done($e));
if ($event) {
$this->onEvent($event->done($e));
}
throw $e;
}
}
@@ -432,16 +454,22 @@ class Connection
* @param string optional savepoint name
* @return void
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
$this->connected || $this->connect();
$event = $this->onEvent ? new Event($this, Event::ROLLBACK, $savepoint) : NULL;
if (!$this->connected) {
$this->connect();
}
$event = $this->onEvent ? new Event($this, Event::ROLLBACK, $savepoint) : null;
try {
$this->driver->rollback($savepoint);
$event && $this->onEvent($event->done());
if ($event) {
$this->onEvent($event->done());
}
} catch (Exception $e) {
$event && $this->onEvent($event->done($e));
if ($event) {
$this->onEvent($event->done($e));
}
throw $e;
}
}
@@ -473,7 +501,7 @@ class Connection
/**
* @param string column name
* @param mixed column name
* @return Fluent
*/
public function select($args)
@@ -543,7 +571,7 @@ class Connection
*/
public function substitute($value)
{
return strpos($value, ':') === FALSE
return strpos($value, ':') === false
? $value
: preg_replace_callback('#:([^:\s]*):#', function ($m) { return $this->substitutes->{$m[1]}; }, $value);
}
@@ -555,7 +583,7 @@ class Connection
/**
* Executes SQL query and fetch result - shortcut for query() & fetch().
* @param array|mixed one or more arguments
* @return Row|bool
* @return Row|false
* @throws Exception
*/
public function fetch($args)
@@ -568,7 +596,7 @@ class Connection
/**
* Executes SQL query and fetch results - shortcut for query() & fetchAll().
* @param array|mixed one or more arguments
* @return Row[]
* @return Row[]|array[]
* @throws Exception
*/
public function fetchAll($args)
@@ -581,7 +609,7 @@ class Connection
/**
* Executes SQL query and fetch first column - shortcut for query() & fetchSingle().
* @param array|mixed one or more arguments
* @return string|bool
* @return mixed
* @throws Exception
*/
public function fetchSingle($args)
@@ -619,11 +647,12 @@ class Connection
/**
* Import SQL dump from file.
* @param string filename
* @param callable function (int $count, ?float $percent): void
* @return int count of sql commands
*/
public function loadFile($file)
public function loadFile($file, callable $onProgress = null)
{
return Helpers::loadFromFile($this, $file);
return Helpers::loadFromFile($this, $file, $onProgress);
}
@@ -633,8 +662,10 @@ class Connection
*/
public function getDatabaseInfo()
{
$this->connected || $this->connect();
return new Reflection\Database($this->driver->getReflector(), isset($this->config['database']) ? $this->config['database'] : NULL);
if (!$this->connected) {
$this->connect();
}
return new Reflection\Database($this->driver->getReflector(), isset($this->config['database']) ? $this->config['database'] : null);
}
@@ -662,5 +693,4 @@ class Connection
call_user_func($handler, $arg);
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -9,8 +9,7 @@ namespace Dibi;
/**
* Default implementation of IDataSource for dibi.
*
* Default implementation of IDataSource.
*/
class DataSource implements IDataSource
{
@@ -22,13 +21,13 @@ class DataSource implements IDataSource
/** @var string */
private $sql;
/** @var Result */
/** @var Result|null */
private $result;
/** @var int */
/** @var int|null */
private $count;
/** @var int */
/** @var int|null */
private $totalCount;
/** @var array */
@@ -40,10 +39,10 @@ class DataSource implements IDataSource
/** @var array */
private $conds = [];
/** @var int */
/** @var int|null */
private $offset;
/** @var int */
/** @var int|null */
private $limit;
@@ -53,7 +52,7 @@ class DataSource implements IDataSource
*/
public function __construct($sql, Connection $connection)
{
if (strpbrk($sql, " \t\r\n") === FALSE) {
if (strpbrk($sql, " \t\r\n") === false) {
$this->sql = $connection->getDriver()->escapeIdentifier($sql); // table name
} else {
$this->sql = '(' . $sql . ') t'; // SQL command
@@ -68,14 +67,14 @@ class DataSource implements IDataSource
* @param string column alias
* @return self
*/
public function select($col, $as = NULL)
public function select($col, $as = null)
{
if (is_array($col)) {
$this->cols = $col;
} else {
$this->cols[$col] = $as;
}
$this->result = NULL;
$this->result = null;
return $this;
}
@@ -93,7 +92,7 @@ class DataSource implements IDataSource
} else {
$this->conds[] = func_get_args();
}
$this->result = $this->count = NULL;
$this->result = $this->count = null;
return $this;
}
@@ -111,28 +110,27 @@ class DataSource implements IDataSource
} else {
$this->sorting[$row] = $sorting;
}
$this->result = NULL;
$this->result = null;
return $this;
}
/**
* Limits number of rows.
* @param int limit
* @param int|null limit
* @param int offset
* @return self
*/
public function applyLimit($limit, $offset = NULL)
public function applyLimit($limit, $offset = null)
{
$this->limit = $limit;
$this->offset = $offset;
$this->result = $this->count = NULL;
$this->result = $this->count = null;
return $this;
}
/**
* Returns the dibi connection.
* @return Connection
*/
final public function getConnection()
@@ -150,7 +148,7 @@ class DataSource implements IDataSource
*/
public function getResult()
{
if ($this->result === NULL) {
if ($this->result === null) {
$this->result = $this->connection->nativeQuery($this->__toString());
}
return $this->result;
@@ -168,7 +166,7 @@ class DataSource implements IDataSource
/**
* Generates, executes SQL query and fetches the single row.
* @return Row|FALSE array on success, FALSE if no next record
* @return Row|false
*/
public function fetch()
{
@@ -178,7 +176,7 @@ class DataSource 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
*/
public function fetchSingle()
{
@@ -213,7 +211,7 @@ class DataSource implements IDataSource
* @param string value
* @return array
*/
public function fetchPairs($key = NULL, $value = NULL)
public function fetchPairs($key = null, $value = null)
{
return $this->getResult()->fetchPairs($key, $value);
}
@@ -225,7 +223,7 @@ class DataSource implements IDataSource
*/
public function release()
{
$this->result = $this->count = $this->totalCount = NULL;
$this->result = $this->count = $this->totalCount = null;
}
@@ -262,12 +260,13 @@ class DataSource implements IDataSource
return $this->connection->translate('
SELECT %n', (empty($this->cols) ? '*' : $this->cols), '
FROM %SQL', $this->sql, '
%ex', $this->conds ? ['WHERE %and', $this->conds] : NULL, '
%ex', $this->sorting ? ['ORDER BY %by', $this->sorting] : NULL, '
%ex', $this->conds ? ['WHERE %and', $this->conds] : null, '
%ex', $this->sorting ? ['ORDER BY %by', $this->sorting] : null, '
%ofs %lmt', $this->offset, $this->limit
);
} catch (\Exception $e) {
trigger_error($e->getMessage(), E_USER_ERROR);
return '';
}
}
@@ -281,11 +280,11 @@ FROM %SQL', $this->sql, '
*/
public function count()
{
if ($this->count === NULL) {
if ($this->count === null) {
$this->count = $this->conds || $this->offset || $this->limit
? (int) $this->connection->nativeQuery(
? Helpers::intVal($this->connection->nativeQuery(
'SELECT COUNT(*) FROM (' . $this->__toString() . ') t'
)->fetchSingle()
)->fetchSingle())
: $this->getTotalCount();
}
return $this->count;
@@ -298,12 +297,11 @@ FROM %SQL', $this->sql, '
*/
public function getTotalCount()
{
if ($this->totalCount === NULL) {
$this->totalCount = (int) $this->connection->nativeQuery(
if ($this->totalCount === null) {
$this->totalCount = Helpers::intVal($this->connection->nativeQuery(
'SELECT COUNT(*) FROM ' . $this->sql
)->fetchSingle();
)->fetchSingle());
}
return $this->totalCount;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -15,12 +15,15 @@ class DateTime extends \DateTime
{
use Strict;
public function __construct($time = 'now', \DateTimeZone $timezone = NULL)
/**
* @param string|int
*/
public function __construct($time = 'now', \DateTimeZone $timezone = null)
{
if (is_numeric($time)) {
parent::__construct('@' . $time);
$this->setTimeZone($timezone ? $timezone : new \DateTimeZone(date_default_timezone_get()));
} elseif ($timezone === NULL) {
$this->setTimeZone($timezone ?: new \DateTimeZone(date_default_timezone_get()));
} elseif ($timezone === null) {
parent::__construct($time);
} else {
parent::__construct($time, $timezone);
@@ -30,7 +33,7 @@ class DateTime extends \DateTime
public function modifyClone($modify = '')
{
$dolly = clone($this);
$dolly = clone $this;
return $modify ? $dolly->modify($modify) : $dolly;
}
@@ -52,7 +55,7 @@ class DateTime extends \DateTime
public function __toString()
{
return $this->format('Y-m-d H:i:s');
return $this->format('Y-m-d H:i:s.u');
}
@@ -68,5 +71,4 @@ class DateTime extends \DateTime
parent::__wakeup();
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver for Firebird/InterBase database.
* The driver for Firebird/InterBase database.
*
* Driver options:
* - database => the path to database file (server:/path/database.fdb)
@@ -20,7 +20,6 @@ use Dibi;
* - charset => character encoding to set
* - buffers (int) => buffers is the number of database buffers to allocate for the server-side cache. If 0 or omitted, server chooses its own default.
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
*/
class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
@@ -28,20 +27,20 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
const ERROR_EXCEPTION_THROWN = -836;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var resource Resultset resource */
/** @var resource|null */
private $transaction;
/** @var bool */
private $inTransaction = FALSE;
private $inTransaction = false;
/**
@@ -60,7 +59,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
Dibi\Helpers::alias($config, 'database', 'db');
@@ -103,7 +102,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException|Dibi\Exception
*/
public function query($sql)
@@ -111,7 +110,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
$resource = $this->inTransaction ? $this->transaction : $this->connection;
$res = ibase_query($resource, $sql);
if ($res === FALSE) {
if ($res === false) {
if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
preg_match('/exception (\d+) (\w+) (.*)/i', ibase_errmsg(), $match);
throw new Dibi\ProcedureException($match[3], $match[1], $match[2], $sql);
@@ -123,12 +122,13 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
} elseif (is_resource($res)) {
return $this->createResultDriver($res);
}
return null;
}
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -139,7 +139,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @param string generator name
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -153,13 +153,13 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
if ($savepoint !== NULL) {
if ($savepoint !== null) {
throw new Dibi\NotSupportedException('Savepoints are not supported in Firebird/Interbase.');
}
$this->transaction = ibase_trans($this->getResource());
$this->inTransaction = TRUE;
$this->inTransaction = true;
}
@@ -169,9 +169,9 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
if ($savepoint !== NULL) {
if ($savepoint !== null) {
throw new Dibi\NotSupportedException('Savepoints are not supported in Firebird/Interbase.');
}
@@ -179,7 +179,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
throw new Dibi\DriverException('Unable to handle operation - failure when commiting transaction.');
}
$this->inTransaction = FALSE;
$this->inTransaction = false;
}
@@ -189,9 +189,9 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
if ($savepoint !== NULL) {
if ($savepoint !== null) {
throw new Dibi\NotSupportedException('Savepoints are not supported in Firebird/Interbase.');
}
@@ -199,7 +199,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
throw new Dibi\DriverException('Unable to handle operation - failure when rolbacking transaction.');
}
$this->inTransaction = FALSE;
$this->inTransaction = false;
}
@@ -215,11 +215,11 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Returns the connection resource.
* @return resource
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -260,24 +260,40 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "'" . str_replace("'", "''", $value) . "'";
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
return '"' . str_replace('"', '""', $value). '"';
return '"' . str_replace('"', '""', $value) . '"';
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -287,12 +303,16 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("'Y-m-d H:i:s'");
return "'" . substr($value->format('Y-m-d H:i:s.u'), 0, -2) . "'";
}
@@ -329,13 +349,18 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit > 0 || $offset > 0) {
// http://www.firebirdsql.org/refdocs/langrefupd20-select.html
$sql = 'SELECT ' . ($limit > 0 ? 'FIRST ' . (int) $limit : '') . ($offset > 0 ? ' SKIP ' . (int) $offset : '') . ' * FROM (' . $sql . ')';
$sql = 'SELECT ' . ($limit > 0 ? 'FIRST ' . Dibi\Helpers::intVal($limit) : '')
. ($offset > 0 ? ' SKIP ' . Dibi\Helpers::intVal($offset) : '')
. ' * FROM (' . $sql . ')';
}
}
@@ -349,7 +374,9 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && $this->free();
if ($this->autoFree && $this->getResultResource()) {
$this->free();
}
}
@@ -365,7 +392,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -389,7 +416,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
* @throws Dibi\Exception
*/
public function seek($row)
@@ -405,18 +432,18 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
public function free()
{
ibase_free_result($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
/**
* Returns the result set resource.
* @return resource
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
@@ -457,7 +484,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
WHERE RDB\$SYSTEM_FLAG = 0;"
);
$tables = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$tables[] = [
'name' => $row[0],
'view' => $row[1] === 'TRUE',
@@ -506,7 +533,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
);
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$key = $row['FIELD_NAME'];
$columns[$key] = [
'name' => $key,
@@ -515,7 +542,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
'size' => $row['FIELD_LENGTH'],
'nullable' => $row['NULLABLE'] === 'TRUE',
'default' => $row['DEFAULT_VALUE'],
'autoincrement' => FALSE,
'autoincrement' => false,
];
}
return $columns;
@@ -544,7 +571,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
ORDER BY s.RDB\$FIELD_POSITION"
);
$indexes = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$key = $row['INDEX_NAME'];
$indexes[$key]['name'] = $key;
$indexes[$key]['unique'] = $row['UNIQUE_FLAG'] === 1;
@@ -574,7 +601,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
ORDER BY s.RDB\$FIELD_POSITION"
);
$keys = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$key = $row['INDEX_NAME'];
$keys[$key] = [
'name' => $key,
@@ -601,7 +628,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
AND RDB\$FOREIGN_KEY IS NULL;"
);
$indices = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$indices[] = $row[0];
}
return $indices;
@@ -625,7 +652,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
);"
);
$constraints = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$constraints[] = $row[0];
}
return $constraints;
@@ -639,7 +666,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @param string
* @return array
*/
public function getTriggersMeta($table = NULL)
public function getTriggersMeta($table = null)
{
$res = $this->query("
SELECT TRIM(RDB\$TRIGGER_NAME) AS TRIGGER_NAME,
@@ -665,10 +692,10 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
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 = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$triggers[$row['TRIGGER_NAME']] = [
'name' => $row['TRIGGER_NAME'],
'table' => $row['TABLE_NAME'],
@@ -687,16 +714,16 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @param string
* @return array
*/
public function getTriggers($table = NULL)
public function getTriggers($table = null)
{
$q = "SELECT TRIM(RDB\$TRIGGER_NAME)
FROM RDB\$TRIGGERS
WHERE RDB\$SYSTEM_FLAG = 0";
$q .= $table === NULL ? ';' : " AND RDB\$RELATION_NAME = UPPER('$table')";
$q = 'SELECT TRIM(RDB$TRIGGER_NAME)
FROM RDB$TRIGGERS
WHERE RDB$SYSTEM_FLAG = 0';
$q .= $table === null ? ';' : " AND RDB\$RELATION_NAME = UPPER('$table')";
$res = $this->query($q);
$triggers = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$triggers[] = $row[0];
}
return $triggers;
@@ -743,7 +770,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
ORDER BY p.RDB\$PARAMETER_TYPE, p.RDB\$PARAMETER_NUMBER;"
);
$procedures = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$key = $row['PROCEDURE_NAME'];
$io = trim($row['PARAMETER_TYPE']);
$num = $row['PARAMETER_NUMBER'];
@@ -762,12 +789,12 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function getProcedures()
{
$res = $this->query("
SELECT TRIM(RDB\$PROCEDURE_NAME)
FROM RDB\$PROCEDURES;"
$res = $this->query('
SELECT TRIM(RDB$PROCEDURE_NAME)
FROM RDB$PROCEDURES;'
);
$procedures = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$procedures[] = $row[0];
}
return $procedures;
@@ -780,13 +807,13 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function getGenerators()
{
$res = $this->query("
SELECT TRIM(RDB\$GENERATOR_NAME)
FROM RDB\$GENERATORS
WHERE RDB\$SYSTEM_FLAG = 0;"
$res = $this->query('
SELECT TRIM(RDB$GENERATOR_NAME)
FROM RDB$GENERATORS
WHERE RDB$SYSTEM_FLAG = 0;'
);
$generators = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$generators[] = $row[0];
}
return $generators;
@@ -799,16 +826,15 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function getFunctions()
{
$res = $this->query("
SELECT TRIM(RDB\$FUNCTION_NAME)
FROM RDB\$FUNCTIONS
WHERE RDB\$SYSTEM_FLAG = 0;"
$res = $this->query('
SELECT TRIM(RDB$FUNCTION_NAME)
FROM RDB$FUNCTIONS
WHERE RDB$SYSTEM_FLAG = 0;'
);
$functions = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$functions[] = $row[0];
}
return $functions;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver for MS SQL database.
* The driver for MS SQL database.
*
* Driver options:
* - host => the MS SQL server host name. It can also include a port number (hostname:port)
@@ -26,14 +26,14 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
{
use Dibi\Strict;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/**
@@ -52,12 +52,12 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
if (isset($config['resource'])) {
$this->connection = $config['resource'];
} elseif (empty($config['persistent'])) {
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], TRUE); // intentionally @
$this->connection = @mssql_connect($config['host'], $config['username'], $config['password'], true); // intentionally @
} else {
$this->connection = @mssql_pconnect($config['host'], $config['username'], $config['password']); // intentionally @
}
@@ -85,25 +85,26 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
$res = @mssql_query($sql, $this->connection); // intentionally @
if ($res === FALSE) {
if ($res === false) {
throw new Dibi\DriverException(mssql_get_last_message(), 0, $sql);
} elseif (is_resource($res)) {
return $this->createResultDriver($res);
}
return null;
}
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -113,7 +114,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -122,7 +123,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
$row = mssql_fetch_row($res);
return $row[0];
}
return FALSE;
return false;
}
@@ -132,7 +133,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->query('BEGIN TRANSACTION');
}
@@ -144,7 +145,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
$this->query('COMMIT');
}
@@ -156,7 +157,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
$this->query('ROLLBACK');
}
@@ -164,11 +165,11 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the connection resource.
* @return mixed
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -200,7 +201,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -209,12 +210,20 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "'" . str_replace("'", "''", $value) . "'";
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
@@ -222,12 +231,20 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -237,12 +254,16 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("'Y-m-d H:i:s'");
return 'CONVERT(DATETIME2(7), ' . $value->format("'Y-m-d H:i:s.u'") . ')';
}
@@ -280,9 +301,12 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($offset) {
throw new Dibi\NotSupportedException('Offset is not supported by this database.');
@@ -290,8 +314,8 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
} elseif ($limit < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
} elseif ($limit !== NULL) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
} elseif ($limit !== null) {
$sql = 'SELECT TOP ' . Dibi\Helpers::intVal($limit) . ' * FROM (' . $sql . ') t';
}
}
@@ -305,7 +329,9 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && $this->free();
if ($this->autoFree && $this->getResultResource()) {
$this->free();
}
}
@@ -321,7 +347,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -333,7 +359,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* 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
*/
public function seek($row)
{
@@ -348,7 +374,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
public function free()
{
mssql_free_result($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -375,12 +401,11 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the result set resource.
* @return mixed
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi reflector for MS SQL databases.
* The reflector for MS SQL databases.
* @internal
*/
class MsSqlReflector implements Dibi\Reflector
@@ -39,7 +39,7 @@ class MsSqlReflector implements Dibi\Reflector
FROM INFORMATION_SCHEMA.TABLES
');
$tables = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$tables[] = [
'name' => $row[0],
'view' => isset($row[1]) && $row[1] === 'VIEW',
@@ -54,27 +54,27 @@ class MsSqlReflector implements Dibi\Reflector
* @param string
* @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)
FROM sys.sysindexes
WHERE id=OBJECT_ID({$this->driver->escapeIdentifier($table)})
");
$row = $result->fetch(FALSE);
$row = $result->fetch(false);
if (!is_array($row) || count($row) < 1) {
if ($fallback) {
$row = $this->driver->query("SELECT COUNT(*) FROM {$this->driver->escapeIdentifier($table)}")->fetch(FALSE);
$count = intval($row[0]);
$row = $this->driver->query("SELECT COUNT(*) FROM {$this->driver->escapeIdentifier($table)}")->fetch(false);
$count = Dibi\Helpers::intVal($row[0]);
} else {
$count = FALSE;
$count = false;
}
} else {
$count = intval($row[0]);
$count = Dibi\Helpers::intVal($row[0]);
}
return $count;
@@ -95,11 +95,8 @@ class MsSqlReflector implements Dibi\Reflector
ORDER BY TABLE_NAME, ORDINAL_POSITION
");
$columns = [];
while ($row = $res->fetch(TRUE)) {
$size = FALSE;
$type = strtoupper($row['DATA_TYPE']);
$size_cols = [
while ($row = $res->fetch(true)) {
static $size_cols = [
'DATETIME' => 'DATETIME_PRECISION',
'DECIMAL' => 'NUMERIC_PRECISION',
'CHAR' => 'CHARACTER_MAXIMUM_LENGTH',
@@ -108,21 +105,17 @@ class MsSqlReflector implements Dibi\Reflector
'VARCHAR' => 'CHARACTER_OCTET_LENGTH',
];
if (isset($size_cols[$type])) {
if ($size_cols[$type]) {
$size = $row[$size_cols[$type]];
}
}
$type = strtoupper($row['DATA_TYPE']);
$columns[] = [
'name' => $row['COLUMN_NAME'],
'table' => $table,
'nativetype' => $type,
'size' => $size,
'unsigned' => NULL,
'size' => isset($size_cols[$type], $row[$size_cols[$type]]) ? $row[$size_cols[$type]] : null,
'unsigned' => null,
'nullable' => $row['IS_NULLABLE'] === 'YES',
'default' => $row['COLUMN_DEFAULT'],
'autoincrement' => FALSE,
'autoincrement' => false,
'vendor' => $row,
];
}
@@ -155,7 +148,7 @@ class MsSqlReflector implements Dibi\Reflector
");
$indexes = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$index_name = $row['index_name'];
if (!isset($indexes[$index_name])) {
@@ -195,7 +188,7 @@ class MsSqlReflector implements Dibi\Reflector
");
$keys = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$key_name = $row['foreign_key'];
if (!isset($keys[$key_name])) {
@@ -203,8 +196,8 @@ class MsSqlReflector implements Dibi\Reflector
$keys[$key_name]['local'] = [$row['column_name']]; // local columns
$keys[$key_name]['table'] = $row['reference_table_name']; // referenced table
$keys[$key_name]['foreign'] = [$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
@@ -212,5 +205,4 @@ class MsSqlReflector implements Dibi\Reflector
}
return array_values($keys);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver for MySQL database.
* The driver for MySQL database.
*
* Driver options:
* - host => the MySQL server host name
@@ -33,17 +33,19 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
use Dibi\Strict;
const ERROR_ACCESS_DENIED = 1045;
const ERROR_DUPLICATE_ENTRY = 1062;
const ERROR_DATA_TRUNCATED = 1265;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var bool Is buffered (seekable and countable)? */
private $buffered;
@@ -65,7 +67,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
if (isset($config['resource'])) {
$this->connection = $config['resource'];
@@ -88,7 +90,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
if (!isset($config['socket'])) {
$config['socket'] = ini_get('mysql.default_socket');
}
$config['host'] = NULL;
$config['host'] = null;
}
}
@@ -99,7 +101,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
if (empty($config['persistent'])) {
$this->connection = @mysql_connect($host, $config['username'], $config['password'], TRUE, $config['flags']); // intentionally @
$this->connection = @mysql_connect($host, $config['username'], $config['password'], true, $config['flags']); // intentionally @
} else {
$this->connection = @mysql_pconnect($host, $config['username'], $config['password'], $config['flags']); // intentionally @
}
@@ -146,7 +148,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
@@ -187,7 +189,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -197,7 +199,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -211,7 +213,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
}
@@ -223,7 +225,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
}
@@ -235,7 +237,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
}
@@ -243,11 +245,11 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the connection resource.
* @return mixed
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -279,7 +281,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -291,6 +293,10 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
if (!is_resource($this->connection)) {
@@ -300,6 +306,10 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
// @see http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
@@ -307,12 +317,20 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -322,12 +340,16 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("'Y-m-d H:i:s'");
return $value->format("'Y-m-d H:i:s.u'");
}
@@ -365,17 +387,20 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
} elseif ($limit !== NULL || $offset) {
} elseif ($limit !== null || $offset) {
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
$sql .= ' LIMIT ' . ($limit === NULL ? '18446744073709551615' : (int) $limit)
. ($offset ? ' OFFSET ' . (int) $offset : '');
$sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : Dibi\Helpers::intVal($limit))
. ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : '');
}
}
@@ -408,7 +433,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -420,7 +445,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
* @throws Dibi\Exception
*/
public function seek($row)
@@ -440,7 +465,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
public function free()
{
mysql_free_result($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -459,7 +484,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
'table' => $row['table'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'nativetype' => strtoupper($row['type']),
'type' => $row['type'] === 'time' ? Dibi\Type::TIME_INTERVAL : NULL,
'type' => $row['type'] === 'time' ? Dibi\Type::TIME_INTERVAL : null,
'vendor' => $row,
];
}
@@ -469,12 +494,11 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the result set resource.
* @return mixed
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi reflector for MySQL databases.
* The reflector for MySQL databases.
* @internal
*/
class MySqlReflector implements Dibi\Reflector
@@ -36,7 +36,7 @@ class MySqlReflector implements Dibi\Reflector
{
$res = $this->driver->query('SHOW FULL TABLES');
$tables = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$tables[] = [
'name' => $row[0],
'view' => isset($row[1]) && $row[1] === 'VIEW',
@@ -55,13 +55,13 @@ class MySqlReflector implements Dibi\Reflector
{
$res = $this->driver->query("SHOW FULL COLUMNS FROM {$this->driver->escapeIdentifier($table)}");
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$type = explode('(', $row['Type']);
$columns[] = [
'name' => $row['Field'],
'table' => $table,
'nativetype' => strtoupper($type[0]),
'size' => isset($type[1]) ? (int) $type[1] : NULL,
'size' => isset($type[1]) ? (int) $type[1] : null,
'unsigned' => (bool) strstr($row['Type'], 'unsigned'),
'nullable' => $row['Null'] === 'YES',
'default' => $row['Default'],
@@ -82,7 +82,7 @@ class MySqlReflector implements Dibi\Reflector
{
$res = $this->driver->query("SHOW INDEX FROM {$this->driver->escapeIdentifier($table)}");
$indexes = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$indexes[$row['Key_name']]['name'] = $row['Key_name'];
$indexes[$row['Key_name']]['unique'] = !$row['Non_unique'];
$indexes[$row['Key_name']]['primary'] = $row['Key_name'] === 'PRIMARY';
@@ -100,7 +100,7 @@ class MySqlReflector implements Dibi\Reflector
*/
public function getForeignKeys($table)
{
$data = $this->driver->query("SELECT `ENGINE` FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = {$this->driver->escapeText($table)}")->fetch(TRUE);
$data = $this->driver->query("SELECT `ENGINE` FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = {$this->driver->escapeText($table)}")->fetch(true);
if ($data['ENGINE'] !== 'InnoDB') {
throw new Dibi\NotSupportedException("Foreign keys are not supported in {$data['ENGINE']} tables.");
}
@@ -119,7 +119,7 @@ class MySqlReflector implements Dibi\Reflector
");
$foreignKeys = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$keyName = $row['CONSTRAINT_NAME'];
$foreignKeys[$keyName]['name'] = $keyName;
@@ -131,5 +131,4 @@ class MySqlReflector implements Dibi\Reflector
}
return array_values($foreignKeys);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver for MySQL database via improved extension.
* The driver for MySQL database.
*
* Driver options:
* - host => the MySQL server host name
@@ -27,24 +27,25 @@ use Dibi;
* - unbuffered (bool) => sends query without fetching and buffering the result rows automatically?
* - sqlmode => see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
* - resource (mysqli) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
*/
class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
{
use Dibi\Strict;
const ERROR_ACCESS_DENIED = 1045;
const ERROR_DUPLICATE_ENTRY = 1062;
const ERROR_DATA_TRUNCATED = 1265;
/** @var mysqli Connection resource */
/** @var \mysqli|null */
private $connection;
/** @var mysqli_result Resultset resource */
/** @var \mysqli_result|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var bool Is buffered (seekable and countable)? */
private $buffered;
@@ -66,7 +67,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
mysqli_report(MYSQLI_REPORT_OFF);
if (isset($config['resource'])) {
@@ -80,7 +81,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
'username' => ini_get('mysqli.default_user'),
'password' => ini_get('mysqli.default_pw'),
'socket' => (string) ini_get('mysqli.default_socket'),
'port' => NULL,
'port' => null,
];
if (!isset($config['host'])) {
$host = ini_get('mysqli.default_host');
@@ -88,23 +89,18 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
$config['host'] = $host;
$config['port'] = ini_get('mysqli.default_port');
} else {
$config['host'] = NULL;
$config['port'] = NULL;
$config['host'] = null;
$config['port'] = null;
}
}
$foo = & $config['flags'];
$foo = & $config['database'];
$foo = &$config['flags'];
$foo = &$config['database'];
$this->connection = mysqli_init();
if (isset($config['options'])) {
if (is_scalar($config['options'])) {
$config['flags'] = $config['options']; // back compatibility
trigger_error(__CLASS__ . ": configuration item 'options' must be array; for constants MYSQLI_CLIENT_* use 'flags'.", E_USER_NOTICE);
} else {
foreach ((array) $config['options'] as $key => $value) {
mysqli_options($this->connection, $key, $value);
}
foreach ($config['options'] as $key => $value) {
mysqli_options($this->connection, $key, $value);
}
}
@mysqli_real_connect($this->connection, (empty($config['persistent']) ? '' : 'p:') . $config['host'], $config['username'], $config['password'], $config['database'], $config['port'], $config['socket'], $config['flags']); // intentionally @
@@ -145,7 +141,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
@@ -153,11 +149,12 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
$res = @mysqli_query($this->connection, $sql, $this->buffered ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); // intentionally @
if ($code = mysqli_errno($this->connection)) {
throw self::createException(mysqli_error($this->connection), $code, $sql);
throw static::createException(mysqli_error($this->connection), $code, $sql);
} elseif (is_object($res)) {
return $this->createResultDriver($res);
}
return null;
}
@@ -166,13 +163,13 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
*/
public static function createException($message, $code, $sql)
{
if (in_array($code, [1216, 1217, 1451, 1452, 1701], TRUE)) {
if (in_array($code, [1216, 1217, 1451, 1452, 1701], true)) {
return new Dibi\ForeignKeyConstraintViolationException($message, $code, $sql);
} elseif (in_array($code, [1062, 1557, 1569, 1586], TRUE)) {
} elseif (in_array($code, [1062, 1557, 1569, 1586], true)) {
return new Dibi\UniqueConstraintViolationException($message, $code, $sql);
} elseif (in_array($code, [1048, 1121, 1138, 1171, 1252, 1263, 1566], TRUE)) {
} elseif (in_array($code, [1048, 1121, 1138, 1171, 1252, 1263, 1566], true)) {
return new Dibi\NotNullConstraintViolationException($message, $code, $sql);
} else {
@@ -202,17 +199,17 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
return mysqli_affected_rows($this->connection) === -1 ? FALSE : mysqli_affected_rows($this->connection);
return mysqli_affected_rows($this->connection) === -1 ? false : mysqli_affected_rows($this->connection);
}
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -226,7 +223,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
}
@@ -238,7 +235,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
}
@@ -250,7 +247,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
}
@@ -258,11 +255,11 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the connection resource.
* @return mysqli
* @return \mysqli|null
*/
public function getResource()
{
return @$this->connection->thread_id ? $this->connection : NULL;
return @$this->connection->thread_id ? $this->connection : null;
}
@@ -278,7 +275,6 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Result set driver factory.
* @param mysqli_result
* @return Dibi\ResultDriver
*/
public function createResultDriver(\mysqli_result $resource)
@@ -294,7 +290,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -303,24 +299,40 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "_binary'" . mysqli_real_escape_string($this->connection, $value) . "'";
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
return '`' . str_replace('`', '``', $value) . '`';
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -330,12 +342,16 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("'Y-m-d H:i:s'");
return $value->format("'Y-m-d H:i:s.u'");
}
@@ -373,17 +389,20 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
} elseif ($limit !== NULL || $offset) {
} elseif ($limit !== null || $offset) {
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
$sql .= ' LIMIT ' . ($limit === NULL ? '18446744073709551615' : (int) $limit)
. ($offset ? ' OFFSET ' . (int) $offset : '');
$sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : Dibi\Helpers::intVal($limit))
. ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : '');
}
}
@@ -397,7 +416,9 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && @$this->free();
if ($this->autoFree && $this->getResultResource()) {
@$this->free();
}
}
@@ -416,7 +437,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -428,7 +449,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
* @throws Dibi\Exception
*/
public function seek($row)
@@ -447,7 +468,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
public function free()
{
mysqli_free_result($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -458,8 +479,8 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
public function getResultColumns()
{
static $types;
if ($types === NULL) {
$consts = get_defined_constants(TRUE);
if ($types === null) {
$consts = get_defined_constants(true);
$types = [];
foreach (isset($consts['mysqli']) ? $consts['mysqli'] : [] as $key => $value) {
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
@@ -478,7 +499,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
'table' => $row['orgtable'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'nativetype' => isset($types[$row['type']]) ? $types[$row['type']] : $row['type'],
'type' => $row['type'] === MYSQLI_TYPE_TIME ? Dibi\Type::TIME_INTERVAL : NULL,
'type' => $row['type'] === MYSQLI_TYPE_TIME ? Dibi\Type::TIME_INTERVAL : null,
'vendor' => $row,
];
}
@@ -488,12 +509,11 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the result set resource.
* @return mysqli_result
* @return \mysqli_result|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
$this->autoFree = false;
return $this->resultSet;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver interacting with databases via ODBC connections.
* The driver interacting with databases via ODBC connections.
*
* Driver options:
* - dsn => driver specific DSN
@@ -19,23 +19,26 @@ use Dibi;
* - password (or pass)
* - persistent (bool) => try to find a persistent link?
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
* - microseconds (bool) => use microseconds in datetime format?
*/
class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
use Dibi\Strict;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var int|FALSE Affected rows */
private $affectedRows = FALSE;
/** @var bool */
private $microseconds = true;
/** @var int|false Affected rows */
private $affectedRows = false;
/** @var int Cursor */
private $row = 0;
@@ -57,7 +60,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
if (isset($config['resource'])) {
$this->connection = $config['resource'];
@@ -79,6 +82,10 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
if (!is_resource($this->connection)) {
throw new Dibi\DriverException(odbc_errormsg() . ' ' . odbc_error());
}
if (isset($config['microseconds'])) {
$this->microseconds = (bool) $config['microseconds'];
}
}
@@ -95,27 +102,28 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
$this->affectedRows = FALSE;
$this->affectedRows = false;
$res = @odbc_exec($this->connection, $sql); // intentionally @
if ($res === FALSE) {
if ($res === false) {
throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection), 0, $sql);
} elseif (is_resource($res)) {
$this->affectedRows = odbc_num_rows($res);
return $this->createResultDriver($res);
return odbc_num_fields($res) ? $this->createResultDriver($res) : null;
}
return null;
}
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -125,7 +133,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -139,9 +147,9 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
if (!odbc_autocommit($this->connection, FALSE)) {
if (!odbc_autocommit($this->connection, false)) {
throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
}
}
@@ -153,12 +161,12 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
if (!odbc_commit($this->connection)) {
throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
}
odbc_autocommit($this->connection, TRUE);
odbc_autocommit($this->connection, true);
}
@@ -168,12 +176,12 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
if (!odbc_rollback($this->connection)) {
throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection));
}
odbc_autocommit($this->connection, TRUE);
odbc_autocommit($this->connection, true);
}
@@ -189,11 +197,11 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Returns the connection resource.
* @return mixed
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -225,7 +233,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -234,39 +242,59 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "'" . str_replace("'", "''", $value) . "'";
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
return '[' . str_replace(['[', ']'], ['[[', ']]'], $value) . ']';
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("#m/d/Y#");
return $value->format('#m/d/Y#');
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("#m/d/Y H:i:s#");
return $value->format($this->microseconds ? '#m/d/Y H:i:s.u#' : '#m/d/Y H:i:s#');
}
@@ -304,9 +332,12 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($offset) {
throw new Dibi\NotSupportedException('Offset is not supported by this database.');
@@ -314,8 +345,8 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
} elseif ($limit < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
} elseif ($limit !== NULL) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
} elseif ($limit !== null) {
$sql = 'SELECT TOP ' . Dibi\Helpers::intVal($limit) . ' * FROM (' . $sql . ') t';
}
}
@@ -329,7 +360,9 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && $this->free();
if ($this->autoFree && $this->getResultResource()) {
$this->free();
}
}
@@ -346,7 +379,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -356,7 +389,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
} else {
$set = $this->resultSet;
if (!odbc_fetch_row($set, ++$this->row)) {
return FALSE;
return false;
}
$count = odbc_num_fields($set);
$cols = [];
@@ -371,12 +404,12 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
*/
public function seek($row)
{
$this->row = $row;
return TRUE;
return true;
}
@@ -387,7 +420,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
public function free()
{
odbc_free_result($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -402,7 +435,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
for ($i = 1; $i <= $count; $i++) {
$columns[] = [
'name' => odbc_field_name($this->resultSet, $i),
'table' => NULL,
'table' => null,
'fullname' => odbc_field_name($this->resultSet, $i),
'nativetype' => odbc_field_type($this->resultSet, $i),
];
@@ -413,12 +446,12 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Returns the result set resource.
* @return mixed
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
@@ -492,5 +525,4 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
throw new Dibi\NotImplementedException;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver for Oracle database.
* The driver for Oracle database.
*
* Driver options:
* - database => the name of the local Oracle instance or the name of the entry in tnsnames.ora
@@ -19,33 +19,33 @@ use Dibi;
* - 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)
* - nativeDate => use native date format (defaults to false)
* - resource (resource) => existing connection resource
* - persistent => Creates persistent connections with oci_pconnect instead of oci_new_connect
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
*/
class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
use Dibi\Strict;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var bool */
private $autocommit = TRUE;
private $autocommit = true;
/** @var string Date and datetime format */
private $fmtDate, $fmtDateTime;
private $fmtDate;
/** @var int|FALSE Number of affected rows */
private $affectedRows = FALSE;
private $fmtDateTime;
/** @var int|false Number of affected rows */
private $affectedRows = false;
/**
@@ -64,11 +64,17 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
$foo = & $config['charset'];
$this->fmtDate = isset($config['formatDate']) ? $config['formatDate'] : 'U';
$this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U';
$foo = &$config['charset'];
if (isset($config['formatDate']) || isset($config['formatDateTime'])) {
trigger_error('OracleDriver: options formatDate and formatDateTime are deprecated.', E_USER_DEPRECATED);
}
if (empty($config['nativeDate'])) {
$this->fmtDate = isset($config['formatDate']) ? $config['formatDate'] : 'U';
$this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U';
}
if (isset($config['resource'])) {
$this->connection = $config['resource'];
@@ -102,27 +108,28 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
$this->affectedRows = FALSE;
$this->affectedRows = false;
$res = oci_parse($this->connection, $sql);
if ($res) {
@oci_execute($res, $this->autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
$err = oci_error($res);
if ($err) {
throw self::createException($err['message'], $err['code'], $sql);
throw static::createException($err['message'], $err['code'], $sql);
} elseif (is_resource($res)) {
$this->affectedRows = oci_num_rows($res);
return $this->createResultDriver($res);
return oci_num_fields($res) ? $this->createResultDriver($res) : null;
}
} else {
$err = oci_error($this->connection);
throw new Dibi\DriverException($err['message'], $err['code'], $sql);
}
return null;
}
@@ -131,13 +138,13 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public static function createException($message, $code, $sql)
{
if (in_array($code, [1, 2299, 38911], TRUE)) {
if (in_array($code, [1, 2299, 38911], true)) {
return new Dibi\UniqueConstraintViolationException($message, $code, $sql);
} elseif (in_array($code, [1400], TRUE)) {
} elseif (in_array($code, [1400], true)) {
return new Dibi\NotNullConstraintViolationException($message, $code, $sql);
} elseif (in_array($code, [2266, 2291, 2292], TRUE)) {
} elseif (in_array($code, [2266, 2291, 2292], true)) {
return new Dibi\ForeignKeyConstraintViolationException($message, $code, $sql);
} else {
@@ -148,7 +155,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -158,12 +165,12 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
$row = $this->query("SELECT $sequence.CURRVAL AS ID FROM DUAL")->fetch(TRUE);
return isset($row['ID']) ? (int) $row['ID'] : FALSE;
$row = $this->query("SELECT $sequence.CURRVAL AS ID FROM DUAL")->fetch(true);
return isset($row['ID']) ? Dibi\Helpers::intVal($row['ID']) : false;
}
@@ -172,9 +179,9 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @param string optional savepoint name
* @return void
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->autocommit = FALSE;
$this->autocommit = false;
}
@@ -184,13 +191,13 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
if (!oci_commit($this->connection)) {
$err = oci_error($this->connection);
throw new Dibi\DriverException($err['message'], $err['code']);
}
$this->autocommit = TRUE;
$this->autocommit = true;
}
@@ -200,23 +207,23 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
if (!oci_rollback($this->connection)) {
$err = oci_error($this->connection);
throw new Dibi\DriverException($err['message'], $err['code']);
}
$this->autocommit = TRUE;
$this->autocommit = true;
}
/**
* Returns the connection resource.
* @return mixed
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -248,7 +255,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -257,12 +264,20 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "'" . str_replace("'", "''", $value) . "'"; // TODO: not tested
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
// @see http://download.oracle.com/docs/cd/B10500_01/server.920/a96540/sql_elements9a.htm
@@ -270,27 +285,43 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format($this->fmtDate);
return $this->fmtDate
? $value->format($this->fmtDate)
: "to_date('" . $value->format('Y-m-d') . "', 'YYYY-mm-dd')";
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format($this->fmtDateTime);
return $this->fmtDateTime
? $value->format($this->fmtDateTime)
: "to_date('" . $value->format('Y-m-d G:i:s') . "', 'YYYY-mm-dd hh24:mi:ss')";
}
@@ -329,9 +360,12 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
@@ -339,11 +373,11 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
} elseif ($offset) {
// see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
$sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t '
. ($limit !== NULL ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '')
. ') WHERE "__rnum" > '. (int) $offset;
. ($limit !== null ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '')
. ') WHERE "__rnum" > ' . $offset;
} elseif ($limit !== NULL) {
$sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit;
} elseif ($limit !== null) {
$sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . Dibi\Helpers::intVal($limit);
}
}
@@ -357,7 +391,9 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && $this->free();
if ($this->autoFree && $this->getResultResource()) {
$this->free();
}
}
@@ -373,7 +409,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -385,7 +421,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
*/
public function seek($row)
{
@@ -400,7 +436,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
public function free()
{
oci_free_statement($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -416,7 +452,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
$type = oci_field_type($this->resultSet, $i);
$columns[] = [
'name' => oci_field_name($this->resultSet, $i),
'table' => NULL,
'table' => null,
'fullname' => oci_field_name($this->resultSet, $i),
'nativetype' => $type === 'NUMBER' && oci_field_scale($this->resultSet, $i) === 0 ? 'INTEGER' : $type,
];
@@ -427,12 +463,12 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Returns the result set resource.
* @return mixed
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
@@ -447,7 +483,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
$res = $this->query('SELECT * FROM cat');
$tables = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
if ($row[1] === 'TABLE' || $row[1] === 'VIEW') {
$tables[] = [
'name' => $row[0],
@@ -468,12 +504,12 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
$res = $this->query('SELECT * FROM "ALL_TAB_COLUMNS" WHERE "TABLE_NAME" = ' . $this->escapeText($table));
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$columns[] = [
'table' => $row['TABLE_NAME'],
'name' => $row['COLUMN_NAME'],
'nativetype' => $row['DATA_TYPE'],
'size' => isset($row['DATA_LENGTH']) ? $row['DATA_LENGTH'] : NULL,
'size' => isset($row['DATA_LENGTH']) ? $row['DATA_LENGTH'] : null,
'nullable' => $row['NULLABLE'] === 'Y',
'default' => $row['DATA_DEFAULT'],
'vendor' => $row,
@@ -503,5 +539,4 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
throw new Dibi\NotImplementedException;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -12,7 +12,7 @@ use PDO;
/**
* The dibi driver for PDO.
* The driver for PDO.
*
* Driver options:
* - dsn => driver specific DSN
@@ -21,26 +21,25 @@ use PDO;
* - options (array) => driver specific options {@see PDO::__construct}
* - resource (PDO) => existing connection
* - version
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
*/
class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
{
use Dibi\Strict;
/** @var PDO Connection resource */
/** @var PDO|null Connection resource */
private $connection;
/** @var \PDOStatement Resultset resource */
/** @var \PDOStatement|null Resultset resource */
private $resultSet;
/** @var int|FALSE Affected rows */
private $affectedRows = FALSE;
/** @var int|false Affected rows */
private $affectedRows = false;
/** @var string */
private $driverName;
/** @var string */
private $serverVersion;
private $serverVersion = '';
/**
@@ -59,10 +58,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
$foo = & $config['dsn'];
$foo = & $config['options'];
$foo = &$config['dsn'];
$foo = &$config['options'];
Dibi\Helpers::alias($config, 'resource', 'pdo');
if ($config['resource'] instanceof PDO) {
@@ -79,6 +78,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
}
}
if ($this->connection->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_SILENT) {
throw new Dibi\DriverException('PDO connection in exception or warning error mode is not supported.');
}
$this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);
$this->serverVersion = isset($config['version'])
? $config['version']
@@ -92,35 +95,26 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
*/
public function disconnect()
{
$this->connection = NULL;
$this->connection = null;
}
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
// must detect if SQL returns result set or num of affected rows
$cmd = strtoupper(substr(ltrim($sql), 0, 6));
static $list = ['UPDATE' => 1, 'DELETE' => 1, 'INSERT' => 1, 'REPLAC' => 1];
$this->affectedRows = FALSE;
if (isset($list[$cmd])) {
$this->affectedRows = $this->connection->exec($sql);
if ($this->affectedRows !== FALSE) {
return;
}
} else {
$res = $this->connection->query($sql);
if ($res) {
return $this->createResultDriver($res);
}
$res = $this->connection->query($sql);
if ($res) {
$this->affectedRows = $res->rowCount();
return $res->columnCount() ? $this->createResultDriver($res) : null;
}
$this->affectedRows = false;
list($sqlState, $code, $message) = $this->connection->errorInfo();
$message = "SQLSTATE[$sqlState]: $message";
switch ($this->driverName) {
@@ -144,7 +138,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -154,11 +148,11 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
return $this->connection->lastInsertId();
return $this->connection->lastInsertId($sequence);
}
@@ -168,7 +162,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
if (!$this->connection->beginTransaction()) {
$err = $this->connection->errorInfo();
@@ -183,7 +177,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
if (!$this->connection->commit()) {
$err = $this->connection->errorInfo();
@@ -198,7 +192,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
if (!$this->connection->rollBack()) {
$err = $this->connection->errorInfo();
@@ -209,7 +203,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the connection resource.
* @return PDO
* @return PDO|null
*/
public function getResource()
{
@@ -254,7 +248,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -267,6 +261,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
if ($this->driverName === 'odbc') {
@@ -277,6 +275,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
switch ($this->driverName) {
@@ -304,16 +306,24 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
if ($this->driverName === 'pgsql') {
return $value ? 'TRUE' : 'FALSE';
} else {
return $value ? 1 : 0;
return $value ? '1' : '0';
}
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -323,12 +333,24 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format($this->driverName === 'odbc' ? "#m/d/Y H:i:s#" : "'Y-m-d H:i:s'");
switch ($this->driverName) {
case 'odbc':
return $value->format('#m/d/Y H:i:s.u#');
case 'mssql':
case 'sqlsrv':
return 'CONVERT(DATETIME2(7), ' . $value->format("'Y-m-d H:i:s.u'") . ')';
default:
return $value->format("'Y-m-d H:i:s.u'");
}
}
@@ -394,9 +416,12 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
@@ -404,26 +429,26 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
switch ($this->driverName) {
case 'mysql':
if ($limit !== NULL || $offset) {
if ($limit !== null || $offset) {
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
$sql .= ' LIMIT ' . ($limit === NULL ? '18446744073709551615' : (int) $limit)
. ($offset ? ' OFFSET ' . (int) $offset : '');
$sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : Dibi\Helpers::intVal($limit))
. ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : '');
}
break;
case 'pgsql':
if ($limit !== NULL) {
$sql .= ' LIMIT ' . (int) $limit;
if ($limit !== null) {
$sql .= ' LIMIT ' . Dibi\Helpers::intVal($limit);
}
if ($offset) {
$sql .= ' OFFSET ' . (int) $offset;
$sql .= ' OFFSET ' . Dibi\Helpers::intVal($offset);
}
break;
case 'sqlite':
if ($limit !== NULL || $offset) {
$sql .= ' LIMIT ' . ($limit === NULL ? '-1' : (int) $limit)
. ($offset ? ' OFFSET ' . (int) $offset : '');
if ($limit !== null || $offset) {
$sql .= ' LIMIT ' . ($limit === null ? '-1' : Dibi\Helpers::intVal($limit))
. ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : '');
}
break;
@@ -431,11 +456,11 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
if ($offset) {
// see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
$sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t '
. ($limit !== NULL ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '')
. ') WHERE "__rnum" > '. (int) $offset;
. ($limit !== null ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '')
. ') WHERE "__rnum" > ' . $offset;
} elseif ($limit !== NULL) {
$sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit;
} elseif ($limit !== null) {
$sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . Dibi\Helpers::intVal($limit);
}
break;
@@ -444,25 +469,23 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
case 'dblib':
if (version_compare($this->serverVersion, '11.0') >= 0) { // 11 == SQL Server 2012
// requires ORDER BY, see https://technet.microsoft.com/en-us/library/gg699618(v=sql.110).aspx
if ($limit !== NULL) {
if ($limit !== null) {
$sql = sprintf('%s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY', rtrim($sql), $offset, $limit);
} elseif ($offset) {
$sql = sprintf('%s OFFSET %d ROWS', rtrim($sql), $offset);
}
break;
}
// intentionally break omitted
// break omitted
case 'odbc':
if ($offset) {
throw new Dibi\NotSupportedException('Offset is not supported by this database.');
} elseif ($limit !== NULL) {
$sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t';
} elseif ($limit !== null) {
$sql = 'SELECT TOP ' . Dibi\Helpers::intVal($limit) . ' * FROM (' . $sql . ') t';
break;
}
// intentionally break omitted
// break omitted
default:
throw new Dibi\NotSupportedException('PDO or driver does not support applying limit or offset.');
}
@@ -484,7 +507,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -496,7 +519,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
*/
public function seek($row)
{
@@ -510,7 +533,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
*/
public function free()
{
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -525,11 +548,11 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
$columns = [];
for ($i = 0; $i < $count; $i++) {
$row = @$this->resultSet->getColumnMeta($i); // intentionally @
if ($row === FALSE) {
if ($row === false) {
throw new Dibi\NotSupportedException('Driver does not support meta data.');
}
$row = $row + [
'table' => NULL,
'table' => null,
'native_type' => 'VAR_STRING',
];
@@ -537,7 +560,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
'name' => $row['name'],
'table' => $row['table'],
'nativetype' => $row['native_type'],
'type' => $row['native_type'] === 'TIME' && $this->driverName === 'mysql' ? Dibi\Type::TIME_INTERVAL : NULL,
'type' => $row['native_type'] === 'TIME' && $this->driverName === 'mysql' ? Dibi\Type::TIME_INTERVAL : null,
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'vendor' => $row,
];
@@ -548,11 +571,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the result set resource.
* @return \PDOStatement
* @return \PDOStatement|null
*/
public function getResultResource()
{
return $this->resultSet;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi driver for PostgreSQL database.
* The driver for PostgreSQL database.
*
* Driver options:
* - host, hostaddr, port, dbname, user, password, connect_timeout, options, sslmode, service => see PostgreSQL API
@@ -20,23 +20,22 @@ use Dibi;
* - charset => character encoding to set (default is utf8)
* - persistent (bool) => try to find a persistent link?
* - resource (resource) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
*/
class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
{
use Dibi\Strict;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var int|FALSE Affected rows */
private $affectedRows = FALSE;
/** @var int|false Affected rows */
private $affectedRows = false;
/**
@@ -55,9 +54,9 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
$error = NULL;
$error = null;
if (isset($config['resource'])) {
$this->connection = $config['resource'];
@@ -78,7 +77,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
}
set_error_handler(function($severity, $message) use (& $error) {
set_error_handler(function ($severity, $message) use (&$error) {
$error = $message;
});
if (empty($config['persistent'])) {
@@ -96,7 +95,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
pg_set_error_verbosity($this->connection, PGSQL_ERRORS_VERBOSE);
if (isset($config['charset']) && pg_set_client_encoding($this->connection, $config['charset'])) {
throw self::createException(pg_last_error($this->connection));
throw static::createException(pg_last_error($this->connection));
}
if (isset($config['schema'])) {
@@ -128,16 +127,16 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
$this->affectedRows = FALSE;
$this->affectedRows = false;
$res = @pg_query($this->connection, $sql); // intentionally @
if ($res === FALSE) {
throw self::createException(pg_last_error($this->connection), NULL, $sql);
if ($res === false) {
throw static::createException(pg_last_error($this->connection), null, $sql);
} elseif (is_resource($res)) {
$this->affectedRows = pg_affected_rows($res);
@@ -145,20 +144,21 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
return $this->createResultDriver($res);
}
}
return null;
}
/**
* @return Dibi\DriverException
*/
public static function createException($message, $code = NULL, $sql = NULL)
public static function createException($message, $code = null, $sql = null)
{
if ($code === NULL && preg_match('#^ERROR:\s+(\S+):\s*#', $message, $m)) {
if ($code === null && preg_match('#^ERROR:\s+(\S+):\s*#', $message, $m)) {
$code = $m[1];
$message = substr($message, strlen($m[0]));
}
if ($code === '0A000' && strpos($message, 'truncate') !== FALSE) {
if ($code === '0A000' && strpos($message, 'truncate') !== false) {
return new Dibi\ForeignKeyConstraintViolationException($message, $code, $sql);
} elseif ($code === '23502') {
@@ -178,7 +178,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -188,11 +188,11 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
if ($sequence === NULL) {
if ($sequence === null) {
// PostgreSQL 8.1 is needed
$res = $this->query('SELECT LASTVAL()');
} else {
@@ -200,11 +200,11 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
if (!$res) {
return FALSE;
return false;
}
$row = $res->fetch(FALSE);
return is_array($row) ? $row[0] : FALSE;
$row = $res->fetch(false);
return is_array($row) ? $row[0] : false;
}
@@ -214,7 +214,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
}
@@ -226,7 +226,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
}
@@ -238,7 +238,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
}
@@ -250,17 +250,17 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function inTransaction()
{
return !in_array(pg_transaction_status($this->connection), [PGSQL_TRANSACTION_UNKNOWN, PGSQL_TRANSACTION_IDLE], TRUE);
return !in_array(pg_transaction_status($this->connection), [PGSQL_TRANSACTION_UNKNOWN, PGSQL_TRANSACTION_IDLE], true);
}
/**
* Returns the connection resource.
* @return mixed
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -292,7 +292,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -304,6 +304,10 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
if (!is_resource($this->connection)) {
@@ -313,6 +317,10 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
// @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
@@ -320,12 +328,20 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 'TRUE' : 'FALSE';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -335,12 +351,16 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("'Y-m-d H:i:s'");
return $value->format("'Y-m-d H:i:s.u'");
}
@@ -380,18 +400,21 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
}
if ($limit !== NULL) {
$sql .= ' LIMIT ' . (int) $limit;
if ($limit !== null) {
$sql .= ' LIMIT ' . Dibi\Helpers::intVal($limit);
}
if ($offset) {
$sql .= ' OFFSET ' . (int) $offset;
$sql .= ' OFFSET ' . Dibi\Helpers::intVal($offset);
}
}
@@ -405,7 +428,9 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && $this->free();
if ($this->autoFree && $this->getResultResource()) {
$this->free();
}
}
@@ -421,19 +446,19 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
{
return pg_fetch_array($this->resultSet, NULL, $assoc ? PGSQL_ASSOC : PGSQL_NUM);
return pg_fetch_array($this->resultSet, null, $assoc ? PGSQL_ASSOC : PGSQL_NUM);
}
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
*/
public function seek($row)
{
@@ -448,7 +473,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
public function free()
{
pg_free_result($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -475,12 +500,12 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
/**
* Returns the result set resource.
* @return mixed
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
@@ -523,7 +548,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
$res = $this->query($query);
$tables = pg_fetch_all($res->resultSet);
return $tables ? $tables : [];
return $tables ?: [];
}
@@ -577,13 +602,13 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
}
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$size = (int) max($row['character_maximum_length'], $row['numeric_precision']);
$columns[] = [
'name' => $row['column_name'],
'table' => $table,
'nativetype' => strtoupper($row['udt_name']),
'size' => $size > 0 ? $size : NULL,
'size' => $size > 0 ? $size : null,
'nullable' => $row['is_nullable'] === 'YES' || $row['is_nullable'] === 't',
'default' => $row['column_default'],
'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'], 0, 7) === 'nextval',
@@ -617,7 +642,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
");
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$columns[$row['ordinal_position']] = $row['column_name'];
}
@@ -630,7 +655,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
");
$indexes = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$indexes[$row['relname']]['name'] = $row['relname'];
$indexes[$row['relname']]['unique'] = $row['indisunique'] === 't';
$indexes[$row['relname']]['primary'] = $row['indisprimary'] === 't';
@@ -691,7 +716,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
");
$fKeys = $references = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
if (!isset($fKeys[$row['name']])) {
$fKeys[$row['name']] = [
'name' => $row['name'],
@@ -716,5 +741,4 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
return $fKeys;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -12,7 +12,7 @@ use SQLite3;
/**
* The dibi driver for SQLite3 database.
* The driver for SQLite3 database.
*
* Driver options:
* - database (or file) => the filename of the SQLite3 database
@@ -21,26 +21,30 @@ use SQLite3;
* - dbcharset => database character encoding (will be converted to 'charset')
* - charset => character encoding to set (default is UTF-8)
* - resource (SQLite3) => existing connection resource
* - lazy, profiler, result, substitutes, ... => see Dibi\Connection options
*/
class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
{
use Dibi\Strict;
/** @var SQLite3 Connection resource */
/** @var SQLite3|null */
private $connection;
/** @var \SQLite3Result Resultset resource */
/** @var \SQLite3Result|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var string Date and datetime format */
private $fmtDate, $fmtDateTime;
/** @var string Date format */
private $fmtDate;
/** @var string Datetime format */
private $fmtDateTime;
/** @var string character encoding */
private $dbcharset, $charset;
private $dbcharset;
private $charset;
/**
@@ -59,7 +63,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
Dibi\Helpers::alias($config, 'database', 'file');
$this->fmtDate = isset($config['formatDate']) ? $config['formatDate'] : 'U';
@@ -78,7 +82,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
$this->dbcharset = empty($config['dbcharset']) ? 'UTF-8' : $config['dbcharset'];
$this->charset = empty($config['charset']) ? 'UTF-8' : $config['charset'];
if (strcasecmp($this->dbcharset, $this->charset) === 0) {
$this->dbcharset = $this->charset = NULL;
$this->dbcharset = $this->charset = null;
}
// enable foreign keys support (defaultly disabled; if disabled then foreign key constraints are not enforced)
@@ -102,22 +106,23 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
if ($this->dbcharset !== NULL) {
if ($this->dbcharset !== null) {
$sql = iconv($this->charset, $this->dbcharset . '//IGNORE', $sql);
}
$res = @$this->connection->query($sql); // intentionally @
if ($code = $this->connection->lastErrorCode()) {
throw self::createException($this->connection->lastErrorMsg(), $code, $sql);
throw static::createException($this->connection->lastErrorMsg(), $code, $sql);
} elseif ($res instanceof \SQLite3Result) {
} elseif ($res instanceof \SQLite3Result && $res->numColumns()) {
return $this->createResultDriver($res);
}
return null;
}
@@ -129,19 +134,19 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
if ($code !== 19) {
return new Dibi\DriverException($message, $code, $sql);
} elseif (strpos($message, 'must be unique') !== FALSE
|| strpos($message, 'is not unique') !== FALSE
|| strpos($message, 'UNIQUE constraint failed') !== FALSE
} elseif (strpos($message, 'must be unique') !== false
|| strpos($message, 'is not unique') !== false
|| strpos($message, 'UNIQUE constraint failed') !== false
) {
return new Dibi\UniqueConstraintViolationException($message, $code, $sql);
} elseif (strpos($message, 'may not be NULL') !== FALSE
|| strpos($message, 'NOT NULL constraint failed') !== FALSE
} elseif (strpos($message, 'may not be NULL') !== false
|| strpos($message, 'NOT NULL constraint failed') !== false
) {
return new Dibi\NotNullConstraintViolationException($message, $code, $sql);
} elseif (strpos($message, 'foreign key constraint failed') !== FALSE
|| strpos($message, 'FOREIGN KEY constraint failed') !== FALSE
} elseif (strpos($message, 'foreign key constraint failed') !== false
|| strpos($message, 'FOREIGN KEY constraint failed') !== false
) {
return new Dibi\ForeignKeyConstraintViolationException($message, $code, $sql);
@@ -153,7 +158,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -163,7 +168,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -177,7 +182,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
$this->query($savepoint ? "SAVEPOINT $savepoint" : 'BEGIN');
}
@@ -189,7 +194,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
$this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
}
@@ -201,7 +206,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
$this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
}
@@ -209,7 +214,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the connection resource.
* @return mixed
* @return SQLite3|null
*/
public function getResource()
{
@@ -245,7 +250,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -254,24 +259,40 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "X'" . bin2hex((string) $value) . "'";
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
return '[' . strtr($value, '[]', ' ') . ']';
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -281,6 +302,10 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -324,16 +349,19 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
} elseif ($limit !== NULL || $offset) {
$sql .= ' LIMIT ' . ($limit === NULL ? '-1' : (int) $limit)
. ($offset ? ' OFFSET ' . (int) $offset : '');
} elseif ($limit !== null || $offset) {
$sql .= ' LIMIT ' . ($limit === null ? '-1' : Dibi\Helpers::intVal($limit))
. ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : '');
}
}
@@ -347,7 +375,9 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
*/
public function __destruct()
{
$this->autoFree && $this->resultSet && @$this->free();
if ($this->autoFree && $this->getResultResource()) {
@$this->free();
}
}
@@ -364,22 +394,19 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
{
$row = $this->resultSet->fetchArray($assoc ? SQLITE3_ASSOC : SQLITE3_NUM);
$charset = $this->charset === NULL ? NULL : $this->charset . '//TRANSLIT';
if ($row && ($assoc || $charset)) {
$tmp = [];
$charset = $this->charset === null ? null : $this->charset . '//TRANSLIT';
if ($row && $charset) {
foreach ($row as $k => $v) {
if ($charset !== NULL && is_string($v)) {
$v = iconv($this->dbcharset, $charset, $v);
if (is_string($v)) {
$row[$k] = iconv($this->dbcharset, $charset, $v);
}
$tmp[str_replace(['[', ']'], '', $k)] = $v;
}
return $tmp;
}
return $row;
}
@@ -388,7 +415,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
* @throws Dibi\NotSupportedException
*/
public function seek($row)
@@ -404,7 +431,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
public function free()
{
$this->resultSet->finalize();
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -420,7 +447,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
for ($i = 0; $i < $count; $i++) {
$columns[] = [
'name' => $this->resultSet->columnName($i),
'table' => NULL,
'table' => null,
'fullname' => $this->resultSet->columnName($i),
'nativetype' => $types[$this->resultSet->columnType($i)],
];
@@ -431,11 +458,11 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the result set resource.
* @return mixed
* @return \SQLite3Result|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
$this->autoFree = false;
return $this->resultSet;
}
@@ -468,5 +495,4 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
{
$this->connection->createAggregate($name, $rowCallback, $agrCallback, $numArgs);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi reflector for SQLite database.
* The reflector for SQLite database.
* @internal
*/
class SqliteReflector implements Dibi\Reflector
@@ -41,7 +41,7 @@ class SqliteReflector implements Dibi\Reflector
ORDER BY name
");
$tables = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$tables[] = $row;
}
return $tables;
@@ -57,7 +57,7 @@ class SqliteReflector implements Dibi\Reflector
{
$res = $this->driver->query("PRAGMA table_info({$this->driver->escapeIdentifier($table)})");
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$column = $row['name'];
$type = explode('(', $row['type']);
$columns[] = [
@@ -65,7 +65,7 @@ class SqliteReflector implements Dibi\Reflector
'table' => $table,
'fullname' => "$table.$column",
'nativetype' => strtoupper($type[0]),
'size' => isset($type[1]) ? (int) $type[1] : NULL,
'size' => isset($type[1]) ? (int) $type[1] : null,
'nullable' => $row['notnull'] == '0',
'default' => $row['dflt_value'],
'autoincrement' => $row['pk'] && $type[0] === 'INTEGER',
@@ -85,14 +85,14 @@ class SqliteReflector implements Dibi\Reflector
{
$res = $this->driver->query("PRAGMA index_list({$this->driver->escapeIdentifier($table)})");
$indexes = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$indexes[$row['name']]['name'] = $row['name'];
$indexes[$row['name']]['unique'] = (bool) $row['unique'];
}
foreach ($indexes as $index => $values) {
$res = $this->driver->query("PRAGMA index_info({$this->driver->escapeIdentifier($index)})");
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$indexes[$index]['columns'][$row['seqno']] = $row['name'];
}
}
@@ -100,7 +100,7 @@ class SqliteReflector implements Dibi\Reflector
$columns = $this->getColumns($table);
foreach ($indexes as $index => $values) {
$column = $indexes[$index]['columns'][0];
$primary = FALSE;
$primary = false;
foreach ($columns as $info) {
if ($column == $info['name']) {
$primary = $info['vendor']['pk'];
@@ -114,8 +114,8 @@ class SqliteReflector implements Dibi\Reflector
if ($column['vendor']['pk']) {
$indexes[] = [
'name' => 'ROWID',
'unique' => TRUE,
'primary' => TRUE,
'unique' => true,
'primary' => true,
'columns' => [$column['name']],
];
break;
@@ -136,7 +136,7 @@ class SqliteReflector implements Dibi\Reflector
{
$res = $this->driver->query("PRAGMA foreign_key_list({$this->driver->escapeIdentifier($table)})");
$keys = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$keys[$row['id']]['name'] = $row['id']; // foreign key name
$keys[$row['id']]['local'][$row['seq']] = $row['from']; // local columns
$keys[$row['id']]['table'] = $row['table']; // referenced table
@@ -144,11 +144,10 @@ class SqliteReflector implements Dibi\Reflector
$keys[$row['id']]['onDelete'] = $row['on_delete'];
$keys[$row['id']]['onUpdate'] = $row['on_update'];
if ($keys[$row['id']]['foreign'][0] == NULL) {
$keys[$row['id']]['foreign'] = NULL;
if ($keys[$row['id']]['foreign'][0] == null) {
$keys[$row['id']]['foreign'] = null;
}
}
return array_values($keys);
}
}

View File

@@ -1,19 +1,18 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi\Drivers;
use Dibi;
use Dibi\Connection;
use Dibi\Helpers;
/**
* The dibi driver for Microsoft SQL Server and SQL Azure databases.
* The driver for Microsoft SQL Server and SQL Azure databases.
*
* Driver options:
* - host => the MS SQL server host name. It can also include a port number (hostname:port)
@@ -23,26 +22,25 @@ use Dibi\Helpers;
* - 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 Dibi\Connection options
*/
class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
{
use Dibi\Strict;
/** @var resource Connection resource */
/** @var resource|null */
private $connection;
/** @var resource Resultset resource */
/** @var resource|null */
private $resultSet;
/** @var bool */
private $autoFree = TRUE;
private $autoFree = true;
/** @var int|FALSE Affected rows */
private $affectedRows = FALSE;
/** @var int|false Affected rows */
private $affectedRows = false;
/** @var string */
private $version;
private $version = '';
/**
@@ -61,7 +59,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\Exception
*/
public function connect(array & $config)
public function connect(array &$config)
{
Helpers::alias($config, 'options|UID', 'username');
Helpers::alias($config, 'options|PWD', 'password');
@@ -106,28 +104,29 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Executes the SQL query.
* @param string SQL statement.
* @return Dibi\ResultDriver|NULL
* @return Dibi\ResultDriver|null
* @throws Dibi\DriverException
*/
public function query($sql)
{
$this->affectedRows = FALSE;
$this->affectedRows = false;
$res = sqlsrv_query($this->connection, $sql);
if ($res === FALSE) {
if ($res === false) {
$info = sqlsrv_errors();
throw new Dibi\DriverException($info[0]['message'], $info[0]['code'], $sql);
} elseif (is_resource($res)) {
$this->affectedRows = sqlsrv_rows_affected($res);
return $this->createResultDriver($res);
return sqlsrv_num_fields($res) ? $this->createResultDriver($res) : null;
}
return null;
}
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
public function getAffectedRows()
{
@@ -137,7 +136,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
public function getInsertId($sequence)
{
@@ -146,7 +145,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
$row = sqlsrv_fetch_array($res, SQLSRV_FETCH_NUMERIC);
return $row[0];
}
return FALSE;
return false;
}
@@ -156,7 +155,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function begin($savepoint = NULL)
public function begin($savepoint = null)
{
sqlsrv_begin_transaction($this->connection);
}
@@ -168,7 +167,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function commit($savepoint = NULL)
public function commit($savepoint = null)
{
sqlsrv_commit($this->connection);
}
@@ -180,7 +179,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
* @return void
* @throws Dibi\DriverException
*/
public function rollback($savepoint = NULL)
public function rollback($savepoint = null)
{
sqlsrv_rollback($this->connection);
}
@@ -188,11 +187,11 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the connection resource.
* @return mixed
* @return resource|null
*/
public function getResource()
{
return is_resource($this->connection) ? $this->connection : NULL;
return is_resource($this->connection) ? $this->connection : null;
}
@@ -224,7 +223,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
public function escapeText($value)
@@ -233,12 +232,20 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param string
* @return string
*/
public function escapeBinary($value)
{
return "'" . str_replace("'", "''", $value) . "'";
}
/**
* @param string
* @return string
*/
public function escapeIdentifier($value)
{
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
@@ -246,12 +253,20 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param bool
* @return string
*/
public function escapeBool($value)
{
return $value ? 1 : 0;
return $value ? '1' : '0';
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDate($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
@@ -261,12 +276,16 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
}
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
public function escapeDateTime($value)
{
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
$value = new Dibi\DateTime($value);
}
return $value->format("'Y-m-d H:i:s'");
return 'CONVERT(DATETIME2(7), ' . $value->format("'Y-m-d H:i:s.u'") . ')';
}
@@ -304,22 +323,25 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
public function applyLimit(& $sql, $limit, $offset)
public function applyLimit(&$sql, $limit, $offset)
{
if ($limit < 0 || $offset < 0) {
throw new Dibi\NotSupportedException('Negative offset or limit.');
} elseif (version_compare($this->version, 11, '<')) { // 11 == SQL Server 2012
} elseif (version_compare($this->version, '11', '<')) { // 11 == SQL Server 2012
if ($offset) {
throw new Dibi\NotSupportedException('Offset is not supported by this database.');
} elseif ($limit !== NULL) {
} elseif ($limit !== null) {
$sql = sprintf('SELECT TOP (%d) * FROM (%s) t', $limit, $sql);
}
} elseif ($limit !== NULL) {
} elseif ($limit !== null) {
// requires ORDER BY, see https://technet.microsoft.com/en-us/library/gg699618(v=sql.110).aspx
$sql = sprintf('%s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY', rtrim($sql), $offset, $limit);
} elseif ($offset) {
@@ -338,7 +360,9 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
*/
public function __destruct()
{
$this->autoFree && $this->getResultResource() && $this->free();
if ($this->autoFree && $this->getResultResource()) {
$this->free();
}
}
@@ -354,7 +378,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
*/
public function fetch($assoc)
@@ -366,7 +390,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
*/
public function seek($row)
{
@@ -381,7 +405,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
public function free()
{
sqlsrv_free_stmt($this->resultSet);
$this->resultSet = NULL;
$this->resultSet = null;
}
@@ -405,12 +429,11 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
/**
* Returns the result set resource.
* @return mixed
* @return resource|null
*/
public function getResultResource()
{
$this->autoFree = FALSE;
return is_resource($this->resultSet) ? $this->resultSet : NULL;
$this->autoFree = false;
return is_resource($this->resultSet) ? $this->resultSet : null;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* The dibi reflector for Microsoft SQL Server and SQL Azure databases.
* The reflector for Microsoft SQL Server and SQL Azure databases.
* @internal
*/
class SqlsrvReflector implements Dibi\Reflector
@@ -36,7 +36,7 @@ class SqlsrvReflector implements Dibi\Reflector
{
$res = $this->driver->query("SELECT TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE [TABLE_SCHEMA] = 'dbo'");
$tables = [];
while ($row = $res->fetch(FALSE)) {
while ($row = $res->fetch(false)) {
$tables[] = [
'name' => $row[0],
'view' => isset($row[1]) && $row[1] === 'VIEW',
@@ -61,7 +61,7 @@ class SqlsrvReflector implements Dibi\Reflector
");
$autoIncrements = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$autoIncrements[$row['COLUMN_NAME']] = (bool) $row['AUTO_INCREMENT'];
}
@@ -81,13 +81,13 @@ class SqlsrvReflector implements Dibi\Reflector
WHERE C.TABLE_NAME = {$this->driver->escapeText($table)}
");
$columns = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$columns[] = [
'name' => $row['COLUMN_NAME'],
'table' => $table,
'nativetype' => strtoupper($row['DATA_TYPE']),
'size' => $row['CHARACTER_MAXIMUM_LENGTH'],
'unsigned' => TRUE,
'unsigned' => true,
'nullable' => $row['IS_NULLABLE'] === 'YES',
'default' => $row['COLUMN_DEFAULT'],
'autoincrement' => $autoIncrements[$row['COLUMN_NAME']],
@@ -105,15 +105,15 @@ class SqlsrvReflector implements Dibi\Reflector
*/
public function getIndexes($table)
{
$keyUsagesRes = $this->driver->query(sprintf("EXEC [sys].[sp_helpindex] @objname = N%s", $this->driver->escapeText($table)));
$keyUsagesRes = $this->driver->query(sprintf('EXEC [sys].[sp_helpindex] @objname = N%s', $this->driver->escapeText($table)));
$keyUsages = [];
while ($row = $keyUsagesRes->fetch(TRUE)) {
while ($row = $keyUsagesRes->fetch(true)) {
$keyUsages[$row['index_name']] = explode(',', $row['index_keys']);
}
$res = $this->driver->query("SELECT [i].* FROM [sys].[indexes] [i] INNER JOIN [sys].[tables] [t] ON [i].[object_id] = [t].[object_id] WHERE [t].[name] = {$this->driver->escapeText($table)}");
$indexes = [];
while ($row = $res->fetch(TRUE)) {
while ($row = $res->fetch(true)) {
$indexes[$row['name']]['name'] = $row['name'];
$indexes[$row['name']]['unique'] = $row['is_unique'] === 1;
$indexes[$row['name']]['primary'] = $row['is_primary_key'] === 1;
@@ -132,5 +132,4 @@ class SqlsrvReflector implements Dibi\Reflector
{
throw new Dibi\NotImplementedException;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -37,25 +37,25 @@ class Event
/** @var string */
public $sql;
/** @var Result|DriverException|NULL */
/** @var Result|DriverException|null */
public $result;
/** @var float */
public $time;
/** @var int */
/** @var int|null */
public $count;
/** @var array */
/** @var array|null */
public $source;
public function __construct(Connection $connection, $type, $sql = NULL)
public function __construct(Connection $connection, $type, $sql = null)
{
$this->connection = $connection;
$this->type = $type;
$this->sql = trim($sql);
$this->time = -microtime(TRUE);
$this->time = -microtime(true);
if ($type === self::QUERY && preg_match('#\(?\s*(SELECT|UPDATE|INSERT|DELETE)#iA', $this->sql, $matches)) {
static $types = [
@@ -67,32 +67,34 @@ class Event
$rc = new \ReflectionClass('dibi');
$dibiDir = dirname($rc->getFileName()) . DIRECTORY_SEPARATOR;
foreach (debug_backtrace(FALSE) as $row) {
foreach (debug_backtrace(false) as $row) {
if (isset($row['file']) && is_file($row['file']) && strpos($row['file'], $dibiDir) !== 0) {
$this->source = [$row['file'], (int) $row['line']];
break;
}
}
\dibi::$elapsedTime = FALSE;
\dibi::$elapsedTime = null;
\dibi::$numOfQueries++;
\dibi::$sql = $sql;
}
public function done($result = NULL)
/**
* @param Result|DriverException|null
*/
public function done($result = null)
{
$this->result = $result;
try {
$this->count = $result instanceof Result ? count($result) : NULL;
$this->count = $result instanceof Result ? count($result) : null;
} catch (Exception $e) {
$this->count = NULL;
$this->count = null;
}
$this->time += microtime(TRUE);
$this->time += microtime(true);
\dibi::$elapsedTime = $this->time;
\dibi::$totalTime += $this->time;
return $this;
}
}

32
src/Dibi/Expression.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
/**
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi;
/**
* SQL expression.
*/
class Expression
{
use Strict;
/** @var array */
private $values;
public function __construct()
{
$this->values = func_get_args();
}
public function getValues()
{
return $this->values;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -9,11 +9,11 @@ namespace Dibi;
/**
* dibi SQL builder via fluent interfaces. EXPERIMENTAL!
* SQL builder via fluent interfaces.
*
* @method Fluent select(...$field)
* @method Fluent distinct()
* @method Fluent from($table)
* @method Fluent from($table, ...$args = null)
* @method Fluent where(...$cond)
* @method Fluent groupBy(...$field)
* @method Fluent having(...$cond)
@@ -33,12 +33,12 @@ class Fluent implements IDataSource
{
use Strict;
const REMOVE = FALSE;
const REMOVE = false;
/** @var array */
public static $masks = [
'SELECT' => ['SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY',
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET'],
'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', ],
'UPDATE' => ['UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT'],
'INSERT' => ['INSERT', 'INTO', 'VALUES', 'SELECT'],
'DELETE' => ['DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT'],
@@ -65,11 +65,11 @@ class Fluent implements IDataSource
'GROUP BY' => ',',
'HAVING' => 'AND',
'ORDER BY' => ',',
'LIMIT' => FALSE,
'OFFSET' => FALSE,
'LIMIT' => false,
'OFFSET' => false,
'SET' => ',',
'VALUES' => ',',
'INTO' => FALSE,
'INTO' => false,
];
/** @var array clauses */
@@ -86,7 +86,7 @@ class Fluent implements IDataSource
/** @var array */
private $setups = [];
/** @var string */
/** @var string|null */
private $command;
/** @var array */
@@ -95,7 +95,7 @@ class Fluent implements IDataSource
/** @var array */
private $flags = [];
/** @var array */
/** @var array|null */
private $cursor;
/** @var HashMap normalized clauses */
@@ -109,7 +109,7 @@ class Fluent implements IDataSource
{
$this->connection = $connection;
if (self::$normalizer === NULL) {
if (self::$normalizer === null) {
self::$normalizer = new HashMap([__CLASS__, '_formatClause']);
}
}
@@ -126,33 +126,33 @@ class Fluent implements IDataSource
$clause = self::$normalizer->$clause;
// lazy initialization
if ($this->command === NULL) {
if ($this->command === null) {
if (isset(self::$masks[$clause])) {
$this->clauses = array_fill_keys(self::$masks[$clause], NULL);
$this->clauses = array_fill_keys(self::$masks[$clause], null);
}
$this->cursor = & $this->clauses[$clause];
$this->cursor = &$this->clauses[$clause];
$this->cursor = [];
$this->command = $clause;
}
// auto-switch to a clause
if (isset(self::$clauseSwitches[$clause])) {
$this->cursor = & $this->clauses[self::$clauseSwitches[$clause]];
$this->cursor = &$this->clauses[self::$clauseSwitches[$clause]];
}
if (array_key_exists($clause, $this->clauses)) {
// append to clause
$this->cursor = & $this->clauses[$clause];
$this->cursor = &$this->clauses[$clause];
// TODO: really delete?
if ($args === [self::REMOVE]) {
$this->cursor = NULL;
$this->cursor = null;
return $this;
}
if (isset(self::$separators[$clause])) {
$sep = self::$separators[$clause];
if ($sep === FALSE) { // means: replace
if ($sep === false) { // means: replace
$this->cursor = [];
} elseif (!empty($this->cursor)) {
@@ -169,15 +169,15 @@ class Fluent implements IDataSource
$this->cursor[] = $clause;
}
if ($this->cursor === NULL) {
if ($this->cursor === null) {
$this->cursor = [];
}
// special types or argument
if (count($args) === 1) {
$arg = $args[0];
// TODO: really ignore TRUE?
if ($arg === TRUE) { // flag
// TODO: really ignore true?
if ($arg === true) { // flag
return $this;
} elseif (is_string($arg) && preg_match('#^[a-z:_][a-z0-9_.:]*\z#i', $arg)) { // identifier
@@ -190,7 +190,7 @@ class Fluent implements IDataSource
} elseif (is_string(key($arg))) { // associative array
$args = ['%a', $arg];
}
} // case $arg === FALSE is handled above
} // case $arg === false is handled above
}
foreach ($args as $arg) {
@@ -211,8 +211,8 @@ class Fluent implements IDataSource
*/
public function clause($clause)
{
$this->cursor = & $this->clauses[self::$normalizer->$clause];
if ($this->cursor === NULL) {
$this->cursor = &$this->clauses[self::$normalizer->$clause];
if ($this->cursor === null) {
$this->cursor = [];
}
@@ -227,7 +227,7 @@ class Fluent implements IDataSource
*/
public function removeClause($clause)
{
$this->clauses[self::$normalizer->$clause] = NULL;
$this->clauses[self::$normalizer->$clause] = null;
return $this;
}
@@ -238,11 +238,11 @@ class Fluent implements IDataSource
* @param bool value
* @return self
*/
public function setFlag($flag, $value = TRUE)
public function setFlag($flag, $value = true)
{
$flag = strtoupper($flag);
if ($value) {
$this->flags[$flag] = TRUE;
$this->flags[$flag] = true;
} else {
unset($this->flags[$flag]);
}
@@ -272,7 +272,6 @@ class Fluent implements IDataSource
/**
* Returns the dibi connection.
* @return Connection
*/
final public function getConnection()
@@ -300,10 +299,10 @@ class Fluent implements IDataSource
/**
* Generates and executes SQL query.
* @param mixed what to return?
* @return Result|int result set object (if any)
* @return Result|int result set or number of affected rows
* @throws Exception
*/
public function execute($return = NULL)
public function execute($return = null)
{
$res = $this->query($this->_export());
switch ($return) {
@@ -319,12 +318,12 @@ class Fluent implements IDataSource
/**
* Generates, executes SQL query and fetches the single row.
* @return Row|FALSE array on success, FALSE if no next record
* @return Row|false
*/
public function fetch()
{
if ($this->command === 'SELECT' && !$this->clauses['LIMIT']) {
return $this->query($this->_export(NULL, ['%lmt', 1]))->fetch();
return $this->query($this->_export(null, ['%lmt', 1]))->fetch();
} else {
return $this->query($this->_export())->fetch();
}
@@ -333,12 +332,12 @@ class Fluent 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
*/
public function fetchSingle()
{
if ($this->command === 'SELECT' && !$this->clauses['LIMIT']) {
return $this->query($this->_export(NULL, ['%lmt', 1]))->fetchSingle();
return $this->query($this->_export(null, ['%lmt', 1]))->fetchSingle();
} else {
return $this->query($this->_export())->fetchSingle();
}
@@ -351,9 +350,9 @@ class Fluent implements IDataSource
* @param int limit
* @return array
*/
public function fetchAll($offset = NULL, $limit = NULL)
public function fetchAll($offset = null, $limit = null)
{
return $this->query($this->_export(NULL, ['%ofs %lmt', $offset, $limit]))->fetchAll();
return $this->query($this->_export(null, ['%ofs %lmt', $offset, $limit]))->fetchAll();
}
@@ -374,7 +373,7 @@ class Fluent implements IDataSource
* @param string value
* @return array
*/
public function fetchPairs($key = NULL, $value = NULL)
public function fetchPairs($key = null, $value = null)
{
return $this->query($this->_export())->fetchPairs($key, $value);
}
@@ -386,9 +385,9 @@ class Fluent implements IDataSource
* @param int limit
* @return ResultIterator
*/
public function getIterator($offset = NULL, $limit = NULL)
public function getIterator($offset = null, $limit = null)
{
return $this->query($this->_export(NULL, ['%ofs %lmt', $offset, $limit]))->getIterator();
return $this->query($this->_export(null, ['%ofs %lmt', $offset, $limit]))->getIterator();
}
@@ -397,7 +396,7 @@ class Fluent implements IDataSource
* @param string clause name
* @return bool
*/
public function test($clause = NULL)
public function test($clause = null)
{
return $this->connection->test($this->_export($clause));
}
@@ -408,14 +407,14 @@ class Fluent implements IDataSource
*/
public function count()
{
return (int) $this->query([
return Helpers::intVal($this->query([
'SELECT COUNT(*) FROM (%ex', $this->_export(), ') [data]',
])->fetchSingle();
])->fetchSingle());
}
/**
* @return Result
* @return Result|int
*/
private function query($args)
{
@@ -449,6 +448,7 @@ class Fluent implements IDataSource
return $this->connection->translate($this->_export());
} catch (\Exception $e) {
trigger_error($e->getMessage(), E_USER_ERROR);
return '';
}
}
@@ -458,9 +458,9 @@ class Fluent implements IDataSource
* @param string clause name
* @return array
*/
protected function _export($clause = NULL, $args = [])
protected function _export($clause = null, $args = [])
{
if ($clause === NULL) {
if ($clause === null) {
$data = $this->clauses;
if ($this->command === 'SELECT' && ($data['LIMIT'] || $data['OFFSET'])) {
$args = array_merge(['%lmt %ofs', $data['LIMIT'][0], $data['OFFSET'][0]], $args);
@@ -477,7 +477,7 @@ class Fluent implements IDataSource
}
foreach ($data as $clause => $statement) {
if ($statement !== NULL) {
if ($statement !== null) {
$args[] = $clause;
if ($clause === $this->command && $this->flags) {
$args[] = implode(' ', array_keys($this->flags));
@@ -512,10 +512,9 @@ class Fluent implements IDataSource
{
// remove references
foreach ($this->clauses as $clause => $val) {
$this->clauses[$clause] = & $val;
$this->clauses[$clause] = &$val;
unset($val);
}
$this->cursor = & $foo;
$this->cursor = &$foo;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -14,6 +14,7 @@ namespace Dibi;
*/
abstract class HashMapBase
{
/** @var callable */
private $callback;
@@ -33,21 +34,18 @@ abstract class HashMapBase
{
return $this->callback;
}
}
/**
* Lazy cached storage.
*
* @internal
*/
final class HashMap extends HashMapBase
{
public function __set($nm, $val)
{
if ($nm == '') {
if ($nm === '') {
$nm = "\xFF";
}
$this->$nm = $val;
@@ -56,12 +54,11 @@ final class HashMap extends HashMapBase
public function __get($nm)
{
if ($nm == '') {
if ($nm === '') {
$nm = "\xFF";
return isset($this->$nm) ? $this->$nm : $this->$nm = call_user_func($this->getCallback(), '');
} else {
return $this->$nm = call_user_func($this->getCallback(), $nm);
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -12,16 +12,17 @@ class Helpers
{
use Strict;
/** @var array */
/** @var HashMap */
private static $types;
/**
* Prints out a syntax highlighted version of the SQL command or Result.
* @param string|Result
* @param bool return output instead of printing it?
* @return string
*/
public static function dump($sql = NULL, $return = FALSE)
public static function dump($sql = null, $return = false)
{
ob_start();
if ($sql instanceof Result && PHP_SAPI === 'cli') {
@@ -38,7 +39,7 @@ class Helpers
echo $hasColors ? "\033[1;37m#row: $i\033[0m\n" : "#row: $i\n";
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";
}
@@ -50,14 +51,14 @@ class Helpers
if ($i === 0) {
echo "\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n";
foreach ($row as $col => $foo) {
echo "\t\t<th>" . htmlSpecialChars($col) . "</th>\n";
echo "\t\t<th>" . htmlspecialchars((string) $col) . "</th>\n";
}
echo "\t</tr>\n</thead>\n<tbody>\n";
}
echo "\t<tr>\n\t\t<th>", $i, "</th>\n";
foreach ($row as $col) {
echo "\t\t<td>", htmlSpecialChars($col), "</td>\n";
echo "\t\t<td>", htmlspecialchars((string) $col), "</td>\n";
}
echo "\t</tr>\n";
}
@@ -67,7 +68,7 @@ class Helpers
: "</tbody>\n</table>\n";
} else {
if ($sql === NULL) {
if ($sql === null) {
$sql = \dibi::$sql;
}
@@ -106,7 +107,7 @@ class Helpers
echo trim($sql) . "\n\n";
} else {
$sql = htmlSpecialChars($sql);
$sql = htmlspecialchars($sql);
$sql = preg_replace_callback($highlighter, function ($m) {
if (!empty($m[1])) { // comment
return '<em style="color:gray">' . $m[1] . '</em>';
@@ -135,12 +136,12 @@ class Helpers
/**
* Finds the best suggestion.
* @return string|NULL
* @return string|null
* @internal
*/
public static function getSuggestion(array $items, $value)
{
$best = NULL;
$best = null;
$min = (strlen($value) / 4 + 1) * 10 + .1;
foreach (array_unique($items, SORT_REGULAR) as $item) {
$item = is_object($item) ? $item->getName() : $item;
@@ -175,7 +176,7 @@ class Helpers
/**
* Heuristic type detection.
* @param string
* @return string|NULL
* @return string|null
* @internal
*/
public static function detectType($type)
@@ -197,7 +198,7 @@ class Helpers
return $val;
}
}
return NULL;
return null;
}
@@ -206,7 +207,7 @@ class Helpers
*/
public static function getTypeCache()
{
if (self::$types === NULL) {
if (self::$types === null) {
self::$types = new HashMap([__CLASS__, 'detectType']);
}
return self::$types;
@@ -220,11 +221,11 @@ class Helpers
* @param string alias key
* @return void
*/
public static function alias(& $config, $key, $alias)
public static function alias(&$config, $key, $alias)
{
$foo = & $config;
$foo = &$config;
foreach (explode('|', $key) as $key) {
$foo = & $foo[$key];
$foo = &$foo[$key];
}
if (!isset($foo) && isset($config[$alias])) {
@@ -238,7 +239,7 @@ class Helpers
* Import SQL dump from file.
* @return int count of sql commands
*/
public static function loadFromFile(Connection $connection, $file)
public static function loadFromFile(Connection $connection, $file, callable $onProgress = null)
{
@set_time_limit(0); // intentionally @
@@ -247,31 +248,55 @@ class Helpers
throw new \RuntimeException("Cannot open file '$file'.");
}
$count = 0;
$stat = fstat($handle);
$count = $size = 0;
$delimiter = ';';
$sql = '';
$driver = $connection->getDriver();
while (!feof($handle)) {
$s = rtrim(fgets($handle));
if (substr($s, 0, 10) === 'DELIMITER ') {
$delimiter = substr($s, 10);
while (($s = fgets($handle)) !== false) {
$size += strlen($s);
if (strtoupper(substr($s, 0, 10)) === 'DELIMITER ') {
$delimiter = trim(substr($s, 10));
} elseif (substr($s, -strlen($delimiter)) === $delimiter) {
$sql .= substr($s, 0, -strlen($delimiter));
} elseif (substr($ts = rtrim($s), -strlen($delimiter)) === $delimiter) {
$sql .= substr($ts, 0, -strlen($delimiter));
$driver->query($sql);
$sql = '';
$count++;
if ($onProgress) {
call_user_func($onProgress, $count, isset($stat['size']) ? $size * 100 / $stat['size'] : null);
}
} else {
$sql .= $s . "\n";
$sql .= $s;
}
}
if (trim($sql) !== '') {
if (rtrim($sql) !== '') {
$driver->query($sql);
$count++;
if ($onProgress) {
call_user_func($onProgress, $count, isset($stat['size']) ? 100 : null);
}
}
fclose($handle);
return $count;
}
/**
* @internal
* @return string|int
*/
public static function intVal($value)
{
if (is_int($value)) {
return $value;
} elseif (is_string($value) && preg_match('#-?\d++\z#A', $value)) {
// support for long numbers - keep them unchanged
return is_float($number = $value * 1) ? $value : $number;
} else {
throw new Exception("Expected number, '$value' given.");
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -32,5 +32,4 @@ class Literal
{
return $this->value;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* dibi file logger.
* Dibi file logger.
*/
class FileLogger
{
@@ -24,7 +24,7 @@ class FileLogger
public $filter;
public function __construct($file, $filter = NULL)
public function __construct($file, $filter = null)
{
$this->file = $file;
$this->filter = $filter ? (int) $filter : Dibi\Event::QUERY;
@@ -72,5 +72,4 @@ class FileLogger
}
fclose($handle);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -11,7 +11,7 @@ use Dibi;
/**
* dibi FirePHP logger.
* FirePHP logger.
*/
class FirePhpLogger
{
@@ -29,7 +29,7 @@ class FirePhpLogger
/** @var int */
public $filter;
/** @var int Elapsed time for all queries */
/** @var float Elapsed time for all queries */
public $totalTime = 0;
/** @var int Number of all queries */
@@ -48,7 +48,7 @@ class FirePhpLogger
}
public function __construct($filter = NULL)
public function __construct($filter = null)
{
$this->filter = $filter ? (int) $filter : Dibi\Event::QUERY;
}
@@ -91,5 +91,4 @@ class FirePhpLogger
}
header("X-Wf-dibi-1-1-d$num: |$s|");
}
}

View File

@@ -1,14 +1,13 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
namespace Dibi\Reflection;
use Dibi;
use Dibi\Type;
/**
@@ -19,24 +18,24 @@ use Dibi\Type;
* @property-read Table $table
* @property-read string $type
* @property-read mixed $nativeType
* @property-read int $size
* @property-read bool $unsigned
* @property-read bool $nullable
* @property-read bool $autoIncrement
* @property-read int|null $size
* @property-read bool|null $unsigned
* @property-read bool|null $nullable
* @property-read bool|null $autoIncrement
* @property-read mixed $default
*/
class Column
{
use Dibi\Strict;
/** @var Dibi\Reflector|NULL when created by Result */
/** @var Dibi\Reflector|null when created by Result */
private $reflector;
/** @var array (name, nativetype, [table], [fullname], [size], [nullable], [default], [autoincrement], [vendor]) */
private $info;
public function __construct(Dibi\Reflector $reflector = NULL, array $info)
public function __construct(Dibi\Reflector $reflector = null, array $info)
{
$this->reflector = $reflector;
$this->info = $info;
@@ -57,7 +56,7 @@ class Column
*/
public function getFullName()
{
return isset($this->info['fullname']) ? $this->info['fullname'] : NULL;
return isset($this->info['fullname']) ? $this->info['fullname'] : null;
}
@@ -76,18 +75,18 @@ class Column
public function getTable()
{
if (empty($this->info['table']) || !$this->reflector) {
throw new Dibi\Exception("Table is unknown or not available.");
throw new Dibi\Exception('Table is unknown or not available.');
}
return new Table($this->reflector, ['name' => $this->info['table']]);
}
/**
* @return string
* @return string|null
*/
public function getTableName()
{
return isset($this->info['table']) && $this->info['table'] != NULL ? $this->info['table'] : NULL; // intentionally ==
return isset($this->info['table']) && $this->info['table'] != null ? $this->info['table'] : null; // intentionally ==
}
@@ -101,7 +100,7 @@ class Column
/**
* @return mixed
* @return string
*/
public function getNativeType()
{
@@ -110,38 +109,38 @@ class Column
/**
* @return int
* @return int|null
*/
public function getSize()
{
return isset($this->info['size']) ? (int) $this->info['size'] : NULL;
return isset($this->info['size']) ? (int) $this->info['size'] : null;
}
/**
* @return bool
* @return bool|null
*/
public function isUnsigned()
{
return isset($this->info['unsigned']) ? (bool) $this->info['unsigned'] : NULL;
return isset($this->info['unsigned']) ? (bool) $this->info['unsigned'] : null;
}
/**
* @return bool
* @return bool|null
*/
public function isNullable()
{
return isset($this->info['nullable']) ? (bool) $this->info['nullable'] : NULL;
return isset($this->info['nullable']) ? (bool) $this->info['nullable'] : null;
}
/**
* @return bool
* @return bool|null
*/
public function isAutoIncrement()
{
return isset($this->info['autoincrement']) ? (bool) $this->info['autoincrement'] : NULL;
return isset($this->info['autoincrement']) ? (bool) $this->info['autoincrement'] : null;
}
@@ -150,7 +149,7 @@ class Column
*/
public function getDefault()
{
return isset($this->info['default']) ? $this->info['default'] : NULL;
return isset($this->info['default']) ? $this->info['default'] : null;
}
@@ -160,7 +159,6 @@ class Column
*/
public function getVendorInfo($key)
{
return isset($this->info['vendor'][$key]) ? $this->info['vendor'][$key] : NULL;
return isset($this->info['vendor'][$key]) ? $this->info['vendor'][$key] : null;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -24,10 +24,10 @@ class Database
/** @var Dibi\Reflector */
private $reflector;
/** @var string */
/** @var string|null */
private $name;
/** @var array */
/** @var Table[]|null */
private $tables;
@@ -39,7 +39,7 @@ class Database
/**
* @return string
* @return string|null
*/
public function getName()
{
@@ -104,12 +104,11 @@ class Database
*/
protected function init()
{
if ($this->tables === NULL) {
if ($this->tables === null) {
$this->tables = [];
foreach ($this->reflector->getTables() as $info) {
$this->tables[strtolower($info['name'])] = new Table($this->reflector, $info);
}
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -50,5 +50,4 @@ class ForeignKey
{
return $this->references;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -66,5 +66,4 @@ class Index
{
return !empty($this->info['primary']);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -23,10 +23,10 @@ class Result
/** @var Dibi\ResultDriver */
private $driver;
/** @var array */
/** @var Column[]|null */
private $columns;
/** @var array */
/** @var string[]|null */
private $names;
@@ -50,7 +50,7 @@ class Result
* @param bool
* @return string[]
*/
public function getColumnNames($fullNames = FALSE)
public function getColumnNames($fullNames = false)
{
$this->initColumns();
$res = [];
@@ -94,13 +94,12 @@ class Result
*/
protected function initColumns()
{
if ($this->columns === NULL) {
if ($this->columns === null) {
$this->columns = [];
$reflector = $this->driver instanceof Dibi\Reflector ? $this->driver : NULL;
$reflector = $this->driver instanceof Dibi\Reflector ? $this->driver : null;
foreach ($this->driver->getResultColumns() as $info) {
$this->columns[] = $this->names[strtolower($info['name'])] = new Column($reflector, $info);
}
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -34,16 +34,16 @@ class Table
/** @var bool */
private $view;
/** @var array */
/** @var Column[]|null */
private $columns;
/** @var array */
/** @var ForeignKey[]|null */
private $foreignKeys;
/** @var array */
/** @var Index[]|null */
private $indexes;
/** @var Index */
/** @var Index|null */
private $primaryKey;
@@ -160,7 +160,7 @@ class Table
*/
protected function initColumns()
{
if ($this->columns === NULL) {
if ($this->columns === null) {
$this->columns = [];
foreach ($this->reflector->getColumns($this->name) as $info) {
$this->columns[strtolower($info['name'])] = new Column($this->reflector, $info);
@@ -174,7 +174,7 @@ class Table
*/
protected function initIndexes()
{
if ($this->indexes === NULL) {
if ($this->indexes === null) {
$this->initColumns();
$this->indexes = [];
foreach ($this->reflector->getIndexes($this->name) as $info) {
@@ -197,5 +197,4 @@ class Table
{
throw new Dibi\NotImplementedException;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -9,20 +9,7 @@ namespace Dibi;
/**
* dibi result set.
*
* <code>
* $result = dibi::query('SELECT * FROM [table]');
*
* $row = $result->fetch();
* $value = $result->fetchSingle();
* $table = $result->fetchAll();
* $pairs = $result->fetchPairs();
* $assoc = $result->fetchAssoc('col1');
* $assoc = $result->fetchAssoc('col1[]col2->col3');
*
* unset($result);
* </code>
* Query result.
*
* @property-read int $rowCount
*/
@@ -40,12 +27,12 @@ class Result implements IDataSource
private $meta;
/** @var bool Already fetched? Used for allowance for first seek(0) */
private $fetched = FALSE;
private $fetched = false;
/** @var string returned object class */
/** @var string|null returned object class */
private $rowClass = 'Dibi\Row';
/** @var callable returned object factory*/
/** @var callable|null returned object factory */
private $rowFactory;
/** @var array format */
@@ -78,9 +65,9 @@ class Result implements IDataSource
*/
final public function free()
{
if ($this->driver !== NULL) {
if ($this->driver !== null) {
$this->driver->free();
$this->driver = $this->meta = NULL;
$this->driver = $this->meta = null;
}
}
@@ -92,7 +79,7 @@ class Result implements IDataSource
*/
final public function getResultDriver()
{
if ($this->driver === NULL) {
if ($this->driver === null) {
throw new \RuntimeException('Result-set was released from memory.');
}
@@ -106,12 +93,14 @@ class Result implements IDataSource
/**
* Moves cursor position without fetching row.
* @param int the 0-based cursor pos to seek to
* @return bool TRUE on success, FALSE if unable to seek to specified record
* @return bool true on success, false if unable to seek to specified record
* @throws Exception
*/
final public function seek($row)
{
return ($row !== 0 || $this->fetched) ? (bool) $this->getResultDriver()->seek($row) : TRUE;
return ($row != 0 || $this->fetched) // intentionally ==
? (bool) $this->getResultDriver()->seek($row)
: true;
}
@@ -145,6 +134,16 @@ class Result implements IDataSource
}
/**
* Returns the number of columns in a result set.
* @return int
*/
final public function getColumnCount()
{
return count($this->types);
}
/********************* fetching rows ****************d*g**/
@@ -184,15 +183,15 @@ class Result implements IDataSource
/**
* Fetches the row at current position, process optional type conversion.
* and moves the internal cursor to the next position
* @return Row|FALSE array on success, FALSE if no next record
* @return Row|false
*/
final public function fetch()
{
$row = $this->getResultDriver()->fetch(TRUE);
$row = $this->getResultDriver()->fetch(true);
if (!is_array($row)) {
return FALSE;
return false;
}
$this->fetched = TRUE;
$this->fetched = true;
$this->normalize($row);
if ($this->rowFactory) {
return call_user_func($this->rowFactory, $row);
@@ -205,15 +204,15 @@ class Result 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()
{
$row = $this->getResultDriver()->fetch(TRUE);
$row = $this->getResultDriver()->fetch(true);
if (!is_array($row)) {
return FALSE;
return false;
}
$this->fetched = TRUE;
$this->fetched = true;
$this->normalize($row);
return reset($row);
}
@@ -223,12 +222,12 @@ class Result implements IDataSource
* Fetches all records from table.
* @param int offset
* @param int limit
* @return Row[]
* @return Row[]|array[]
*/
final public function fetchAll($offset = NULL, $limit = NULL)
final public function fetchAll($offset = null, $limit = null)
{
$limit = $limit === NULL ? -1 : (int) $limit;
$this->seek((int) $offset);
$limit = $limit === null ? -1 : Helpers::intVal($limit);
$this->seek($offset);
$row = $this->fetch();
if (!$row) {
return []; // empty result set
@@ -260,7 +259,7 @@ class Result implements IDataSource
*/
final public function fetchAssoc($assoc)
{
if (strpos($assoc, ',') !== FALSE) {
if (strpos($assoc, ',') !== false) {
return $this->oldFetchAssoc($assoc);
}
@@ -270,12 +269,12 @@ class Result implements IDataSource
return []; // empty result set
}
$data = NULL;
$assoc = preg_split('#(\[\]|->|=|\|)#', $assoc, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$data = null;
$assoc = preg_split('#(\[\]|->|=|\|)#', $assoc, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
// check columns
foreach ($assoc as $as) {
// offsetExists ignores NULL in PHP 5.2.1, isset() surprisingly NULL accepts
// offsetExists ignores null in PHP 5.2.1, isset() surprisingly null accepts
if ($as !== '[]' && $as !== '=' && $as !== '->' && $as !== '|' && !property_exists($row, $as)) {
throw new \InvalidArgumentException("Unknown column '$as' in associative descriptor.");
}
@@ -291,35 +290,34 @@ class Result implements IDataSource
// make associative tree
do {
$x = & $data;
$x = &$data;
// iterative deepening
foreach ($assoc as $i => $as) {
if ($as === '[]') { // indexed-array node
$x = & $x[];
$x = &$x[];
} elseif ($as === '=') { // "value" node
$x = $row->{$assoc[$i + 1]};
continue 2;
} elseif ($as === '->') { // "object" node
if ($x === NULL) {
if ($x === null) {
$x = clone $row;
$x = & $x->{$assoc[$i + 1]};
$x = NULL; // prepare child node
$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
$x = & $x[$row->$as];
$x = &$x[$row->$as];
}
}
if ($x === NULL) { // build leaf
if ($x === null) { // build leaf
$x = $row;
}
} while ($row = $this->fetch());
unset($x);
@@ -338,7 +336,7 @@ class Result implements IDataSource
return []; // empty result set
}
$data = NULL;
$data = null;
$assoc = explode(',', $assoc);
// strip leading = and @
@@ -356,43 +354,42 @@ class Result implements IDataSource
}
do {
$x = & $data;
$x = &$data;
foreach ($assoc as $i => $as) {
if ($as === '#') { // indexed-array node
$x = & $x[];
$x = &$x[];
} elseif ($as === '=') { // "record" node
if ($x === NULL) {
if ($x === null) {
$x = $row->toArray();
$x = & $x[ $assoc[$i + 1] ];
$x = NULL; // prepare child node
$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) {
if ($x === null) {
$x = clone $row;
$x = & $x->{$assoc[$i + 1]};
$x = NULL; // prepare child node
$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];
$x = &$x[$row->$as];
}
}
if ($x === NULL) { // build leaf
if ($x === null) { // build leaf
if ($leaf === '=') {
$x = $row->toArray();
} else {
$x = $row;
}
}
} while ($row = $this->fetch());
unset($x);
@@ -407,7 +404,7 @@ class Result implements IDataSource
* @return array
* @throws \InvalidArgumentException
*/
final public function fetchPairs($key = NULL, $value = NULL)
final public function fetchPairs($key = null, $value = null)
{
$this->seek(0);
$row = $this->fetch();
@@ -417,8 +414,8 @@ class Result implements IDataSource
$data = [];
if ($value === NULL) {
if ($key !== NULL) {
if ($value === null) {
if ($key !== null) {
throw new \InvalidArgumentException('Either none or both columns must be specified.');
}
@@ -439,7 +436,7 @@ class Result implements IDataSource
throw new \InvalidArgumentException("Unknown value column '$value'.");
}
if ($key === NULL) { // indexed-array
if ($key === null) { // indexed-array
do {
$data[] = $row[$value];
} while ($row = $this->fetch());
@@ -452,7 +449,7 @@ class Result implements IDataSource
}
do {
$data[ (string) $row[$key] ] = $row[$value];
$data[(string) $row[$key]] = $row[$value];
} while ($row = $this->fetch());
return $data;
@@ -483,10 +480,10 @@ class Result implements IDataSource
* @param array
* @return void
*/
private function normalize(array & $row)
private function normalize(array &$row)
{
foreach ($this->types as $key => $type) {
if (!isset($row[$key])) { // NULL
if (!isset($row[$key])) { // null
continue;
}
$value = $row[$key];
@@ -499,9 +496,9 @@ class Result implements IDataSource
: $tmp;
} elseif ($type === Type::FLOAT) {
$value = ltrim($value, '0');
$value = ltrim((string) $value, '0');
$p = strpos($value, '.');
if ($p !== FALSE) {
if ($p !== false) {
$value = rtrim(rtrim($value, '0'), '.');
}
if ($value === '' || $value[0] === '.') {
@@ -515,11 +512,11 @@ class Result implements IDataSource
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
} elseif ($type === Type::DATETIME || $type === Type::DATE || $type === Type::TIME) {
if ($value && substr((string) $value, 0, 3) !== '000') { // '', NULL, FALSE, '0000-00-00', ...
if ($value && substr((string) $value, 0, 3) !== '000') { // '', null, false, '0000-00-00', ...
$value = new DateTime($value);
$row[$key] = empty($this->formats[$type]) ? $value : $value->format($this->formats[$type]);
} else {
$row[$key] = NULL;
$row[$key] = null;
}
} elseif ($type === Type::TIME_INTERVAL) {
@@ -553,14 +550,14 @@ class Result implements IDataSource
*/
final public function getType($col)
{
return isset($this->types[$col]) ? $this->types[$col] : NULL;
return isset($this->types[$col]) ? $this->types[$col] : null;
}
/**
* Sets data format.
* @param string type (use constant Type::*)
* @param string format
* Sets date format.
* @param string
* @param string|null format
* @return self
*/
final public function setFormat($type, $format)
@@ -572,11 +569,11 @@ class Result implements IDataSource
/**
* Returns data format.
* @return string
* @return string|null
*/
final public function getFormat($type)
{
return isset($this->formats[$type]) ? $this->formats[$type] : NULL;
return isset($this->formats[$type]) ? $this->formats[$type] : null;
}
@@ -589,7 +586,7 @@ class Result implements IDataSource
*/
public function getInfo()
{
if ($this->meta === NULL) {
if ($this->meta === null) {
$this->meta = new Reflection\Result($this->getResultDriver());
}
return $this->meta;
@@ -616,5 +613,4 @@ class Result implements IDataSource
{
echo Helpers::dump($this);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -10,15 +10,6 @@ namespace Dibi;
/**
* External result set iterator.
*
* This can be returned by Result::getIterator() method or using foreach
* <code>
* $result = dibi::query('SELECT * FROM table');
* foreach ($result as $row) {
* print_r($row);
* }
* unset($result);
* </code>
*/
class ResultIterator implements \Iterator, \Countable
{
@@ -27,11 +18,11 @@ class ResultIterator implements \Iterator, \Countable
/** @var Result */
private $result;
/** @var int */
/** @var mixed */
private $row;
/** @var int */
private $pointer;
private $pointer = 0;
/**
@@ -104,5 +95,4 @@ class ResultIterator implements \Iterator, \Countable
{
return $this->result->getRowCount();
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -13,7 +13,6 @@ namespace Dibi;
*/
class Row implements \ArrayAccess, \IteratorAggregate, \Countable
{
public function __construct($arr)
{
foreach ($arr as $k => $v) {
@@ -32,18 +31,18 @@ class Row implements \ArrayAccess, \IteratorAggregate, \Countable
* Converts value to DateTime object.
* @param string key
* @param string format
* @return \DateTime
* @return DateTime|string|null
*/
public function asDateTime($key, $format = NULL)
public function asDateTime($key, $format = null)
{
$time = $this[$key];
if (!$time instanceof DateTime) {
if (!$time || substr((string) $time, 0, 3) === '000') { // '', NULL, FALSE, '0000-00-00', ...
return NULL;
if (!$time || substr((string) $time, 0, 3) === '000') { // '', null, false, '0000-00-00', ...
return null;
}
$time = new DateTime($time);
}
return $format === NULL ? $time : $time->format($format);
return $format === null ? $time : $time->format($format);
}
@@ -91,5 +90,4 @@ class Row implements \ArrayAccess, \IteratorAggregate, \Countable
{
unset($this->$nm);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -88,7 +88,7 @@ trait Strict
*/
public function __isset($name)
{
return FALSE;
return false;
}
@@ -105,33 +105,33 @@ trait Strict
/**
* @param string method name
* @param callabke
* @param callable
* @return mixed
*/
public static function extensionMethod($name, $callback = NULL)
public static function extensionMethod($name, $callback = null)
{
if (strpos($name, '::') === FALSE) {
if (strpos($name, '::') === false) {
$class = get_called_class();
} else {
list($class, $name) = explode('::', $name);
$class = (new ReflectionClass($class))->getName();
}
if (self::$extMethods === NULL) { // for backwards compatibility
if (self::$extMethods === null) { // for backwards compatibility
$list = get_defined_functions();
foreach ($list['user'] as $fce) {
$pair = explode('_prototype_', $fce);
if (count($pair) === 2) {
trigger_error("Extension method defined as $fce() is deprecated, use $class::extensionMethod('$name', ...).", E_USER_DEPRECATED);
self::$extMethods[$pair[1]][(new ReflectionClass($pair[0]))->getName()] = $fce;
self::$extMethods[$pair[1]][''] = NULL;
self::$extMethods[$pair[1]][''] = null;
}
}
}
$list = & self::$extMethods[strtolower($name)];
if ($callback === NULL) { // getter
$cache = & $list[''][$class];
$list = &self::$extMethods[strtolower($name)];
if ($callback === null) { // getter
$cache = &$list[''][$class];
if (isset($cache)) {
return $cache;
}
@@ -141,12 +141,11 @@ trait Strict
return $cache = $list[$cl];
}
}
return $cache = FALSE;
return $cache = false;
} else { // setter
$list[$class] = $callback;
$list[''] = NULL;
$list[''] = null;
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -9,7 +9,7 @@ namespace Dibi;
/**
* dibi SQL translator.
* SQL translator.
*/
final class Translator
{
@@ -31,7 +31,7 @@ final class Translator
private $errors;
/** @var bool */
private $comment = FALSE;
private $comment = false;
/** @var int */
private $ifLevel = 0;
@@ -39,10 +39,10 @@ final class Translator
/** @var int */
private $ifLevelStart = 0;
/** @var int */
/** @var int|null */
private $limit;
/** @var int */
/** @var int|null */
private $offset;
/** @var HashMap */
@@ -70,11 +70,12 @@ final class Translator
$args = array_values($args[0]);
}
$this->args = $args;
$this->errors = [];
$commandIns = NULL;
$lastArr = NULL;
$cursor = & $this->cursor;
$comment = & $this->comment;
$commandIns = null;
$lastArr = null;
$cursor = &$this->cursor;
$comment = &$this->comment;
// iterate
$sql = [];
@@ -127,7 +128,7 @@ final class Translator
if (is_array($arg) && is_string(key($arg))) {
// associative array -> autoselect between SET or VALUES & LIST
if ($commandIns === NULL) {
if ($commandIns === null) {
$commandIns = strtoupper(substr(ltrim($this->args[0]), 0, 6));
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
@@ -142,7 +143,7 @@ final class Translator
}
// default processing
$sql[] = $this->formatValue($arg, FALSE);
$sql[] = $this->formatValue($arg, false);
} // while
@@ -157,7 +158,7 @@ final class Translator
}
// apply limit
if ($this->limit !== NULL || $this->offset !== NULL) {
if ($this->limit !== null || $this->offset !== null) {
$this->driver->applyLimit($sql, $this->limit, $this->offset);
}
@@ -196,7 +197,7 @@ final class Translator
$pair = explode('%', $k, 2); // split into identifier & modifier
$k = $this->identifiers->{$pair[0]} . ' ';
if (!isset($pair[1])) {
$v = $this->formatValue($v, FALSE);
$v = $this->formatValue($v, false);
$vx[] = $k . ($v === 'NULL' ? 'IS ' : '= ') . $v;
} elseif ($pair[1] === 'ex') {
@@ -206,7 +207,7 @@ final class Translator
$v = $this->formatValue($v, $pair[1]);
if ($pair[1] === 'l' || $pair[1] === 'in') {
$op = 'IN ';
} elseif (strpos($pair[1], 'like') !== FALSE) {
} elseif (strpos($pair[1], 'like') !== false) {
$op = 'LIKE ';
} elseif ($v === 'NULL') {
$op = 'IS ';
@@ -238,7 +239,7 @@ final class Translator
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->identifiers->{$pair[0]} . '='
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : false));
}
return implode(', ', $vx);
@@ -246,8 +247,8 @@ final class Translator
case 'in':// replaces scalar %in modifier!
case 'l': // (val, val, ...)
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
$pair = explode('%', (string) $k, 2); // split into identifier & modifier
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : false));
}
return '(' . (($vx || $modifier === 'l') ? implode(', ', $vx) : 'NULL') . ')';
@@ -256,7 +257,7 @@ final class Translator
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$kx[] = $this->identifiers->{$pair[0]};
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : FALSE));
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : (is_array($v) ? 'ex' : false));
}
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
@@ -277,7 +278,7 @@ final class Translator
$pair = explode('%', $k, 2); // split into identifier & modifier
$kx[] = $this->identifiers->{$pair[0]};
foreach ($v as $k2 => $v2) {
$vx[$k2][] = $this->formatValue($v2, isset($pair[1]) ? $pair[1] : (is_array($v2) ? 'ex' : FALSE));
$vx[$k2][] = $this->formatValue($v2, isset($pair[1]) ? $pair[1] : (is_array($v2) ? 'ex' : false));
}
}
foreach ($vx as $k => $v) {
@@ -313,10 +314,14 @@ final class Translator
// with modifier procession
if ($modifier) {
if ($value !== NULL && !is_scalar($value)) { // array is already processed
if ($value !== null && !is_scalar($value)) { // array is already processed
if ($value instanceof Literal && ($modifier === 'sql' || $modifier === 'SQL')) {
$modifier = 'SQL';
} elseif (($value instanceof \DateTime || $value instanceof \DateTimeInterface) && ($modifier === 'd' || $modifier === 't')) {
return (string) $value;
} elseif ($value instanceof Expression && $modifier === 'ex') {
return call_user_func_array([$this->connection, 'translate'], $value->getValues());
} elseif (($value instanceof \DateTime || $value instanceof \DateTimeInterface) && ($modifier === 'd' || $modifier === 't' || $modifier === 'dt')) {
// continue
} else {
$type = is_object($value) ? get_class($value) : gettype($value);
@@ -326,59 +331,65 @@ final class Translator
switch ($modifier) {
case 's': // string
return $value === NULL ? 'NULL' : $this->driver->escapeText($value);
return $value === null ? 'NULL' : $this->driver->escapeText((string) $value);
case 'bin':// binary
return $value === NULL ? 'NULL' : $this->driver->escapeBinary($value);
return $value === null ? 'NULL' : $this->driver->escapeBinary($value);
case 'b': // boolean
return $value === NULL ? 'NULL' : $this->driver->escapeBool($value);
return $value === null ? 'NULL' : $this->driver->escapeBool($value);
case 'sN': // string or NULL
case 'sN': // string or null
case 'sn':
return $value == '' ? 'NULL' : $this->driver->escapeText($value); // notice two equal signs
return $value == '' ? 'NULL' : $this->driver->escapeText((string) $value); // notice two equal signs
case 'in': // deprecated
trigger_error('Modifier %in is deprecated, use %iN.', E_USER_DEPRECATED);
// intentionally break omitted
case 'iN': // signed int or NULL
// break omitted
case 'iN': // signed int or null
if ($value == '') {
$value = NULL;
$value = null;
}
// intentionally break omitted
// break omitted
case 'i': // signed int
case 'u': // unsigned int, ignored
if ($value === NULL) {
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);
} elseif (is_string($value)) {
if (preg_match('#[+-]?\d++(?:e\d+)?\z#A', $value)) {
return $value; // support for long numbers - keep them unchanged
} elseif (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 {
throw new Exception("Expected number, '$value' given.");
}
} else {
return (string) (int) $value;
}
// break omitted
case 'f': // float
if ($value === NULL) {
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
} elseif (is_string($value)) {
if (is_numeric($value) && substr($value, 1, 1) !== 'x') {
return $value; // support for long numbers - keep them unchanged
} else {
throw new Exception("Expected number, '$value' given.");
}
} else {
return rtrim(rtrim(number_format($value + 0, 10, '.', ''), '0'), '.');
}
// break omitted
case 'd': // date
case 't': // datetime
case 'dt': // datetime
if ($value === NULL) {
if ($value === null) {
return 'NULL';
} else {
return $modifier === 'd' ? $this->driver->escapeDate($value) : $this->driver->escapeDateTime($value);
}
// break omitted
case 'by':
case 'n': // composed identifier name
return $this->identifiers->$value;
@@ -443,7 +454,7 @@ final class Translator
} elseif (is_bool($value)) {
return $this->driver->escapeBool($value);
} elseif ($value === NULL) {
} elseif ($value === null) {
return 'NULL';
} elseif ($value instanceof \DateTime || $value instanceof \DateTimeInterface) {
@@ -452,6 +463,9 @@ final class Translator
} elseif ($value instanceof Literal) {
return (string) $value;
} elseif ($value instanceof Expression) {
return call_user_func_array([$this->connection, 'translate'], $value->getValues());
} else {
$type = is_object($value) ? get_class($value) : gettype($value);
return $this->errors[] = "**Unexpected $type**";
@@ -480,19 +494,19 @@ final class Translator
if (!empty($matches[11])) { // placeholder
$cursor = & $this->cursor;
$cursor = &$this->cursor;
if ($cursor >= count($this->args)) {
return $this->errors[] = '**Extra placeholder**';
}
$cursor++;
return $this->formatValue($this->args[$cursor - 1], FALSE);
return $this->formatValue($this->args[$cursor - 1], false);
}
if (!empty($matches[10])) { // modifier
$mod = $matches[10];
$cursor = & $this->cursor;
$cursor = &$this->cursor;
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
return $this->errors[] = "**Extra modifier %$mod**";
@@ -504,7 +518,7 @@ final class Translator
if (!$this->comment && !$this->args[$cursor - 1]) {
// open comment
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
$this->comment = true;
return '/*';
}
return '';
@@ -512,11 +526,11 @@ final class Translator
} elseif ($mod === 'else') {
if ($this->ifLevelStart === $this->ifLevel) {
$this->ifLevelStart = 0;
$this->comment = FALSE;
$this->comment = false;
return '*/';
} elseif (!$this->comment) {
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
$this->comment = true;
return '/*';
}
@@ -525,7 +539,7 @@ final class Translator
if ($this->ifLevelStart === $this->ifLevel + 1) {
// close comment
$this->ifLevelStart = 0;
$this->comment = FALSE;
$this->comment = false;
return '*/';
}
return '';
@@ -536,21 +550,21 @@ final class Translator
} elseif ($mod === 'lmt') { // apply limit
$arg = $this->args[$cursor++];
if ($arg === NULL) {
if ($arg === null) {
} elseif ($this->comment) {
return "(limit $arg)";
} else {
$this->limit = (int) $arg;
$this->limit = Helpers::intVal($arg);
}
return '';
} elseif ($mod === 'ofs') { // apply offset
$arg = $this->args[$cursor++];
if ($arg === NULL) {
if ($arg === null) {
} elseif ($this->comment) {
return "(offset $arg)";
} else {
$this->offset = (int) $arg;
$this->offset = Helpers::intVal($arg);
}
return '';
@@ -583,7 +597,7 @@ final class Translator
if ($matches[8]) { // SQL identifier substitution
$m = substr($matches[8], 0, -1);
$m = $this->connection->getSubstitutes()->$m;
return $matches[9] == '' ? $this->formatValue($m, FALSE) : $m . $matches[9]; // value or identifier
return $matches[9] == '' ? $this->formatValue($m, false) : $m . $matches[9]; // value or identifier
}
throw new \Exception('this should be never executed');
@@ -600,12 +614,11 @@ final class Translator
{
$value = $this->connection->substitute($value);
$parts = explode('.', $value);
foreach ($parts as & $v) {
foreach ($parts as &$v) {
if ($v !== '*') {
$v = $this->driver->escapeIdentifier($v);
}
}
return implode('.', $parts);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -24,9 +24,9 @@ class Type
TIME = 't',
TIME_INTERVAL = 'ti';
final public function __construct()
{
throw new \LogicException('Cannot instantiate static class ' . __CLASS__);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -9,8 +9,7 @@ use Dibi\Type;
/**
* This class is static container class for creating DB objects and
* store connections info.
* Static container class for Dibi connections.
*/
class dibi
{
@@ -22,8 +21,8 @@ class dibi
/** version */
const
VERSION = '3.0.7',
REVISION = 'released on 2017-01-04';
VERSION = '3.2.3',
REVISION = 'released on 2018-09-17';
/** sorting order */
const
@@ -49,19 +48,13 @@ class dibi
FIELD_DATETIME = Type::DATETIME,
FIELD_TIME = Type::TIME;
/** @var Dibi\Connection[] Connection registry storage for DibiConnection objects */
private static $registry = [];
/** @var Dibi\Connection Current connection */
private static $connection;
/** @var string Last SQL command @see dibi::query() */
/** @var string|null Last SQL command @see dibi::query() */
public static $sql;
/** @var int Elapsed time for last query */
/** @var float|null Elapsed time for last query */
public static $elapsedTime;
/** @var int Elapsed time for all queries */
/** @var float Elapsed time for all queries */
public static $totalTime;
/** @var int Number or queries */
@@ -70,6 +63,12 @@ class dibi
/** @var string Default dibi driver */
public static $defaultDriver = 'mysqli';
/** @var Dibi\Connection[] Connection registry storage for Dibi\Connection objects */
private static $registry = [];
/** @var Dibi\Connection Current connection */
private static $connection;
/**
* Static class - cannot be instantiated.
@@ -85,12 +84,12 @@ class dibi
/**
* Creates a new Connection object and connects it to specified database.
* @param mixed connection parameters
* @param array|string connection parameters
* @param string connection name
* @return Dibi\Connection
* @throws Dibi\Exception
*/
public static function connect($config = [], $name = 0)
public static function connect($config = [], $name = '0')
{
return self::$connection = self::$registry[$name] = new Dibi\Connection($config, $name);
}
@@ -107,12 +106,12 @@ class dibi
/**
* Returns TRUE when connection was established.
* Returns true when connection was established.
* @return bool
*/
public static function isConnected()
{
return (self::$connection !== NULL) && self::$connection->isConnected();
return (self::$connection !== null) && self::$connection->isConnected();
}
@@ -122,10 +121,10 @@ class dibi
* @return Dibi\Connection
* @throws Dibi\Exception
*/
public static function getConnection($name = NULL)
public static function getConnection($name = null)
{
if ($name === NULL) {
if (self::$connection === NULL) {
if ($name === null) {
if (self::$connection === null) {
throw new Dibi\Exception('Dibi is not connected to database.');
}
@@ -167,7 +166,7 @@ class dibi
/**
* Generates and executes SQL query - Monostate for Dibi\Connection::query().
* @param array|mixed one or more arguments
* @return Dibi\Result|int result set object (if any)
* @return Dibi\Result|int result set or number of affected rows
* @throws Dibi\Exception
*/
public static function query($args)
@@ -180,7 +179,7 @@ class dibi
/**
* Executes the SQL query - Monostate for Dibi\Connection::nativeQuery().
* @param string SQL statement.
* @return Dibi\Result|int result set object (if any)
* @return Dibi\Result|int result set or number of affected rows
*/
public static function nativeQuery($sql)
{
@@ -241,7 +240,7 @@ class dibi
/**
* Executes SQL query and fetch first column - Monostate for Dibi\Connection::query() & fetchSingle().
* @param array|mixed one or more arguments
* @return string
* @return mixed
* @throws Dibi\Exception
*/
public static function fetchSingle($args)
@@ -277,12 +276,11 @@ class dibi
/**
* Gets the number of affected rows. Alias for getAffectedRows().
* @return int number of rows
* @throws Dibi\Exception
* @deprecated
*/
public static function affectedRows()
{
trigger_error(__METHOD__ . '() is deprecated, use getAffectedRows()', E_USER_DEPRECATED);
return self::getConnection()->getAffectedRows();
}
@@ -294,20 +292,18 @@ class dibi
* @return int
* @throws Dibi\Exception
*/
public static function getInsertId($sequence = NULL)
public static function getInsertId($sequence = null)
{
return self::getConnection()->getInsertId($sequence);
}
/**
* Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
* @param string optional sequence name
* @return int
* @throws Dibi\Exception
* @deprecated
*/
public static function insertId($sequence = NULL)
public static function insertId($sequence = null)
{
trigger_error(__METHOD__ . '() is deprecated, use getInsertId()', E_USER_DEPRECATED);
return self::getConnection()->getInsertId($sequence);
}
@@ -318,19 +314,19 @@ class dibi
* @return void
* @throws Dibi\Exception
*/
public static function begin($savepoint = NULL)
public static function begin($savepoint = null)
{
self::getConnection()->begin($savepoint);
}
/**
* Commits statements in a transaction - Monostate for Dibi\Connection::commit($savepoint = NULL).
* Commits statements in a transaction - Monostate for Dibi\Connection::commit($savepoint = null).
* @param string optional savepoint name
* @return void
* @throws Dibi\Exception
*/
public static function commit($savepoint = NULL)
public static function commit($savepoint = null)
{
self::getConnection()->commit($savepoint);
}
@@ -342,7 +338,7 @@ class dibi
* @return void
* @throws Dibi\Exception
*/
public static function rollback($savepoint = NULL)
public static function rollback($savepoint = null)
{
self::getConnection()->rollback($savepoint);
}
@@ -382,7 +378,7 @@ class dibi
/**
* @param string column name
* @param mixed column name
* @return Dibi\Fluent
*/
public static function select($args)
@@ -444,11 +440,22 @@ class dibi
* Prints out a syntax highlighted version of the SQL command or Result.
* @param string|Result
* @param bool return output instead of printing it?
* @return string
* @return string|null
*/
public static function dump($sql = NULL, $return = FALSE)
public static function dump($sql = null, $return = false)
{
return Dibi\Helpers::dump($sql, $return);
}
/**
* Strips microseconds part.
* @param \DateTime|\DateTimeInterface
* @return \DateTime|\DateTimeInterface
*/
public static function stripMicroseconds($dt)
{
$class = get_class($dt);
return new $class($dt->format('Y-m-d H:i:s'), $dt->getTimezone());
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -9,23 +9,23 @@ namespace Dibi;
/**
* dibi common exception.
* Dibi common exception.
*/
class Exception extends \Exception
{
/** @var string|NULL */
/** @var string|null */
private $sql;
/**
* Construct a dibi exception.
* @param string Message describing the exception
* @param mixed
* @param string|int
* @param string SQL command
* @param \Exception
*/
public function __construct($message = NULL, $code = 0, $sql = NULL)
public function __construct($message = '', $code = 0, $sql = null, \Exception $previous = null)
{
parent::__construct($message);
parent::__construct($message, 0, $previous);
$this->code = $code;
$this->sql = $sql;
}
@@ -47,7 +47,6 @@ class Exception extends \Exception
{
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
}
}
@@ -64,7 +63,6 @@ class DriverException extends Exception
*/
class PcreException extends Exception
{
public function __construct($message = '%msg.')
{
static $messages = [
@@ -105,7 +103,7 @@ class ProcedureException extends Exception
* @param int Some code
* @param string SQL command
*/
public function __construct($message = NULL, $code = 0, $severity = NULL, $sql = NULL)
public function __construct($message = '', $code = 0, $severity = '', $sql = null)
{
parent::__construct($message, (int) $code, $sql);
$this->severity = $severity;
@@ -118,9 +116,8 @@ class ProcedureException extends Exception
*/
public function getSeverity()
{
$this->severity;
return $this->severity;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -19,18 +19,17 @@ interface IDataSource extends \Countable, \IteratorAggregate
/**
* dibi driver interface.
* Driver interface.
*/
interface Driver
{
/**
* Connects to a database.
* @param array
* @return void
* @throws Exception
*/
function connect(array & $config);
function connect(array &$config);
/**
* Disconnects from a database.
@@ -42,20 +41,20 @@ interface Driver
/**
* Internal: Executes the SQL query.
* @param string SQL statement.
* @return ResultDriver|NULL
* @return ResultDriver|null
* @throws DriverException
*/
function query($sql);
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
* @return int|FALSE number of rows or FALSE on error
* @return int|false number of rows or false on error
*/
function getAffectedRows();
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
* @return int|FALSE int on success or FALSE on failure
* @return int|false int on success or false on failure
*/
function getInsertId($sequence);
@@ -65,7 +64,7 @@ interface Driver
* @return void
* @throws DriverException
*/
function begin($savepoint = NULL);
function begin($savepoint = null);
/**
* Commits statements in a transaction.
@@ -73,7 +72,7 @@ interface Driver
* @return void
* @throws DriverException
*/
function commit($savepoint = NULL);
function commit($savepoint = null);
/**
* Rollback changes in a transaction.
@@ -81,7 +80,7 @@ interface Driver
* @return void
* @throws DriverException
*/
function rollback($savepoint = NULL);
function rollback($savepoint = null);
/**
* Returns the connection resource.
@@ -97,19 +96,39 @@ interface Driver
/**
* Encodes data for use in a SQL statement.
* @param mixed value
* @param string value
* @return string encoded value
*/
function escapeText($value);
/**
* @param string
* @return string
*/
function escapeBinary($value);
/**
* @param string
* @return string
*/
function escapeIdentifier($value);
/**
* @param bool
* @return string
*/
function escapeBool($value);
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
function escapeDate($value);
/**
* @param \DateTime|\DateTimeInterface|string|int
* @return string
*/
function escapeDateTime($value);
/**
@@ -122,19 +141,20 @@ interface Driver
/**
* Injects LIMIT/OFFSET to the SQL query.
* @param string
* @param int|null
* @param int|null
* @return void
*/
function applyLimit(& $sql, $limit, $offset);
function applyLimit(&$sql, $limit, $offset);
}
/**
* dibi result set driver interface.
* Result set driver interface.
*/
interface ResultDriver
{
/**
* Returns the number of rows in a result set.
* @return int
@@ -144,14 +164,14 @@ interface ResultDriver
/**
* 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 Exception
*/
function seek($row);
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* @param bool TRUE for associative array, FALSE for numeric
* @param bool true for associative array, false for numeric
* @return array array on success, nonarray if no next record
* @internal
*/
@@ -182,16 +202,14 @@ interface ResultDriver
* @return string
*/
function unescapeBinary($value);
}
/**
* dibi driver reflection.
* Reflection driver.
*/
interface Reflector
{
/**
* Returns list of tables.
* @return array of {name [, (bool) view ]}
@@ -218,5 +236,4 @@ interface Reflector
* @return array
*/
function getForeignKeys($table);
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* This file is part of the "dibi" - smart database abstraction layer.
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
@@ -15,31 +15,32 @@ spl_autoload_register(function ($class) {
static $map = [
'dibi' => 'dibi.php',
'Dibi\Bridges\Nette\DibiExtension22' => 'Bridges/Nette/DibiExtension22.php',
'Dibi\Bridges\Nette\DibiExtension21' => 'Bridges/Nette/DibiExtension21.php',
'Dibi\Bridges\Nette\Panel' => 'Bridges/Nette/Panel.php',
'Dibi\Bridges\Tracy\Panel' => 'Bridges/Tracy/Panel.php',
'Dibi\Connection' => 'Connection.php',
'Dibi\ConstraintViolationException' => 'exceptions.php',
'Dibi\DataSource' => 'DataSource.php',
'Dibi\DateTime' => 'DateTime.php',
'Dibi\Driver' => 'interfaces.php',
'Dibi\DriverException' => 'exceptions.php',
'Dibi\Drivers\FirebirdDriver' => 'Drivers/FirebirdDriver.php',
'Dibi\Drivers\SqlsrvDriver' => 'Drivers/SqlsrvDriver.php',
'Dibi\Drivers\SqlsrvReflector' => 'Drivers/SqlsrvReflector.php',
'Dibi\Drivers\MsSqlDriver' => 'Drivers/MsSqlDriver.php',
'Dibi\Drivers\MsSqlReflector' => 'Drivers/MsSqlReflector.php',
'Dibi\Drivers\MySqlDriver' => 'Drivers/MySqlDriver.php',
'Dibi\Drivers\MySqliDriver' => 'Drivers/MySqliDriver.php',
'Dibi\Drivers\MySqlReflector' => 'Drivers/MySqlReflector.php',
'Dibi\Drivers\MySqliDriver' => 'Drivers/MySqliDriver.php',
'Dibi\Drivers\OdbcDriver' => 'Drivers/OdbcDriver.php',
'Dibi\Drivers\OracleDriver' => 'Drivers/OracleDriver.php',
'Dibi\Drivers\PdoDriver' => 'Drivers/PdoDriver.php',
'Dibi\Drivers\PostgreDriver' => 'Drivers/PostgreDriver.php',
'Dibi\Drivers\Sqlite3Driver' => 'Drivers/Sqlite3Driver.php',
'Dibi\Drivers\SqliteReflector' => 'Drivers/SqliteReflector.php',
'Dibi\Drivers\SqlsrvDriver' => 'Drivers/SqlsrvDriver.php',
'Dibi\Drivers\SqlsrvReflector' => 'Drivers/SqlsrvReflector.php',
'Dibi\Event' => 'Event.php',
'Dibi\Exception' => 'exceptions.php',
'Dibi\Expression' => 'Expression.php',
'Dibi\Fluent' => 'Fluent.php',
'Dibi\ForeignKeyConstraintViolationException' => 'exceptions.php',
'Dibi\HashMap' => 'HashMap.php',
'Dibi\HashMapBase' => 'HashMap.php',
'Dibi\Helpers' => 'Helpers.php',
@@ -48,6 +49,7 @@ spl_autoload_register(function ($class) {
'Dibi\Loggers\FileLogger' => 'Loggers/FileLogger.php',
'Dibi\Loggers\FirePhpLogger' => 'Loggers/FirePhpLogger.php',
'Dibi\NotImplementedException' => 'exceptions.php',
'Dibi\NotNullConstraintViolationException' => 'exceptions.php',
'Dibi\NotSupportedException' => 'exceptions.php',
'Dibi\PcreException' => 'exceptions.php',
'Dibi\ProcedureException' => 'exceptions.php',
@@ -65,8 +67,8 @@ spl_autoload_register(function ($class) {
'Dibi\Strict' => 'Strict.php',
'Dibi\Translator' => 'Translator.php',
'Dibi\Type' => 'Type.php',
'Dibi\UniqueConstraintViolationException' => 'exceptions.php',
], $old2new = [
'Dibi' => 'dibi.php',
'DibiColumnInfo' => 'Dibi\Reflection\Column',
'DibiConnection' => 'Dibi\Connection',
'DibiDatabaseInfo' => 'Dibi\Reflection\Database',
@@ -91,8 +93,6 @@ spl_autoload_register(function ($class) {
'DibiMySqlDriver' => 'Dibi\Drivers\MySqlDriver',
'DibiMySqliDriver' => 'Dibi\Drivers\MySqliDriver',
'DibiMySqlReflector' => 'Dibi\Drivers\MySqlReflector',
'DibiNette21Extension' => 'Dibi\Bridges\Nette\DibiExtension21',
'DibiNettePanel' => 'Dibi\Bridges\Nette\Panel',
'DibiNotImplementedException' => 'Dibi\NotImplementedException',
'DibiNotSupportedException' => 'Dibi\NotSupportedException',
'DibiOdbcDriver' => 'Dibi\Drivers\OdbcDriver',
@@ -119,26 +119,9 @@ spl_autoload_register(function ($class) {
if (isset($map[$class])) {
require __DIR__ . '/Dibi/' . $map[$class];
} elseif (isset($old2new[$class])) {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$location = isset($trace[1]['file']) ? 'used in ' . $trace[1]['file'] . ':' . $trace[1]['line'] : '';
trigger_error("Class $class $location has been renamed to {$old2new[$class]}.", E_USER_DEPRECATED);
class_alias($old2new[$class], $class);
}
});
// preload for compatiblity
array_map('class_exists', [
'DibiConnection',
'DibiDateTime',
'DibiDriverException',
'DibiEvent',
'DibiException',
'DibiFluent',
'DibiLiteral',
'DibiNotImplementedException',
'DibiNotSupportedException',
'DibiPcreException',
'DibiProcedureException',
'DibiResult',
'DibiRow',
'IDataSource',
'IDibiDriver',
]);

View File

@@ -73,13 +73,13 @@ system = sqlsrv
;password = "Password12!"
;system = sqlsrv
[sqlsrv 2014]
driver = sqlsrv
host = "(local)\SQL2014"
database = master
username = sa
password = "Password12!"
system = sqlsrv
;[sqlsrv 2014]
;driver = sqlsrv
;host = "(local)\SQL2014"
;database = master
;username = sa
;password = "Password12!"
;system = sqlsrv
;[sqlsrv 2014-pdo]
;driver = pdo

View File

@@ -4,8 +4,8 @@
* @dataProvider ../databases.ini
*/
use Tester\Assert;
use Dibi\Connection;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
@@ -20,7 +20,7 @@ test(function () use ($config) {
test(function () use ($config) { // lazy
$conn = new Connection($config + ['lazy' => TRUE]);
$conn = new Connection($config + ['lazy' => true]);
Assert::false($conn->isConnected());
$conn->query('SELECT 1');
@@ -29,7 +29,7 @@ test(function () use ($config) { // lazy
test(function () use ($config) { // query string
$conn = new Connection(http_build_query($config, NULL, '&'));
$conn = new Connection(http_build_query($config, '', '&'));
Assert::true($conn->isConnected());
Assert::null($conn->getConfig('lazy'));

View File

@@ -4,8 +4,8 @@
* @dataProvider ../databases.ini
*/
use Tester\Assert;
use Dibi\Row;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
@@ -61,9 +61,9 @@ Assert::equal([
// more complex association array
function query($conn) {
return $conn->query(in_array($conn->getConfig('system'), ['odbc', 'sqlsrv']) ? '
function query($conn)
{
return $conn->query(in_array($conn->getConfig('system'), ['odbc', 'sqlsrv'], true) ? '
SELECT products.title, customers.name, orders.amount
FROM ([products]
INNER JOIN [orders] ON [products.product_id] = [orders.product_id])
@@ -170,11 +170,11 @@ Assert::equal([
Assert::equal([
new Row(['title' => 'Chair', 'name' => 'Arnold Rimmer', 'amount' => num(7.0)]),
new Row([
'title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0)]),
'title' => 'Computer', 'name' => 'Arnold Rimmer', 'amount' => num(2.0), ]),
new Row([
'title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0)]),
'title' => 'Table', 'name' => 'Dave Lister', 'amount' => num(3.0), ]),
new Row([
'title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0)]),
'title' => 'Computer', 'name' => 'Kristine Kochanski', 'amount' => num(5.0), ]),
], query($conn)->fetchAssoc('@,='));

View File

@@ -1,7 +1,7 @@
<?php
use Tester\Assert;
use Dibi\Row;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';

View File

@@ -1,7 +1,7 @@
<?php
use Tester\Assert;
use Dibi\Fluent;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';

View File

@@ -30,7 +30,7 @@ Assert::same(
(string) $fluent
);
$fluent->setFlag('IGNORE', FALSE);
$fluent->setFlag('IGNORE', false);
Assert::same(
reformat('DELETE FROM [anotherTable] USING [thirdTable]'),

View File

@@ -7,25 +7,31 @@ require __DIR__ . '/bootstrap.php';
class MockDriver extends Dibi\Drivers\SqlsrvDriver
{
function __construct()
{}
public function __construct()
{
}
function connect(array & $config)
{}
function query($sql)
public function connect(array &$config)
{
}
public function query($sql)
{
return $this;
}
function getResultColumns()
public function getResultColumns()
{
return [];
}
function fetch($assoc)
public function fetch($assoc)
{
return FALSE;
return false;
}
}

View File

@@ -4,8 +4,8 @@
* @dataProvider ../databases.ini
*/
use Tester\Assert;
use Dibi\Row;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
@@ -28,7 +28,7 @@ Assert::equal([
// more complex association array
if (!in_array($config['system'], ['odbc', 'sqlsrv'])) {
if (!in_array($config['system'], ['odbc', 'sqlsrv'], true)) {
$res = $conn->select(['products.title' => 'title', 'customers.name' => 'name'])->select('orders.amount')->as('amount')
->from('products')
->innerJoin('orders')->using('(product_id)')
@@ -48,3 +48,8 @@ if (!in_array($config['system'], ['odbc', 'sqlsrv'])) {
],
], $res->fetchAssoc('name,title'));
}
// affected rows
$res = $conn->update('products', ['title' => 'new'])->execute();
Assert::same(3, $res);

View File

@@ -11,7 +11,7 @@ $conn = new Dibi\Connection($config);
$arr = [
'title' => 'Super Product',
'price' => 12,
'brand' => NULL,
'brand' => null,
];
$fluent = $conn->insert('table', $arr)
@@ -22,7 +22,7 @@ Assert::same(
(string) $fluent
);
$fluent->setFlag('IGNORE', FALSE);
$fluent->setFlag('IGNORE', false);
Assert::same(
reformat('INSERT DELAYED INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'),

View File

@@ -142,10 +142,9 @@ if ($config['system'] === 'mysql') {
->limit(' 1; DROP TABLE users')
->offset(' 1; DROP TABLE users');
Assert::same(
reformat(' SELECT * LIMIT 1 OFFSET 1'),
(string) $fluent
);
Assert::error(function () use ($fluent) {
(string) $fluent;
}, E_USER_ERROR, "Expected number, ' 1; DROP TABLE users' given.");
}

View File

@@ -11,7 +11,7 @@ $conn = new Dibi\Connection($config);
$arr = [
'title' => 'Super Product',
'price' => 12,
'brand' => NULL,
'brand' => null,
];
$fluent = $conn->update('table', $arr)

View File

@@ -6,19 +6,19 @@ use Tester\Assert;
require __DIR__ . '/bootstrap.php';
Assert::same(NULL, Helpers::getSuggestion([], ''));
Assert::same(NULL, Helpers::getSuggestion([], 'a'));
Assert::same(NULL, Helpers::getSuggestion(['a'], 'a'));
Assert::same(null, Helpers::getSuggestion([], ''));
Assert::same(null, Helpers::getSuggestion([], 'a'));
Assert::same(null, Helpers::getSuggestion(['a'], 'a'));
Assert::same('a', Helpers::getSuggestion(['a', 'b'], ''));
Assert::same('b', Helpers::getSuggestion(['a', 'b'], 'a')); // ignore 100% match
Assert::same('a1', Helpers::getSuggestion(['a1', 'a2'], 'a')); // take first
Assert::same(NULL, Helpers::getSuggestion(['aaa', 'bbb'], 'a'));
Assert::same(NULL, Helpers::getSuggestion(['aaa', 'bbb'], 'ab'));
Assert::same(NULL, Helpers::getSuggestion(['aaa', 'bbb'], 'abc'));
Assert::same(null, Helpers::getSuggestion(['aaa', 'bbb'], 'a'));
Assert::same(null, Helpers::getSuggestion(['aaa', 'bbb'], 'ab'));
Assert::same(null, Helpers::getSuggestion(['aaa', 'bbb'], 'abc'));
Assert::same('bar', Helpers::getSuggestion(['foo', 'bar', 'baz'], 'baz'));
Assert::same('abcd', Helpers::getSuggestion(['abcd'], 'acbd'));
Assert::same('abcd', Helpers::getSuggestion(['abcd'], 'axbd'));
Assert::same(NULL, Helpers::getSuggestion(['abcd'], 'axyd'));
Assert::same(null, Helpers::getSuggestion(['abcd'], 'axyd'));
/*

View File

@@ -0,0 +1,25 @@
<?php
use Dibi\Helpers;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
Assert::same(0, Helpers::intVal(0));
Assert::same(0, Helpers::intVal('0'));
Assert::same(-10, Helpers::intVal('-10'));
Assert::same('12345678901234567890123456879', Helpers::intVal('12345678901234567890123456879'));
Assert::same('-12345678901234567890123456879', Helpers::intVal('-12345678901234567890123456879'));
Assert::exception(function () {
Helpers::intVal('');
}, 'Dibi\Exception', "Expected number, '' given.");
Assert::exception(function () {
Helpers::intVal('not number');
}, 'Dibi\Exception', "Expected number, 'not number' given.");
Assert::exception(function () {
Helpers::intVal(null);
}, 'Dibi\Exception', "Expected number, '' given.");

View File

@@ -0,0 +1,41 @@
<?php
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
function buildPdoDriver($errorMode)
{
$pdo = new PDO('sqlite::memory:');
if ($errorMode !== null) {
$pdo->setAttribute(PDO::ATTR_ERRMODE, $errorMode);
}
$config = ['resource' => $pdo];
$driver = new Dibi\Drivers\PdoDriver;
$driver->connect($config);
}
// PDO error mode: exception
Assert::exception(function () {
buildPdoDriver(PDO::ERRMODE_EXCEPTION);
}, 'Dibi\DriverException', 'PDO connection in exception or warning error mode is not supported.');
// PDO error mode: warning
Assert::exception(function () {
buildPdoDriver(PDO::ERRMODE_WARNING);
}, 'Dibi\DriverException', 'PDO connection in exception or warning error mode is not supported.');
// PDO error mode: explicitly set silent
test(function () {
buildPdoDriver(PDO::ERRMODE_SILENT);
});
// PDO error mode: implicitly set silent
test(function () {
buildPdoDriver(null);
});

View File

@@ -11,12 +11,17 @@ require __DIR__ . '/bootstrap.php';
$conn = new Dibi\Connection($config);
$conn->loadFile(__DIR__ . "/data/$config[system].sql");
$info = $conn->query('
$res = $conn->query('
SELECT products.product_id, orders.order_id, customers.name, products.product_id + 1 AS [xXx]
FROM ([products]
INNER JOIN [orders] ON [products.product_id] = [orders.product_id])
INNER JOIN [customers] ON [orders.customer_id] = [customers.customer_id]
')->getInfo();
');
$info = $res->getInfo();
Assert::same(4, $res->getColumnCount());
Assert::same(
@@ -25,10 +30,10 @@ Assert::same(
);
if (!in_array($config['driver'], ['sqlite3', 'pdo', 'sqlsrv'])) {
if (!in_array($config['driver'], ['sqlite3', 'pdo', 'sqlsrv'], true)) {
Assert::same(
['products.product_id', 'orders.order_id', 'customers.name', 'xXx'],
$info->getColumnNames(TRUE)
$info->getColumnNames(true)
);
}
@@ -36,18 +41,18 @@ if (!in_array($config['driver'], ['sqlite3', 'pdo', 'sqlsrv'])) {
$columns = $info->getColumns();
Assert::same('product_id', $columns[0]->getName());
if (!in_array($config['driver'], ['sqlite3', 'pdo', 'sqlsrv'])) {
if (!in_array($config['driver'], ['sqlite3', 'pdo', 'sqlsrv'], true)) {
Assert::same('products', $columns[0]->getTableName());
}
Assert::null($columns[0]->getVendorInfo('xxx'));
if (!in_array($config['system'], ['sqlite', 'sqlsrv'])) {
if (!in_array($config['system'], ['sqlite', 'sqlsrv'], true)) {
Assert::same('i', $columns[0]->getType());
}
Assert::null($columns[0]->isNullable());
Assert::same('xXx', $columns[3]->getName());
Assert::null($columns[3]->getTableName());
if (!in_array($config['system'], ['sqlite', 'sqlsrv'])) {
if (!in_array($config['system'], ['sqlite', 'sqlsrv'], true)) {
Assert::same('i', $columns[0]->getType());
}
Assert::null($columns[3]->isNullable());

View File

@@ -1,21 +1,23 @@
<?php
use Tester\Assert;
use Dibi\Type;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
class MockResult extends Dibi\Result
{
function __construct()
{}
public function __construct()
{
}
function test($row)
public function test($row)
{
$normalize = new ReflectionMethod('Dibi\Result', 'normalize');
$normalize->setAccessible(TRUE);
$normalize->invokeArgs($this, [& $row]);
$normalize->setAccessible(true);
$normalize->invokeArgs($this, [&$row]);
return $row;
}
}
@@ -25,21 +27,21 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::BOOL);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => TRUE], $result->test(['col' => TRUE]));
Assert::same(['col' => FALSE], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::same(['col' => true], $result->test(['col' => true]));
Assert::same(['col' => false], $result->test(['col' => false]));
Assert::same(['col' => FALSE], $result->test(['col' => '']));
Assert::same(['col' => FALSE], $result->test(['col' => '0']));
Assert::same(['col' => TRUE], $result->test(['col' => '1']));
Assert::same(['col' => TRUE], $result->test(['col' => 't']));
Assert::same(['col' => FALSE], $result->test(['col' => 'f']));
Assert::same(['col' => TRUE], $result->test(['col' => 'T']));
Assert::same(['col' => FALSE], $result->test(['col' => 'F']));
Assert::same(['col' => FALSE], $result->test(['col' => 0]));
Assert::same(['col' => FALSE], $result->test(['col' => 0.0]));
Assert::same(['col' => TRUE], $result->test(['col' => 1]));
Assert::same(['col' => TRUE], $result->test(['col' => 1.0]));
Assert::same(['col' => false], $result->test(['col' => '']));
Assert::same(['col' => false], $result->test(['col' => '0']));
Assert::same(['col' => true], $result->test(['col' => '1']));
Assert::same(['col' => true], $result->test(['col' => 't']));
Assert::same(['col' => false], $result->test(['col' => 'f']));
Assert::same(['col' => true], $result->test(['col' => 'T']));
Assert::same(['col' => false], $result->test(['col' => 'F']));
Assert::same(['col' => false], $result->test(['col' => 0]));
Assert::same(['col' => false], $result->test(['col' => 0.0]));
Assert::same(['col' => true], $result->test(['col' => 1]));
Assert::same(['col' => true], $result->test(['col' => 1.0]));
});
@@ -47,9 +49,9 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::TEXT);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => '1'], $result->test(['col' => TRUE]));
Assert::same(['col' => ''], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::same(['col' => '1'], $result->test(['col' => true]));
Assert::same(['col' => ''], $result->test(['col' => false]));
Assert::same(['col' => ''], $result->test(['col' => '']));
Assert::same(['col' => '0'], $result->test(['col' => '0']));
@@ -63,9 +65,9 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::FLOAT);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => 1.0], $result->test(['col' => TRUE]));
Assert::same(['col' => 0.0], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::same(['col' => 1.0], $result->test(['col' => true]));
Assert::same(['col' => 0.0], $result->test(['col' => false]));
Assert::same(['col' => 0.0], $result->test(['col' => '']));
Assert::same(['col' => 0.0], $result->test(['col' => '0']));
@@ -135,9 +137,9 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::INTEGER);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => 1], $result->test(['col' => TRUE]));
Assert::same(['col' => 0], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::same(['col' => 1], $result->test(['col' => true]));
Assert::same(['col' => 0], $result->test(['col' => false]));
Assert::same(['col' => 0], @$result->test(['col' => ''])); // triggers warning in PHP 7.1
Assert::same(['col' => 0], $result->test(['col' => '0']));
@@ -161,14 +163,14 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::DATETIME);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::exception(function () use ($result) {
$result->test(['col' => TRUE]);
$result->test(['col' => true]);
}, 'Exception');
Assert::same(['col' => NULL], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => false]));
Assert::same(['col' => NULL], $result->test(['col' => '']));
Assert::same(['col' => NULL], $result->test(['col' => '0000-00-00']));
Assert::same(['col' => null], $result->test(['col' => '']));
Assert::same(['col' => null], $result->test(['col' => '0000-00-00']));
Assert::equal(['col' => new Dibi\DateTime('00:00:00')], $result->test(['col' => '00:00:00']));
Assert::equal(['col' => new Dibi\DateTime('2015-10-13')], $result->test(['col' => '2015-10-13']));
Assert::equal(['col' => new Dibi\DateTime('2015-10-13 14:30')], $result->test(['col' => '2015-10-13 14:30']));
@@ -180,14 +182,14 @@ test(function () {
$result->setType('col', Type::DATETIME);
$result->setFormat(Type::DATETIME, 'Y-m-d H:i:s');
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::exception(function () use ($result) {
$result->test(['col' => TRUE]);
$result->test(['col' => true]);
}, 'Exception');
Assert::same(['col' => NULL], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => false]));
Assert::same(['col' => NULL], $result->test(['col' => '']));
Assert::same(['col' => NULL], $result->test(['col' => '0000-00-00']));
Assert::same(['col' => null], $result->test(['col' => '']));
Assert::same(['col' => null], $result->test(['col' => '0000-00-00']));
Assert::same(['col' => date('Y-m-d 00:00:00')], $result->test(['col' => '00:00:00']));
Assert::equal(['col' => '2015-10-13 00:00:00'], $result->test(['col' => '2015-10-13']));
Assert::equal(['col' => '2015-10-13 14:30:00'], $result->test(['col' => '2015-10-13 14:30']));
@@ -198,14 +200,14 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::DATE);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::exception(function () use ($result) {
$result->test(['col' => TRUE]);
$result->test(['col' => true]);
}, 'Exception');
Assert::same(['col' => NULL], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => false]));
Assert::same(['col' => NULL], $result->test(['col' => '']));
Assert::same(['col' => NULL], $result->test(['col' => '0000-00-00']));
Assert::same(['col' => null], $result->test(['col' => '']));
Assert::same(['col' => null], $result->test(['col' => '0000-00-00']));
Assert::equal(['col' => new Dibi\DateTime('2015-10-13')], $result->test(['col' => '2015-10-13']));
});
@@ -214,14 +216,14 @@ test(function () {
$result = new MockResult;
$result->setType('col', Type::TIME);
Assert::same(['col' => NULL], $result->test(['col' => NULL]));
Assert::same(['col' => null], $result->test(['col' => null]));
Assert::exception(function () use ($result) {
$result->test(['col' => TRUE]);
$result->test(['col' => true]);
}, 'Exception');
Assert::same(['col' => NULL], $result->test(['col' => FALSE]));
Assert::same(['col' => null], $result->test(['col' => false]));
Assert::same(['col' => NULL], $result->test(['col' => '']));
Assert::same(['col' => NULL], $result->test(['col' => '0000-00-00']));
Assert::same(['col' => null], $result->test(['col' => '']));
Assert::same(['col' => null], $result->test(['col' => '0000-00-00']));
Assert::equal(['col' => new Dibi\DateTime('00:00:00')], $result->test(['col' => '00:00:00']));
Assert::equal(['col' => new Dibi\DateTime('14:30')], $result->test(['col' => '14:30']));
});

View File

@@ -9,7 +9,7 @@ use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$conn = new Dibi\Connection($config);
$conn->loadFile(__DIR__ . "/data/sqlsrv.insert.sql");
$conn->loadFile(__DIR__ . '/data/sqlsrv.insert.sql');
for ($i = 1; $i <= 5; $i++) {
$conn->query('INSERT INTO %n DEFAULT VALUES', 'aaa');

View File

@@ -11,27 +11,37 @@ class TestClass
public $public;
protected $protected;
public static $publicStatic;
protected $protected;
public function publicMethod()
{}
{
}
public static function publicMethodStatic()
{}
{
}
protected function protectedMethod()
{}
{
}
protected static function protectedMethodS()
{}
{
}
public function getBar()
{
return 123;
}
public function isFoo()
{
return 456;

View File

@@ -13,5 +13,5 @@ $translator = new Dibi\Translator($conn);
$datetime = new DateTime('1978-01-23 00:00:00');
Assert::equal($datetime->format('U'), $translator->formatValue(new DateTime($datetime->format('c')), NULL));
Assert::equal($datetime->format('U'), $translator->formatValue(new DateTimeImmutable($datetime->format('c')), NULL));
Assert::equal($datetime->format('U'), $translator->formatValue(new DateTime($datetime->format('c')), null));
Assert::equal($datetime->format('U'), $translator->formatValue(new DateTimeImmutable($datetime->format('c')), null));

View File

@@ -33,7 +33,7 @@ FROM [customers] /* ... */'),
$conn->translate('
SELECT *
FROM %if', TRUE, '[customers] %else [products]'
FROM %if', true, '[customers] %else [products]'
));
@@ -51,8 +51,8 @@ WHERE [id] > 0
SELECT *
FROM [people]
WHERE [id] > 0
%if', FALSE, 'AND [foo]=%i', 1, '
%else %if', TRUE, 'AND [bar]=%i', 1, '
%if', false, 'AND [foo]=%i', 1, '
%else %if', true, 'AND [bar]=%i', 1, '
'));
@@ -70,8 +70,8 @@ WHERE
SELECT *
FROM [customers]
WHERE
%if', TRUE, '[name] LIKE %s', 'xxx', '
%if', FALSE, 'AND [admin]=1 %end
%if', true, '[name] LIKE %s', 'xxx', '
%if', false, 'AND [admin]=1 %end
%else 1 LIMIT 10 %end'
));
@@ -81,7 +81,7 @@ Assert::same(
'SELECT * FROM foo /* (limit 3) (offset 5) */',
$conn->translate(
'SELECT * FROM foo',
'%if', FALSE,
'%if', false,
'%lmt', 3,
'%ofs', 5,
'%end'

View File

@@ -4,28 +4,29 @@
* @dataProvider ../databases.ini
*/
use Tester\Assert;
use Dibi\DateTime;
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$conn = new Dibi\Connection($config + ['formatDateTime' => "'Y-m-d H:i:s'", 'formatDate' => "'Y-m-d'"]);
$conn = new Dibi\Connection($config + ['formatDateTime' => "'Y-m-d H:i:s.u'", 'formatDate' => "'Y-m-d'"]);
// dibi detects INSERT or REPLACE command & booleans
// Dibi detects INSERT or REPLACE command & booleans
Assert::same(
reformat("REPLACE INTO [products] ([title], [price]) VALUES ('Drticka', 318)"),
$conn->translate('REPLACE INTO [products]', [
'title' => 'Drticka',
'price' => 318,
]));
'title' => 'Drticka',
'price' => 318,
])
);
// multiple INSERT command
$array = [
'title' => 'Super Product',
'price' => 12,
'brand' => NULL,
'brand' => null,
];
Assert::same(
reformat('INSERT INTO [products] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL)'),
@@ -45,13 +46,14 @@ Assert::same(
);
// dibi detects UPDATE command
// Dibi detects UPDATE command
Assert::same(
reformat("UPDATE [colors] SET [color]='blue', [order]=12 WHERE [id]=123"),
$conn->translate('UPDATE [colors] SET', [
'color' => 'blue',
'order' => 12,
], 'WHERE [id]=%i', 123));
'color' => 'blue',
'order' => 12,
], 'WHERE [id]=%i', 123)
);
// IN array
@@ -95,7 +97,7 @@ Assert::same(
$conn->translate('TEST %and', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()'])
);
//
$where = [];
$where[] = '[age] > 20';
$where[] = '[email] IS NOT NULL';
@@ -106,7 +108,7 @@ Assert::same(
$where = [];
$where['age'] = NULL;
$where['age'] = null;
$where['email'] = 'ahoj';
$where['id%l'] = [10, 20, 30];
Assert::same(
@@ -128,8 +130,8 @@ $order = [
'field2' => 'desc',
'field3' => 1,
'field4' => -1,
'field5' => TRUE,
'field6' => FALSE,
'field5' => true,
'field6' => false,
];
Assert::same(
reformat('SELECT * FROM [people] ORDER BY [field1] ASC, [field2] DESC, [field3] ASC, [field4] DESC, [field5] ASC, [field6] DESC'),
@@ -156,7 +158,7 @@ if ($config['system'] === 'odbc') {
Assert::same(
reformat([
'sqlsrv' => 'SELECT * FROM [products] OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY',
'SELECT * FROM [products] LIMIT 2 OFFSET 1'
'SELECT * FROM [products] LIMIT 2 OFFSET 1',
]),
$conn->translate('SELECT * FROM [products] %lmt %ofs', 2, 1)
);
@@ -178,22 +180,26 @@ if ($config['system'] === 'odbc') {
Assert::same(
reformat([
'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)",
'odbc' => 'INSERT INTO test ([a2], [a4], [b1], [b2], [b3], [b4], [b5], [b6], [b7], [b8], [b9], [c1]) VALUES (#09/26/1212 00:00:00.000000#, #12/31/1969 22:13:20.000000#, #09/26/1212#, #09/26/1212 00:00:00.000000#, #12/31/1969#, #12/31/1969 22:13:20.000000#, #09/26/1212 00:00:00.000000#, #09/26/1212#, #09/26/1212 00:00:00.000000#, NULL, NULL, #09/26/1212 16:51:34.012400#)',
'mssql' => "INSERT INTO test ([a2], [a4], [b1], [b2], [b3], [b4], [b5], [b6], [b7], [b8], [b9], [c1]) VALUES (CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), CONVERT(DATETIME2(7), '1969-12-31 22:13:20.000000'), '1212-09-26', CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), '1969-12-31', CONVERT(DATETIME2(7), '1969-12-31 22:13:20.000000'), CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), '1212-09-26', CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), NULL, NULL, CONVERT(DATETIME2(7), '1212-09-26 16:51:34.012400'))",
'sqlsrv' => "INSERT INTO test ([a2], [a4], [b1], [b2], [b3], [b4], [b5], [b6], [b7], [b8], [b9], [c1]) VALUES (CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), CONVERT(DATETIME2(7), '1969-12-31 22:13:20.000000'), '1212-09-26', CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), '1969-12-31', CONVERT(DATETIME2(7), '1969-12-31 22:13:20.000000'), CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), '1212-09-26', CONVERT(DATETIME2(7), '1212-09-26 00:00:00.000000'), NULL, NULL, CONVERT(DATETIME2(7), '1212-09-26 16:51:34.012400'))",
"INSERT INTO test ([a2], [a4], [b1], [b2], [b3], [b4], [b5], [b6], [b7], [b8], [b9], [c1]) VALUES ('1212-09-26 00:00:00.000000', '1969-12-31 22:13:20.000000', '1212-09-26', '1212-09-26 00:00:00.000000', '1969-12-31', '1969-12-31 22:13:20.000000', '1212-09-26 00:00:00.000000', '1212-09-26', '1212-09-26 00:00:00.000000', NULL, NULL, '1212-09-26 16:51:34.012400')",
]),
$conn->translate('INSERT INTO test', [
'a2' => new DateTime('1212-09-26'),
'a4' => new DateTime(-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,
]));
'a2' => new DateTime('1212-09-26'),
'a4' => new DateTime(-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,
'c1%t' => new DateTime('1212-09-26 16:51:34.0124'),
])
);
Assert::exception(function () use ($conn) {
$conn->translate('SELECT %s', new DateTime('1212-09-26'));
@@ -284,7 +290,7 @@ $array3 = [
];
$array4 = [
'a' => 12,
'b' => NULL,
'b' => null,
'c' => new DateTime('12.3.2007'),
'd' => 'any string',
];
@@ -395,9 +401,9 @@ WHERE ([test.a] LIKE %d', '1995-03-01', '
OR [b10] IN (', [], ")
AND [c] = 'embedded '' string'
OR [d]=%i", 10.3, '
OR [e]=%i', NULL, '
OR [true]=', TRUE, '
OR [false]=', FALSE, '
OR [e]=%i', null, '
OR [true]=', true, '
OR [false]=', false, '
OR [str_null]=%sn', '', '
OR [str_not_null]=%sn', 'hello', '
LIMIT 10')
@@ -439,7 +445,7 @@ Assert::same(
$where = [
'tablename.column' => 1,
'tablename.column' => 1,
];
Assert::same(
reformat('SELECT * FROM [tablename] WHERE ([tablename].[column] = 1)'),
@@ -449,7 +455,7 @@ Assert::same(
Assert::same(
reformat('SELECT FROM ... '),
$conn->translate('SELECT FROM ... %lmt', NULL)
$conn->translate('SELECT FROM ... %lmt', null)
);
Assert::same(
@@ -466,20 +472,48 @@ Assert::same(
Assert::same(
reformat('INSERT INTO [products] ([product_id], [title]) VALUES (1, SHA1(\'Test product\')) , (1, SHA1(\'Test product\'))'),
$conn->translate('INSERT INTO [products]', [
'product_id' => 1,
'title' => ['SHA1(%s)', 'Test product'],
], [
'product_id' => 1,
'title' => ['SHA1(%s)', 'Test product'],
])
'product_id' => 1,
'title' => ['SHA1(%s)', 'Test product'],
], [
'product_id' => 1,
'title' => new Dibi\Expression('SHA1(%s)', 'Test product'),
])
);
Assert::same(
reformat('UPDATE [products] [product_id]=1, [title]=SHA1(\'Test product\')'),
$conn->translate('UPDATE [products]', [
'product_id' => 1,
'title' => ['SHA1(%s)', 'Test product'],
])
'product_id' => 1,
'title' => ['SHA1(%s)', 'Test product'],
])
);
Assert::same(
reformat('UPDATE [products] [product_id]=1, [title]=SHA1(\'Test product\')'),
$conn->translate('UPDATE [products]', [
'product_id' => 1,
'title' => new Dibi\Expression('SHA1(%s)', 'Test product'),
])
);
Assert::same(
reformat('SELECT * FROM [products] WHERE [product_id]=1, [title]=SHA1(\'Test product\')'),
$conn->translate('SELECT * FROM [products] WHERE', [
'product_id' => 1,
'title' => new Dibi\Expression('SHA1(%s)', 'Test product'),
])
);
Assert::same(
reformat('SELECT * FROM [table] WHERE (([left] = 1) OR ([top] = 2)) AND (number < 100)'),
$conn->translate('SELECT * FROM `table` WHERE %and', [
new Dibi\Expression('%or', [
'left' => 1,
'top' => 2,
]),
new Dibi\Expression('number < %i', 100),
])
);
@@ -496,11 +530,11 @@ Assert::same('INSERT INTO test **Multi-insert array "num%i" is different**', $e-
$array6 = [
'id' => [1, 2, 3, 4],
'text' => ['ahoj', 'jak', 'se', ['SUM(%i)', '5']],
'num%i' => ['1', '', 10.3, 1],
'num%i' => ['1', '-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)'),
reformat('INSERT INTO test ([id], [text], [num]) VALUES (1, \'ahoj\', 1), (2, \'jak\', -1), (3, \'se\', 10), (4, SUM(5), 1)'),
$conn->translate('INSERT INTO test %m', $array6)
);
@@ -520,10 +554,13 @@ Assert::same(
$conn->translate('INSERT INTO [test.*]')
);
Assert::same(
reformat('INSERT INTO 0'),
@$conn->translate('INSERT INTO %f', 'ahoj') // triggers warning in PHP 7.1
);
Assert::exception(function () use ($conn) {
$conn->translate('INSERT INTO %i', 'ahoj');
}, 'Dibi\Exception', "Expected number, 'ahoj' given.");
Assert::exception(function () use ($conn) {
$conn->translate('INSERT INTO %f', 'ahoj');
}, 'Dibi\Exception', "Expected number, 'ahoj' given.");
Assert::same(
@@ -548,17 +585,17 @@ Assert::same(
);
setLocale(LC_ALL, 'czech');
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', [
'color' => 'blue',
'price' => -12.4,
'spec%f' => '-9E-005',
'spec2%f' => 1000.00,
'spec3%i' => 10000,
'spec4' => 10000,
], 'WHERE [price]=%f', 123.5)
'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

@@ -18,7 +18,7 @@ date_default_timezone_set('Europe/Prague');
try {
$config = Tester\Environment::loadData();
} catch (Exception $e) {
$config = parse_ini_file(__DIR__ . '/../databases.ini', TRUE);
$config = parse_ini_file(__DIR__ . '/../databases.ini', true);
$config = reset($config);
}
@@ -40,9 +40,6 @@ if ($config['driver'] === 'mysql' && PHP_VERSION_ID >= 70000) {
}
$conn = new Dibi\Connection($config);
function test(Closure $function)
{
$function();
@@ -63,7 +60,7 @@ function reformat($s)
return strtr($s, '[]', '``');
} elseif ($config['system'] === 'postgre') {
return strtr($s, '[]', '""');
} elseif (in_array($config['system'], ['odbc', 'sqlite', 'sqlsrv'])) {
} elseif (in_array($config['system'], ['odbc', 'sqlite', 'sqlsrv'], true)) {
return $s;
} else {
trigger_error("Unsupported driver $config[system]", E_USER_WARNING);

View File

@@ -0,0 +1,11 @@
<?php
use Tester\Assert;
require __DIR__ . '/bootstrap.php';
$dt = new DateTime('2018-04-18 13:40:09.123456');
$res = dibi::stripMicroseconds($dt);
Assert::same('2018-04-18 13:40:09.123456', $dt->format('Y-m-d H:i:s.u'));
Assert::same('2018-04-18 13:40:09.000000', $res->format('Y-m-d H:i:s.u'));

View File

@@ -15,7 +15,7 @@ $conn->loadFile(__DIR__ . "/data/$config[system].sql");
$e = Assert::exception(function () use ($conn) {
$conn->query('SELECT');
}, 'Dibi\DriverException', "%a% error in your SQL syntax;%a%", 1064);
}, 'Dibi\DriverException', '%a% error in your SQL syntax;%a%', 1064);
Assert::same('SELECT', $e->getSql());

View File

@@ -15,21 +15,21 @@ $conn->loadFile(__DIR__ . "/data/$config[system].sql");
$e = Assert::exception(function () use ($conn) {
$conn->query('SELECT');
}, 'Dibi\DriverException', '%a% syntax error', 1);
}, 'Dibi\DriverException', '%a%', 1);
Assert::same('SELECT', $e->getSql());
$e = Assert::exception(function () use ($conn) {
$conn->query('INSERT INTO products (product_id, title) VALUES (1, "New")');
}, 'Dibi\UniqueConstraintViolationException', NULL, 19);
}, 'Dibi\UniqueConstraintViolationException', null, 19);
Assert::same("INSERT INTO products (product_id, title) VALUES (1, 'New')", $e->getSql());
$e = Assert::exception(function () use ($conn) {
$conn->query('INSERT INTO products (title) VALUES (NULL)');
}, 'Dibi\NotNullConstraintViolationException', NULL, 19);
}, 'Dibi\NotNullConstraintViolationException', null, 19);
Assert::same('INSERT INTO products (title) VALUES (NULL)', $e->getSql());
@@ -37,6 +37,6 @@ Assert::same('INSERT INTO products (title) VALUES (NULL)', $e->getSql());
$e = Assert::exception(function () use ($conn) {
$conn->query('PRAGMA foreign_keys=true');
$conn->query('INSERT INTO orders (customer_id, product_id, amount) VALUES (100, 1, 1)');
}, 'Dibi\ForeignKeyConstraintViolationException', NULL, 19);
}, 'Dibi\ForeignKeyConstraintViolationException', null, 19);
Assert::same('INSERT INTO orders (customer_id, product_id, amount) VALUES (100, 1, 1)', $e->getSql());