mirror of
https://github.com/dg/dibi.git
synced 2025-08-30 09:19:48 +02:00
Compare commits
78 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d571460a6f | ||
|
dc3e1cda19 | ||
|
21039ff379 | ||
|
22b15d9859 | ||
|
6aa8a431c2 | ||
|
69ea60cc16 | ||
|
906e1f2407 | ||
|
6a4f77b684 | ||
|
689597a237 | ||
|
a8ed2a34e5 | ||
|
c8e5f5c8d1 | ||
|
4bfd314225 | ||
|
2b4ea9abe7 | ||
|
3711b1739f | ||
|
45d7e0b365 | ||
|
7d07db1f12 | ||
|
34bdd5f267 | ||
|
5a7543a5a6 | ||
|
2848c965f9 | ||
|
3660f26e03 | ||
|
f474abfeda | ||
|
809386edf8 | ||
|
1909c98e6d | ||
|
8985c71276 | ||
|
0d5fd9d65b | ||
|
4049ea4717 | ||
|
cec699af0f | ||
|
59a4cc2fe0 | ||
|
985f09417e | ||
|
729d133d70 | ||
|
759c63bca0 | ||
|
f9fc7e330d | ||
|
dbca915bfe | ||
|
1bae6eae08 | ||
|
34b7e22d40 | ||
|
369f5ee7d6 | ||
|
2d74bb3da0 | ||
|
a5422a65c9 | ||
|
5c806ea517 | ||
|
ecafed6246 | ||
|
504b7725c7 | ||
|
822405b478 | ||
|
43d3b57a8d | ||
|
4f0566ece7 | ||
|
67521084d9 | ||
|
22ac601502 | ||
|
b740b70f18 | ||
|
44fc3f4553 | ||
|
fa35c0cf7d | ||
|
8a25700c8c | ||
|
1352437e08 | ||
|
f0d08a990c | ||
|
4472fb3a3d | ||
|
d4b87490a1 | ||
|
9486b65b84 | ||
|
f47ad15af0 | ||
|
6c147f2ea5 | ||
|
0af64b5f9b | ||
|
03c6eeeb16 | ||
|
ad3a9c50f9 | ||
|
d31f2e3dd4 | ||
|
3253a5b092 | ||
|
be3a0aa57d | ||
|
6a4cc4f36f | ||
|
1815b214ee | ||
|
4f75637b63 | ||
|
ebf0be1fd0 | ||
|
b439ee9df1 | ||
|
e45a86d58c | ||
|
e891bdd862 | ||
|
8dc5567bdd | ||
|
e3bfac2316 | ||
|
53475ba05a | ||
|
c219726914 | ||
|
ed0cb63df0 | ||
|
1ab69f3576 | ||
|
70f29f6857 | ||
|
d365077319 |
69
.travis.yml
69
.travis.yml
@@ -5,20 +5,16 @@ php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
|
||||
script:
|
||||
- vendor/bin/tester tests -s -p php -c tests/php-unix.ini $COVERAGE
|
||||
- php temp/code-checker/src/code-checker.php --short-arrays
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
|
||||
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
|
||||
@@ -26,16 +22,51 @@ 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
|
||||
|
||||
dist: trusty
|
||||
|
10
appveyor.yml
10
appveyor.yml
@@ -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" )
|
||||
|
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
trigger_error('Dibi was moved to /src/loader.php', E_USER_WARNING);
|
||||
require __DIR__ . '/../src/loader.php';
|
@@ -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) {
|
||||
|
@@ -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";
|
||||
|
@@ -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)
|
||||
|
@@ -9,11 +9,11 @@ Tracy\Debugger::enable();
|
||||
?>
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Fetching Examples | dibi</h1>
|
||||
<h1>Fetching Examples | Dibi</h1>
|
||||
|
||||
<?php
|
||||
|
||||
dibi::connect([
|
||||
$dibi = new Dibi\Connection([
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
]);
|
||||
@@ -33,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)
|
||||
@@ -84,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);
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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'
|
||||
|
@@ -13,18 +13,18 @@ date_default_timezone_set('Europe/Prague');
|
||||
?>
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Result Set Data Types | dibi</h1>
|
||||
<h1>Result Set Data Types | Dibi</h1>
|
||||
|
||||
<?php
|
||||
|
||||
dibi::connect([
|
||||
$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)
|
||||
@@ -40,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:
|
||||
|
@@ -9,22 +9,22 @@ 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">
|
||||
|
||||
|
@@ -9,25 +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);
|
||||
|
||||
|
||||
// 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]');
|
||||
|
||||
|
||||
?>
|
||||
|
@@ -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'),
|
||||
|
@@ -9,11 +9,11 @@ Tracy\Debugger::enable();
|
||||
?>
|
||||
<!DOCTYPE html><link rel="stylesheet" href="data/style.css">
|
||||
|
||||
<h1>Using Extension Methods | dibi</h1>
|
||||
<h1>Using Extension Methods | Dibi</h1>
|
||||
|
||||
<?php
|
||||
|
||||
dibi::connect([
|
||||
$dibi = new Dibi\Connection([
|
||||
'driver' => 'sqlite3',
|
||||
'database' => 'data/sample.s3db',
|
||||
]);
|
||||
@@ -28,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);
|
||||
|
@@ -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]
|
||||
|
@@ -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
|
||||
|
@@ -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>';
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
60
readme.md
60
readme.md
@@ -1,4 +1,4 @@
|
||||
[Dibi](https://dibiphp.com) - smart database layer for PHP [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9XXL5ZJHAYQUN)
|
||||
[Dibi](https://dibiphp.com) - smart database layer for PHP [](https://nette.org/make-donation?to=dibi)
|
||||
=========================================================
|
||||
|
||||
[](https://packagist.org/packages/dibi/dibi)
|
||||
@@ -7,22 +7,30 @@
|
||||
[](https://github.com/dg/dibi/releases)
|
||||
[](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')
|
||||
|
@@ -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']]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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 ms</th><th>SQL Statement</th><th>Rows</th><th>Connection</th></tr>' . $s . '
|
||||
</table>
|
||||
</div>';
|
||||
}
|
||||
|
||||
}
|
@@ -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
|
||||
|
@@ -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 array|NULL
|
||||
* @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),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -96,25 +96,25 @@ class Panel implements Tracy\IBarPanel
|
||||
|
||||
/**
|
||||
* Returns HTML code for custom panel. (Tracy\IBarPanel)
|
||||
* @return string|NULL
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPanel()
|
||||
{
|
||||
if (!$this->events) {
|
||||
return NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
$totalTime = $s = NULL;
|
||||
$totalTime = $s = null;
|
||||
foreach ($this->events as $event) {
|
||||
$totalTime += $event->time;
|
||||
$connection = $event->connection;
|
||||
$explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS()
|
||||
$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 = [$connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime];
|
||||
$connection->onEvent = NULL;
|
||||
$cmd = is_string($this->explain) ? $this->explain : ($connection->getConfig('driver') === 'oracle' ? 'EXPLAIN PLAN FOR' : 'EXPLAIN');
|
||||
$explain = @Helpers::dump($connection->nativeQuery("$cmd $event->sql"), TRUE);
|
||||
$explain = @Helpers::dump($connection->nativeQuery("$cmd $event->sql"), true);
|
||||
} catch (Dibi\Exception $e) {
|
||||
}
|
||||
list($connection->onEvent, \dibi::$numOfQueries, \dibi::$totalTime) = $backup;
|
||||
@@ -127,7 +127,7 @@ class Panel implements Tracy\IBarPanel
|
||||
$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>";
|
||||
}
|
||||
@@ -142,8 +142,8 @@ class Panel implements Tracy\IBarPanel
|
||||
#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 ? '' : ', time: ' . number_format($totalTime * 1000, 1, '.', ' ') . ' ms') . ', '
|
||||
. htmlSpecialChars($connection->getConfig('driver') . ($connection->getConfig('name') ? '/' . $connection->getConfig('name') : '')
|
||||
. ($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>
|
||||
@@ -151,5 +151,4 @@ class Panel implements Tracy\IBarPanel
|
||||
</table>
|
||||
</div>';
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
@@ -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])) {
|
||||
@@ -217,7 +216,9 @@ class Connection
|
||||
*/
|
||||
final public function getDriver()
|
||||
{
|
||||
$this->connected || $this->connect();
|
||||
if (!$this->connected) {
|
||||
$this->connect();
|
||||
}
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -308,15 +311,19 @@ class Connection
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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|FALSE
|
||||
* @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)
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var int|null */
|
||||
private $offset;
|
||||
|
||||
/** @var int|NULL */
|
||||
/** @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|NULL 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
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -18,12 +18,12 @@ class DateTime extends \DateTime
|
||||
/**
|
||||
* @param string|int
|
||||
*/
|
||||
public function __construct($time = 'now', \DateTimeZone $timezone = NULL)
|
||||
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);
|
||||
@@ -33,7 +33,7 @@ class DateTime extends \DateTime
|
||||
|
||||
public function modifyClone($modify = '')
|
||||
{
|
||||
$dolly = clone($this);
|
||||
$dolly = clone $this;
|
||||
return $modify ? $dolly->modify($modify) : $dolly;
|
||||
}
|
||||
|
||||
@@ -55,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');
|
||||
}
|
||||
|
||||
|
||||
@@ -71,5 +71,4 @@ class DateTime extends \DateTime
|
||||
parent::__wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = TRUE;
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @var resource|null */
|
||||
private $transaction;
|
||||
|
||||
/** @var bool */
|
||||
private $inTransaction = FALSE;
|
||||
private $inTransaction = false;
|
||||
|
||||
|
||||
/**
|
||||
@@ -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,13 +122,13 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
} elseif (is_resource($res)) {
|
||||
return $this->createResultDriver($res);
|
||||
}
|
||||
return 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()
|
||||
{
|
||||
@@ -140,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)
|
||||
{
|
||||
@@ -154,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,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.');
|
||||
}
|
||||
|
||||
@@ -180,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,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.');
|
||||
}
|
||||
|
||||
@@ -200,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -216,11 +215,11 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
* @return resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -277,7 +276,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
*/
|
||||
public function escapeIdentifier($value)
|
||||
{
|
||||
return '"' . str_replace('"', '""', $value). '"';
|
||||
return '"' . str_replace('"', '""', $value) . '"';
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +312,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
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) . "'";
|
||||
}
|
||||
|
||||
|
||||
@@ -351,15 +350,17 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
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 . ')';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -389,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)
|
||||
@@ -413,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)
|
||||
@@ -429,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|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -481,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',
|
||||
@@ -530,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,
|
||||
@@ -539,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;
|
||||
@@ -568,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;
|
||||
@@ -598,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,
|
||||
@@ -625,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;
|
||||
@@ -649,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;
|
||||
@@ -663,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,
|
||||
@@ -689,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'],
|
||||
@@ -711,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;
|
||||
@@ -767,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'];
|
||||
@@ -786,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;
|
||||
@@ -804,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;
|
||||
@@ -823,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = TRUE;
|
||||
private $autoFree = true;
|
||||
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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,26 +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;
|
||||
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()
|
||||
{
|
||||
@@ -114,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)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
$row = mssql_fetch_row($res);
|
||||
return $row[0];
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,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');
|
||||
}
|
||||
@@ -145,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');
|
||||
}
|
||||
@@ -157,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');
|
||||
}
|
||||
@@ -165,11 +165,11 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
* @return resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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'") . ')';
|
||||
}
|
||||
|
||||
|
||||
@@ -302,8 +302,8 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -314,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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -345,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)
|
||||
@@ -357,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)
|
||||
{
|
||||
@@ -372,7 +374,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
public function free()
|
||||
{
|
||||
mssql_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -399,12 +401,11 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = TRUE;
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var bool Is buffered (seekable and countable)? */
|
||||
private $buffered;
|
||||
@@ -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 resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -347,7 +349,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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'");
|
||||
}
|
||||
|
||||
|
||||
@@ -386,8 +388,8 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -395,10 +397,10 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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) : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,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)
|
||||
@@ -443,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)
|
||||
@@ -463,7 +465,7 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
public function free()
|
||||
{
|
||||
mysql_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -482,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,
|
||||
];
|
||||
}
|
||||
@@ -492,12 +494,11 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var \mysqli|null */
|
||||
private $connection;
|
||||
|
||||
/** @var \mysqli_result|NULL */
|
||||
/** @var \mysqli_result|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = TRUE;
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var bool Is buffered (seekable and countable)? */
|
||||
private $buffered;
|
||||
@@ -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,8 +89,8 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,13 +99,8 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
$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,12 +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;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,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 {
|
||||
@@ -203,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)
|
||||
{
|
||||
@@ -227,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');
|
||||
}
|
||||
@@ -239,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');
|
||||
}
|
||||
@@ -251,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');
|
||||
}
|
||||
@@ -259,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -355,7 +351,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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'");
|
||||
}
|
||||
|
||||
|
||||
@@ -394,8 +390,8 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -403,10 +399,10 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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) : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -439,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)
|
||||
@@ -451,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)
|
||||
@@ -470,7 +468,7 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
public function free()
|
||||
{
|
||||
mysqli_free_result($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -481,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) {
|
||||
@@ -501,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,
|
||||
];
|
||||
}
|
||||
@@ -511,12 +509,11 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return \mysqli_result|NULL
|
||||
* @return \mysqli_result|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = FALSE;
|
||||
$this->autoFree = false;
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @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;
|
||||
@@ -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,28 +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;
|
||||
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()
|
||||
{
|
||||
@@ -126,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)
|
||||
{
|
||||
@@ -140,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));
|
||||
}
|
||||
}
|
||||
@@ -154,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -169,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -190,11 +197,11 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
* @return resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +281,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
|
||||
$value = new Dibi\DateTime($value);
|
||||
}
|
||||
return $value->format("#m/d/Y#");
|
||||
return $value->format('#m/d/Y#');
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +294,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
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#');
|
||||
}
|
||||
|
||||
|
||||
@@ -326,8 +333,8 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -338,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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -370,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)
|
||||
@@ -380,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 = [];
|
||||
@@ -395,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -411,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -426,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),
|
||||
];
|
||||
@@ -437,12 +446,12 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -516,5 +525,4 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
{
|
||||
throw new Dibi\NotImplementedException;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -67,8 +67,14 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
public function connect(array &$config)
|
||||
{
|
||||
$foo = &$config['charset'];
|
||||
$this->fmtDate = isset($config['formatDate']) ? $config['formatDate'] : 'U';
|
||||
$this->fmtDateTime = isset($config['formatDateTime']) ? $config['formatDateTime'] : 'U';
|
||||
|
||||
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,28 +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;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,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 {
|
||||
@@ -149,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()
|
||||
{
|
||||
@@ -159,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -173,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,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 resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +304,9 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
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')";
|
||||
}
|
||||
|
||||
|
||||
@@ -311,7 +319,9 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
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')";
|
||||
}
|
||||
|
||||
|
||||
@@ -351,8 +361,8 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -363,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -397,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)
|
||||
@@ -409,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)
|
||||
{
|
||||
@@ -424,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -440,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,
|
||||
];
|
||||
@@ -451,12 +463,12 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -471,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],
|
||||
@@ -492,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,
|
||||
@@ -527,5 +539,4 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
{
|
||||
throw new Dibi\NotImplementedException;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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,20 +21,19 @@ 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|NULL 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;
|
||||
@@ -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 NULL;
|
||||
}
|
||||
} 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()
|
||||
{
|
||||
@@ -348,7 +342,15 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -415,8 +417,8 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -427,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;
|
||||
|
||||
@@ -454,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;
|
||||
|
||||
@@ -467,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.');
|
||||
}
|
||||
@@ -507,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)
|
||||
@@ -519,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)
|
||||
{
|
||||
@@ -533,7 +533,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->resultSet = NULL;
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -548,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',
|
||||
];
|
||||
|
||||
@@ -560,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,
|
||||
];
|
||||
@@ -571,11 +571,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return \PDOStatement|NULL
|
||||
* @return \PDOStatement|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -57,7 +56,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
*/
|
||||
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,21 +144,21 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
return $this->createResultDriver($res);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
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') {
|
||||
@@ -179,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()
|
||||
{
|
||||
@@ -189,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 {
|
||||
@@ -201,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,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');
|
||||
}
|
||||
@@ -227,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');
|
||||
}
|
||||
@@ -239,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');
|
||||
}
|
||||
@@ -251,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 resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -361,7 +360,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
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'");
|
||||
}
|
||||
|
||||
|
||||
@@ -402,8 +401,8 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -411,11 +410,11 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -445,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)
|
||||
{
|
||||
@@ -472,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -499,12 +500,12 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -547,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 ?: [];
|
||||
}
|
||||
|
||||
|
||||
@@ -601,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',
|
||||
@@ -641,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'];
|
||||
}
|
||||
|
||||
@@ -654,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';
|
||||
@@ -715,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'],
|
||||
@@ -740,5 +741,4 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
|
||||
return $fKeys;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL */
|
||||
/** @var SQLite3|null */
|
||||
private $connection;
|
||||
|
||||
/** @var \SQLite3Result|NULL */
|
||||
/** @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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -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,23 +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;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,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);
|
||||
|
||||
@@ -154,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()
|
||||
{
|
||||
@@ -164,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)
|
||||
{
|
||||
@@ -178,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');
|
||||
}
|
||||
@@ -190,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');
|
||||
}
|
||||
@@ -202,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');
|
||||
}
|
||||
@@ -210,7 +214,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
* @return SQLite3
|
||||
* @return SQLite3|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
@@ -346,8 +350,8 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -355,9 +359,9 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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) : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,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;
|
||||
}
|
||||
@@ -412,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)
|
||||
@@ -428,7 +431,7 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
public function free()
|
||||
{
|
||||
$this->resultSet->finalize();
|
||||
$this->resultSet = NULL;
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -442,11 +445,12 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
$columns = [];
|
||||
static $types = [SQLITE3_INTEGER => 'int', SQLITE3_FLOAT => 'float', SQLITE3_TEXT => 'text', SQLITE3_BLOB => 'blob', SQLITE3_NULL => 'null'];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$type = $this->resultSet->columnType($i); // buggy in PHP 7.4.4 & 7.3.16, bug 79414
|
||||
$columns[] = [
|
||||
'name' => $this->resultSet->columnName($i),
|
||||
'table' => NULL,
|
||||
'table' => null,
|
||||
'fullname' => $this->resultSet->columnName($i),
|
||||
'nativetype' => $types[$this->resultSet->columnType($i)],
|
||||
'nativetype' => $type ? $types[$type] : null,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
@@ -455,11 +459,11 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return \SQLite3Result|NULL
|
||||
* @return \SQLite3Result|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = FALSE;
|
||||
$this->autoFree = false;
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
@@ -492,5 +496,4 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
{
|
||||
$this->connection->createAggregate($name, $rowCallback, $agrCallback, $numArgs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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,23 +22,22 @@ 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|NULL */
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|NULL */
|
||||
/** @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 = '';
|
||||
@@ -106,29 +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;
|
||||
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()
|
||||
{
|
||||
@@ -138,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)
|
||||
{
|
||||
@@ -147,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,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);
|
||||
}
|
||||
@@ -169,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);
|
||||
}
|
||||
@@ -181,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);
|
||||
}
|
||||
@@ -189,11 +187,11 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the connection resource.
|
||||
* @return resource|NULL
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return is_resource($this->connection) ? $this->connection : NULL;
|
||||
return is_resource($this->connection) ? $this->connection : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +285,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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'") . ')';
|
||||
}
|
||||
|
||||
|
||||
@@ -326,8 +324,8 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
public function applyLimit(&$sql, $limit, $offset)
|
||||
@@ -339,11 +337,11 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
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) {
|
||||
@@ -362,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -378,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)
|
||||
@@ -390,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)
|
||||
{
|
||||
@@ -405,7 +405,7 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
public function free()
|
||||
{
|
||||
sqlsrv_free_stmt($this->resultSet);
|
||||
$this->resultSet = NULL;
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -429,12 +429,11 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
32
src/Dibi/Expression.php
Normal 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;
|
||||
}
|
||||
}
|
@@ -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,9 +126,9 @@ 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 = [];
|
||||
@@ -146,13 +146,13 @@ class Fluent implements IDataSource
|
||||
|
||||
// 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) {
|
||||
@@ -212,7 +212,7 @@ class Fluent implements IDataSource
|
||||
public function clause($clause)
|
||||
{
|
||||
$this->cursor = &$this->clauses[self::$normalizer->$clause];
|
||||
if ($this->cursor === NULL) {
|
||||
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()
|
||||
@@ -303,7 +302,7 @@ class Fluent implements IDataSource
|
||||
* @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
|
||||
* @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));
|
||||
@@ -517,5 +517,4 @@ class Fluent implements IDataSource
|
||||
}
|
||||
$this->cursor = &$foo;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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((string) $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((string) $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;
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|");
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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|NULL $size
|
||||
* @property-read bool|NULL $unsigned
|
||||
* @property-read bool|NULL $nullable
|
||||
* @property-read bool|NULL $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|NULL
|
||||
* @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 ==
|
||||
}
|
||||
|
||||
|
||||
@@ -110,38 +109,38 @@ class Column
|
||||
|
||||
|
||||
/**
|
||||
* @return int|NULL
|
||||
* @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|NULL
|
||||
* @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|NULL
|
||||
* @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|NULL
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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']);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
* @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;
|
||||
$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.");
|
||||
}
|
||||
@@ -303,10 +302,10 @@ class Result implements IDataSource
|
||||
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 = null; // prepare child node
|
||||
} else {
|
||||
$x = &$x->{$assoc[$i + 1]};
|
||||
}
|
||||
@@ -316,10 +315,9 @@ class Result implements IDataSource
|
||||
}
|
||||
}
|
||||
|
||||
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 @
|
||||
@@ -363,19 +361,19 @@ class Result implements IDataSource
|
||||
$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 = null; // prepare child node
|
||||
} else {
|
||||
$x = &$x->{$assoc[$i + 1]};
|
||||
}
|
||||
@@ -385,14 +383,13 @@ class Result implements IDataSource
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -486,7 +483,7 @@ class Result implements IDataSource
|
||||
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];
|
||||
@@ -501,8 +498,11 @@ class Result implements IDataSource
|
||||
} elseif ($type === Type::FLOAT) {
|
||||
$value = ltrim((string) $value, '0');
|
||||
$p = strpos($value, '.');
|
||||
if ($p !== FALSE) {
|
||||
$e = strpos($value, 'e');
|
||||
if ($p !== false && $e === false) {
|
||||
$value = rtrim(rtrim($value, '0'), '.');
|
||||
} elseif ($p !== false && $e !== false) {
|
||||
$value = rtrim($value, '.');
|
||||
}
|
||||
if ($value === '' || $value[0] === '.') {
|
||||
$value = '0' . $value;
|
||||
@@ -515,11 +515,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) {
|
||||
@@ -529,6 +529,9 @@ class Result implements IDataSource
|
||||
|
||||
} elseif ($type === Type::BINARY) {
|
||||
$row[$key] = $this->getResultDriver()->unescapeBinary($value);
|
||||
|
||||
} else {
|
||||
$row[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -553,14 +556,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 date format.
|
||||
* @param string
|
||||
* @param string|NULL format
|
||||
* @param string|null format
|
||||
* @return self
|
||||
*/
|
||||
final public function setFormat($type, $format)
|
||||
@@ -572,11 +575,11 @@ class Result implements IDataSource
|
||||
|
||||
/**
|
||||
* Returns data format.
|
||||
* @return string|NULL
|
||||
* @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 +592,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 +619,4 @@ class Result implements IDataSource
|
||||
{
|
||||
echo Helpers::dump($this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
{
|
||||
@@ -31,7 +22,7 @@ class ResultIterator implements \Iterator, \Countable
|
||||
private $row;
|
||||
|
||||
/** @var int */
|
||||
private $pointer;
|
||||
private $pointer = 0;
|
||||
|
||||
|
||||
/**
|
||||
@@ -104,5 +95,4 @@ class ResultIterator implements \Iterator, \Countable
|
||||
{
|
||||
return $this->result->getRowCount();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,29 +108,29 @@ trait Strict
|
||||
* @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
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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,9 +70,10 @@ final class Translator
|
||||
$args = array_values($args[0]);
|
||||
}
|
||||
$this->args = $args;
|
||||
$this->errors = [];
|
||||
|
||||
$commandIns = NULL;
|
||||
$lastArr = NULL;
|
||||
$commandIns = null;
|
||||
$lastArr = null;
|
||||
$cursor = &$this->cursor;
|
||||
$comment = &$this->comment;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -247,7 +248,7 @@ final class Translator
|
||||
case 'l': // (val, val, ...)
|
||||
foreach ($value as $k => $v) {
|
||||
$pair = explode('%', (string) $k, 2); // split into identifier & modifier
|
||||
$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 '(' . (($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((string) $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((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**";
|
||||
@@ -487,7 +501,7 @@ final class Translator
|
||||
}
|
||||
|
||||
$cursor++;
|
||||
return $this->formatValue($this->args[$cursor - 1], FALSE);
|
||||
return $this->formatValue($this->args[$cursor - 1], false);
|
||||
}
|
||||
|
||||
if (!empty($matches[10])) { // modifier
|
||||
@@ -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');
|
||||
@@ -607,5 +621,4 @@ final class Translator
|
||||
}
|
||||
return implode('.', $parts);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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__);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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.8',
|
||||
REVISION = 'released on 2017-06-09';
|
||||
VERSION = '3.2.4',
|
||||
REVISION = 'released on 2020-03-26';
|
||||
|
||||
/** 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,7 +84,7 @@ 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
|
||||
@@ -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.');
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
@@ -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 = '', $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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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,11 +19,10 @@ interface IDataSource extends \Countable, \IteratorAggregate
|
||||
|
||||
|
||||
/**
|
||||
* dibi driver interface.
|
||||
* Driver interface.
|
||||
*/
|
||||
interface Driver
|
||||
{
|
||||
|
||||
/**
|
||||
* Connects to a database.
|
||||
* @param array
|
||||
@@ -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.
|
||||
@@ -143,21 +142,19 @@ interface Driver
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
* @param string
|
||||
* @param int|NULL
|
||||
* @param int|NULL
|
||||
* @param int|null
|
||||
* @param int|null
|
||||
* @return void
|
||||
*/
|
||||
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
|
||||
@@ -167,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
|
||||
*/
|
||||
@@ -205,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 ]}
|
||||
@@ -241,5 +236,4 @@ interface Reflector
|
||||
* @return array
|
||||
*/
|
||||
function getForeignKeys($table);
|
||||
|
||||
}
|
||||
|
@@ -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',
|
||||
]);
|
||||
|
@@ -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');
|
||||
|
@@ -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('@,='));
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
use Dibi\Row;
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Tester\Assert;
|
||||
use Dibi\Fluent;
|
||||
use Tester\Assert;
|
||||
|
||||
require __DIR__ . '/bootstrap.php';
|
||||
|
||||
|
@@ -30,7 +30,7 @@ Assert::same(
|
||||
(string) $fluent
|
||||
);
|
||||
|
||||
$fluent->setFlag('IGNORE', FALSE);
|
||||
$fluent->setFlag('IGNORE', false);
|
||||
|
||||
Assert::same(
|
||||
reformat('DELETE FROM [anotherTable] USING [thirdTable]'),
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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)'),
|
||||
|
@@ -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.");
|
||||
}
|
||||
|
||||
|
||||
|
@@ -11,7 +11,7 @@ $conn = new Dibi\Connection($config);
|
||||
$arr = [
|
||||
'title' => 'Super Product',
|
||||
'price' => 12,
|
||||
'brand' => NULL,
|
||||
'brand' => null,
|
||||
];
|
||||
|
||||
$fluent = $conn->update('table', $arr)
|
||||
|
@@ -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'));
|
||||
|
||||
|
||||
/*
|
||||
|
25
tests/dibi/Helpers.intVal().phpt
Normal file
25
tests/dibi/Helpers.intVal().phpt
Normal 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.");
|
41
tests/dibi/PdoDriver.providedConnection.phpt
Normal file
41
tests/dibi/PdoDriver.providedConnection.phpt
Normal 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);
|
||||
});
|
@@ -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());
|
||||
|
@@ -1,20 +1,22 @@
|
||||
<?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->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']));
|
||||
@@ -97,6 +99,11 @@ test(function () {
|
||||
Assert::same(['col' => 1.0], $result->test(['col' => 1]));
|
||||
Assert::same(['col' => 1.0], $result->test(['col' => 1.0]));
|
||||
|
||||
Assert::same(['col' => '1.1e+10'], $result->test(['col' => '1.1e+10']));
|
||||
Assert::same(['col' => '1.1e-10'], $result->test(['col' => '1.1e-10']));
|
||||
Assert::same(['col' => '1.1e+10'], $result->test(['col' => '001.1e+10']));
|
||||
Assert::notSame(['col' => '1.1e+1'], $result->test(['col' => '1.1e+10']));
|
||||
|
||||
setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');
|
||||
Assert::same(['col' => 0.0], $result->test(['col' => '']));
|
||||
Assert::same(['col' => 0.0], $result->test(['col' => '0']));
|
||||
@@ -135,9 +142,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 +168,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 +187,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 +205,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 +221,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']));
|
||||
});
|
||||
|
@@ -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');
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
|
@@ -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'
|
||||
|
@@ -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)
|
||||
);
|
||||
|
@@ -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);
|
||||
|
11
tests/dibi/dibi.stripMicroseconds.phpt
Normal file
11
tests/dibi/dibi.stripMicroseconds.phpt
Normal 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'));
|
@@ -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());
|
||||
|
||||
|
@@ -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());
|
||||
|
Reference in New Issue
Block a user