mirror of
https://github.com/dg/dibi.git
synced 2025-08-30 09:19:48 +02:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d70e274244 | ||
|
e05eb01233 | ||
|
2ac618ffff | ||
|
1881fea0e5 | ||
|
cb82357cfb | ||
|
0a29fcb502 | ||
|
8270b7c1c3 | ||
|
73e16eb1a3 | ||
|
0b394a993d | ||
|
df3edee70b | ||
|
245da39a9f | ||
|
3df64fc3b3 | ||
|
95c3f72a17 | ||
|
d71caf0c75 | ||
|
3066fea2aa | ||
|
b00e556289 | ||
|
877dffd460 | ||
|
7049949b14 | ||
|
771e846a62 | ||
|
4e056c52dd | ||
|
40ad77cf5f |
31
.github/workflows/coding-style.yml
vendored
Normal file
31
.github/workflows/coding-style.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
name: Coding Style
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
nette_cc:
|
||||||
|
name: Nette Code Checker
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 8.0
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress
|
||||||
|
- run: php temp/code-checker/code-checker --strict-types --no-progress --ignore "tests/*/fixtures"
|
||||||
|
|
||||||
|
|
||||||
|
nette_cs:
|
||||||
|
name: Nette Coding Standard
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 8.0
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress --ignore-platform-reqs
|
||||||
|
- run: php temp/coding-standard/ecs check
|
21
.github/workflows/static-analysis.yml
vendored
Normal file
21
.github/workflows/static-analysis.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
name: Static Analysis (only informative)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
phpstan:
|
||||||
|
name: PHPStan
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 8.0
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- run: composer install --no-progress --prefer-dist
|
||||||
|
- run: composer phpstan -- --no-progress
|
||||||
|
continue-on-error: true # is only informative
|
121
.github/workflows/tests.yml
vendored
Normal file
121
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
php-extensions: mbstring, intl, mysqli, pgsql, sqlsrv-5.9.0preview1, pdo_sqlsrv-5.9.0preview1
|
||||||
|
php-tools: "composer:v2, pecl"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php: ['7.2', '7.3', '7.4', '8.0', '8.1']
|
||||||
|
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
name: PHP ${{ matrix.php }} tests
|
||||||
|
|
||||||
|
services:
|
||||||
|
mysql57:
|
||||||
|
image: mysql:5.7
|
||||||
|
env:
|
||||||
|
MYSQL_DATABASE: dibi_test
|
||||||
|
MYSQL_ROOT_PASSWORD: root
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
options: >-
|
||||||
|
--health-cmd "mysqladmin ping -ppass"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-start-period 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 10
|
||||||
|
|
||||||
|
mysql80:
|
||||||
|
image: mysql:8.0
|
||||||
|
ports:
|
||||||
|
- 3307:3306
|
||||||
|
options: >-
|
||||||
|
--health-cmd="mysqladmin ping -ppass"
|
||||||
|
--health-interval=10s
|
||||||
|
--health-timeout=5s
|
||||||
|
--health-retries=5
|
||||||
|
-e MYSQL_ROOT_PASSWORD=root
|
||||||
|
-e MYSQL_DATABASE=dibi_test
|
||||||
|
--entrypoint sh mysql:8 -c "exec docker-entrypoint.sh mysqld --default-authentication-plugin=mysql_native_password"
|
||||||
|
|
||||||
|
postgres96:
|
||||||
|
image: postgres:9.6
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: dibi_test
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
|
||||||
|
postgres13:
|
||||||
|
image: postgres:13
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: dibi_test
|
||||||
|
ports:
|
||||||
|
- 5433:5432
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
|
||||||
|
mssql:
|
||||||
|
image: mcr.microsoft.com/mssql/server:latest
|
||||||
|
env:
|
||||||
|
ACCEPT_EULA: Y
|
||||||
|
SA_PASSWORD: YourStrong!Passw0rd
|
||||||
|
MSSQL_PID: Developer
|
||||||
|
ports:
|
||||||
|
- 1433:1433
|
||||||
|
options: >-
|
||||||
|
--name=mssql
|
||||||
|
--health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'YourStrong!Passw0rd' -Q 'SELECT 1'"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
extensions: ${{ env.php-extensions }}
|
||||||
|
tools: ${{ env.php-tools }}
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- name: Create databases.ini
|
||||||
|
run: cp ./tests/databases.github.ini ./tests/databases.ini
|
||||||
|
|
||||||
|
- name: Create MS SQL Database
|
||||||
|
run: docker exec -i mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'YourStrong!Passw0rd' -Q 'CREATE DATABASE dibi_test'
|
||||||
|
|
||||||
|
- run: composer install --no-progress --prefer-dist
|
||||||
|
- run: vendor/bin/tester -p phpdbg tests -s -C --coverage ./coverage.xml --coverage-src ./src
|
||||||
|
- if: failure()
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: output
|
||||||
|
path: tests/**/output
|
||||||
|
|
||||||
|
|
||||||
|
- name: Save Code Coverage
|
||||||
|
if: ${{ matrix.php == '8.0' }}
|
||||||
|
env:
|
||||||
|
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar
|
||||||
|
php php-coveralls.phar --verbose --config tests/.coveralls.yml
|
76
.travis.yml
76
.travis.yml
@@ -1,76 +0,0 @@
|
|||||||
language: php
|
|
||||||
php:
|
|
||||||
- 7.2
|
|
||||||
- 7.3
|
|
||||||
- 7.4
|
|
||||||
- 8.0snapshot
|
|
||||||
|
|
||||||
services:
|
|
||||||
- mysql
|
|
||||||
- postgresql
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# turn off XDebug
|
|
||||||
- phpenv config-rm xdebug.ini || return 0
|
|
||||||
|
|
||||||
# Create databases.ini
|
|
||||||
- cp ./tests/databases.travis.ini ./tests/databases.ini
|
|
||||||
|
|
||||||
# Create Postgre database
|
|
||||||
- psql -c 'CREATE DATABASE dibi_test' -U postgres
|
|
||||||
|
|
||||||
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:
|
|
||||||
- name: Nette Code Checker
|
|
||||||
install:
|
|
||||||
- travis_retry composer create-project nette/code-checker temp/code-checker ^3 --no-progress
|
|
||||||
script:
|
|
||||||
- php temp/code-checker/code-checker --strict-types
|
|
||||||
|
|
||||||
|
|
||||||
- name: Nette Coding Standard
|
|
||||||
php: 7.4
|
|
||||||
install:
|
|
||||||
- travis_retry composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress
|
|
||||||
script:
|
|
||||||
- php temp/coding-standard/ecs check src tests
|
|
||||||
|
|
||||||
|
|
||||||
- stage: Static Analysis (informative)
|
|
||||||
php: 7.4
|
|
||||||
script:
|
|
||||||
- composer run-script phpstan
|
|
||||||
|
|
||||||
|
|
||||||
- stage: Code Coverage
|
|
||||||
php: 7.4
|
|
||||||
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:
|
|
||||||
- stage: Static Analysis (informative)
|
|
||||||
- stage: Code Coverage
|
|
||||||
|
|
||||||
|
|
||||||
dist: xenial
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.composer/cache
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
10
appveyor.yml
10
appveyor.yml
@@ -15,17 +15,17 @@ init:
|
|||||||
- SET ANSICON=121x90 (121x90)
|
- SET ANSICON=121x90 (121x90)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
# Install PHP 7.1
|
# Install PHP 7.2
|
||||||
- IF EXIST c:\php7 (SET PHP=0) ELSE (SET PHP=1)
|
- IF EXIST c:\php7 (SET PHP=0) ELSE (SET PHP=1)
|
||||||
- IF %PHP%==1 mkdir c:\php7
|
- IF %PHP%==1 mkdir c:\php7
|
||||||
- IF %PHP%==1 cd c:\php7
|
- IF %PHP%==1 cd c:\php7
|
||||||
- IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-7.1.5-Win32-VC14-x64.zip --output php.zip
|
- IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-7.2.18-Win32-VC15-x64.zip --output php.zip
|
||||||
- IF %PHP%==1 7z x php.zip >nul
|
- IF %PHP%==1 7z x php.zip >nul
|
||||||
- IF %PHP%==1 echo extension_dir=ext >> php.ini
|
- IF %PHP%==1 echo extension_dir=ext >> php.ini
|
||||||
- IF %PHP%==1 echo extension=php_openssl.dll >> 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
|
- IF %PHP%==1 curl https://github.com/microsoft/msphpsql/releases/download/v5.8.0/Windows-7.2.zip -L --output sqlsrv.zip
|
||||||
- IF %PHP%==1 7z x php-sqlsrv.zip >nul
|
- IF %PHP%==1 7z x sqlsrv.zip >nul
|
||||||
- IF %PHP%==1 copy SQLSRV\php_sqlsrv_71_ts.dll ext\php_sqlsrv_71_ts.dll
|
- IF %PHP%==1 copy Windows-7.2\x64\php_sqlsrv_72_ts.dll ext\php_sqlsrv_ts.dll
|
||||||
- IF %PHP%==1 del /Q *.zip
|
- IF %PHP%==1 del /Q *.zip
|
||||||
|
|
||||||
# Install Microsoft Access Database Engine x64
|
# Install Microsoft Access Database Engine x64
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
=========================================================
|
=========================================================
|
||||||
|
|
||||||
[](https://packagist.org/packages/dibi/dibi)
|
[](https://packagist.org/packages/dibi/dibi)
|
||||||
[](https://travis-ci.org/dg/dibi)
|
[](https://github.com/dg/dibi/actions)
|
||||||
[](https://ci.appveyor.com/project/dg/dibi/branch/master)
|
[](https://ci.appveyor.com/project/dg/dibi/branch/master)
|
||||||
[](https://github.com/dg/dibi/releases)
|
[](https://github.com/dg/dibi/releases)
|
||||||
[](https://github.com/dg/dibi/blob/master/license.md)
|
[](https://github.com/dg/dibi/blob/master/license.md)
|
||||||
@@ -34,7 +34,7 @@ Install Dibi via Composer:
|
|||||||
composer require dibi/dibi
|
composer require dibi/dibi
|
||||||
```
|
```
|
||||||
|
|
||||||
The Dibi 4.2 requires PHP version 7.2 and supports PHP up to 8.0.
|
The Dibi 4.2 requires PHP version 7.2 and supports PHP up to 8.1.
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
@@ -22,10 +22,14 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
|
|||||||
/** @var bool|null */
|
/** @var bool|null */
|
||||||
private $debugMode;
|
private $debugMode;
|
||||||
|
|
||||||
|
/** @var bool|null */
|
||||||
|
private $cliMode;
|
||||||
|
|
||||||
public function __construct(bool $debugMode = null)
|
|
||||||
|
public function __construct(bool $debugMode = null, bool $cliMode = null)
|
||||||
{
|
{
|
||||||
$this->debugMode = $debugMode;
|
$this->debugMode = $debugMode;
|
||||||
|
$this->cliMode = $cliMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +42,11 @@ class DibiExtension22 extends Nette\DI\CompilerExtension
|
|||||||
$this->debugMode = $container->parameters['debugMode'];
|
$this->debugMode = $container->parameters['debugMode'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$useProfiler = $config['profiler'] ?? (class_exists(Tracy\Debugger::class) && $this->debugMode);
|
if ($this->cliMode === null) {
|
||||||
|
$this->cliMode = $container->parameters['consoleMode'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$useProfiler = $config['profiler'] ?? (class_exists(Tracy\Debugger::class) && $this->debugMode && !$this->cliMode);
|
||||||
|
|
||||||
unset($config['profiler']);
|
unset($config['profiler']);
|
||||||
|
|
||||||
|
@@ -40,6 +40,8 @@ class Connection implements IConnection
|
|||||||
/** @var HashMap Substitutes for identifiers */
|
/** @var HashMap Substitutes for identifiers */
|
||||||
private $substitutes;
|
private $substitutes;
|
||||||
|
|
||||||
|
private $transactionDepth = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection options: (see driver-specific options too)
|
* Connection options: (see driver-specific options too)
|
||||||
@@ -335,6 +337,10 @@ class Connection implements IConnection
|
|||||||
*/
|
*/
|
||||||
public function begin(string $savepoint = null): void
|
public function begin(string $savepoint = null): void
|
||||||
{
|
{
|
||||||
|
if ($this->transactionDepth !== 0) {
|
||||||
|
throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->driver) {
|
if (!$this->driver) {
|
||||||
$this->connect();
|
$this->connect();
|
||||||
}
|
}
|
||||||
@@ -359,6 +365,10 @@ class Connection implements IConnection
|
|||||||
*/
|
*/
|
||||||
public function commit(string $savepoint = null): void
|
public function commit(string $savepoint = null): void
|
||||||
{
|
{
|
||||||
|
if ($this->transactionDepth !== 0) {
|
||||||
|
throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->driver) {
|
if (!$this->driver) {
|
||||||
$this->connect();
|
$this->connect();
|
||||||
}
|
}
|
||||||
@@ -383,6 +393,10 @@ class Connection implements IConnection
|
|||||||
*/
|
*/
|
||||||
public function rollback(string $savepoint = null): void
|
public function rollback(string $savepoint = null): void
|
||||||
{
|
{
|
||||||
|
if ($this->transactionDepth !== 0) {
|
||||||
|
throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->driver) {
|
if (!$this->driver) {
|
||||||
$this->connect();
|
$this->connect();
|
||||||
}
|
}
|
||||||
@@ -407,14 +421,26 @@ class Connection implements IConnection
|
|||||||
*/
|
*/
|
||||||
public function transaction(callable $callback)
|
public function transaction(callable $callback)
|
||||||
{
|
{
|
||||||
$this->begin();
|
if ($this->transactionDepth === 0) {
|
||||||
|
$this->begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->transactionDepth++;
|
||||||
try {
|
try {
|
||||||
$res = $callback();
|
$res = $callback($this);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->rollback();
|
$this->transactionDepth--;
|
||||||
|
if ($this->transactionDepth === 0) {
|
||||||
|
$this->rollback();
|
||||||
|
}
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
$this->commit();
|
|
||||||
|
$this->transactionDepth--;
|
||||||
|
if ($this->transactionDepth === 0) {
|
||||||
|
$this->commit();
|
||||||
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -72,7 +72,7 @@ class MySqliDriver implements Dibi\Driver
|
|||||||
$host = ini_get('mysqli.default_host');
|
$host = ini_get('mysqli.default_host');
|
||||||
if ($host) {
|
if ($host) {
|
||||||
$config['host'] = $host;
|
$config['host'] = $host;
|
||||||
$config['port'] = ini_get('mysqli.default_port');
|
$config['port'] = (int) ini_get('mysqli.default_port');
|
||||||
} else {
|
} else {
|
||||||
$config['host'] = null;
|
$config['host'] = null;
|
||||||
$config['port'] = null;
|
$config['port'] = null;
|
||||||
|
@@ -11,6 +11,7 @@ namespace Dibi\Drivers;
|
|||||||
|
|
||||||
use Dibi;
|
use Dibi;
|
||||||
use Dibi\Helpers;
|
use Dibi\Helpers;
|
||||||
|
use PgSql;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +30,7 @@ class PostgreDriver implements Dibi\Driver
|
|||||||
{
|
{
|
||||||
use Dibi\Strict;
|
use Dibi\Strict;
|
||||||
|
|
||||||
/** @var resource */
|
/** @var resource|PgSql\Connection */
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
/** @var int|null Affected rows */
|
/** @var int|null Affected rows */
|
||||||
@@ -74,7 +75,7 @@ class PostgreDriver implements Dibi\Driver
|
|||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_resource($this->connection)) {
|
if (!is_resource($this->connection) && !$this->connection instanceof PgSql\Connection) {
|
||||||
throw new Dibi\DriverException($error ?: 'Connecting error.');
|
throw new Dibi\DriverException($error ?: 'Connecting error.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ class PostgreDriver implements Dibi\Driver
|
|||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
throw static::createException(pg_last_error($this->connection), null, $sql);
|
throw static::createException(pg_last_error($this->connection), null, $sql);
|
||||||
|
|
||||||
} elseif (is_resource($res)) {
|
} elseif (is_resource($res) || $res instanceof PgSql\Result) {
|
||||||
$this->affectedRows = Helpers::false2Null(pg_affected_rows($res));
|
$this->affectedRows = Helpers::false2Null(pg_affected_rows($res));
|
||||||
if (pg_num_fields($res)) {
|
if (pg_num_fields($res)) {
|
||||||
return $this->createResultDriver($res);
|
return $this->createResultDriver($res);
|
||||||
@@ -227,7 +228,9 @@ class PostgreDriver implements Dibi\Driver
|
|||||||
*/
|
*/
|
||||||
public function getResource()
|
public function getResource()
|
||||||
{
|
{
|
||||||
return is_resource($this->connection) ? $this->connection : null;
|
return is_resource($this->connection) || $this->connection instanceof PgSql\Connection
|
||||||
|
? $this->connection
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -258,7 +261,7 @@ class PostgreDriver implements Dibi\Driver
|
|||||||
*/
|
*/
|
||||||
public function escapeText(string $value): string
|
public function escapeText(string $value): string
|
||||||
{
|
{
|
||||||
if (!is_resource($this->connection)) {
|
if (!$this->getResource()) {
|
||||||
throw new Dibi\Exception('Lost connection to server.');
|
throw new Dibi\Exception('Lost connection to server.');
|
||||||
}
|
}
|
||||||
return "'" . pg_escape_string($this->connection, $value) . "'";
|
return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||||
@@ -267,7 +270,7 @@ class PostgreDriver implements Dibi\Driver
|
|||||||
|
|
||||||
public function escapeBinary(string $value): string
|
public function escapeBinary(string $value): string
|
||||||
{
|
{
|
||||||
if (!is_resource($this->connection)) {
|
if (!$this->getResource()) {
|
||||||
throw new Dibi\Exception('Lost connection to server.');
|
throw new Dibi\Exception('Lost connection to server.');
|
||||||
}
|
}
|
||||||
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
return "'" . pg_escape_bytea($this->connection, $value) . "'";
|
||||||
|
@@ -102,7 +102,7 @@ class PostgreReflector implements Dibi\Reflector
|
|||||||
a.atttypmod-4 AS character_maximum_length,
|
a.atttypmod-4 AS character_maximum_length,
|
||||||
NOT a.attnotnull AS is_nullable,
|
NOT a.attnotnull AS is_nullable,
|
||||||
a.attnum AS ordinal_position,
|
a.attnum AS ordinal_position,
|
||||||
adef.adsrc AS column_default
|
pg_get_expr(adef.adbin, adef.adrelid) AS column_default
|
||||||
FROM
|
FROM
|
||||||
pg_attribute a
|
pg_attribute a
|
||||||
JOIN pg_type ON a.atttypid = pg_type.oid
|
JOIN pg_type ON a.atttypid = pg_type.oid
|
||||||
|
@@ -11,6 +11,7 @@ namespace Dibi\Drivers;
|
|||||||
|
|
||||||
use Dibi;
|
use Dibi;
|
||||||
use Dibi\Helpers;
|
use Dibi\Helpers;
|
||||||
|
use PgSql;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,7 +21,7 @@ class PostgreResult implements Dibi\ResultDriver
|
|||||||
{
|
{
|
||||||
use Dibi\Strict;
|
use Dibi\Strict;
|
||||||
|
|
||||||
/** @var resource */
|
/** @var resource|PgSql\Result */
|
||||||
private $resultSet;
|
private $resultSet;
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
@@ -28,7 +29,7 @@ class PostgreResult implements Dibi\ResultDriver
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param resource $resultSet
|
* @param resource|PgSql\Result $resultSet
|
||||||
*/
|
*/
|
||||||
public function __construct($resultSet)
|
public function __construct($resultSet)
|
||||||
{
|
{
|
||||||
@@ -108,12 +109,14 @@ class PostgreResult implements Dibi\ResultDriver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the result set resource.
|
* Returns the result set resource.
|
||||||
* @return resource|null
|
* @return resource|PgSql\Result|null
|
||||||
*/
|
*/
|
||||||
public function getResultResource()
|
public function getResultResource()
|
||||||
{
|
{
|
||||||
$this->autoFree = false;
|
$this->autoFree = false;
|
||||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
return is_resource($this->resultSet) || $this->resultSet instanceof PgSql\Result
|
||||||
|
? $this->resultSet
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -53,6 +53,9 @@ class SqlsrvDriver implements Dibi\Driver
|
|||||||
|
|
||||||
if (isset($config['resource'])) {
|
if (isset($config['resource'])) {
|
||||||
$this->connection = $config['resource'];
|
$this->connection = $config['resource'];
|
||||||
|
if (!is_resource($this->connection)) {
|
||||||
|
throw new \InvalidArgumentException("Configuration option 'resource' is not resource.");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$options = $config['options'];
|
$options = $config['options'];
|
||||||
@@ -63,13 +66,15 @@ class SqlsrvDriver implements Dibi\Driver
|
|||||||
$options['UID'] = (string) $options['UID'];
|
$options['UID'] = (string) $options['UID'];
|
||||||
$options['Database'] = (string) $options['Database'];
|
$options['Database'] = (string) $options['Database'];
|
||||||
|
|
||||||
|
sqlsrv_configure('WarningsReturnAsErrors', 0);
|
||||||
$this->connection = sqlsrv_connect($config['host'], $options);
|
$this->connection = sqlsrv_connect($config['host'], $options);
|
||||||
|
if (!is_resource($this->connection)) {
|
||||||
|
$info = sqlsrv_errors(SQLSRV_ERR_ERRORS);
|
||||||
|
throw new Dibi\DriverException($info[0]['message'], $info[0]['code']);
|
||||||
|
}
|
||||||
|
sqlsrv_configure('WarningsReturnAsErrors', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_resource($this->connection)) {
|
|
||||||
$info = sqlsrv_errors();
|
|
||||||
throw new Dibi\DriverException($info[0]['message'], $info[0]['code']);
|
|
||||||
}
|
|
||||||
$this->version = sqlsrv_server_info($this->connection)['SQLServerVersion'];
|
$this->version = sqlsrv_server_info($this->connection)['SQLServerVersion'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -181,6 +181,7 @@ class Helpers
|
|||||||
{
|
{
|
||||||
static $patterns = [
|
static $patterns = [
|
||||||
'^_' => Type::TEXT, // PostgreSQL arrays
|
'^_' => Type::TEXT, // PostgreSQL arrays
|
||||||
|
'RANGE$' => Type::TEXT, // PostgreSQL range types
|
||||||
'BYTEA|BLOB|BIN' => Type::BINARY,
|
'BYTEA|BLOB|BIN' => Type::BINARY,
|
||||||
'TEXT|CHAR|POINT|INTERVAL|STRING' => Type::TEXT,
|
'TEXT|CHAR|POINT|INTERVAL|STRING' => Type::TEXT,
|
||||||
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT|^TINY$' => Type::INTEGER,
|
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT|^TINY$' => Type::INTEGER,
|
||||||
|
@@ -489,7 +489,7 @@ class Result implements IDataSource
|
|||||||
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
|
$row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F';
|
||||||
|
|
||||||
} elseif ($type === Type::DATETIME || $type === Type::DATE || $type === Type::TIME) {
|
} 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, 7) !== '0000-00') { // '', null, false, '0000-00-00', ...
|
||||||
$value = new DateTime($value);
|
$value = new DateTime($value);
|
||||||
$row[$key] = $format ? $value->format($format) : $value;
|
$row[$key] = $format ? $value->format($format) : $value;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -44,6 +44,7 @@ class ResultIterator implements \Iterator, \Countable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
/**
|
/**
|
||||||
* Returns the key of the current element.
|
* Returns the key of the current element.
|
||||||
* @return mixed
|
* @return mixed
|
||||||
@@ -54,6 +55,7 @@ class ResultIterator implements \Iterator, \Countable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
/**
|
/**
|
||||||
* Returns the current element.
|
* Returns the current element.
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
@@ -37,7 +37,7 @@ class Row implements \ArrayAccess, \IteratorAggregate, \Countable
|
|||||||
{
|
{
|
||||||
$time = $this[$key];
|
$time = $this[$key];
|
||||||
if (!$time instanceof DateTime) {
|
if (!$time instanceof DateTime) {
|
||||||
if (!$time || substr((string) $time, 0, 3) === '000') { // '', null, false, '0000-00-00', ...
|
if (!$time || substr((string) $time, 0, 7) === '0000-00') { // '', null, false, '0000-00-00', ...
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$time = new DateTime($time);
|
$time = new DateTime($time);
|
||||||
@@ -53,40 +53,47 @@ class Row implements \ArrayAccess, \IteratorAggregate, \Countable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function __isset(string $key): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************* interfaces ArrayAccess, Countable & IteratorAggregate ****************d*g**/
|
/********************* interfaces ArrayAccess, Countable & IteratorAggregate ****************d*g**/
|
||||||
|
|
||||||
|
|
||||||
final public function count()
|
final public function count(): int
|
||||||
{
|
{
|
||||||
return count((array) $this);
|
return count((array) $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final public function getIterator()
|
final public function getIterator(): \ArrayIterator
|
||||||
{
|
{
|
||||||
return new \ArrayIterator($this);
|
return new \ArrayIterator($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final public function offsetSet($nm, $val)
|
final public function offsetSet($nm, $val): void
|
||||||
{
|
{
|
||||||
$this->$nm = $val;
|
$this->$nm = $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
final public function offsetGet($nm)
|
final public function offsetGet($nm)
|
||||||
{
|
{
|
||||||
return $this->$nm;
|
return $this->$nm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final public function offsetExists($nm)
|
final public function offsetExists($nm): bool
|
||||||
{
|
{
|
||||||
return isset($this->$nm);
|
return isset($this->$nm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final public function offsetUnset($nm)
|
final public function offsetUnset($nm): void
|
||||||
{
|
{
|
||||||
unset($this->$nm);
|
unset($this->$nm);
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,7 @@ class dibi
|
|||||||
|
|
||||||
/** version */
|
/** version */
|
||||||
public const
|
public const
|
||||||
VERSION = '4.2.1';
|
VERSION = '4.2.5';
|
||||||
|
|
||||||
/** sorting order */
|
/** sorting order */
|
||||||
public const
|
public const
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# for php-coveralls
|
# for php-coveralls
|
||||||
service_name: travis-ci
|
service_name: github-actions
|
||||||
coverage_clover: coverage.xml
|
coverage_clover: coverage.xml
|
||||||
json_path: coverage.json
|
json_path: coverage.json
|
||||||
|
89
tests/databases.github.ini
Normal file
89
tests/databases.github.ini
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
[sqlite] ; default
|
||||||
|
driver = sqlite
|
||||||
|
database = :memory:
|
||||||
|
system = sqlite
|
||||||
|
|
||||||
|
[sqlite pdo]
|
||||||
|
driver = pdo
|
||||||
|
dsn = "sqlite::memory:"
|
||||||
|
system = sqlite
|
||||||
|
|
||||||
|
[mysql 5.7]
|
||||||
|
driver = mysqli
|
||||||
|
host = "127.0.0.1"
|
||||||
|
database = dibi_test
|
||||||
|
username = root
|
||||||
|
password = root
|
||||||
|
port = 3306
|
||||||
|
system = mysql
|
||||||
|
|
||||||
|
[mysql 5.7pdo]
|
||||||
|
driver = pdo
|
||||||
|
dsn = "mysql:host=127.0.0.1;port=3306;dbname=dibi_test"
|
||||||
|
user = root
|
||||||
|
password = root
|
||||||
|
system = mysql
|
||||||
|
|
||||||
|
[mysql 8.0]
|
||||||
|
driver = mysqli
|
||||||
|
host = "127.0.0.1"
|
||||||
|
database = dibi_test
|
||||||
|
username = root
|
||||||
|
password = root
|
||||||
|
port = 3307
|
||||||
|
system = mysql
|
||||||
|
|
||||||
|
[mysql 8.0pdo]
|
||||||
|
driver = pdo
|
||||||
|
dsn = "mysql:host=127.0.0.1;port=3307;dbname=dibi_test"
|
||||||
|
user = root
|
||||||
|
password = root
|
||||||
|
system = mysql
|
||||||
|
|
||||||
|
[postgre 9.6]
|
||||||
|
driver = postgre
|
||||||
|
host = "127.0.0.1"
|
||||||
|
database = dibi_test
|
||||||
|
username = postgres
|
||||||
|
password = postgres
|
||||||
|
port = 5432
|
||||||
|
system = postgre
|
||||||
|
|
||||||
|
[postgre 9.6pdo]
|
||||||
|
driver = pdo
|
||||||
|
dsn = "pgsql:host=127.0.0.1;port=5432;dbname=dibi_test"
|
||||||
|
user = postgres
|
||||||
|
password = postgres
|
||||||
|
system = postgre
|
||||||
|
|
||||||
|
[postgre 13]
|
||||||
|
driver = postgre
|
||||||
|
host = "127.0.0.1"
|
||||||
|
database = dibi_test
|
||||||
|
username = postgres
|
||||||
|
password = postgres
|
||||||
|
port = 5433
|
||||||
|
system = postgre
|
||||||
|
|
||||||
|
[postgre 13pdo]
|
||||||
|
driver = pdo
|
||||||
|
dsn = "pgsql:host=127.0.0.1;port=5433;dbname=dibi_test"
|
||||||
|
user = postgres
|
||||||
|
password = postgres
|
||||||
|
system = postgre
|
||||||
|
|
||||||
|
[sqlsrv]
|
||||||
|
driver = sqlsrv
|
||||||
|
host = "localhost"
|
||||||
|
username = SA
|
||||||
|
password = "YourStrong!Passw0rd"
|
||||||
|
database = dibi_test
|
||||||
|
port = 1433
|
||||||
|
system = sqlsrv
|
||||||
|
|
||||||
|
;[sqlsrv pdo]
|
||||||
|
;driver = pdo
|
||||||
|
;dsn = "sqlsrv:Server=localhost,1433;Database=dibi_test"
|
||||||
|
;user = SA
|
||||||
|
;password = "YourStrong!Passw0rd"
|
||||||
|
;system = sqlsrv
|
@@ -1,38 +0,0 @@
|
|||||||
[sqlite] ; default
|
|
||||||
driver = sqlite
|
|
||||||
database = :memory:
|
|
||||||
system = sqlite
|
|
||||||
|
|
||||||
[sqlite pdo]
|
|
||||||
driver = pdo
|
|
||||||
dsn = "sqlite::memory:"
|
|
||||||
system = sqlite
|
|
||||||
|
|
||||||
[mysql improved]
|
|
||||||
driver = mysqli
|
|
||||||
host = 127.0.0.1
|
|
||||||
username = root
|
|
||||||
password =
|
|
||||||
charset = utf8
|
|
||||||
system = mysql
|
|
||||||
|
|
||||||
[mysql pdo]
|
|
||||||
driver = pdo
|
|
||||||
dsn = "mysql:host=127.0.0.1"
|
|
||||||
username = root
|
|
||||||
password =
|
|
||||||
system = mysql
|
|
||||||
|
|
||||||
[postgre]
|
|
||||||
driver = postgre
|
|
||||||
host = 127.0.0.1
|
|
||||||
username = postgres
|
|
||||||
password =
|
|
||||||
system = postgre
|
|
||||||
|
|
||||||
[postgre pdo]
|
|
||||||
driver = pdo
|
|
||||||
dsn = "pgsql:host=127.0.0.1;dbname=dibi_test"
|
|
||||||
username = postgres
|
|
||||||
password =
|
|
||||||
system = postgre
|
|
@@ -30,42 +30,102 @@ Assert::exception(function () use ($conn) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
$conn->begin();
|
test('begin() & rollback()', function () use ($conn) {
|
||||||
Assert::same(3, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
$conn->begin();
|
||||||
$conn->query('INSERT INTO [products]', [
|
Assert::same(3, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
'title' => 'Test product',
|
|
||||||
]);
|
|
||||||
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
|
||||||
$conn->rollback();
|
|
||||||
Assert::same(3, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$conn->begin();
|
|
||||||
$conn->query('INSERT INTO [products]', [
|
|
||||||
'title' => 'Test product',
|
|
||||||
]);
|
|
||||||
$conn->commit();
|
|
||||||
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Assert::exception(function () use ($conn) {
|
|
||||||
$conn->transaction(function () use ($conn) {
|
|
||||||
$conn->query('INSERT INTO [products]', [
|
|
||||||
'title' => 'Test product',
|
|
||||||
]);
|
|
||||||
throw new Exception('my exception');
|
|
||||||
});
|
|
||||||
}, \Throwable::class, 'my exception');
|
|
||||||
|
|
||||||
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
|
||||||
|
|
||||||
$conn->transaction(function () use ($conn) {
|
|
||||||
$conn->query('INSERT INTO [products]', [
|
$conn->query('INSERT INTO [products]', [
|
||||||
'title' => 'Test product',
|
'title' => 'Test product',
|
||||||
]);
|
]);
|
||||||
|
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
|
$conn->rollback();
|
||||||
|
Assert::same(3, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert::same(5, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
|
||||||
|
test('begin() & commit()', function () use ($conn) {
|
||||||
|
$conn->begin();
|
||||||
|
$conn->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
$conn->commit();
|
||||||
|
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('transaction() fail', function () use ($conn) {
|
||||||
|
Assert::exception(function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
throw new Exception('my exception');
|
||||||
|
});
|
||||||
|
}, \Throwable::class, 'my exception');
|
||||||
|
Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('transaction() success', function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
Assert::same(5, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('nested transaction() call fail', function () use ($conn) {
|
||||||
|
Assert::exception(function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$connection->transaction(function (Dibi\Connection $connection2) {
|
||||||
|
$connection2->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
throw new Exception('my exception');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, \Throwable::class, 'my exception');
|
||||||
|
Assert::same(5, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('nested transaction() call success', function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$connection->transaction(function (Dibi\Connection $connection2) {
|
||||||
|
$connection2->query('INSERT INTO [products]', [
|
||||||
|
'title' => 'Test product',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Assert::same(7, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('begin(), commit() & rollback() calls are forbidden in transaction()', function () use ($conn) {
|
||||||
|
Assert::exception(function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->begin();
|
||||||
|
});
|
||||||
|
}, \LogicException::class, Dibi\Connection::class . '::begin() call is forbidden inside a transaction() callback');
|
||||||
|
|
||||||
|
Assert::exception(function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->commit();
|
||||||
|
});
|
||||||
|
}, \LogicException::class, Dibi\Connection::class . '::commit() call is forbidden inside a transaction() callback');
|
||||||
|
|
||||||
|
Assert::exception(function () use ($conn) {
|
||||||
|
$conn->transaction(function (Dibi\Connection $connection) {
|
||||||
|
$connection->rollback();
|
||||||
|
});
|
||||||
|
}, \LogicException::class, Dibi\Connection::class . '::rollback() call is forbidden inside a transaction() callback');
|
||||||
|
});
|
||||||
|
@@ -14,8 +14,6 @@ Assert::same('1978-01-23 11:40:00.000000', (string) new DateTime(254400000));
|
|||||||
Assert::same('1978-01-23 11:40:00.000000', (string) (new DateTime)->setTimestamp(254400000));
|
Assert::same('1978-01-23 11:40:00.000000', (string) (new DateTime)->setTimestamp(254400000));
|
||||||
Assert::same(254400000, (new DateTime(254400000))->getTimestamp());
|
Assert::same(254400000, (new DateTime(254400000))->getTimestamp());
|
||||||
|
|
||||||
Assert::same('2050-08-13 11:40:00.000000', (string) new DateTime(2544000000));
|
|
||||||
Assert::same('2050-08-13 11:40:00.000000', (string) (new DateTime)->setTimestamp(2544000000));
|
|
||||||
Assert::same(is_int(2544000000) ? 2544000000 : '2544000000', (new DateTime(2544000000))->getTimestamp()); // 64 bit
|
Assert::same(is_int(2544000000) ? 2544000000 : '2544000000', (new DateTime(2544000000))->getTimestamp()); // 64 bit
|
||||||
|
|
||||||
Assert::same('1978-05-05 00:00:00.000000', (string) new DateTime('1978-05-05'));
|
Assert::same('1978-05-05 00:00:00.000000', (string) new DateTime('1978-05-05'));
|
||||||
|
@@ -32,7 +32,7 @@ Assert::same(
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (!in_array($config['driver'], ['sqlite', 'pdo', 'sqlsrv'], true)) {
|
if (!in_array($config['driver'], ['sqlite', 'sqlite3', 'pdo', 'sqlsrv'], true)) {
|
||||||
Assert::same(
|
Assert::same(
|
||||||
['products.product_id', 'orders.order_id', 'customers.name', 'xXx'],
|
['products.product_id', 'orders.order_id', 'customers.name', 'xXx'],
|
||||||
$info->getColumnNames(true)
|
$info->getColumnNames(true)
|
||||||
@@ -43,7 +43,7 @@ if (!in_array($config['driver'], ['sqlite', 'pdo', 'sqlsrv'], true)) {
|
|||||||
$columns = $info->getColumns();
|
$columns = $info->getColumns();
|
||||||
|
|
||||||
Assert::same('product_id', $columns[0]->getName());
|
Assert::same('product_id', $columns[0]->getName());
|
||||||
if (!in_array($config['driver'], ['sqlite', 'pdo', 'sqlsrv'], true)) {
|
if (!in_array($config['driver'], ['sqlite', 'sqlite3', 'pdo', 'sqlsrv'], true)) {
|
||||||
Assert::same('products', $columns[0]->getTableName());
|
Assert::same('products', $columns[0]->getTableName());
|
||||||
}
|
}
|
||||||
Assert::null($columns[0]->getVendorInfo('xxx'));
|
Assert::null($columns[0]->getVendorInfo('xxx'));
|
||||||
|
@@ -35,6 +35,10 @@ Assert::error(function () use ($row) {
|
|||||||
Assert::false(isset($row->missing));
|
Assert::false(isset($row->missing));
|
||||||
Assert::false(isset($row['missing']));
|
Assert::false(isset($row['missing']));
|
||||||
|
|
||||||
|
// ??
|
||||||
|
Assert::same(123, $row->missing ?? 123);
|
||||||
|
Assert::same(123, $row['missing'] ?? 123);
|
||||||
|
|
||||||
|
|
||||||
// suggestions
|
// suggestions
|
||||||
Assert::error(function () use ($row) {
|
Assert::error(function () use ($row) {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider ../databases.ini
|
* @dataProvider ../databases.ini !=sqlsrv
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
@@ -23,6 +23,10 @@ try {
|
|||||||
$config = reset($config);
|
$config = reset($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($config['port'])) {
|
||||||
|
$config['port'] = (int) $config['port'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
define('TEMP_DIR', __DIR__ . '/../tmp');
|
define('TEMP_DIR', __DIR__ . '/../tmp');
|
||||||
|
@@ -36,7 +36,7 @@ Assert::same('SELECT', $e->getSql());
|
|||||||
|
|
||||||
$e = Assert::exception(function () use ($conn) {
|
$e = Assert::exception(function () use ($conn) {
|
||||||
$conn->query('INSERT INTO products (product_id, title) VALUES (1, "New")');
|
$conn->query('INSERT INTO products (product_id, title) VALUES (1, "New")');
|
||||||
}, Dibi\UniqueConstraintViolationException::class, "%a?%Duplicate entry '1' for key 'PRIMARY'", 1062);
|
}, Dibi\UniqueConstraintViolationException::class, "%a?%Duplicate entry '1' for key '%a?%PRIMARY'", 1062);
|
||||||
|
|
||||||
Assert::same("INSERT INTO products (product_id, title) VALUES (1, 'New')", $e->getSql());
|
Assert::same("INSERT INTO products (product_id, title) VALUES (1, 'New')", $e->getSql());
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ Assert::same("INSERT INTO products (product_id, title) VALUES (1, 'New')", $e->g
|
|||||||
|
|
||||||
$e = Assert::exception(function () use ($conn) {
|
$e = Assert::exception(function () use ($conn) {
|
||||||
$conn->query('INSERT INTO products (title) VALUES (NULL)');
|
$conn->query('INSERT INTO products (title) VALUES (NULL)');
|
||||||
}, Dibi\NotNullConstraintViolationException::class, '%a?%null value in column "title" violates not-null constraint%A?%', '23502');
|
}, Dibi\NotNullConstraintViolationException::class, '%a?%null value in column "title"%a%violates not-null constraint%A?%', '23502');
|
||||||
|
|
||||||
Assert::same('INSERT INTO products (title) VALUES (NULL)', $e->getSql());
|
Assert::same('INSERT INTO products (title) VALUES (NULL)', $e->getSql());
|
||||||
|
|
||||||
|
@@ -12,5 +12,5 @@ extension=php_pdo_pgsql.dll
|
|||||||
extension=php_pdo_sqlite.dll
|
extension=php_pdo_sqlite.dll
|
||||||
extension=php_pgsql.dll
|
extension=php_pgsql.dll
|
||||||
extension=php_sqlite3.dll
|
extension=php_sqlite3.dll
|
||||||
extension=php_sqlsrv_71_ts.dll
|
extension=php_sqlsrv_ts.dll
|
||||||
extension=php_odbc.dll
|
extension=php_odbc.dll
|
||||||
|
Reference in New Issue
Block a user