1
0
mirror of https://github.com/dg/dibi.git synced 2025-09-07 12:50:39 +02:00

Compare commits

..

6 Commits
v5.0.2 ... v5.0

Author SHA1 Message Date
David Grudl
befde664fe tests: improved descriptions 2025-08-07 00:00:40 +02:00
David Grudl
e1c4cbaece exception: use natural explanatory style 2025-08-07 00:00:40 +02:00
David Grudl
1df20ced10 cs 2025-08-07 00:00:40 +02:00
David Grudl
ce1ba4668b uses promoted properties 2025-08-07 00:00:40 +02:00
David Grudl
0f21a6ab3d removed dead code 2025-08-07 00:00:40 +02:00
David Grudl
78f552fe8e github actions updated 2025-08-07 00:00:40 +02:00
34 changed files with 141 additions and 241 deletions

View File

@@ -10,7 +10,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2 - uses: shivammathur/setup-php@v2
with: with:
php-version: 8.0 php-version: 8.3
coverage: none coverage: none
- run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress
@@ -24,7 +24,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2 - uses: shivammathur/setup-php@v2
with: with:
php-version: 8.0 php-version: 8.3
coverage: none coverage: none
- run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress

View File

@@ -105,9 +105,9 @@ jobs:
- run: composer install --no-progress --prefer-dist - run: composer install --no-progress --prefer-dist
- run: vendor/bin/tester -p phpdbg tests -s -C --coverage ./coverage.xml --coverage-src ./src - run: vendor/bin/tester -p phpdbg tests -s -C --coverage ./coverage.xml --coverage-src ./src
- if: failure() - if: failure()
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: output name: output-${{ matrix.php }}
path: tests/**/output path: tests/**/output

View File

