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

Compare commits

...

12 Commits

Author SHA1 Message Date
David Grudl
34bc742245 refactoring 2020-10-08 16:49:47 +02:00
Miloslav Hůla
f5fa2255ff FileLogger: fixed object to string conversion with custom driver (#376) (#376)
Co-authored-by: Miloslav Hůla <miloslav.hula@fsv.cvut.cz>
2020-10-08 16:38:35 +02:00
Miloslav Hůla
7b02296f3e Tracy\Panel: fixed object to string converion error with custom driver (#373)
Co-authored-by: Miloslav Hůla <miloslav.hula@fsv.cvut.cz>
2020-10-08 16:38:35 +02:00
David Grudl
df4cddac1f Tracy\Panel: supports multiple connections [Closes #365]
Partially reverts "Tracy\Panel: one panel is used per connection"

This reverts commit ae6c8756b6.
2020-10-08 16:38:35 +02:00
groupnet
cc37121390 Postgre driver - add connect_type config parameter (#370)
- adds the option to pass the connect_type as config parameter
 - PHP default is 0, but to make this change non-breaking defauls to PGSQL_CONNECT_FORCE_NEW
 - see PHP docs: https://www.php.net/manual/en/function.pg-connect.php
2020-10-08 15:55:11 +02:00
LHavlicek
a95b409231 MySqliDriver: fixed DateInterval encoding (#371) 2020-10-08 15:55:11 +02:00
Jakub Bouček
3b057c2e35 MySqliDriver: added support for ping (#372) 2020-10-08 15:55:11 +02:00
David Grudl
f444b5d993 typo 2020-10-08 15:55:11 +02:00
David Grudl
6e41c4223b tests: test() with description 2020-10-08 15:55:11 +02:00
David Grudl
0ee4628712 SqlsrvDriver: improved escapeBinary [Closes #287] 2020-10-07 03:19:03 +02:00
David Grudl
ab3677203c added funding.yml 2020-10-07 03:19:03 +02:00
Jan Barášek
1bdf6e93d0 PhpStan fixes (#363) 2020-05-07 21:41:28 +02:00
15 changed files with 133 additions and 69 deletions

1
.github/funding.yml vendored Normal file
View File

@@ -0,0 +1 @@
github: dg

View File

@@ -16,6 +16,7 @@
"require-dev": { "require-dev": {
"tracy/tracy": "~2.2", "tracy/tracy": "~2.2",
"nette/tester": "~2.0", "nette/tester": "~2.0",
"nette/di": "^3.0",
"phpstan/phpstan": "^0.12" "phpstan/phpstan": "^0.12"
}, },
"replace": { "replace": {

View File

@@ -14,7 +14,13 @@ Introduction
Database access functions in PHP are not standardised. This library Database access functions in PHP are not standardised. This library
hides the differences between them, and above all, it gives you a very handy interface. hides the differences between them, and above all, it gives you a very handy interface.
If you like Dibi, **[please make a donation now](https://nette.org/make-donation?to=dibi)**. Thank you!
Support Project
---------------
Do you like Dibi? Are you looking forward to the new features?
[![Donate](https://files.nette.org/icons/donation-1.svg?)](https://nette.org/make-donation?to=dibi)
Installation Installation

View File

@@ -105,6 +105,15 @@ class Panel implements Tracy\IBarPanel
} }
$totalTime = $s = null; $totalTime = $s = null;
$singleConnection = reset($this->events)->connection;
foreach ($this->events as $event) {
if ($event->connection !== $singleConnection) {
$singleConnection = null;
break;
}
}
foreach ($this->events as $event) { foreach ($this->events as $event) {
$totalTime += $event->time; $totalTime += $event->time;
$connection = $event->connection; $connection = $event->connection;
@@ -135,7 +144,10 @@ class Panel implements Tracy\IBarPanel
$s .= Tracy\Helpers::editorLink($event->source[0], $event->source[1]);//->class('tracy-DibiProfiler-source'); $s .= Tracy\Helpers::editorLink($event->source[0], $event->source[1]);//->class('tracy-DibiProfiler-source');
} }
$s .= "</td><td>{$event->count}</td></tr>"; $s .= "</td><td>{$event->count}</td>";
if (!$singleConnection) {
$s .= '<td>' . htmlspecialchars($this->getConnectionName($connection)) . '</td></tr>';
}
} }
return '<style> #tracy-debug td.tracy-DibiProfiler-sql { background: white !important } return '<style> #tracy-debug td.tracy-DibiProfiler-sql { background: white !important }
@@ -143,12 +155,21 @@ class Panel implements Tracy\IBarPanel
#tracy-debug tracy-DibiProfiler tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style> #tracy-debug tracy-DibiProfiler tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style>
<h1>Queries: ' . count($this->events) <h1>Queries: ' . count($this->events)
. ($totalTime === null ? '' : ', time: ' . number_format($totalTime * 1000, 1, '.', '') . 'ms') . ', ' . ($totalTime === null ? '' : ', time: ' . number_format($totalTime * 1000, 1, '.', '') . 'ms') . ', '
. htmlspecialchars($connection->getConfig('driver') . ($connection->getConfig('name') ? '/' . $connection->getConfig('name') : '') . htmlspecialchars($this->getConnectionName($singleConnection)) . '</h1>
. ($connection->getConfig('host') ? '@' . $connection->getConfig('host') : '')) . '</h1>
<div class="tracy-inner tracy-DibiProfiler"> <div class="tracy-inner tracy-DibiProfiler">
<table> <table>
<tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th></tr>' . $s . ' <tr><th>Time&nbsp;ms</th><th>SQL Statement</th><th>Rows</th>' . (!$singleConnection ? '<th>Connection</th>' : '') . '</tr>
' . $s . '
</table> </table>
</div>'; </div>';
} }
private function getConnectionName(Dibi\Connection $connection): string
{
$driver = $connection->getConfig('driver');
return (is_object($driver) ? get_class($driver) : $driver)
. ($connection->getConfig('name') ? '/' . $connection->getConfig('name') : '')
. ($connection->getConfig('host') ? '@' . $connection->getConfig('host') : '');
}
} }

View File

@@ -130,6 +130,15 @@ class MySqliDriver implements Dibi\Driver
} }
/**
* Pings a server connection, or tries to reconnect if the connection has gone down.
*/
public function ping(): bool
{
return $this->connection->ping();
}
/** /**
* Executes the SQL query. * Executes the SQL query.
* @throws Dibi\DriverException * @throws Dibi\DriverException
@@ -148,6 +157,9 @@ class MySqliDriver implements Dibi\Driver
} }
/**
* @param int|string $code
*/
public static function createException(string $message, $code, string $sql): Dibi\DriverException public static function createException(string $message, $code, string $sql): Dibi\DriverException
{ {
if (in_array($code, [1216, 1217, 1451, 1452, 1701], true)) { if (in_array($code, [1216, 1217, 1451, 1452, 1701], true)) {
@@ -305,7 +317,7 @@ class MySqliDriver implements Dibi\Driver
if ($value->y || $value->m || $value->d) { if ($value->y || $value->m || $value->d) {
throw new Dibi\NotSupportedException('Only time interval is supported.'); throw new Dibi\NotSupportedException('Only time interval is supported.');
} }
return $value->format('%r%H:%I:%S.%f'); return $value->format("'%r%H:%I:%S.%f'");
} }

View File

@@ -23,6 +23,7 @@ use Dibi\Helpers;
* - charset => character encoding to set (default is utf8) * - charset => character encoding to set (default is utf8)
* - persistent (bool) => try to find a persistent link? * - persistent (bool) => try to find a persistent link?
* - resource (resource) => existing connection resource * - resource (resource) => existing connection resource
* - connect_type (int) => see pg_connect()
*/ */
class PostgreDriver implements Dibi\Driver class PostgreDriver implements Dibi\Driver
{ {
@@ -62,14 +63,15 @@ class PostgreDriver implements Dibi\Driver
} }
} }
} }
$connectType = $config['connect_type'] ?? PGSQL_CONNECT_FORCE_NEW;
set_error_handler(function (int $severity, string $message) use (&$error) { set_error_handler(function (int $severity, string $message) use (&$error) {
$error = $message; $error = $message;
}); });
if (empty($config['persistent'])) { if (empty($config['persistent'])) {
$this->connection = pg_connect($string, PGSQL_CONNECT_FORCE_NEW); $this->connection = pg_connect($string, $connectType);
} else { } else {
$this->connection = pg_pconnect($string); $this->connection = pg_pconnect($string, $connectType);
} }
restore_error_handler(); restore_error_handler();
} }

View File

@@ -200,7 +200,7 @@ class SqlsrvDriver implements Dibi\Driver
public function escapeBinary(string $value): string public function escapeBinary(string $value): string
{ {
return "'" . str_replace("'", "''", $value) . "'"; return '0x' . bin2hex($value);
} }

View File

@@ -32,6 +32,12 @@ namespace Dibi;
* @method Fluent and(...$cond) * @method Fluent and(...$cond)
* @method Fluent or(...$cond) * @method Fluent or(...$cond)
* @method Fluent using(...$cond) * @method Fluent using(...$cond)
* @method Fluent update(...$cond)
* @method Fluent insert(...$cond)
* @method Fluent delete(...$cond)
* @method Fluent into(...$cond)
* @method Fluent values(...$cond)
* @method Fluent set(...$args)
* @method Fluent asc() * @method Fluent asc()
* @method Fluent desc() * @method Fluent desc()
*/ */

View File

@@ -73,8 +73,9 @@ class FileLogger
private function writeToFile(Dibi\Event $event, string $message): void private function writeToFile(Dibi\Event $event, string $message): void
{ {
$driver = $event->connection->getConfig('driver');
$message .= $message .=
"\n-- driver: " . $event->connection->getConfig('driver') . '/' . $event->connection->getConfig('name') "\n-- driver: " . (is_object($driver) ? get_class($driver) : $driver) . '/' . $event->connection->getConfig('name')
. "\n-- " . date('Y-m-d H:i:s') . "\n-- " . date('Y-m-d H:i:s')
. "\n\n"; . "\n\n";
file_put_contents($this->file, $message, FILE_APPEND | LOCK_EX); file_put_contents($this->file, $message, FILE_APPEND | LOCK_EX);

View File

@@ -19,7 +19,7 @@ class Result implements IDataSource
{ {
use Strict; use Strict;
/** @var ResultDriver */ /** @var ResultDriver|null */
private $driver; private $driver;
/** @var array Translate table */ /** @var array Translate table */
@@ -242,6 +242,9 @@ class Result implements IDataSource
$data = null; $data = null;
$assoc = preg_split('#(\[\]|->|=|\|)#', $assoc, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $assoc = preg_split('#(\[\]|->|=|\|)#', $assoc, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
if (!$assoc) {
throw new \InvalidArgumentException("Invalid descriptor '$assoc'.");
}
// check columns // check columns
foreach ($assoc as $as) { foreach ($assoc as $as) {
@@ -292,6 +295,7 @@ class Result implements IDataSource
} while ($row = $this->fetch()); } while ($row = $this->fetch());
unset($x); unset($x);
/** @var mixed[] $data */
return $data; return $data;
} }

View File

@@ -92,21 +92,22 @@ final class Translator
$sql[] = $arg; $sql[] = $arg;
} else { } else {
$sql[] = substr($arg, 0, $toSkip) $sql[] = substr($arg, 0, $toSkip)
/* // note: this can change $this->args & $this->cursor & ...
. preg_replace_callback('/ . preg_replace_callback(<<<'XX'
(?=[`[\'":%?]) ## speed-up /
(?=[`['":%?]) ## speed-up
(?: (?:
`(.+?)`| ## 1) `identifier` `(.+?)`| ## 1) `identifier`
\[(.+?)\]| ## 2) [identifier] \[(.+?)\]| ## 2) [identifier]
(\')((?:\'\'|[^\'])*)\'| ## 3,4) 'string' (')((?:''|[^'])*)'| ## 3,4) string
(")((?:""|[^"])*)"| ## 5,6) "string" (")((?:""|[^"])*)"| ## 5,6) "string"
(\'|")| ## 7) lone quote ('|")| ## 7) lone quote
:(\S*?:)([a-zA-Z0-9._]?)| ## 8,9) :substitution: :(\S*?:)([a-zA-Z0-9._]?)| ## 8,9) :substitution:
%([a-zA-Z~][a-zA-Z0-9~]{0,5})|## 10) modifier %([a-zA-Z~][a-zA-Z0-9~]{0,5})| ## 10) modifier
(\?) ## 11) placeholder (\?) ## 11) placeholder
)/xs', )/xs
*/ // note: this can change $this->args & $this->cursor & ... XX
. preg_replace_callback('/(?=[`[\'":%?])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?)|%([a-zA-Z~][a-zA-Z0-9~]{0,5})|(\?))/s', ,
[$this, 'cb'], [$this, 'cb'],
substr($arg, $toSkip) substr($arg, $toSkip)
); );
@@ -400,8 +401,19 @@ final class Translator
$toSkip = strcspn($value, '`[\'":'); $toSkip = strcspn($value, '`[\'":');
if (strlen($value) !== $toSkip) { if (strlen($value) !== $toSkip) {
$value = substr($value, 0, $toSkip) $value = substr($value, 0, $toSkip)
. preg_replace_callback( . preg_replace_callback(<<<'XX'
'/(?=[`[\'":])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?))/s', /
(?=[`['":])
(?:
`(.+?)`|
\[(.+?)\]|
(')((?:''|[^'])*)'|
(")((?:""|[^"])*)"|
('|")|
:(\S*?:)([a-zA-Z0-9._]?)
)/sx
XX
,
[$this, 'cb'], [$this, 'cb'],
substr($value, $toSkip) substr($value, $toSkip)
); );

View File

@@ -12,7 +12,7 @@ use Tester\Assert;
require __DIR__ . '/bootstrap.php'; require __DIR__ . '/bootstrap.php';
test(function () use ($config) { test('', function () use ($config) {
$conn = new Connection($config); $conn = new Connection($config);
Assert::true($conn->isConnected()); Assert::true($conn->isConnected());
@@ -21,7 +21,7 @@ test(function () use ($config) {
}); });
test(function () use ($config) { // lazy test('lazy', function () use ($config) {
$conn = new Connection($config + ['lazy' => true]); $conn = new Connection($config + ['lazy' => true]);
Assert::false($conn->isConnected()); Assert::false($conn->isConnected());
@@ -30,7 +30,7 @@ test(function () use ($config) { // lazy
}); });
test(function () use ($config) { test('', function () use ($config) {
$conn = new Connection($config); $conn = new Connection($config);
Assert::true($conn->isConnected()); Assert::true($conn->isConnected());
@@ -40,7 +40,7 @@ test(function () use ($config) {
}); });
test(function () use ($config) { test('', function () use ($config) {
$conn = new Connection($config); $conn = new Connection($config);
Assert::true($conn->isConnected()); Assert::true($conn->isConnected());
@@ -52,7 +52,7 @@ test(function () use ($config) {
}); });
test(function () use ($config) { test('', function () use ($config) {
$conn = new Connection($config); $conn = new Connection($config);
Assert::equal('hello', $conn->query('SELECT %s', 'hello')->fetchSingle()); Assert::equal('hello', $conn->query('SELECT %s', 'hello')->fetchSingle());
@@ -63,7 +63,7 @@ test(function () use ($config) {
}); });
test(function () use ($config) { test('', function () use ($config) {
Assert::exception(function () use ($config) { Assert::exception(function () use ($config) {
new Connection($config + ['onConnect' => '']); new Connection($config + ['onConnect' => '']);
}, InvalidArgumentException::class, "Configuration option 'onConnect' must be array."); }, InvalidArgumentException::class, "Configuration option 'onConnect' must be array.");

View File

@@ -29,13 +29,11 @@ Assert::exception(function () {
}, Dibi\DriverException::class, 'PDO connection in exception or warning error mode is not supported.'); }, Dibi\DriverException::class, 'PDO connection in exception or warning error mode is not supported.');
// PDO error mode: explicitly set silent test('PDO error mode: explicitly set silent', function () {
test(function () {
buildPdoDriver(PDO::ERRMODE_SILENT); buildPdoDriver(PDO::ERRMODE_SILENT);
}); });
// PDO error mode: implicitly set silent test('PDO error mode: implicitly set silent', function () {
test(function () {
buildPdoDriver(null); buildPdoDriver(null);
}); });

View File

@@ -24,7 +24,7 @@ class MockResult extends Dibi\Result
} }
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::BOOL); $result->setType('col', Type::BOOL);
@@ -46,7 +46,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::TEXT); $result->setType('col', Type::TEXT);
@@ -62,7 +62,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::FLOAT); $result->setType('col', Type::FLOAT);
@@ -139,7 +139,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::INTEGER); $result->setType('col', Type::INTEGER);
@@ -165,7 +165,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::DATETIME); $result->setType('col', Type::DATETIME);
@@ -183,7 +183,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::DATETIME); $result->setType('col', Type::DATETIME);
$result->setFormat(Type::DATETIME, 'Y-m-d H:i:s'); $result->setFormat(Type::DATETIME, 'Y-m-d H:i:s');
@@ -202,7 +202,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::DATE); $result->setType('col', Type::DATE);
@@ -218,7 +218,7 @@ test(function () {
}); });
test(function () { test('', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::TIME); $result->setType('col', Type::TIME);

View File

@@ -37,7 +37,7 @@ if ($config['system'] === 'odbc') {
} }
function test(Closure $function) function test(string $title, Closure $function): void
{ {
$function(); $function();
} }