@@ -19,14 +19,10 @@ use Tracy;
*/ */
class DibiExtension22 extends Nette\DI\CompilerExtension class DibiExtension22 extends Nette\DI\CompilerExtension
{ {
private ?bool $debugMode; public function __construct(
private ?bool $cliMode; private ?bool $debugMode = null,
private ?bool $cliMode = null,
) {
public function __construct(?bool $debugMode = null, ?bool $cliMode = null)
{
$this->debugMode = $debugMode;
$this->cliMode = $cliMode;
} }

View File

@@ -20,14 +20,10 @@ use Tracy;
*/ */
class DibiExtension3 extends Nette\DI\CompilerExtension class DibiExtension3 extends Nette\DI\CompilerExtension
{ {
private ?bool $debugMode; public function __construct(
private ?bool $cliMode; private ?bool $debugMode = null,
private ?bool $cliMode = null,
) {
public function __construct(?bool $debugMode = null, ?bool $cliMode = null)
{
$this->debugMode = $debugMode;
$this->cliMode = $cliMode;
} }

View File

@@ -21,15 +21,14 @@ use Tracy;
class Panel implements Tracy\IBarPanel class Panel implements Tracy\IBarPanel
{ {
public static int $maxLength = 1000; public static int $maxLength = 1000;
public bool|string $explain;
public int $filter;
private array $events = []; private array $events = [];
public function __construct(bool $explain = true, ?int $filter = null) public function __construct(
{ public bool|string $explain = true,
$this->filter = $filter ?: Event::QUERY; public int $filter = Event::QUERY,
$this->explain = $explain; ) {
} }

View File

@@ -17,12 +17,9 @@ use Dibi;
*/ */
class FirebirdReflector implements Dibi\Reflector class FirebirdReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private Dibi\Driver $driver,
) {
public function __construct(Dibi\Driver $driver)
{
$this->driver = $driver;
} }

View File

@@ -18,16 +18,10 @@ use Dibi\Helpers;
*/ */
class FirebirdResult implements Dibi\ResultDriver class FirebirdResult implements Dibi\ResultDriver
{ {
public function __construct(
/** @var resource */ /** @var resource */
private $resultSet; private $resultSet,
) {
/**
* @param resource $resultSet
*/
public function __construct($resultSet)
{
$this->resultSet = $resultSet;
} }

View File

@@ -18,12 +18,9 @@ use Dibi;
*/ */
class MySqlReflector implements Dibi\Reflector class MySqlReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private Dibi\Driver $driver,
) {
public function __construct(Dibi\Driver $driver)
{
$this->driver = $driver;
} }

View File

@@ -17,14 +17,10 @@ use Dibi;
*/ */
class MySqliResult implements Dibi\ResultDriver class MySqliResult implements Dibi\ResultDriver
{ {
private \mysqli_result $resultSet; public function __construct(
private bool $buffered; private \mysqli_result $resultSet,
private bool $buffered,
) {
public function __construct(\mysqli_result $resultSet, bool $buffered)
{
$this->resultSet = $resultSet;
$this->buffered = $buffered;
} }

View File

@@ -17,12 +17,9 @@ use Dibi;
*/ */
class NoDataResult implements Dibi\ResultDriver class NoDataResult implements Dibi\ResultDriver
{ {
private int $rows; public function __construct(
private int $rows,
) {
public function __construct(int $rows)
{
$this->rows = $rows;
} }

View File

@@ -17,12 +17,9 @@ use Dibi;
*/ */
class OdbcReflector implements Dibi\Reflector class OdbcReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private Dibi\Driver $driver,
) {
public function __construct(Dibi\Driver $driver)
{
$this->driver = $driver;
} }

View File

@@ -17,17 +17,13 @@ use Dibi;
*/ */
class OdbcResult implements Dibi\ResultDriver class OdbcResult implements Dibi\ResultDriver
{ {
/** @var resource */
private $resultSet;
private int $row = 0; private int $row = 0;
/** public function __construct(
* @param resource $resultSet /** @var resource */
*/ private $resultSet,
public function __construct($resultSet) ) {
{
$this->resultSet = $resultSet;
} }

View File

@@ -17,12 +17,9 @@ use Dibi;
*/ */
class OracleReflector implements Dibi\Reflector class OracleReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private Dibi\Driver $driver,
) {
public function __construct(Dibi\Driver $driver)
{
$this->driver = $driver;
} }

View File

@@ -17,16 +17,10 @@ use Dibi;
*/ */
class OracleResult implements Dibi\ResultDriver class OracleResult implements Dibi\ResultDriver
{ {
public function __construct(
/** @var resource */ /** @var resource */
private $resultSet; private $resultSet,
) {
/**
* @param resource $resultSet
*/
public function __construct($resultSet)
{
$this->resultSet = $resultSet;
} }

View File

@@ -19,14 +19,10 @@ use PDO;
*/ */
class PdoResult implements Dibi\ResultDriver class PdoResult implements Dibi\ResultDriver
{ {
private ?\PDOStatement $resultSet; public function __construct(
private string $driverName; private ?\PDOStatement $resultSet,
private string $driverName,
) {
public function __construct(\PDOStatement $resultSet, string $driverName)
{
$this->resultSet = $resultSet;
$this->driverName = $driverName;
} }

View File

@@ -17,14 +17,10 @@ use Dibi;
*/ */
class PostgreReflector implements Dibi\Reflector class PostgreReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private string $version; private Dibi\Driver $driver,
private string $version,
) {
public function __construct(Dibi\Driver $driver, string $version)
{
$this->driver = $driver;
$this->version = $version;
} }

View File

@@ -19,16 +19,10 @@ use PgSql;
*/ */
class PostgreResult implements Dibi\ResultDriver class PostgreResult implements Dibi\ResultDriver
{ {
public function __construct(
/** @var resource|PgSql\Result */ /** @var resource|PgSql\Result */
private $resultSet; private $resultSet,
) {
/**
* @param resource|PgSql\Result $resultSet
*/
public function __construct($resultSet)
{
$this->resultSet = $resultSet;
} }

View File

@@ -17,12 +17,9 @@ use Dibi;
*/ */
class SqliteReflector implements Dibi\Reflector class SqliteReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private Dibi\Driver $driver,
) {
public function __construct(Dibi\Driver $driver)
{
$this->driver = $driver;
} }

View File

@@ -18,12 +18,9 @@ use Dibi\Helpers;
*/ */
class SqliteResult implements Dibi\ResultDriver class SqliteResult implements Dibi\ResultDriver
{ {
private \SQLite3Result $resultSet; public function __construct(
private \SQLite3Result $resultSet,
) {
public function __construct(\SQLite3Result $resultSet)
{
$this->resultSet = $resultSet;
} }

View File

@@ -17,12 +17,9 @@ use Dibi;
*/ */
class SqlsrvReflector implements Dibi\Reflector class SqlsrvReflector implements Dibi\Reflector
{ {
private Dibi\Driver $driver; public function __construct(
private Dibi\Driver $driver,
) {
public function __construct(Dibi\Driver $driver)
{
$this->driver = $driver;
} }

View File

@@ -17,16 +17,10 @@ use Dibi;
*/ */
class SqlsrvResult implements Dibi\ResultDriver class SqlsrvResult implements Dibi\ResultDriver
{ {
public function __construct(
/** @var resource */ /** @var resource */
private $resultSet; private $resultSet,
) {
/**
* @param resource $resultSet
*/
public function __construct($resultSet)
{
$this->resultSet = $resultSet;
} }

View File

@@ -17,17 +17,11 @@ use Dibi;
*/ */
class FileLogger class FileLogger
{ {
/** Name of the file where SQL errors should be logged */ public function __construct(
public string $file; public string $file,
public int $filter; public int $filter = Dibi\Event::QUERY,
private bool $errorsOnly; private bool $errorsOnly = false,
) {
public function __construct(string $file, ?int $filter = null, bool $errorsOnly = false)
{
$this->file = $file;
$this->filter = $filter ?: Dibi\Event::QUERY;
$this->errorsOnly = $errorsOnly;
} }

View File

@@ -27,17 +27,10 @@ use Dibi;
*/ */
class Column class Column
{ {
/** when created by Result */ public function __construct(
private ?Dibi\Reflector $reflector; private ?Dibi\Reflector $reflector,
private array $info,
/** @var array (name, nativetype, [table], [fullname], [size], [nullable], [default], [autoincrement], [vendor]) */ ) {
private array $info;
public function __construct(?Dibi\Reflector $reflector, array $info)
{
$this->reflector = $reflector;
$this->info = $info;
} }

View File

@@ -21,17 +21,14 @@ use Dibi;
*/ */
class Database class Database
{ {
private Dibi\Reflector $reflector;
private ?string $name;
/** @var Table[] */ /** @var Table[] */
private array $tables; private array $tables;
public function __construct(Dibi\Reflector $reflector, ?string $name = null) public function __construct(
{ private Dibi\Reflector $reflector,
$this->reflector = $reflector; private ?string $name = null,
$this->name = $name; ) {
} }

View File

@@ -19,16 +19,10 @@ namespace Dibi\Reflection;
*/ */
class ForeignKey class ForeignKey
{ {
private string $name; public function __construct(
private string $name,
/** @var array of [local, foreign, onDelete, onUpdate] */ private array $references,
private array $references; ) {
public function __construct(string $name, array $references)
{
$this->name = $name;
$this->references = $references;
} }

View File

@@ -21,13 +21,9 @@ namespace Dibi\Reflection;
*/ */
class Index class Index
{ {
/** @var array (name, columns, [unique], [primary]) */ public function __construct(
private array $info; private array $info,
) {
public function __construct(array $info)
{
$this->info = $info;
} }

View File

@@ -20,8 +20,6 @@ use Dibi;
*/ */
class Result class Result
{ {
private Dibi\ResultDriver $driver;
/** @var Column[]|null */ /** @var Column[]|null */
private ?array $columns; private ?array $columns;
@@ -29,9 +27,9 @@ class Result
private ?array $names; private ?array $names;
public function __construct(Dibi\ResultDriver $driver) public function __construct(
{ private Dibi\ResultDriver $driver,
$this->driver = $driver; ) {
} }

View File

@@ -15,14 +15,13 @@ namespace Dibi;
*/ */
class ResultIterator implements \Iterator, \Countable class ResultIterator implements \Iterator, \Countable
{ {
private Result $result;
private mixed $row; private mixed $row;
private int $pointer = 0; private int $pointer = 0;
public function __construct(Result $result) public function __construct(
{ private Result $result,
$this->result = $result; ) {
} }

View File

@@ -11,7 +11,7 @@ namespace Dibi;
/** /**
* Dibi common exception. * A database operation failed.
*/ */
class Exception extends \Exception class Exception extends \Exception
{ {
@@ -44,7 +44,7 @@ class Exception extends \Exception
/** /**
* database server exception. * The database server reported an error.
*/ */
class DriverException extends Exception class DriverException extends Exception
{ {
@@ -52,7 +52,7 @@ class DriverException extends Exception
/** /**
* PCRE exception. * Regular expression pattern or execution failed.
*/ */
class PcreException extends Exception class PcreException extends Exception
{ {
@@ -63,18 +63,24 @@ class PcreException extends Exception
} }
/**
* The requested feature is not implemented.
*/
class NotImplementedException extends Exception class NotImplementedException extends Exception
{ {
} }
/**
* The requested operation is not supported.
*/
class NotSupportedException extends Exception class NotSupportedException extends Exception
{ {
} }
/** /**
* Database procedure exception. * A database stored procedure failed.
*/ */
class ProcedureException extends Exception class ProcedureException extends Exception
{ {
@@ -102,7 +108,7 @@ class ProcedureException extends Exception
/** /**
* Base class for all constraint violation related exceptions. * A database constraint was violated.
*/ */
class ConstraintViolationException extends DriverException class ConstraintViolationException extends DriverException
{ {
@@ -110,7 +116,7 @@ class ConstraintViolationException extends DriverException
/** /**
* Exception for a foreign key constraint violation. * The foreign key constraint check failed.
*/ */
class ForeignKeyConstraintViolationException extends ConstraintViolationException class ForeignKeyConstraintViolationException extends ConstraintViolationException
{ {
@@ -118,7 +124,7 @@ class ForeignKeyConstraintViolationException extends ConstraintViolationExceptio
/** /**
* Exception for a NOT NULL constraint violation. * The NOT NULL constraint check failed.
*/ */
class NotNullConstraintViolationException extends ConstraintViolationException class NotNullConstraintViolationException extends ConstraintViolationException
{ {
@@ -126,7 +132,7 @@ class NotNullConstraintViolationException extends ConstraintViolationException
/** /**
* Exception for a unique constraint violation. * The unique constraint check failed.
*/ */
class UniqueConstraintViolationException extends ConstraintViolationException class UniqueConstraintViolationException extends ConstraintViolationException
{ {

View File

@@ -12,7 +12,7 @@ use Tester\Assert;
require __DIR__ . '/bootstrap.php'; require __DIR__ . '/bootstrap.php';
test('', function () use ($config) { test('immediate connection and disconnection state', 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('lazy', function () use ($config) { test('lazy connection initiated on first query', 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('lazy', function () use ($config) {
}); });
test('', function () use ($config) { test('config retrieval and driver instance access', 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('idempotent disconnect calls', 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('reconnect after disconnection', 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('destructor disconnects active connection', function () use ($config) {
$conn = new Connection($config); $conn = new Connection($config);
Assert::true($conn->isConnected()); Assert::true($conn->isConnected());
@@ -72,7 +72,7 @@ test('', function () use ($config) {
}); });
test('', function () use ($config) { test('invalid onConnect option triggers exceptions', function () use ($config) {
Assert::exception( Assert::exception(
fn() => new Connection($config + ['onConnect' => '']), fn() => new Connection($config + ['onConnect' => '']),
InvalidArgumentException::class, InvalidArgumentException::class,

View File

@@ -36,5 +36,5 @@ Assert::exception(
test( test(
'PDO error mode: explicitly set silent', 'PDO error mode: explicitly set silent',
fn() => buildPdoDriver(PDO::ERRMODE_SILENT) fn() => buildPdoDriver(PDO::ERRMODE_SILENT),
); );

View File

@@ -18,9 +18,9 @@ $tests = function ($conn) {
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A%B')->fetchSingle()); Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A%B')->fetchSingle());
Assert::true($conn->query("SELECT 'AA%BB' LIKE %~like~", 'A%B')->fetchSingle()); Assert::true($conn->query("SELECT 'AA%BB' LIKE %~like~", 'A%B')->fetchSingle());
Assert::same('AA\\BB', $conn->query("SELECT 'AA\\BB'")->fetchSingle()); Assert::same('AA\BB', $conn->query("SELECT 'AA\\BB'")->fetchSingle());
Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A\\B')->fetchSingle()); Assert::false($conn->query("SELECT 'AAxBB' LIKE %~like~", 'A\B')->fetchSingle());
Assert::true($conn->query("SELECT 'AA\\BB' LIKE %~like~", 'A\\B')->fetchSingle()); Assert::true($conn->query("SELECT 'AA\\BB' LIKE %~like~", 'A\B')->fetchSingle());
}; };
$conn = new Dibi\Connection($config); $conn = new Dibi\Connection($config);

View File

@@ -25,7 +25,7 @@ class MockResult extends Dibi\Result
} }
test('', function () { test('native text conversion preserves boolean values', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Text); $result->setType('col', Type::Text);
$result->setFormat(Type::Text, 'native'); $result->setFormat(Type::Text, 'native');
@@ -36,7 +36,7 @@ test('', function () {
}); });
test('', function () { test('boolean conversion from diverse representations', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Bool); $result->setType('col', Type::Bool);
@@ -58,7 +58,7 @@ test('', function () {
}); });
test('', function () { test('text conversion of booleans and numerics', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Text); $result->setType('col', Type::Text);
@@ -74,7 +74,7 @@ test('', function () {
}); });
test('', function () { test('float conversion with various numeric formats', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Float); $result->setType('col', Type::Float);
@@ -214,7 +214,7 @@ test('', function () {
}); });
test('', function () { test('strict integer conversion with error on empty string', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Integer); $result->setType('col', Type::Integer);
@@ -222,14 +222,10 @@ test('', function () {
Assert::same(['col' => 1], $result->test(['col' => true])); Assert::same(['col' => 1], $result->test(['col' => true]));
Assert::same(['col' => 0], $result->test(['col' => false])); Assert::same(['col' => 0], $result->test(['col' => false]));
if (PHP_VERSION_ID < 80000) {
Assert::same(['col' => 0], @$result->test(['col' => ''])); // triggers warning since PHP 7.1
} else {
Assert::exception( Assert::exception(
fn() => Assert::same(['col' => 0], $result->test(['col' => ''])), fn() => Assert::same(['col' => 0], $result->test(['col' => ''])),
TypeError::class, TypeError::class,
); );
}
Assert::same(['col' => 0], $result->test(['col' => '0'])); Assert::same(['col' => 0], $result->test(['col' => '0']));
Assert::same(['col' => 1], $result->test(['col' => '1'])); Assert::same(['col' => 1], $result->test(['col' => '1']));
@@ -248,7 +244,7 @@ test('', function () {
}); });
test('', function () { test('dateTime conversion with object instantiation', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::DateTime); $result->setType('col', Type::DateTime);
@@ -267,7 +263,7 @@ test('', function () {
}); });
test('', function () { test('dateTime conversion using custom format', 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');
@@ -287,7 +283,7 @@ test('', function () {
}); });
test('', function () { test('date conversion to DateTime instance', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Date); $result->setType('col', Type::Date);
@@ -304,7 +300,7 @@ test('', function () {
}); });
test('', function () { test('time conversion to DateTime instance', function () {
$result = new MockResult; $result = new MockResult;
$result->setType('col', Type::Time); $result->setType('col', Type::Time);

View File

@@ -32,7 +32,7 @@ Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', "a'a", "a'"));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %like~', "b'", "%'")); Assert::falsey($conn->fetchSingle('SELECT ? LIKE %like~', "b'", "%'"));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', "%'", "%'")); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', "%'", "%'"));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', 'a\\a', 'a\\')); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', 'a\a', 'a\\'));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %like~', 'b\\', '%\\')); Assert::falsey($conn->fetchSingle('SELECT ? LIKE %like~', 'b\\', '%\\'));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', '%\\', '%\\')); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %like~', '%\\', '%\\'));
@@ -60,9 +60,9 @@ Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', "a'a", "'a"));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like', "'b", "'%")); Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like', "'b", "'%"));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', "'%", "'%")); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', "'%", "'%"));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', 'a\\a', '\\a')); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', 'a\a', '\a'));
Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like', '\\b', '\\%')); Assert::falsey($conn->fetchSingle('SELECT ? LIKE %~like', '\b', '\%'));
Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', '\\%', '\\%')); Assert::truthy($conn->fetchSingle('SELECT ? LIKE %~like', '\%', '\%'));
// contains // contains