From d24fc4d033196b531718f915c4c8de57b53fb49e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 23 Apr 2021 17:24:45 +0200 Subject: [PATCH 01/21] added github workflows --- .github/workflows/coding-style.yml | 31 +++++++ .github/workflows/static-analysis.yml | 21 +++++ .github/workflows/tests.yml | 121 ++++++++++++++++++++++++++ tests/databases.github.ini | 89 +++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100644 .github/workflows/coding-style.yml create mode 100644 .github/workflows/static-analysis.yml create mode 100644 .github/workflows/tests.yml create mode 100644 tests/databases.github.ini diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml new file mode 100644 index 000000000..00abb989e --- /dev/null +++ b/.github/workflows/coding-style.yml @@ -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 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 000000000..f985b0526 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -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 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..b81c281de --- /dev/null +++ b/.github/workflows/tests.yml @@ -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'] + + 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 diff --git a/tests/databases.github.ini b/tests/databases.github.ini new file mode 100644 index 000000000..40aeb4641 --- /dev/null +++ b/tests/databases.github.ini @@ -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 From b74ef0910d88f451636bdfb9bd1825ff4a9a92b1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:26:05 +0100 Subject: [PATCH 02/21] opened 5.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d94135ceb..681a683a3 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ }, "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "5.0-dev" } } } From 2ef62cd1925e01fb09c6bcf6f83228725c590e41 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:50:27 +0100 Subject: [PATCH 03/21] requires PHP 8.0 --- .github/workflows/tests.yml | 2 +- .travis.yml | 12 +++++------- appveyor.yml | 20 ++++++++++---------- composer.json | 2 +- readme.md | 2 +- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b81c281de..2abdd2c0f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['7.2', '7.3', '7.4', '8.0'] + php: ['8.0'] fail-fast: false diff --git a/.travis.yml b/.travis.yml index 8200ddb6e..c50067e8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,7 @@ language: php php: - - 7.2 - - 7.3 - - 7.4 - - 8.0snapshot + - 8.0 + - 8.0 services: - mysql @@ -39,7 +37,7 @@ jobs: - name: Nette Coding Standard - php: 7.4 + php: 8.0 install: - travis_retry composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress script: @@ -47,13 +45,13 @@ jobs: - stage: Static Analysis (informative) - php: 7.4 + php: 8.0 script: - composer run-script phpstan - stage: Code Coverage - php: 7.4 + php: 8.0 script: - vendor/bin/tester -p phpdbg tests -s --coverage ./coverage.xml --coverage-src ./src after_script: diff --git a/appveyor.yml b/appveyor.yml index a4330dcf6..30ed27758 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ build: off cache: - - c:\php7 -> appveyor.yml + - c:\php -> appveyor.yml - '%LOCALAPPDATA%\Composer\files -> appveyor.yml' clone_folder: c:\projects\dibi @@ -11,21 +11,21 @@ services: - mysql init: - - SET PATH=c:\php7;%PATH% + - SET PATH=c:\php;%PATH% - SET ANSICON=121x90 (121x90) install: - # Install PHP 7.2 - - 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 curl https://windows.php.net/downloads/releases/archives/php-7.2.18-Win32-VC15-x64.zip --output php.zip + # Install PHP 8.0 + - IF EXIST c:\php (SET PHP=0) ELSE (SET PHP=1) + - IF %PHP%==1 mkdir c:\php + - IF %PHP%==1 cd c:\php + - IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-8.0.1-Win32-vs16-x64.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 curl https://github.com/microsoft/msphpsql/releases/download/v5.8.0/Windows-7.2.zip -L --output sqlsrv.zip + - IF %PHP%==1 curl https://github.com/microsoft/msphpsql/releases/download/v5.9.0/Windows-8.0.zip -L --output sqlsrv.zip - IF %PHP%==1 7z x sqlsrv.zip >nul - - IF %PHP%==1 copy Windows-7.2\x64\php_sqlsrv_72_ts.dll ext\php_sqlsrv_ts.dll + - IF %PHP%==1 copy Windows-8.0\x64\php_sqlsrv_80_ts.dll ext\php_sqlsrv_ts.dll - IF %PHP%==1 del /Q *.zip # Install Microsoft Access Database Engine x64 @@ -41,7 +41,7 @@ install: - copy tests\databases.appveyor.ini tests\databases.ini test_script: - - vendor\bin\tester tests -s -p c:\php7\php -c tests\php-win.ini + - vendor\bin\tester tests -s -p c:\php\php -c tests\php-win.ini on_failure: # Print *.actual content diff --git a/composer.json b/composer.json index 681a683a3..e7612dbc9 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=8.0 <8.1" }, "require-dev": { "tracy/tracy": "~2.2", diff --git a/readme.md b/readme.md index 997b3c415..26d6a9a45 100644 --- a/readme.md +++ b/readme.md @@ -34,7 +34,7 @@ Install Dibi via Composer: 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 8.0. Usage From 3cb9c7ab21d00c1ec174774735348e9ec3756b6c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:01:23 +0100 Subject: [PATCH 04/21] composer: updated dependencies --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e7612dbc9..956492911 100644 --- a/composer.json +++ b/composer.json @@ -14,8 +14,8 @@ "php": ">=8.0 <8.1" }, "require-dev": { - "tracy/tracy": "~2.2", - "nette/tester": "~2.0", + "tracy/tracy": "^2.8", + "nette/tester": "^2.4", "nette/di": "^3.0", "phpstan/phpstan": "^0.12" }, From e1fd9588d57eb65a5b1d61d3a57807e07edb692c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 17:55:56 +0100 Subject: [PATCH 05/21] coding style --- src/Dibi/Bridges/Nette/DibiExtension22.php | 2 +- src/Dibi/Connection.php | 6 +- src/Dibi/DataSource.php | 6 +- src/Dibi/Drivers/FirebirdReflector.php | 2 +- src/Dibi/Drivers/MySqliDriver.php | 2 +- src/Dibi/Drivers/SqlsrvDriver.php | 2 +- src/Dibi/Loggers/FileLogger.php | 4 +- src/Dibi/Strict.php | 14 ++-- src/Dibi/Translator.php | 53 +++++++------ tests/dibi/Connection.fetch.phpt | 4 +- tests/dibi/Connection.substitutions.phpt | 18 ++--- tests/dibi/DataSource.phpt | 20 ++--- tests/dibi/DateTime.phpt | 12 +-- tests/dibi/Fluent.delete.phpt | 10 +-- tests/dibi/Fluent.fetch.limit.mssql.phpt | 22 +++--- tests/dibi/Fluent.fetch.limit.phpt | 28 +++---- tests/dibi/Fluent.insert.phpt | 12 +-- tests/dibi/Fluent.select.phpt | 26 +++---- tests/dibi/Fluent.update.phpt | 6 +- tests/dibi/HashMap.phpt | 4 +- tests/dibi/Result.meta.phpt | 4 +- tests/dibi/Sqlsrv.insert.phpt | 2 +- tests/dibi/Sqlsrv.limits.phpt | 20 ++--- tests/dibi/Translator.conditions.phpt | 18 ++--- tests/dibi/Translator.identifiers.phpt | 12 +-- tests/dibi/Translator.phpt | 90 +++++++++++----------- 26 files changed, 197 insertions(+), 202 deletions(-) diff --git a/src/Dibi/Bridges/Nette/DibiExtension22.php b/src/Dibi/Bridges/Nette/DibiExtension22.php index c317d1bde..1b3082771 100644 --- a/src/Dibi/Bridges/Nette/DibiExtension22.php +++ b/src/Dibi/Bridges/Nette/DibiExtension22.php @@ -57,7 +57,7 @@ public function loadConfiguration() if (class_exists(Tracy\Debugger::class)) { $connection->addSetup( [new Nette\DI\Statement('Tracy\Debugger::getBlueScreen'), 'addPanel'], - [[Dibi\Bridges\Tracy\Panel::class, 'renderException']] + [[Dibi\Bridges\Tracy\Panel::class, 'renderException']], ); } if ($useProfiler) { diff --git a/src/Dibi/Connection.php b/src/Dibi/Connection.php index 1088af4bb..f481a7bc2 100644 --- a/src/Dibi/Connection.php +++ b/src/Dibi/Connection.php @@ -75,7 +75,7 @@ public function __construct(array $config, string $name = null) Helpers::alias($config, 'host', 'hostname'); Helpers::alias($config, 'result|formatDate', 'resultDate'); Helpers::alias($config, 'result|formatDateTime', 'resultDateTime'); - $config['driver'] = $config['driver'] ?? 'mysqli'; + $config['driver'] ??= 'mysqli'; $config['name'] = $name; $this->config = $config; @@ -93,7 +93,7 @@ public function __construct(array $config, string $name = null) $this->onEvent[] = [new Loggers\FileLogger($config['profiler']['file'], $filter, $errorsOnly), 'logEvent']; } - $this->substitutes = new HashMap(function (string $expr) { return ":$expr:"; }); + $this->substitutes = new HashMap(fn(string $expr) => ":$expr:"); if (!empty($config['substitutes'])) { foreach ($config['substitutes'] as $key => $value) { $this->substitutes->$key = $value; @@ -514,7 +514,7 @@ public function substitute(string $value): string { return strpos($value, ':') === false ? $value - : preg_replace_callback('#:([^:\s]*):#', function (array $m) { return $this->substitutes->{$m[1]}; }, $value); + : preg_replace_callback('#:([^:\s]*):#', fn(array $m) => $this->substitutes->{$m[1]}, $value); } diff --git a/src/Dibi/DataSource.php b/src/Dibi/DataSource.php index 26b633017..43101ce28 100644 --- a/src/Dibi/DataSource.php +++ b/src/Dibi/DataSource.php @@ -238,7 +238,7 @@ public function __toString(): string $this->sorting ? ['ORDER BY %by', $this->sorting] : null, "\n%ofs %lmt", $this->offset, - $this->limit + $this->limit, ); } catch (\Throwable $e) { trigger_error($e->getMessage(), E_USER_ERROR); @@ -258,7 +258,7 @@ public function count(): int if ($this->count === null) { $this->count = $this->conds || $this->offset || $this->limit ? Helpers::intVal($this->connection->nativeQuery( - 'SELECT COUNT(*) FROM (' . $this->__toString() . ') t' + 'SELECT COUNT(*) FROM (' . $this->__toString() . ') t', )->fetchSingle()) : $this->getTotalCount(); } @@ -273,7 +273,7 @@ public function getTotalCount(): int { if ($this->totalCount === null) { $this->totalCount = Helpers::intVal($this->connection->nativeQuery( - 'SELECT COUNT(*) FROM ' . $this->sql + 'SELECT COUNT(*) FROM ' . $this->sql, )->fetchSingle()); } return $this->totalCount; diff --git a/src/Dibi/Drivers/FirebirdReflector.php b/src/Dibi/Drivers/FirebirdReflector.php index db1ddf81b..f1dda0e20 100644 --- a/src/Dibi/Drivers/FirebirdReflector.php +++ b/src/Dibi/Drivers/FirebirdReflector.php @@ -236,7 +236,7 @@ public function getTriggersMeta(string $table = null): array 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)) { diff --git a/src/Dibi/Drivers/MySqliDriver.php b/src/Dibi/Drivers/MySqliDriver.php index d9dede68b..97cbcd79c 100644 --- a/src/Dibi/Drivers/MySqliDriver.php +++ b/src/Dibi/Drivers/MySqliDriver.php @@ -95,7 +95,7 @@ public function __construct(array $config) $config['database'] ?? '', $config['port'] ?? 0, $config['socket'], - $config['flags'] ?? 0 + $config['flags'] ?? 0, ); if ($this->connection->connect_errno) { diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index 03ae091d8..a864189d9 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -58,7 +58,7 @@ public function __construct(array $config) $options = $config['options']; // Default values - $options['CharacterSet'] = $options['CharacterSet'] ?? 'UTF-8'; + $options['CharacterSet'] ??= 'UTF-8'; $options['PWD'] = (string) $options['PWD']; $options['UID'] = (string) $options['UID']; $options['Database'] = (string) $options['Database']; diff --git a/src/Dibi/Loggers/FileLogger.php b/src/Dibi/Loggers/FileLogger.php index f35e0ee07..5d4567abf 100644 --- a/src/Dibi/Loggers/FileLogger.php +++ b/src/Dibi/Loggers/FileLogger.php @@ -57,7 +57,7 @@ public function logEvent(Dibi\Event $event): void $this->writeToFile( $event, "ERROR: $message" - . "\n-- SQL: " . $event->sql + . "\n-- SQL: " . $event->sql, ); } else { $this->writeToFile( @@ -65,7 +65,7 @@ public function logEvent(Dibi\Event $event): void 'OK: ' . $event->sql . ($event->count ? ";\n-- rows: " . $event->count : '') . "\n-- takes: " . sprintf('%0.3f ms', $event->time * 1000) - . "\n-- source: " . implode(':', $event->source) + . "\n-- source: " . implode(':', $event->source), ); } } diff --git a/src/Dibi/Strict.php b/src/Dibi/Strict.php index f3386c5ba..a735803d8 100644 --- a/src/Dibi/Strict.php +++ b/src/Dibi/Strict.php @@ -31,7 +31,7 @@ public function __call(string $name, array $args) { $class = method_exists($this, $name) ? 'parent' : static::class; $items = (new ReflectionClass($this))->getMethods(ReflectionMethod::IS_PUBLIC); - $items = array_map(function ($item) { return $item->getName(); }, $items); + $items = array_map(fn($item) => $item->getName(), $items); $hint = ($t = Helpers::getSuggestion($items, $name)) ? ", did you mean $t()?" : '.'; @@ -46,8 +46,8 @@ public function __call(string $name, array $args) public static function __callStatic(string $name, array $args) { $rc = new ReflectionClass(static::class); - $items = array_filter($rc->getMethods(\ReflectionMethod::IS_STATIC), function ($m) { return $m->isPublic(); }); - $items = array_map(function ($item) { return $item->getName(); }, $items); + $items = array_filter($rc->getMethods(\ReflectionMethod::IS_STATIC), fn($m) => $m->isPublic()); + $items = array_map(fn($item) => $item->getName(), $items); $hint = ($t = Helpers::getSuggestion($items, $name)) ? ", did you mean $t()?" : '.'; @@ -68,8 +68,8 @@ public function &__get(string $name) return $ret; } $rc = new ReflectionClass($this); - $items = array_filter($rc->getProperties(ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }); - $items = array_map(function ($item) { return $item->getName(); }, $items); + $items = array_filter($rc->getProperties(ReflectionProperty::IS_PUBLIC), fn($p) => !$p->isStatic()); + $items = array_map(fn($item) => $item->getName(), $items); $hint = ($t = Helpers::getSuggestion($items, $name)) ? ", did you mean $$t?" : '.'; @@ -84,8 +84,8 @@ public function &__get(string $name) public function __set(string $name, $value) { $rc = new ReflectionClass($this); - $items = array_filter($rc->getProperties(ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }); - $items = array_map(function ($item) { return $item->getName(); }, $items); + $items = array_filter($rc->getProperties(ReflectionProperty::IS_PUBLIC), fn($p) => !$p->isStatic()); + $items = array_map(fn($item) => $item->getName(), $items); $hint = ($t = Helpers::getSuggestion($items, $name)) ? ", did you mean $$t?" : '.'; diff --git a/src/Dibi/Translator.php b/src/Dibi/Translator.php index 1a7852e0a..bfdd3ac4e 100644 --- a/src/Dibi/Translator.php +++ b/src/Dibi/Translator.php @@ -95,22 +95,21 @@ public function translate(array $args): string // note: this can change $this->args & $this->cursor & ... . preg_replace_callback( <<<'XX' - / - (?=[`['":%?]) ## speed-up - (?: - `(.+?)`| ## 1) `identifier` - \[(.+?)\]| ## 2) [identifier] - (')((?:''|[^'])*)'| ## 3,4) string - (")((?:""|[^"])*)"| ## 5,6) "string" - ('|")| ## 7) lone quote - :(\S*?:)([a-zA-Z0-9._]?)| ## 8,9) :substitution: - %([a-zA-Z~][a-zA-Z0-9~]{0,5})| ## 10) modifier - (\?) ## 11) placeholder - )/xs -XX -, + / + (?=[`['":%?]) ## speed-up + (?: + `(.+?)`| ## 1) `identifier` + \[(.+?)\]| ## 2) [identifier] + (')((?:''|[^'])*)'| ## 3,4) string + (")((?:""|[^"])*)"| ## 5,6) "string" + ('|")| ## 7) lone quote + :(\S*?:)([a-zA-Z0-9._]?)| ## 8,9) :substitution: + %([a-zA-Z~][a-zA-Z0-9~]{0,5})| ## 10) modifier + (\?) ## 11) placeholder + )/xs + XX, [$this, 'cb'], - substr($arg, $toSkip) + substr($arg, $toSkip), ); if (preg_last_error()) { throw new PcreException; @@ -420,20 +419,20 @@ public function formatValue($value, ?string $modifier): string $value = substr($value, 0, $toSkip) . preg_replace_callback( <<<'XX' - / - (?=[`['":]) - (?: - `(.+?)`| - \[(.+?)\]| - (')((?:''|[^'])*)'| - (")((?:""|[^"])*)"| - ('|")| - :(\S*?:)([a-zA-Z0-9._]?) - )/sx -XX + / + (?=[`['":]) + (?: + `(.+?)`| + \[(.+?)\]| + (')((?:''|[^'])*)'| + (")((?:""|[^"])*)"| + ('|")| + :(\S*?:)([a-zA-Z0-9._]?) + )/sx + XX , [$this, 'cb'], - substr($value, $toSkip) + substr($value, $toSkip), ); if (preg_last_error()) { throw new PcreException; diff --git a/tests/dibi/Connection.fetch.phpt b/tests/dibi/Connection.fetch.phpt index 7b2a01e84..12c1751a5 100644 --- a/tests/dibi/Connection.fetch.phpt +++ b/tests/dibi/Connection.fetch.phpt @@ -33,13 +33,13 @@ Assert::equal([ $res = $conn->query('SELECT * FROM [products] ORDER BY product_id'); Assert::same( [1 => 'Chair', 'Table', 'Computer'], - $res->fetchPairs('product_id', 'title') + $res->fetchPairs('product_id', 'title'), ); $res = $conn->query('SELECT * FROM [products] ORDER BY product_id'); Assert::same( [1 => 'Chair', 'Table', 'Computer'], - $res->fetchPairs() + $res->fetchPairs(), ); diff --git a/tests/dibi/Connection.substitutions.phpt b/tests/dibi/Connection.substitutions.phpt index d21550821..9ffb54326 100644 --- a/tests/dibi/Connection.substitutions.phpt +++ b/tests/dibi/Connection.substitutions.phpt @@ -13,27 +13,27 @@ $conn->getSubstitutes()->blog = 'wp_'; Assert::same( reformat('UPDATE wp_items SET [val]=1'), - $conn->translate('UPDATE :blog:items SET [val]=1') + $conn->translate('UPDATE :blog:items SET [val]=1'), ); Assert::same( reformat('UPDATE [wp_items] SET [val]=1'), - $conn->translate('UPDATE [:blog:items] SET [val]=1') + $conn->translate('UPDATE [:blog:items] SET [val]=1'), ); Assert::same( reformat("UPDATE 'wp_' SET [val]=1"), - $conn->translate('UPDATE :blog: SET [val]=1') + $conn->translate('UPDATE :blog: SET [val]=1'), ); Assert::same( reformat("UPDATE ':blg:' SET [val]=1"), - $conn->translate('UPDATE :blg: SET [val]=1') + $conn->translate('UPDATE :blg: SET [val]=1'), ); Assert::same( reformat("UPDATE table SET [text]=':blog:a'"), - $conn->translate("UPDATE table SET [text]=':blog:a'") + $conn->translate("UPDATE table SET [text]=':blog:a'"), ); @@ -42,16 +42,14 @@ $conn->getSubstitutes()->{''} = 'my_'; Assert::same( reformat('UPDATE my_table SET [val]=1'), - $conn->translate('UPDATE ::table SET [val]=1') + $conn->translate('UPDATE ::table SET [val]=1'), ); // create substitutions using fallback callback -$conn->getSubstitutes()->setCallback(function ($expr) { - return '_' . $expr . '_'; -}); +$conn->getSubstitutes()->setCallback(fn($expr) => '_' . $expr . '_'); Assert::same( reformat('UPDATE _account_user SET [val]=1'), - $conn->translate('UPDATE :account:user SET [val]=1') + $conn->translate('UPDATE :account:user SET [val]=1'), ); diff --git a/tests/dibi/DataSource.phpt b/tests/dibi/DataSource.phpt index 12ac92453..ef19b8b60 100644 --- a/tests/dibi/DataSource.phpt +++ b/tests/dibi/DataSource.phpt @@ -16,7 +16,7 @@ Assert::match( reformat(' SELECT * FROM (SELECT * FROM products) t'), - (string) $ds + (string) $ds, ); @@ -24,7 +24,7 @@ Assert::same(3, $ds->count()); Assert::same(3, $ds->getTotalCount()); Assert::same( reformat('SELECT COUNT(*) FROM (SELECT * FROM products) t'), - dibi::$sql + dibi::$sql, ); @@ -38,7 +38,7 @@ FROM (SELECT * FROM products) t WHERE (title like '%a%') ORDER BY [title] DESC "), - (string) $ds + (string) $ds, ); @@ -52,7 +52,7 @@ FROM (SELECT * FROM products) t WHERE (title like '%a%') AND (product_id = 1) ORDER BY [title] DESC, [product_id] ASC "), - (string) $ds + (string) $ds, ); @@ -66,7 +66,7 @@ FROM (SELECT * FROM products) t WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1) ORDER BY [product_id] ASC "), - (string) $ds + (string) $ds, ); @@ -94,7 +94,7 @@ FROM (SELECT * FROM products) t WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1) ORDER BY [product_id] ASC "), - dibi::$sql + dibi::$sql, ); @@ -107,7 +107,7 @@ FROM (SELECT * FROM products) t WHERE (title like '%a%') AND (product_id = 1) AND (product_id = 1) ORDER BY [product_id] ASC ) t"), - (string) $fluent + (string) $fluent, ); @@ -116,7 +116,7 @@ Assert::match( reformat(' SELECT * FROM (SELECT [title] FROM [products]) t'), - (string) $ds + (string) $ds, ); Assert::equal(new Row([ @@ -128,7 +128,7 @@ Assert::same(1, $conn->dataSource('SELECT * FROM products ORDER BY product_id')- Assert::same( [1 => 'Chair', 'Table', 'Computer'], - $conn->dataSource('SELECT * FROM products ORDER BY product_id')->fetchPairs() + $conn->dataSource('SELECT * FROM products ORDER BY product_id')->fetchPairs(), ); Assert::equal([ @@ -153,7 +153,7 @@ Assert::match( reformat(' SELECT * FROM [products]'), - (string) $ds + (string) $ds, ); Assert::same(3, $ds->count()); diff --git a/tests/dibi/DateTime.phpt b/tests/dibi/DateTime.phpt index 5621c9b0f..fc9008a93 100644 --- a/tests/dibi/DateTime.phpt +++ b/tests/dibi/DateTime.phpt @@ -10,12 +10,12 @@ require __DIR__ . '/bootstrap.php'; date_default_timezone_set('Europe/Prague'); -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(254400000, (new DateTime(254400000))->getTimestamp()); +Assert::same('1978-01-23 11:40:00.000000', (string) new DateTime(254_400_000)); +Assert::same('1978-01-23 11:40:00.000000', (string) (new DateTime)->setTimestamp(254_400_000)); +Assert::same(254_400_000, (new DateTime(254_400_000))->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('2050-08-13 11:40:00.000000', (string) new DateTime(254_400_0000)); +Assert::same('2050-08-13 11:40:00.000000', (string) (new DateTime)->setTimestamp(254_400_0000)); +Assert::same(is_int(2_544_000_000) ? 2_544_000_000 : '2544000000', (new DateTime(2_544_000_000))->getTimestamp()); // 64 bit Assert::same('1978-05-05 00:00:00.000000', (string) new DateTime('1978-05-05')); diff --git a/tests/dibi/Fluent.delete.phpt b/tests/dibi/Fluent.delete.phpt index 5a0a9771c..59d038617 100644 --- a/tests/dibi/Fluent.delete.phpt +++ b/tests/dibi/Fluent.delete.phpt @@ -14,33 +14,33 @@ $fluent = $conn->delete('table')->as('bAlias') Assert::same( reformat('DELETE IGNORE FROM [table] AS [bAlias]'), - (string) $fluent + (string) $fluent, ); $fluent->removeClause('from')->from('anotherTable'); Assert::same( reformat('DELETE IGNORE FROM [anotherTable]'), - (string) $fluent + (string) $fluent, ); $fluent->using('thirdTable'); Assert::same( reformat('DELETE IGNORE FROM [anotherTable] USING [thirdTable]'), - (string) $fluent + (string) $fluent, ); $fluent->setFlag('IGNORE', false); Assert::same( reformat('DELETE FROM [anotherTable] USING [thirdTable]'), - (string) $fluent + (string) $fluent, ); $fluent->limit(10); Assert::same( reformat('DELETE FROM [anotherTable] USING [thirdTable] LIMIT 10'), - (string) $fluent + (string) $fluent, ); diff --git a/tests/dibi/Fluent.fetch.limit.mssql.phpt b/tests/dibi/Fluent.fetch.limit.mssql.phpt index 3bffb7976..197638b88 100644 --- a/tests/dibi/Fluent.fetch.limit.mssql.phpt +++ b/tests/dibi/Fluent.fetch.limit.mssql.phpt @@ -57,28 +57,28 @@ $fluent = $conn->select('*') Assert::same( reformat('SELECT TOP (1) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - (string) $fluent + (string) $fluent, ); $fluent->fetch(); Assert::same( 'SELECT TOP (1) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t', - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT TOP (1) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - dibi::$sql + dibi::$sql, ); $fluent->fetchAll(0, 3); Assert::same( reformat('SELECT TOP (3) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT TOP (1) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - (string) $fluent + (string) $fluent, ); @@ -86,16 +86,16 @@ $fluent->limit(0); $fluent->fetch(); Assert::same( reformat('SELECT TOP (0) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT TOP (0) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT TOP (0) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - (string) $fluent + (string) $fluent, ); @@ -104,14 +104,14 @@ $fluent->removeClause('offset'); $fluent->fetch(); Assert::same( reformat('SELECT TOP (1) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT TOP (1) * FROM (SELECT * FROM [customers] ORDER BY [customer_id]) t'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id]'), - (string) $fluent + (string) $fluent, ); diff --git a/tests/dibi/Fluent.fetch.limit.phpt b/tests/dibi/Fluent.fetch.limit.phpt index f8f4f5d52..dd533e1ec 100644 --- a/tests/dibi/Fluent.fetch.limit.phpt +++ b/tests/dibi/Fluent.fetch.limit.phpt @@ -23,28 +23,28 @@ $fluent = $conn->select('*') Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'), - (string) $fluent + (string) $fluent, ); $fluent->fetch(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'), - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'), - dibi::$sql + dibi::$sql, ); $fluent->fetchAll(2, 3); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 3 OFFSET 2'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'), - (string) $fluent + (string) $fluent, ); @@ -52,16 +52,16 @@ $fluent->limit(0); $fluent->fetch(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 0 OFFSET 3'), - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 0 OFFSET 3'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 0 OFFSET 3'), - (string) $fluent + (string) $fluent, ); @@ -69,16 +69,16 @@ $fluent->removeClause('limit'); $fluent->fetch(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'), - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1 OFFSET 3'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 18446744073709551615 OFFSET 3'), - (string) $fluent + (string) $fluent, ); @@ -86,14 +86,14 @@ $fluent->removeClause('offset'); $fluent->fetch(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1'), - dibi::$sql + dibi::$sql, ); $fluent->fetchSingle(); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id] LIMIT 1'), - dibi::$sql + dibi::$sql, ); Assert::same( reformat('SELECT * FROM [customers] ORDER BY [customer_id]'), - (string) $fluent + (string) $fluent, ); diff --git a/tests/dibi/Fluent.insert.phpt b/tests/dibi/Fluent.insert.phpt index 7b97e4039..4b39f4e42 100644 --- a/tests/dibi/Fluent.insert.phpt +++ b/tests/dibi/Fluent.insert.phpt @@ -20,40 +20,40 @@ $fluent = $conn->insert('table', $arr) Assert::same( reformat('INSERT IGNORE DELAYED INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'), - (string) $fluent + (string) $fluent, ); $fluent->setFlag('IGNORE', false); Assert::same( reformat('INSERT DELAYED INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'), - (string) $fluent + (string) $fluent, ); $fluent->setFlag('HIGH_priority'); Assert::same( reformat('INSERT DELAYED HIGH_PRIORITY INTO [table] ([title], [price], [brand]) VALUES (\'Super Product\', 12, NULL)'), - (string) $fluent + (string) $fluent, ); $fluent->into('anotherTable'); Assert::same( reformat('INSERT DELAYED HIGH_PRIORITY INTO [anotherTable] VALUES (\'Super Product\', 12, NULL)'), - (string) $fluent + (string) $fluent, ); $fluent->values('%l', $arr); Assert::same( reformat('INSERT DELAYED HIGH_PRIORITY INTO [anotherTable] VALUES (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL)'), - (string) $fluent + (string) $fluent, ); $fluent->values($arr); Assert::same( reformat('INSERT DELAYED HIGH_PRIORITY INTO [anotherTable] VALUES (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL) , (\'Super Product\', 12, NULL)'), - (string) $fluent + (string) $fluent, ); diff --git a/tests/dibi/Fluent.select.phpt b/tests/dibi/Fluent.select.phpt index 17a1f914c..7b9ba1855 100644 --- a/tests/dibi/Fluent.select.phpt +++ b/tests/dibi/Fluent.select.phpt @@ -25,7 +25,7 @@ $fluent = $conn->select('*') Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d]'), - (string) $fluent + (string) $fluent, ); $fluent->from('table')->as('table.Alias') @@ -34,21 +34,21 @@ $fluent->from('table')->as('table.Alias') Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [table] AS [table.Alias] INNER JOIN [table1] ON table.col = table1.col INNER JOIN [table2] ON table.col = table2.col'), - (string) $fluent + (string) $fluent, ); $fluent->from('anotherTable'); Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [table] AS [table.Alias] INNER JOIN [table1] ON table.col = table1.col INNER JOIN [table2] ON table.col = table2.col , [anotherTable]'), - (string) $fluent + (string) $fluent, ); $fluent->removeClause('from')->from('anotherTable'); Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable]'), - (string) $fluent + (string) $fluent, ); $fluent->as('anotherAlias') @@ -58,7 +58,7 @@ $fluent->as('anotherAlias') Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable] AS [anotherAlias] INNER JOIN [table3] ON table.col = table3.col'), - (string) $fluent + (string) $fluent, ); $fluent->where('col > %i', $max) @@ -71,14 +71,14 @@ $fluent->where('col > %i', $max) Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable] AS [anotherAlias] INNER JOIN [table3] ON table.col = table3.col WHERE col > 10 OR col < 5 AND active = 1 AND [col] IN (1, 2, 3) ORDER BY [val] ASC , [val2] DESC , [val3] DESC'), - (string) $fluent + (string) $fluent, ); $fluent->orderBy(Dibi\Fluent::REMOVE); Assert::same( reformat('SELECT * , [a] , [b] AS [bAlias] , [c], [d], [e] , [d] FROM [anotherTable] AS [anotherAlias] INNER JOIN [table3] ON table.col = table3.col WHERE col > 10 OR col < 5 AND active = 1 AND [col] IN (1, 2, 3)'), - (string) $fluent + (string) $fluent, ); @@ -86,7 +86,7 @@ $fluent = $conn->select('*') ->select( $conn->select('count(*)') ->from('precteni')->as('P') - ->where('P.id_clanku', '=', 'C.id_clanku') + ->where('P.id_clanku', '=', 'C.id_clanku'), ) ->from('clanky')->as('C') ->where('id_clanku=%i', 123) @@ -99,7 +99,7 @@ Assert::same( 'sqlsrv' => 'SELECT * , (SELECT count(*) FROM [precteni] AS [P] WHERE P.id_clanku = C.id_clanku) FROM [clanky] AS [C] WHERE id_clanku=123 OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY', 'SELECT * , (SELECT count(*) FROM [precteni] AS [P] WHERE P.id_clanku = C.id_clanku) FROM [clanky] AS [C] WHERE id_clanku=123 LIMIT 1', ]), - (string) $fluent + (string) $fluent, ); @@ -112,7 +112,7 @@ $fluent = $conn->select('*') Assert::same( reformat('SELECT * , [x] AS [xAlias] FROM [products] INNER JOIN [orders] USING (product_id) INNER JOIN [customers] USING ([customer_id]) INNER JOIN [items] USING ([customer_id], [order_id])'), - (string) $fluent + (string) $fluent, ); @@ -124,7 +124,7 @@ $fluent = $conn->command()->select() Assert::same( reformat('SELECT * FROM [products] INNER JOIN [orders] USING (product_id)'), - (string) $fluent + (string) $fluent, ); @@ -138,7 +138,7 @@ Assert::same( 'sqlsrv' => "SELECT * FROM [me] AS [t] WHERE col > 10 AND ([x] = N'a') AND (b) AND (c)", "SELECT * FROM [me] AS [t] WHERE col > 10 AND ([x] = 'a') AND (b) AND (c)", ]), - (string) $fluent + (string) $fluent, ); @@ -158,5 +158,5 @@ $fluent = $conn->select('*')->from('abc') Assert::same( reformat('SELECT * FROM [abc] WHERE x IN ((SELECT [id] FROM [xyz]))'), - (string) $fluent + (string) $fluent, ); diff --git a/tests/dibi/Fluent.update.phpt b/tests/dibi/Fluent.update.phpt index 1d4ab3af7..7983c67e1 100644 --- a/tests/dibi/Fluent.update.phpt +++ b/tests/dibi/Fluent.update.phpt @@ -20,14 +20,14 @@ $fluent = $conn->update('table', $arr) Assert::same( reformat('UPDATE IGNORE DELAYED [table] SET [title]=\'Super Product\', [price]=12, [brand]=NULL'), - (string) $fluent + (string) $fluent, ); $fluent->set(['another' => 123]); Assert::same( reformat('UPDATE IGNORE DELAYED [table] SET [title]=\'Super Product\', [price]=12, [brand]=NULL , [another]=123'), - (string) $fluent + (string) $fluent, ); @@ -39,5 +39,5 @@ $arr = [ $fluent = $conn->update(['table1', 'table2'], $arr); Assert::same( reformat('UPDATE [table1], [table2] SET [table1].[title]=\'Super Product\', [table2].[price]=12, [table2].[brand]=NULL'), - (string) $fluent + (string) $fluent, ); diff --git a/tests/dibi/HashMap.phpt b/tests/dibi/HashMap.phpt index f14cfc1ec..582ce63e4 100644 --- a/tests/dibi/HashMap.phpt +++ b/tests/dibi/HashMap.phpt @@ -6,9 +6,7 @@ use Tester\Assert; require __DIR__ . '/bootstrap.php'; -$hash = new Dibi\HashMap(function ($v) { - return "b-$v-e"; -}); +$hash = new Dibi\HashMap(fn($v) => "b-$v-e"); Assert::same('b-X-e', $hash->{'X'}); Assert::same('b--e', $hash->{''}); diff --git a/tests/dibi/Result.meta.phpt b/tests/dibi/Result.meta.phpt index d3310f603..9aa66ce3d 100644 --- a/tests/dibi/Result.meta.phpt +++ b/tests/dibi/Result.meta.phpt @@ -28,14 +28,14 @@ Assert::same(4, $res->getColumnCount()); Assert::same( ['product_id', 'order_id', 'name', 'xXx'], - $info->getColumnNames() + $info->getColumnNames(), ); if (!in_array($config['driver'], ['sqlite', 'sqlite3', 'pdo', 'sqlsrv'], true)) { Assert::same( ['products.product_id', 'orders.order_id', 'customers.name', 'xXx'], - $info->getColumnNames(true) + $info->getColumnNames(true), ); } diff --git a/tests/dibi/Sqlsrv.insert.phpt b/tests/dibi/Sqlsrv.insert.phpt index e0334c9e2..30947a5f5 100644 --- a/tests/dibi/Sqlsrv.insert.phpt +++ b/tests/dibi/Sqlsrv.insert.phpt @@ -25,7 +25,7 @@ $conn->query( 'CREATE TRIGGER %n ON %n AFTER INSERT AS INSERT INTO %n DEFAULT VALUES', 'UpdAAB', 'aab', - 'aaa' + 'aaa', ); $conn->query('INSERT INTO %n DEFAULT VALUES', 'aab'); diff --git a/tests/dibi/Sqlsrv.limits.phpt b/tests/dibi/Sqlsrv.limits.phpt index adc132426..09587747a 100644 --- a/tests/dibi/Sqlsrv.limits.phpt +++ b/tests/dibi/Sqlsrv.limits.phpt @@ -21,19 +21,19 @@ $tests = function ($conn) { // Limit and offset Assert::same( 'SELECT 1 OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY', - $conn->translate('SELECT 1 %ofs %lmt', 10, 10) + $conn->translate('SELECT 1 %ofs %lmt', 10, 10), ); // Limit only Assert::same( 'SELECT 1 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', - $conn->translate('SELECT 1 %lmt', 10) + $conn->translate('SELECT 1 %lmt', 10), ); // Offset only Assert::same( 'SELECT 1 OFFSET 10 ROWS', - $conn->translate('SELECT 1 %ofs', 10) + $conn->translate('SELECT 1 %ofs', 10), ); // Offset invalid @@ -42,7 +42,7 @@ $tests = function ($conn) { $conn->translate('SELECT 1 %ofs', -10); }, Dibi\NotSupportedException::class, - 'Negative offset or limit.' + 'Negative offset or limit.', ); // Limit invalid @@ -51,7 +51,7 @@ $tests = function ($conn) { $conn->translate('SELECT 1 %lmt', -10); }, Dibi\NotSupportedException::class, - 'Negative offset or limit.' + 'Negative offset or limit.', ); // Limit invalid, offset valid @@ -60,7 +60,7 @@ $tests = function ($conn) { $conn->translate('SELECT 1 %ofs %lmt', 10, -10); }, Dibi\NotSupportedException::class, - 'Negative offset or limit.' + 'Negative offset or limit.', ); // Limit valid, offset invalid @@ -69,22 +69,22 @@ $tests = function ($conn) { $conn->translate('SELECT 1 %ofs %lmt', -10, 10); }, Dibi\NotSupportedException::class, - 'Negative offset or limit.' + 'Negative offset or limit.', ); } else { Assert::same( 'SELECT TOP (1) * FROM (SELECT 1) t', - $conn->translate('SELECT 1 %lmt', 1) + $conn->translate('SELECT 1 %lmt', 1), ); Assert::same( 'SELECT 1', - $conn->translate('SELECT 1 %lmt', -10) + $conn->translate('SELECT 1 %lmt', -10), ); Assert::exception( $conn->translate('SELECT 1 %ofs %lmt', 10, 10), - Dibi\NotSupportedException::class + Dibi\NotSupportedException::class, ); } }; diff --git a/tests/dibi/Translator.conditions.phpt b/tests/dibi/Translator.conditions.phpt index 0f356ca17..90123944c 100644 --- a/tests/dibi/Translator.conditions.phpt +++ b/tests/dibi/Translator.conditions.phpt @@ -27,8 +27,8 @@ FROM [customers] isset($name), 'WHERE [name] LIKE %s', 'xxx', - '%end' - ) + '%end', + ), ); @@ -42,8 +42,8 @@ FROM [customers] /* ... */'), SELECT * FROM %if', true, - '[customers] %else [products]' - ) + '[customers] %else [products]', + ), ); @@ -62,7 +62,7 @@ FROM [people] WHERE [id] > 0 %if', false, 'AND [foo]=%i', 1, ' %else %if', true, 'AND [bar]=%i', 1, ' -') +'), ); @@ -97,8 +97,8 @@ WHERE %if', false, 'AND [admin]=1 %end - %else 1 LIMIT 10 %end' - ) + %else 1 LIMIT 10 %end', + ), ); @@ -113,6 +113,6 @@ Assert::same( 3, '%ofs', 5, - '%end' - ) + '%end', + ), ); diff --git a/tests/dibi/Translator.identifiers.phpt b/tests/dibi/Translator.identifiers.phpt index d842bc083..d86344124 100644 --- a/tests/dibi/Translator.identifiers.phpt +++ b/tests/dibi/Translator.identifiers.phpt @@ -15,35 +15,35 @@ $conn = new Dibi\Connection($config); Assert::same( reformat('SELECT * FROM where WHERE select < 2'), - $conn->translate('SELECT * FROM where WHERE select < 2') + $conn->translate('SELECT * FROM where WHERE select < 2'), ); Assert::same( reformat('SELECT * FROM [where] WHERE where.select < 2'), - $conn->translate('SELECT * FROM [where] WHERE where.select < 2') + $conn->translate('SELECT * FROM [where] WHERE where.select < 2'), ); Assert::same( reformat('SELECT * FROM [where] WHERE [where].[select] < 2'), - $conn->translate('SELECT * FROM [where] WHERE [where.select] < 2') + $conn->translate('SELECT * FROM [where] WHERE [where.select] < 2'), ); Assert::same( reformat('SELECT * FROM [where] as [temp] WHERE [temp].[select] < 2'), - $conn->translate('SELECT * FROM [where] as [temp] WHERE [temp.select] < 2') + $conn->translate('SELECT * FROM [where] as [temp] WHERE [temp.select] < 2'), ); Assert::same( reformat('SELECT * FROM [where] WHERE [quot\'n\' space] > 2'), - $conn->translate("SELECT * FROM [where] WHERE [quot'n' space] > 2") + $conn->translate("SELECT * FROM [where] WHERE [quot'n' space] > 2"), ); Assert::same( reformat('SELECT * FROM [where] WHERE [where].[quot\'n\' space] > 2'), - $conn->translate("SELECT * FROM [where] WHERE [where.quot'n' space] > 2") + $conn->translate("SELECT * FROM [where] WHERE [where.quot'n' space] > 2"), ); diff --git a/tests/dibi/Translator.phpt b/tests/dibi/Translator.phpt index 389b7f836..67ffd1c2a 100644 --- a/tests/dibi/Translator.phpt +++ b/tests/dibi/Translator.phpt @@ -23,7 +23,7 @@ Assert::same( $conn->translate('REPLACE INTO [products]', [ 'title' => 'Drticka', 'price' => 318, - ]) + ]), ); @@ -38,7 +38,7 @@ Assert::same( 'sqlsrv' => "INSERT INTO [products] ([title], [price], [brand]) VALUES (N'Super Product', 12, NULL) , (N'Super Product', 12, NULL) , (N'Super Product', 12, NULL)", "INSERT INTO [products] ([title], [price], [brand]) VALUES ('Super Product', 12, NULL) , ('Super Product', 12, NULL) , ('Super Product', 12, NULL)", ]), - $conn->translate('INSERT INTO [products]', $array, $array, $array) + $conn->translate('INSERT INTO [products]', $array, $array, $array), ); @@ -53,7 +53,7 @@ Assert::same( 'sqlsrv' => "INSERT INTO [products] ([pole], [bit]) VALUES (N'hodnota1', 1) , (N'hodnota2', 1) , (N'hodnota3', 1)", "INSERT INTO [products] ([pole], [bit]) VALUES ('hodnota1', 1) , ('hodnota2', 1) , ('hodnota3', 1)", ]), - $conn->translate('INSERT INTO [products] %ex', $array) + $conn->translate('INSERT INTO [products] %ex', $array), ); @@ -66,7 +66,7 @@ Assert::same( $conn->translate('UPDATE [colors] SET', [ 'color' => 'blue', 'order' => 12, - ], 'WHERE [id]=%i', 123) + ], 'WHERE [id]=%i', 123), ); @@ -74,20 +74,20 @@ Assert::same( $array = [1, 2, 3]; Assert::same( reformat('SELECT * FROM [people] WHERE [id] IN ( 1, 2, 3 )'), - $conn->translate('SELECT * FROM [people] WHERE [id] IN (', $array, ')') + $conn->translate('SELECT * FROM [people] WHERE [id] IN (', $array, ')'), ); // long numbers Assert::same( reformat('SELECT -123456789123456789123456789'), - $conn->translate('SELECT %i', '-123456789123456789123456789') + $conn->translate('SELECT %i', '-123456789123456789123456789'), ); // long float numbers Assert::same( reformat('SELECT -.12345678912345678912345678e10'), - $conn->translate('SELECT %f', '-.12345678912345678912345678e10') + $conn->translate('SELECT %f', '-.12345678912345678912345678e10'), ); // invalid input @@ -101,7 +101,7 @@ Assert::same( 'sqlsrv' => "SELECT * FROM [table] WHERE id=10 AND name=N'ahoj'", "SELECT * FROM [table] WHERE id=10 AND name='ahoj'", ]), - $conn->translate('SELECT * FROM [table] WHERE id=%i AND name=%s', 10, 'ahoj') + $conn->translate('SELECT * FROM [table] WHERE id=%i AND name=%s', 10, 'ahoj'), ); Assert::same( @@ -109,7 +109,7 @@ Assert::same( 'sqlsrv' => "TEST ([cond] > 2) OR ([cond2] = N'3') OR (cond3 < RAND())", "TEST ([cond] > 2) OR ([cond2] = '3') OR (cond3 < RAND())", ]), - $conn->translate('TEST %or', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()']) + $conn->translate('TEST %or', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()']), ); Assert::same( @@ -117,7 +117,7 @@ Assert::same( 'sqlsrv' => "TEST ([cond] > 2) AND ([cond2] = N'3') AND (cond3 < RAND())", "TEST ([cond] > 2) AND ([cond2] = '3') AND (cond3 < RAND())", ]), - $conn->translate('TEST %and', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()']) + $conn->translate('TEST %and', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()']), ); @@ -126,7 +126,7 @@ $where[] = '[age] > 20'; $where[] = '[email] IS NOT NULL'; Assert::same( reformat('SELECT * FROM [table] WHERE ([age] > 20) AND ([email] IS NOT NULL)'), - $conn->translate('SELECT * FROM [table] WHERE %and', $where) + $conn->translate('SELECT * FROM [table] WHERE %and', $where), ); @@ -139,14 +139,14 @@ Assert::same( 'sqlsrv' => "SELECT * FROM [table] WHERE ([age] IS NULL) AND ([email] = N'ahoj') AND ([id] IN (10, 20, 30))", "SELECT * FROM [table] WHERE ([age] IS NULL) AND ([email] = 'ahoj') AND ([id] IN (10, 20, 30))", ]), - $conn->translate('SELECT * FROM [table] WHERE %and', $where) + $conn->translate('SELECT * FROM [table] WHERE %and', $where), ); $where = []; Assert::same( reformat('SELECT * FROM [table] WHERE 1=1'), - $conn->translate('SELECT * FROM [table] WHERE %and', $where) + $conn->translate('SELECT * FROM [table] WHERE %and', $where), ); @@ -161,7 +161,7 @@ $order = [ ]; Assert::same( reformat('SELECT * FROM [people] ORDER BY [field1] ASC, [field2] DESC, [field3] ASC, [field4] DESC, [field5] ASC, [field6] DESC'), - $conn->translate('SELECT * FROM [people] ORDER BY %by', $order) + $conn->translate('SELECT * FROM [people] ORDER BY %by', $order), ); @@ -172,7 +172,7 @@ Assert::same( 'sqlsrv' => 'SELECT * FROM [products] OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY', 'SELECT * FROM [products] LIMIT 2', ]), - $conn->translate('SELECT * FROM [products] %lmt', 2) + $conn->translate('SELECT * FROM [products] %lmt', 2), ); if ($config['system'] === 'odbc') { @@ -186,7 +186,7 @@ if ($config['system'] === 'odbc') { 'sqlsrv' => 'SELECT * FROM [products] OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY', 'SELECT * FROM [products] LIMIT 2 OFFSET 1', ]), - $conn->translate('SELECT * FROM [products] %lmt %ofs', 2, 1) + $conn->translate('SELECT * FROM [products] %lmt %ofs', 2, 1), ); // with offset = 50 @@ -197,7 +197,7 @@ if ($config['system'] === 'odbc') { 'sqlsrv' => 'SELECT * FROM [products] OFFSET 50 ROWS', 'SELECT * FROM [products] LIMIT -1 OFFSET 50', ]), - $conn->translate('SELECT * FROM [products] %ofs', 50) + $conn->translate('SELECT * FROM [products] %ofs', 50), ); } @@ -223,7 +223,7 @@ Assert::same( 'b8%d' => null, 'b9%t' => null, 'c1%t' => new DateTime('1212-09-26 16:51:34.0124'), - ]) + ]), ); Assert::exception(function () use ($conn) { @@ -247,13 +247,13 @@ if ($config['system'] === 'postgre') { $conn->query('SET standard_conforming_strings = off'); Assert::same( "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\\\%\\\\_\\\\\\\\''\"%'", - $conn->translate($args[0], $args[1], $args[2], $args[3]) + $conn->translate($args[0], $args[1], $args[2], $args[3]), ); $conn->query('SET standard_conforming_strings = on'); Assert::same( "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n\\%\\_\\\\''\"%'", - $conn->translate($args[0], $args[1], $args[2], $args[3]) + $conn->translate($args[0], $args[1], $args[2], $args[3]), ); } elseif ($config['driver'] !== 'sqlite') { // sqlite2 Assert::same( @@ -263,7 +263,7 @@ if ($config['system'] === 'postgre') { 'sqlsrv' => "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\n[%][_]\\''\"%'", "SELECT * FROM products WHERE (title LIKE 'C%' AND title LIKE '%r') OR title LIKE '%a\\n\\%\\_\\\\\\\\\\'\"%'", ]), - $conn->translate($args[0], $args[1], $args[2], $args[3]) + $conn->translate($args[0], $args[1], $args[2], $args[3]), ); } @@ -305,7 +305,7 @@ HAVING MAX(salary) > %i', 123, " INTO OUTFILE '/tmp/result''.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n' -") +"), ); @@ -457,7 +457,7 @@ WHERE ([test.a] LIKE %d', '1995-03-01', ' OR [false]=', false, ' OR [str_null]=%sn', '', ' OR [str_not_null]=%sn', 'hello', ' -LIMIT 10') +LIMIT 10'), ); @@ -466,19 +466,19 @@ Assert::same( 'sqlsrv' => "TEST [cond] > 2 [cond2] = N'3' cond3 < RAND() 123", "TEST [cond] > 2 [cond2] = '3' cond3 < RAND() 123", ]), - $conn->translate('TEST %ex', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()'], 123) + $conn->translate('TEST %ex', ['[cond] > 2', '[cond2] = "3"', 'cond3 < RAND()'], 123), ); Assert::same( reformat('TEST ([cond] > 2) OR ([cond2] > 3) OR ([cond3] = 10 + 1)'), - $conn->translate('TEST %or', ['`cond` > 2', ['[cond2] > %i', '3'], 'cond3%sql' => ['10 + 1']]) + $conn->translate('TEST %or', ['`cond` > 2', ['[cond2] > %i', '3'], 'cond3%sql' => ['10 + 1']]), ); Assert::same( reformat('TEST ([cond] = 2) OR ([cond3] = RAND())'), - $conn->translate('TEST %or', ['cond' => 2, 'cond3%sql' => 'RAND()']) + $conn->translate('TEST %or', ['cond' => 2, 'cond3%sql' => 'RAND()']), ); @@ -487,7 +487,7 @@ Assert::same( 'sqlsrv' => "TEST ([cond1] 3) OR ([cond2] RAND()) OR ([cond3] LIKE N'string')", "TEST ([cond1] 3) OR ([cond2] RAND()) OR ([cond3] LIKE 'string')", ]), - $conn->translate('TEST %or', ['cond1%ex' => 3, 'cond2%ex' => 'RAND()', 'cond3%ex' => ['LIKE %s', 'string']]) + $conn->translate('TEST %or', ['cond1%ex' => 3, 'cond2%ex' => 'RAND()', 'cond3%ex' => ['LIKE %s', 'string']]), ); @@ -497,7 +497,7 @@ Assert::same( 'sqlsrv' => 'SELECT * FROM [test] WHERE [id] LIKE N\'%d%t\' OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', 'SELECT * FROM [test] WHERE [id] LIKE \'%d%t\' LIMIT 10', ]), - $conn->translate("SELECT * FROM [test] WHERE %n LIKE '%d%t' %lmt", 'id', 10) + $conn->translate("SELECT * FROM [test] WHERE %n LIKE '%d%t' %lmt", 'id', 10), ); @@ -506,13 +506,13 @@ $where = [ ]; Assert::same( reformat('SELECT * FROM [tablename] WHERE ([tablename].[column] = 1)'), - $conn->translate('SELECT * FROM [tablename] WHERE %and', $where) + $conn->translate('SELECT * FROM [tablename] WHERE %and', $where), ); Assert::same( reformat('SELECT FROM ...'), - $conn->translate('SELECT FROM ... %lmt', null) + $conn->translate('SELECT FROM ... %lmt', null), ); Assert::same( @@ -520,7 +520,7 @@ Assert::same( 'sqlsrv' => "SELECT N'%i'", "SELECT '%i'", ]), - $conn->translate("SELECT '%i'") + $conn->translate("SELECT '%i'"), ); Assert::same( @@ -528,7 +528,7 @@ Assert::same( 'sqlsrv' => "SELECT N'%i'", "SELECT '%i'", ]), - $conn->translate('SELECT "%i"') + $conn->translate('SELECT "%i"'), ); @@ -543,7 +543,7 @@ Assert::same( ], [ 'product_id' => 1, 'title' => new Dibi\Expression('SHA1(%s)', 'Test product'), - ]) + ]), ); Assert::same( @@ -554,7 +554,7 @@ Assert::same( $conn->translate('UPDATE [products]', [ 'product_id' => 1, 'title' => new Dibi\Expression('SHA1(%s)', 'Test product'), - ]) + ]), ); Assert::same( @@ -565,7 +565,7 @@ Assert::same( $conn->translate('UPDATE [products]', [ 'product_id' => 1, 'title' => new Dibi\Expression('SHA1(%s)', 'Test product'), - ]) + ]), ); Assert::same( @@ -576,7 +576,7 @@ Assert::same( $conn->translate('SELECT * FROM [products] WHERE', [ 'product_id' => 1, 'title' => new Dibi\Expression('SHA1(%s)', 'Test product'), - ]) + ]), ); @@ -588,7 +588,7 @@ Assert::same( 'top' => 2, ]), new Dibi\Expression('number < %i', 100), - ]) + ]), ); @@ -613,7 +613,7 @@ Assert::same( 'sqlsrv' => "INSERT INTO test ([id], [text], [num]) VALUES (1, N'ahoj', 1), (2, N'jak', -1), (3, N'se', 10), (4, SUM(5), 1)", "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) + $conn->translate('INSERT INTO test %m', $array6), ); @@ -624,12 +624,12 @@ $by = [ Assert::same( reformat('SELECT * FROM table ORDER BY funkce(nazev_pole) ASC, [jine_pole] DESC'), - $conn->translate('SELECT * FROM table ORDER BY %by', $by) + $conn->translate('SELECT * FROM table ORDER BY %by', $by), ); Assert::same( reformat('INSERT INTO [test].*'), - $conn->translate('INSERT INTO [test.*]') + $conn->translate('INSERT INTO [test.*]'), ); Assert::exception(function () use ($conn) { @@ -643,23 +643,23 @@ Assert::exception(function () use ($conn) { Assert::same( reformat('SELECT * FROM table'), - $conn->translate('SELECT', new Dibi\Literal('* FROM table')) + $conn->translate('SELECT', new Dibi\Literal('* FROM table')), ); Assert::same( reformat('SELECT * FROM table'), - $conn->translate('SELECT %SQL', new Dibi\Literal('* FROM table')) + $conn->translate('SELECT %SQL', new Dibi\Literal('* FROM table')), ); Assert::same( reformat('SELECT * FROM table'), - $conn->translate(new Dibi\Literal('SELECT * FROM table')) + $conn->translate(new Dibi\Literal('SELECT * FROM table')), ); Assert::same( reformat('SELECT [a].[b] AS [c.d]'), - $conn->translate('SELECT %n AS %N', 'a.b', 'c.d') + $conn->translate('SELECT %n AS %N', 'a.b', 'c.d'), ); @@ -677,5 +677,5 @@ Assert::same( 'spec2%f' => 1000.00, 'spec3%i' => 10000, 'spec4' => 10000, - ], 'WHERE [price]=%f', 123.5) + ], 'WHERE [price]=%f', 123.5), ); From 03b1f1bf26204a64eb58bb7ccd830e8127d4c7c1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 10 Mar 2021 17:04:42 +0100 Subject: [PATCH 06/21] removed support for PHP 7 --- src/Dibi/DataSource.php | 31 +++++++++++++------------------ src/Dibi/Drivers/OdbcDriver.php | 6 +++--- src/Dibi/Fluent.php | 7 +------ tests/dibi/Fluent.select.phpt | 4 ++-- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/src/Dibi/DataSource.php b/src/Dibi/DataSource.php index 43101ce28..a324fb2ad 100644 --- a/src/Dibi/DataSource.php +++ b/src/Dibi/DataSource.php @@ -226,24 +226,19 @@ public function toDataSource(): self */ public function __toString(): string { - try { - return $this->connection->translate( - "\nSELECT %n", - (empty($this->cols) ? '*' : $this->cols), - "\nFROM %SQL", - $this->sql, - "\n%ex", - $this->conds ? ['WHERE %and', $this->conds] : null, - "\n%ex", - $this->sorting ? ['ORDER BY %by', $this->sorting] : null, - "\n%ofs %lmt", - $this->offset, - $this->limit, - ); - } catch (\Throwable $e) { - trigger_error($e->getMessage(), E_USER_ERROR); - return ''; - } + return $this->connection->translate( + "\nSELECT %n", + (empty($this->cols) ? '*' : $this->cols), + "\nFROM %SQL", + $this->sql, + "\n%ex", + $this->conds ? ['WHERE %and', $this->conds] : null, + "\n%ex", + $this->sorting ? ['ORDER BY %by', $this->sorting] : null, + "\n%ofs %lmt", + $this->offset, + $this->limit, + ); } diff --git a/src/Dibi/Drivers/OdbcDriver.php b/src/Dibi/Drivers/OdbcDriver.php index bbcbccb75..1d13b01ba 100644 --- a/src/Dibi/Drivers/OdbcDriver.php +++ b/src/Dibi/Drivers/OdbcDriver.php @@ -124,7 +124,7 @@ public function getInsertId(?string $sequence): ?int */ public function begin(string $savepoint = null): void { - if (!odbc_autocommit($this->connection, PHP_VERSION_ID < 80000 ? 0 : false)) { + if (!odbc_autocommit($this->connection, false)) { throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection)); } } @@ -139,7 +139,7 @@ public function commit(string $savepoint = null): void if (!odbc_commit($this->connection)) { throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection)); } - odbc_autocommit($this->connection, PHP_VERSION_ID < 80000 ? 1 : true); + odbc_autocommit($this->connection, true); } @@ -152,7 +152,7 @@ public function rollback(string $savepoint = null): void if (!odbc_rollback($this->connection)) { throw new Dibi\DriverException(odbc_errormsg($this->connection) . ' ' . odbc_error($this->connection)); } - odbc_autocommit($this->connection, PHP_VERSION_ID < 80000 ? 1 : true); + odbc_autocommit($this->connection, true); } diff --git a/src/Dibi/Fluent.php b/src/Dibi/Fluent.php index e505aecd4..6590ccd69 100644 --- a/src/Dibi/Fluent.php +++ b/src/Dibi/Fluent.php @@ -408,12 +408,7 @@ public function toDataSource(): DataSource */ final public function __toString(): string { - try { - return $this->connection->translate($this->_export()); - } catch (\Throwable $e) { - trigger_error($e->getMessage(), E_USER_ERROR); - return ''; - } + return $this->connection->translate($this->_export()); } diff --git a/tests/dibi/Fluent.select.phpt b/tests/dibi/Fluent.select.phpt index 7b9ba1855..6c7972290 100644 --- a/tests/dibi/Fluent.select.phpt +++ b/tests/dibi/Fluent.select.phpt @@ -147,9 +147,9 @@ if ($config['system'] === 'mysql') { ->limit(' 1; DROP TABLE users') ->offset(' 1; DROP TABLE users'); - Assert::error(function () use ($fluent) { + Assert::exception(function () use ($fluent) { (string) $fluent; - }, E_USER_ERROR, "Expected number, ' 1; DROP TABLE users' given."); + }, Dibi\Exception::class, "Expected number, ' 1; DROP TABLE users' given."); } From 9fb73cbaab74311d6ee181f20340201acc7d5306 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:17:16 +0100 Subject: [PATCH 07/21] added property typehints --- src/Dibi/Bridges/Nette/DibiExtension22.php | 3 +- src/Dibi/Bridges/Tracy/Panel.php | 13 +++----- src/Dibi/Connection.php | 21 ++++++------ src/Dibi/DataSource.php | 30 ++++++------------ src/Dibi/Drivers/FirebirdDriver.php | 5 ++- src/Dibi/Drivers/FirebirdReflector.php | 3 +- src/Dibi/Drivers/FirebirdResult.php | 3 +- src/Dibi/Drivers/MySqlReflector.php | 3 +- src/Dibi/Drivers/MySqliDriver.php | 7 ++-- src/Dibi/Drivers/MySqliResult.php | 10 +++--- src/Dibi/Drivers/NoDataResult.php | 3 +- src/Dibi/Drivers/OdbcDriver.php | 6 ++-- src/Dibi/Drivers/OdbcReflector.php | 3 +- src/Dibi/Drivers/OdbcResult.php | 6 ++-- src/Dibi/Drivers/OracleDriver.php | 10 +++--- src/Dibi/Drivers/OracleReflector.php | 3 +- src/Dibi/Drivers/OracleResult.php | 3 +- src/Dibi/Drivers/PdoDriver.php | 12 +++---- src/Dibi/Drivers/PdoResult.php | 6 ++-- src/Dibi/Drivers/PostgreDriver.php | 3 +- src/Dibi/Drivers/PostgreReflector.php | 6 ++-- src/Dibi/Drivers/PostgreResult.php | 3 +- src/Dibi/Drivers/SqliteDriver.php | 9 ++---- src/Dibi/Drivers/SqliteReflector.php | 3 +- src/Dibi/Drivers/SqliteResult.php | 6 ++-- src/Dibi/Drivers/SqlsrvDriver.php | 6 ++-- src/Dibi/Drivers/SqlsrvReflector.php | 3 +- src/Dibi/Drivers/SqlsrvResult.php | 3 +- src/Dibi/Event.php | 21 ++++-------- src/Dibi/Expression.php | 3 +- src/Dibi/Fluent.php | 37 +++++++++------------- src/Dibi/Helpers.php | 5 ++- src/Dibi/Literal.php | 3 +- src/Dibi/Loggers/FileLogger.php | 10 +++--- src/Dibi/Reflection/Column.php | 6 ++-- src/Dibi/Reflection/Database.php | 12 +++---- src/Dibi/Reflection/ForeignKey.php | 5 ++- src/Dibi/Reflection/Index.php | 2 +- src/Dibi/Reflection/Result.php | 9 +++--- src/Dibi/Reflection/Table.php | 28 +++++++--------- src/Dibi/Result.php | 23 ++++++-------- src/Dibi/ResultIterator.php | 9 ++---- src/Dibi/Strict.php | 2 +- src/Dibi/Translator.php | 32 +++++++------------ src/Dibi/dibi.php | 22 ++++++------- src/Dibi/exceptions.php | 6 ++-- 46 files changed, 164 insertions(+), 263 deletions(-) diff --git a/src/Dibi/Bridges/Nette/DibiExtension22.php b/src/Dibi/Bridges/Nette/DibiExtension22.php index 1b3082771..a2a6175fa 100644 --- a/src/Dibi/Bridges/Nette/DibiExtension22.php +++ b/src/Dibi/Bridges/Nette/DibiExtension22.php @@ -19,8 +19,7 @@ */ class DibiExtension22 extends Nette\DI\CompilerExtension { - /** @var bool|null */ - private $debugMode; + private ?bool $debugMode; public function __construct(bool $debugMode = null) diff --git a/src/Dibi/Bridges/Tracy/Panel.php b/src/Dibi/Bridges/Tracy/Panel.php index 1b1f88eba..4ca16efff 100644 --- a/src/Dibi/Bridges/Tracy/Panel.php +++ b/src/Dibi/Bridges/Tracy/Panel.php @@ -22,17 +22,14 @@ class Panel implements Tracy\IBarPanel { use Dibi\Strict; - /** @var int maximum SQL length */ - public static $maxLength = 1000; + /** maximum SQL length */ + public static int $maxLength = 1000; - /** @var bool|string explain queries? */ - public $explain; + public bool|string $explain; - /** @var int */ - public $filter; + public int $filter; - /** @var array */ - private $events = []; + private array $events = []; public function __construct($explain = true, int $filter = null) diff --git a/src/Dibi/Connection.php b/src/Dibi/Connection.php index f481a7bc2..d041a2129 100644 --- a/src/Dibi/Connection.php +++ b/src/Dibi/Connection.php @@ -22,25 +22,22 @@ class Connection implements IConnection { use Strict; - /** @var array of function (Event $event); Occurs after query is executed */ - public $onEvent = []; + /** function (Event $event); Occurs after query is executed */ + public array $onEvent = []; - /** @var array Current connection configuration */ - private $config; + /** Current connection configuration */ + private array $config; /** @var string[] resultset formats */ - private $formats; + private array $formats; - /** @var Driver|null */ - private $driver; + private ?Driver $driver = null; - /** @var Translator|null */ - private $translator; + private ?Translator $translator = null; - /** @var HashMap Substitutes for identifiers */ - private $substitutes; + private HashMap $substitutes; - private $transactionDepth = 0; + private int $transactionDepth = 0; /** diff --git a/src/Dibi/DataSource.php b/src/Dibi/DataSource.php index a324fb2ad..f3920e8b9 100644 --- a/src/Dibi/DataSource.php +++ b/src/Dibi/DataSource.php @@ -17,35 +17,25 @@ class DataSource implements IDataSource { use Strict; - /** @var Connection */ - private $connection; + private Connection $connection; - /** @var string */ - private $sql; + private string $sql; - /** @var Result|null */ - private $result; + private ?Result $result = null; - /** @var int|null */ - private $count; + private ?int $count = null; - /** @var int|null */ - private $totalCount; + private ?int $totalCount = null; - /** @var array */ - private $cols = []; + private array $cols = []; - /** @var array */ - private $sorting = []; + private array $sorting = []; - /** @var array */ - private $conds = []; + private array $conds = []; - /** @var int|null */ - private $offset; + private ?int $offset = null; - /** @var int|null */ - private $limit; + private ?int $limit = null; /** diff --git a/src/Dibi/Drivers/FirebirdDriver.php b/src/Dibi/Drivers/FirebirdDriver.php index e1f8c69fc..b91d03aca 100644 --- a/src/Dibi/Drivers/FirebirdDriver.php +++ b/src/Dibi/Drivers/FirebirdDriver.php @@ -33,11 +33,10 @@ class FirebirdDriver implements Dibi\Driver /** @var resource */ private $connection; - /** @var resource|null */ + /** @var ?resource */ private $transaction; - /** @var bool */ - private $inTransaction = false; + private bool $inTransaction = false; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/FirebirdReflector.php b/src/Dibi/Drivers/FirebirdReflector.php index f1dda0e20..baa6bffb4 100644 --- a/src/Dibi/Drivers/FirebirdReflector.php +++ b/src/Dibi/Drivers/FirebirdReflector.php @@ -19,8 +19,7 @@ class FirebirdReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; public function __construct(Dibi\Driver $driver) diff --git a/src/Dibi/Drivers/FirebirdResult.php b/src/Dibi/Drivers/FirebirdResult.php index be998208b..8a07778c9 100644 --- a/src/Dibi/Drivers/FirebirdResult.php +++ b/src/Dibi/Drivers/FirebirdResult.php @@ -23,8 +23,7 @@ class FirebirdResult implements Dibi\ResultDriver /** @var resource */ private $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; /** diff --git a/src/Dibi/Drivers/MySqlReflector.php b/src/Dibi/Drivers/MySqlReflector.php index bed173c22..01f8229e9 100644 --- a/src/Dibi/Drivers/MySqlReflector.php +++ b/src/Dibi/Drivers/MySqlReflector.php @@ -20,8 +20,7 @@ class MySqlReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; public function __construct(Dibi\Driver $driver) diff --git a/src/Dibi/Drivers/MySqliDriver.php b/src/Dibi/Drivers/MySqliDriver.php index 97cbcd79c..11337314e 100644 --- a/src/Dibi/Drivers/MySqliDriver.php +++ b/src/Dibi/Drivers/MySqliDriver.php @@ -40,11 +40,10 @@ class MySqliDriver implements Dibi\Driver public const ERROR_DATA_TRUNCATED = 1265; - /** @var \mysqli */ - private $connection; + private \mysqli $connection; - /** @var bool Is buffered (seekable and countable)? */ - private $buffered; + /** Is buffered (seekable and countable)? */ + private bool $buffered = false; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/MySqliResult.php b/src/Dibi/Drivers/MySqliResult.php index 67a5a86e2..4b4fbae01 100644 --- a/src/Dibi/Drivers/MySqliResult.php +++ b/src/Dibi/Drivers/MySqliResult.php @@ -19,14 +19,12 @@ class MySqliResult implements Dibi\ResultDriver { use Dibi\Strict; - /** @var \mysqli_result */ - private $resultSet; + private \mysqli_result $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; - /** @var bool Is buffered (seekable and countable)? */ - private $buffered; + /** Is buffered (seekable and countable)? */ + private bool $buffered; public function __construct(\mysqli_result $resultSet, bool $buffered) diff --git a/src/Dibi/Drivers/NoDataResult.php b/src/Dibi/Drivers/NoDataResult.php index 00a5f358c..82c309222 100644 --- a/src/Dibi/Drivers/NoDataResult.php +++ b/src/Dibi/Drivers/NoDataResult.php @@ -19,8 +19,7 @@ class NoDataResult implements Dibi\ResultDriver { use Dibi\Strict; - /** @var int */ - private $rows; + private int $rows; public function __construct(int $rows) diff --git a/src/Dibi/Drivers/OdbcDriver.php b/src/Dibi/Drivers/OdbcDriver.php index 1d13b01ba..9a998e955 100644 --- a/src/Dibi/Drivers/OdbcDriver.php +++ b/src/Dibi/Drivers/OdbcDriver.php @@ -30,11 +30,9 @@ class OdbcDriver implements Dibi\Driver /** @var resource */ private $connection; - /** @var int|null Affected rows */ - private $affectedRows; + private ?int $affectedRows; - /** @var bool */ - private $microseconds = true; + private bool $microseconds = true; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/OdbcReflector.php b/src/Dibi/Drivers/OdbcReflector.php index 0b53294b3..148777484 100644 --- a/src/Dibi/Drivers/OdbcReflector.php +++ b/src/Dibi/Drivers/OdbcReflector.php @@ -19,8 +19,7 @@ class OdbcReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; public function __construct(Dibi\Driver $driver) diff --git a/src/Dibi/Drivers/OdbcResult.php b/src/Dibi/Drivers/OdbcResult.php index 45b9fac58..324d84b76 100644 --- a/src/Dibi/Drivers/OdbcResult.php +++ b/src/Dibi/Drivers/OdbcResult.php @@ -22,11 +22,9 @@ class OdbcResult implements Dibi\ResultDriver /** @var resource */ private $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; - /** @var int Cursor */ - private $row = 0; + private int $row = 0; /** diff --git a/src/Dibi/Drivers/OracleDriver.php b/src/Dibi/Drivers/OracleDriver.php index 4b02f2139..70cb5424f 100644 --- a/src/Dibi/Drivers/OracleDriver.php +++ b/src/Dibi/Drivers/OracleDriver.php @@ -32,14 +32,12 @@ class OracleDriver implements Dibi\Driver /** @var resource */ private $connection; - /** @var bool */ - private $autocommit = true; + private bool $autocommit = true; - /** @var bool use native datetime format */ - private $nativeDate; + /** use native datetime format */ + private bool $nativeDate; - /** @var int|null Number of affected rows */ - private $affectedRows; + private ?int $affectedRows; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/OracleReflector.php b/src/Dibi/Drivers/OracleReflector.php index 0598a5e47..31be4ab51 100644 --- a/src/Dibi/Drivers/OracleReflector.php +++ b/src/Dibi/Drivers/OracleReflector.php @@ -19,8 +19,7 @@ class OracleReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; public function __construct(Dibi\Driver $driver) diff --git a/src/Dibi/Drivers/OracleResult.php b/src/Dibi/Drivers/OracleResult.php index 65b90a5cc..bcff77993 100644 --- a/src/Dibi/Drivers/OracleResult.php +++ b/src/Dibi/Drivers/OracleResult.php @@ -22,8 +22,7 @@ class OracleResult implements Dibi\ResultDriver /** @var resource */ private $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; /** diff --git a/src/Dibi/Drivers/PdoDriver.php b/src/Dibi/Drivers/PdoDriver.php index 4b4b54c8e..b384614a8 100644 --- a/src/Dibi/Drivers/PdoDriver.php +++ b/src/Dibi/Drivers/PdoDriver.php @@ -29,17 +29,13 @@ class PdoDriver implements Dibi\Driver { use Dibi\Strict; - /** @var PDO|null Connection resource */ - private $connection; + private ?PDO $connection; - /** @var int|null Affected rows */ - private $affectedRows; + private ?int $affectedRows; - /** @var string */ - private $driverName; + private string $driverName; - /** @var string */ - private $serverVersion = ''; + private string $serverVersion = ''; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/PdoResult.php b/src/Dibi/Drivers/PdoResult.php index 012f4a44e..e430ea9ee 100644 --- a/src/Dibi/Drivers/PdoResult.php +++ b/src/Dibi/Drivers/PdoResult.php @@ -21,11 +21,9 @@ class PdoResult implements Dibi\ResultDriver { use Dibi\Strict; - /** @var \PDOStatement|null */ - private $resultSet; + private ?\PDOStatement $resultSet; - /** @var string */ - private $driverName; + private string $driverName; public function __construct(\PDOStatement $resultSet, string $driverName) diff --git a/src/Dibi/Drivers/PostgreDriver.php b/src/Dibi/Drivers/PostgreDriver.php index f020876f6..dd1f2a2c8 100644 --- a/src/Dibi/Drivers/PostgreDriver.php +++ b/src/Dibi/Drivers/PostgreDriver.php @@ -32,8 +32,7 @@ class PostgreDriver implements Dibi\Driver /** @var resource */ private $connection; - /** @var int|null Affected rows */ - private $affectedRows; + private ?int $affectedRows; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/PostgreReflector.php b/src/Dibi/Drivers/PostgreReflector.php index 5ce469221..d7117f18b 100644 --- a/src/Dibi/Drivers/PostgreReflector.php +++ b/src/Dibi/Drivers/PostgreReflector.php @@ -19,11 +19,9 @@ class PostgreReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; - /** @var string */ - private $version; + private string $version; public function __construct(Dibi\Driver $driver, string $version) diff --git a/src/Dibi/Drivers/PostgreResult.php b/src/Dibi/Drivers/PostgreResult.php index 6f6ac597c..db159e612 100644 --- a/src/Dibi/Drivers/PostgreResult.php +++ b/src/Dibi/Drivers/PostgreResult.php @@ -23,8 +23,7 @@ class PostgreResult implements Dibi\ResultDriver /** @var resource */ private $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; /** diff --git a/src/Dibi/Drivers/SqliteDriver.php b/src/Dibi/Drivers/SqliteDriver.php index fe0b216f6..0f0d59388 100644 --- a/src/Dibi/Drivers/SqliteDriver.php +++ b/src/Dibi/Drivers/SqliteDriver.php @@ -27,14 +27,11 @@ class SqliteDriver implements Dibi\Driver { use Dibi\Strict; - /** @var SQLite3 */ - private $connection; + private SQLite3 $connection; - /** @var string Date format */ - private $fmtDate; + private string $fmtDate; - /** @var string Datetime format */ - private $fmtDateTime; + private string $fmtDateTime; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/SqliteReflector.php b/src/Dibi/Drivers/SqliteReflector.php index db1a37b72..1f19983c7 100644 --- a/src/Dibi/Drivers/SqliteReflector.php +++ b/src/Dibi/Drivers/SqliteReflector.php @@ -19,8 +19,7 @@ class SqliteReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; public function __construct(Dibi\Driver $driver) diff --git a/src/Dibi/Drivers/SqliteResult.php b/src/Dibi/Drivers/SqliteResult.php index 4f31b90e5..0604b88bd 100644 --- a/src/Dibi/Drivers/SqliteResult.php +++ b/src/Dibi/Drivers/SqliteResult.php @@ -20,11 +20,9 @@ class SqliteResult implements Dibi\ResultDriver { use Dibi\Strict; - /** @var \SQLite3Result */ - private $resultSet; + private \SQLite3Result $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; public function __construct(\SQLite3Result $resultSet) diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index a864189d9..d5fe653f5 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -32,11 +32,9 @@ class SqlsrvDriver implements Dibi\Driver /** @var resource */ private $connection; - /** @var int|null Affected rows */ - private $affectedRows; + private ?int $affectedRows; - /** @var string */ - private $version = ''; + private string $version = ''; /** @throws Dibi\NotSupportedException */ diff --git a/src/Dibi/Drivers/SqlsrvReflector.php b/src/Dibi/Drivers/SqlsrvReflector.php index 28049537e..50cbdf9b2 100644 --- a/src/Dibi/Drivers/SqlsrvReflector.php +++ b/src/Dibi/Drivers/SqlsrvReflector.php @@ -19,8 +19,7 @@ class SqlsrvReflector implements Dibi\Reflector { use Dibi\Strict; - /** @var Dibi\Driver */ - private $driver; + private Dibi\Driver $driver; public function __construct(Dibi\Driver $driver) diff --git a/src/Dibi/Drivers/SqlsrvResult.php b/src/Dibi/Drivers/SqlsrvResult.php index 1b5a50cf0..21b4b523e 100644 --- a/src/Dibi/Drivers/SqlsrvResult.php +++ b/src/Dibi/Drivers/SqlsrvResult.php @@ -22,8 +22,7 @@ class SqlsrvResult implements Dibi\ResultDriver /** @var resource */ private $resultSet; - /** @var bool */ - private $autoFree = true; + private bool $autoFree = true; /** diff --git a/src/Dibi/Event.php b/src/Dibi/Event.php index 55fcdf4d7..c3b9de089 100644 --- a/src/Dibi/Event.php +++ b/src/Dibi/Event.php @@ -31,26 +31,19 @@ class Event TRANSACTION = 448, // BEGIN | COMMIT | ROLLBACK ALL = 1023; - /** @var Connection */ - public $connection; + public Connection $connection; - /** @var int */ - public $type; + public int $type; - /** @var string */ - public $sql; + public string $sql; - /** @var Result|DriverException|null */ - public $result; + public Result|DriverException|null $result; - /** @var float */ - public $time; + public float $time; - /** @var int|null */ - public $count; + public ?int $count = null; - /** @var array|null */ - public $source; + public ?array $source = null; public function __construct(Connection $connection, int $type, string $sql = null) diff --git a/src/Dibi/Expression.php b/src/Dibi/Expression.php index 969345f5b..e9671355f 100644 --- a/src/Dibi/Expression.php +++ b/src/Dibi/Expression.php @@ -17,8 +17,7 @@ class Expression { use Strict; - /** @var array */ - private $values; + private array $values; public function __construct(...$values) diff --git a/src/Dibi/Fluent.php b/src/Dibi/Fluent.php index 6590ccd69..cfb2113f8 100644 --- a/src/Dibi/Fluent.php +++ b/src/Dibi/Fluent.php @@ -47,8 +47,7 @@ class Fluent implements IDataSource public const REMOVE = false; - /** @var array */ - public static $masks = [ + public static array $masks = [ 'SELECT' => ['SELECT', 'DISTINCT', 'FROM', 'WHERE', 'GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT', 'OFFSET', ], 'UPDATE' => ['UPDATE', 'SET', 'WHERE', 'ORDER BY', 'LIMIT'], @@ -56,8 +55,8 @@ class Fluent implements IDataSource 'DELETE' => ['DELETE', 'FROM', 'USING', 'WHERE', 'ORDER BY', 'LIMIT'], ]; - /** @var array default modifiers for arrays */ - public static $modifiers = [ + /** default modifiers for arrays */ + public static array $modifiers = [ 'SELECT' => '%n', 'FROM' => '%n', 'IN' => '%in', @@ -69,8 +68,8 @@ class Fluent implements IDataSource 'GROUP BY' => '%by', ]; - /** @var array clauses separators */ - public static $separators = [ + /** clauses separators */ + public static array $separators = [ 'SELECT' => ',', 'FROM' => ',', 'WHERE' => 'AND', @@ -84,41 +83,35 @@ class Fluent implements IDataSource 'INTO' => false, ]; - /** @var array clauses */ - public static $clauseSwitches = [ + /** clauses */ + public static array $clauseSwitches = [ 'JOIN' => 'FROM', 'INNER JOIN' => 'FROM', 'LEFT JOIN' => 'FROM', 'RIGHT JOIN' => 'FROM', ]; - /** @var Connection */ - private $connection; + private Connection $connection; - /** @var array */ - private $setups = []; + private array $setups = []; - /** @var string|null */ - private $command; + private ?string $command = null; - /** @var array */ - private $clauses = []; + private array $clauses = []; - /** @var array */ - private $flags = []; + private array $flags = []; - /** @var array|null */ private $cursor; - /** @var HashMap normalized clauses */ - private static $normalizer; + /** normalized clauses */ + private static HashMap $normalizer; public function __construct(Connection $connection) { $this->connection = $connection; - if (self::$normalizer === null) { + if (!isset(self::$normalizer)) { self::$normalizer = new HashMap([self::class, '_formatClause']); } } diff --git a/src/Dibi/Helpers.php b/src/Dibi/Helpers.php index a21e318a6..e208309ec 100644 --- a/src/Dibi/Helpers.php +++ b/src/Dibi/Helpers.php @@ -14,8 +14,7 @@ class Helpers { use Strict; - /** @var HashMap */ - private static $types; + private static HashMap $types; /** @@ -204,7 +203,7 @@ public static function detectType(string $type): ?string /** @internal */ public static function getTypeCache(): HashMap { - if (self::$types === null) { + if (!isset(self::$types)) { self::$types = new HashMap([self::class, 'detectType']); } return self::$types; diff --git a/src/Dibi/Literal.php b/src/Dibi/Literal.php index e81c4632b..5ea4d0a4a 100644 --- a/src/Dibi/Literal.php +++ b/src/Dibi/Literal.php @@ -17,8 +17,7 @@ class Literal { use Strict; - /** @var string */ - private $value; + private string $value; public function __construct($value) diff --git a/src/Dibi/Loggers/FileLogger.php b/src/Dibi/Loggers/FileLogger.php index 5d4567abf..f5ffb4af5 100644 --- a/src/Dibi/Loggers/FileLogger.php +++ b/src/Dibi/Loggers/FileLogger.php @@ -19,14 +19,12 @@ class FileLogger { use Dibi\Strict; - /** @var string Name of the file where SQL errors should be logged */ - public $file; + /** Name of the file where SQL errors should be logged */ + public string $file; - /** @var int */ - public $filter; + public int $filter; - /** @var bool */ - private $errorsOnly; + private bool $errorsOnly; public function __construct(string $file, int $filter = null, bool $errorsOnly = false) diff --git a/src/Dibi/Reflection/Column.php b/src/Dibi/Reflection/Column.php index 3d7ed23d2..0019c2b1d 100644 --- a/src/Dibi/Reflection/Column.php +++ b/src/Dibi/Reflection/Column.php @@ -29,11 +29,11 @@ class Column { use Dibi\Strict; - /** @var Dibi\Reflector|null when created by Result */ - private $reflector; + /** when created by Result */ + private ?Dibi\Reflector $reflector; /** @var array (name, nativetype, [table], [fullname], [size], [nullable], [default], [autoincrement], [vendor]) */ - private $info; + private array $info; public function __construct(Dibi\Reflector $reflector = null, array $info) diff --git a/src/Dibi/Reflection/Database.php b/src/Dibi/Reflection/Database.php index 8c6e11ed4..da3b9c4bd 100644 --- a/src/Dibi/Reflection/Database.php +++ b/src/Dibi/Reflection/Database.php @@ -23,14 +23,12 @@ class Database { use Dibi\Strict; - /** @var Dibi\Reflector */ - private $reflector; + private Dibi\Reflector $reflector; - /** @var string|null */ - private $name; + private ?string $name; - /** @var Table[]|null */ - private $tables; + /** @var Table[] */ + private array $tables; public function __construct(Dibi\Reflector $reflector, string $name = null) @@ -88,7 +86,7 @@ public function hasTable(string $name): bool protected function init(): void { - if ($this->tables === null) { + if (!isset($this->tables)) { $this->tables = []; foreach ($this->reflector->getTables() as $info) { $this->tables[strtolower($info['name'])] = new Table($this->reflector, $info); diff --git a/src/Dibi/Reflection/ForeignKey.php b/src/Dibi/Reflection/ForeignKey.php index 040d33252..c4c77777c 100644 --- a/src/Dibi/Reflection/ForeignKey.php +++ b/src/Dibi/Reflection/ForeignKey.php @@ -22,11 +22,10 @@ class ForeignKey { use Dibi\Strict; - /** @var string */ - private $name; + private string $name; /** @var array of [local, foreign, onDelete, onUpdate] */ - private $references; + private array $references; public function __construct(string $name, array $references) diff --git a/src/Dibi/Reflection/Index.php b/src/Dibi/Reflection/Index.php index 27287baee..40c5fe525 100644 --- a/src/Dibi/Reflection/Index.php +++ b/src/Dibi/Reflection/Index.php @@ -25,7 +25,7 @@ class Index use Dibi\Strict; /** @var array (name, columns, [unique], [primary]) */ - private $info; + private array $info; public function __construct(array $info) diff --git a/src/Dibi/Reflection/Result.php b/src/Dibi/Reflection/Result.php index 2d8f92aa6..e9d9ca14e 100644 --- a/src/Dibi/Reflection/Result.php +++ b/src/Dibi/Reflection/Result.php @@ -22,14 +22,13 @@ class Result { use Dibi\Strict; - /** @var Dibi\ResultDriver */ - private $driver; + private Dibi\ResultDriver $driver; /** @var Column[]|null */ - private $columns; + private ?array $columns; /** @var Column[]|null */ - private $names; + private ?array $names; public function __construct(Dibi\ResultDriver $driver) @@ -80,7 +79,7 @@ public function hasColumn(string $name): bool protected function initColumns(): void { - if ($this->columns === null) { + if (!isset($this->columns)) { $this->columns = []; $reflector = $this->driver instanceof Dibi\Reflector ? $this->driver diff --git a/src/Dibi/Reflection/Table.php b/src/Dibi/Reflection/Table.php index f79802df5..7e2621d86 100644 --- a/src/Dibi/Reflection/Table.php +++ b/src/Dibi/Reflection/Table.php @@ -27,26 +27,22 @@ class Table { use Dibi\Strict; - /** @var Dibi\Reflector */ - private $reflector; + private Dibi\Reflector $reflector; - /** @var string */ - private $name; + private string $name; - /** @var bool */ - private $view; + private bool $view; - /** @var Column[]|null */ - private $columns; + /** @var Column[] */ + private array $columns; - /** @var ForeignKey[]|null */ - private $foreignKeys; + /** @var ForeignKey[] */ + private array $foreignKeys; - /** @var Index[]|null */ - private $indexes; + /** @var Index[] */ + private array $indexes; - /** @var Index|null */ - private $primaryKey; + private ?Index $primaryKey; public function __construct(Dibi\Reflector $reflector, array $info) @@ -134,7 +130,7 @@ public function getPrimaryKey(): Index protected function initColumns(): void { - if ($this->columns === null) { + if (!isset($this->columns)) { $this->columns = []; foreach ($this->reflector->getColumns($this->name) as $info) { $this->columns[strtolower($info['name'])] = new Column($this->reflector, $info); @@ -145,7 +141,7 @@ protected function initColumns(): void protected function initIndexes(): void { - if ($this->indexes === null) { + if (!isset($this->indexes)) { $this->initColumns(); $this->indexes = []; foreach ($this->reflector->getIndexes($this->name) as $info) { diff --git a/src/Dibi/Result.php b/src/Dibi/Result.php index a84ef6f28..41cecc1e4 100644 --- a/src/Dibi/Result.php +++ b/src/Dibi/Result.php @@ -19,26 +19,23 @@ class Result implements IDataSource { use Strict; - /** @var ResultDriver|null */ - private $driver; + private ?ResultDriver $driver; - /** @var array Translate table */ - private $types = []; + /** Translate table */ + private array $types = []; - /** @var Reflection\Result|null */ - private $meta; + private ?Reflection\Result $meta; - /** @var bool Already fetched? Used for allowance for first seek(0) */ - private $fetched = false; + /** Already fetched? Used for allowance for first seek(0) */ + private bool $fetched = false; - /** @var string|null returned object class */ - private $rowClass = Row::class; + /** returned object class */ + private ?string $rowClass = Row::class; /** @var callable|null returned object factory */ private $rowFactory; - /** @var array format */ - private $formats = []; + private array $formats = []; public function __construct(ResultDriver $driver, bool $normalize = true) @@ -587,7 +584,7 @@ final public function getFormat(string $type): ?string */ public function getInfo(): Reflection\Result { - if ($this->meta === null) { + if (!isset($this->meta)) { $this->meta = new Reflection\Result($this->getResultDriver()); } return $this->meta; diff --git a/src/Dibi/ResultIterator.php b/src/Dibi/ResultIterator.php index a4ee1daac..3c23e6c3a 100644 --- a/src/Dibi/ResultIterator.php +++ b/src/Dibi/ResultIterator.php @@ -17,14 +17,11 @@ class ResultIterator implements \Iterator, \Countable { use Strict; - /** @var Result */ - private $result; + private Result $result; - /** @var mixed */ - private $row; + private mixed $row; - /** @var int */ - private $pointer = 0; + private int $pointer = 0; public function __construct(Result $result) diff --git a/src/Dibi/Strict.php b/src/Dibi/Strict.php index a735803d8..6f8a1b95e 100644 --- a/src/Dibi/Strict.php +++ b/src/Dibi/Strict.php @@ -20,7 +20,7 @@ trait Strict { /** @var array [method => [type => callback]] */ - private static $extMethods; + private static array $extMethods; /** diff --git a/src/Dibi/Translator.php b/src/Dibi/Translator.php index bfdd3ac4e..097354822 100644 --- a/src/Dibi/Translator.php +++ b/src/Dibi/Translator.php @@ -17,38 +17,28 @@ final class Translator { use Strict; - /** @var Connection */ - private $connection; + private Connection $connection; - /** @var Driver */ - private $driver; + private Driver $driver; - /** @var int */ - private $cursor = 0; + private int $cursor = 0; - /** @var array */ - private $args; + private array $args; /** @var string[] */ - private $errors; + private array $errors; - /** @var bool */ - private $comment = false; + private bool $comment = false; - /** @var int */ - private $ifLevel = 0; + private int $ifLevel = 0; - /** @var int */ - private $ifLevelStart = 0; + private int $ifLevelStart = 0; - /** @var int|null */ - private $limit; + private ?int $limit = null; - /** @var int|null */ - private $offset; + private ?int $offset = null; - /** @var HashMap */ - private $identifiers; + private HashMap $identifiers; public function __construct(Connection $connection) diff --git a/src/Dibi/dibi.php b/src/Dibi/dibi.php index bb8c41478..cad0c815b 100644 --- a/src/Dibi/dibi.php +++ b/src/Dibi/dibi.php @@ -52,23 +52,23 @@ class dibi ASC = 'ASC', DESC = 'DESC'; - /** @var string|null Last SQL command @see dibi::query() */ - public static $sql; + /** Last SQL command @see dibi::query() */ + public static ?string $sql = null; - /** @var float|null Elapsed time for last query */ - public static $elapsedTime; + /** Elapsed time for last query */ + public static ?float $elapsedTime = null; - /** @var float Elapsed time for all queries */ - public static $totalTime; + /** Elapsed time for all queries */ + public static float $totalTime = 0; - /** @var int Number or queries */ - public static $numOfQueries = 0; + /** Number or queries */ + public static int $numOfQueries = 0; /** @var Dibi\Connection[] Connection registry storage for Dibi\Connection objects */ - private static $registry = []; + private static array $registry = []; - /** @var Dibi\Connection Current connection */ - private static $connection; + /** Current connection */ + private static Dibi\Connection $connection; /** diff --git a/src/Dibi/exceptions.php b/src/Dibi/exceptions.php index 86bab81be..48b78c022 100644 --- a/src/Dibi/exceptions.php +++ b/src/Dibi/exceptions.php @@ -15,8 +15,7 @@ */ class Exception extends \Exception { - /** @var string|null */ - private $sql; + private ?string $sql; /** @@ -86,8 +85,7 @@ class NotSupportedException extends Exception */ class ProcedureException extends Exception { - /** @var string */ - protected $severity; + protected string $severity; /** From 15a9c989ce80dc8e1e54ffc07e0acb2d6dcc39db Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:51:41 +0100 Subject: [PATCH 08/21] added PHP 8 typehints --- src/Dibi/Bridges/Tracy/Panel.php | 2 +- src/Dibi/Connection.php | 33 +++++++++-------------------- src/Dibi/DataSource.php | 10 ++++----- src/Dibi/DateTime.php | 5 +---- src/Dibi/Drivers/DummyDriver.php | 5 +++-- src/Dibi/Drivers/FirebirdDriver.php | 2 +- src/Dibi/Drivers/FirebirdResult.php | 2 +- src/Dibi/Drivers/MySqliDriver.php | 5 +---- src/Dibi/Drivers/NoDataResult.php | 2 +- src/Dibi/Drivers/OdbcDriver.php | 2 +- src/Dibi/Drivers/OdbcResult.php | 2 +- src/Dibi/Drivers/OracleDriver.php | 2 +- src/Dibi/Drivers/OracleResult.php | 2 +- src/Dibi/Drivers/PostgreDriver.php | 2 +- src/Dibi/Drivers/PostgreResult.php | 2 +- src/Dibi/Drivers/SqlsrvDriver.php | 2 +- src/Dibi/Drivers/SqlsrvResult.php | 2 +- src/Dibi/Event.php | 5 +---- src/Dibi/Fluent.php | 21 +++++++++--------- src/Dibi/Helpers.php | 9 ++++---- src/Dibi/Reflection/Column.php | 6 ++---- src/Dibi/Result.php | 17 +++++++-------- src/Dibi/ResultIterator.php | 6 ++---- src/Dibi/Row.php | 3 +-- src/Dibi/Translator.php | 3 +-- src/Dibi/dibi.php | 5 ++--- src/Dibi/exceptions.php | 11 +++++----- src/Dibi/interfaces.php | 7 ++---- 28 files changed, 71 insertions(+), 104 deletions(-) diff --git a/src/Dibi/Bridges/Tracy/Panel.php b/src/Dibi/Bridges/Tracy/Panel.php index 4ca16efff..5062932f5 100644 --- a/src/Dibi/Bridges/Tracy/Panel.php +++ b/src/Dibi/Bridges/Tracy/Panel.php @@ -32,7 +32,7 @@ class Panel implements Tracy\IBarPanel private array $events = []; - public function __construct($explain = true, int $filter = null) + public function __construct(bool $explain = true, int $filter = null) { $this->filter = $filter ?: Event::QUERY; $this->explain = $explain; diff --git a/src/Dibi/Connection.php b/src/Dibi/Connection.php index d041a2129..070688ce2 100644 --- a/src/Dibi/Connection.php +++ b/src/Dibi/Connection.php @@ -186,9 +186,8 @@ final public function isConnected(): bool /** * Returns configuration variable. If no $key is passed, returns the entire array. * @see self::__construct - * @return mixed */ - final public function getConfig(string $key = null, $default = null) + final public function getConfig(string $key = null, $default = null): mixed { return $key === null ? $this->config @@ -210,10 +209,9 @@ final public function getDriver(): Driver /** * Generates (translates) and executes SQL query. - * @param mixed ...$args * @throws Exception */ - final public function query(...$args): Result + final public function query(mixed ...$args): Result { return $this->nativeQuery($this->translate(...$args)); } @@ -221,10 +219,9 @@ final public function query(...$args): Result /** * Generates SQL query. - * @param mixed ...$args * @throws Exception */ - final public function translate(...$args): string + final public function translate(mixed ...$args): string { if (!$this->driver) { $this->connect(); @@ -235,9 +232,8 @@ final public function translate(...$args): string /** * Generates and prints SQL query. - * @param mixed ...$args */ - final public function test(...$args): bool + final public function test(mixed ...$args): bool { try { Helpers::dump($this->translate(...$args)); @@ -256,10 +252,9 @@ final public function test(...$args): bool /** * Generates (translates) and returns SQL query as DataSource. - * @param mixed ...$args * @throws Exception */ - final public function dataSource(...$args): DataSource + final public function dataSource(mixed ...$args): DataSource { return new DataSource($this->translate(...$args), $this); } @@ -413,10 +408,7 @@ public function rollback(string $savepoint = null): void } - /** - * @return mixed - */ - public function transaction(callable $callback) + public function transaction(callable $callback): mixed { if ($this->transactionDepth === 0) { $this->begin(); @@ -520,10 +512,9 @@ public function substitute(string $value): string /** * Executes SQL query and fetch result - shortcut for query() & fetch(). - * @param mixed ...$args * @throws Exception */ - public function fetch(...$args): ?Row + public function fetch(mixed ...$args): ?Row { return $this->query($args)->fetch(); } @@ -531,11 +522,10 @@ public function fetch(...$args): ?Row /** * Executes SQL query and fetch results - shortcut for query() & fetchAll(). - * @param mixed ...$args * @return Row[]|array[] * @throws Exception */ - public function fetchAll(...$args): array + public function fetchAll(mixed ...$args): array { return $this->query($args)->fetchAll(); } @@ -543,11 +533,9 @@ public function fetchAll(...$args): array /** * Executes SQL query and fetch first column - shortcut for query() & fetchSingle(). - * @param mixed ...$args - * @return mixed * @throws Exception */ - public function fetchSingle(...$args) + public function fetchSingle(mixed ...$args): mixed { return $this->query($args)->fetchSingle(); } @@ -555,10 +543,9 @@ public function fetchSingle(...$args) /** * Executes SQL query and fetch pairs - shortcut for query() & fetchPairs(). - * @param mixed ...$args * @throws Exception */ - public function fetchPairs(...$args): array + public function fetchPairs(mixed ...$args): array { return $this->query($args)->fetchPairs(); } diff --git a/src/Dibi/DataSource.php b/src/Dibi/DataSource.php index f3920e8b9..4dd2497bb 100644 --- a/src/Dibi/DataSource.php +++ b/src/Dibi/DataSource.php @@ -55,7 +55,7 @@ public function __construct(string $sql, Connection $connection) * @param string|array $col column name or array of column names * @param string $as column alias */ - public function select($col, string $as = null): self + public function select(string|array $col, string $as = null): static { if (is_array($col)) { $this->cols = $col; @@ -70,7 +70,7 @@ public function select($col, string $as = null): self /** * Adds conditions to query. */ - public function where($cond): self + public function where($cond): static { $this->conds[] = is_array($cond) ? $cond // TODO: not consistent with select and orderBy @@ -84,7 +84,7 @@ public function where($cond): self * Selects columns to order by. * @param string|array $row column name or array of column names */ - public function orderBy($row, string $direction = 'ASC'): self + public function orderBy(string|array $row, string $direction = 'ASC'): static { if (is_array($row)) { $this->sorting = $row; @@ -99,7 +99,7 @@ public function orderBy($row, string $direction = 'ASC'): self /** * Limits number of rows. */ - public function applyLimit(int $limit, int $offset = null): self + public function applyLimit(int $limit, int $offset = null): static { $this->limit = $limit; $this->offset = $offset; @@ -148,7 +148,7 @@ public function fetch(): ?Row * Like fetch(), but returns only first field. * @return mixed value on success, null if no next record */ - public function fetchSingle() + public function fetchSingle(): mixed { return $this->getResult()->fetchSingle(); } diff --git a/src/Dibi/DateTime.php b/src/Dibi/DateTime.php index c18c1b2cf..cbb897d49 100644 --- a/src/Dibi/DateTime.php +++ b/src/Dibi/DateTime.php @@ -17,10 +17,7 @@ class DateTime extends \DateTimeImmutable { use Strict; - /** - * @param string|int $time - */ - public function __construct($time = 'now', \DateTimeZone $timezone = null) + public function __construct(string|int $time = 'now', \DateTimeZone $timezone = null) { $timezone = $timezone ?: new \DateTimeZone(date_default_timezone_get()); if (is_numeric($time)) { diff --git a/src/Dibi/Drivers/DummyDriver.php b/src/Dibi/Drivers/DummyDriver.php index 523179a46..d83d1fa14 100644 --- a/src/Dibi/Drivers/DummyDriver.php +++ b/src/Dibi/Drivers/DummyDriver.php @@ -57,7 +57,7 @@ public function rollback(string $savepoint = null): void } - public function getResource() + public function getResource(): mixed { return null; } @@ -171,8 +171,9 @@ public function free(): void } - public function getResultResource() + public function getResultResource(): mixed { + return null; } diff --git a/src/Dibi/Drivers/FirebirdDriver.php b/src/Dibi/Drivers/FirebirdDriver.php index b91d03aca..efe78b994 100644 --- a/src/Dibi/Drivers/FirebirdDriver.php +++ b/src/Dibi/Drivers/FirebirdDriver.php @@ -189,7 +189,7 @@ public function inTransaction(): bool * Returns the connection resource. * @return resource|null */ - public function getResource() + public function getResource(): mixed { return is_resource($this->connection) ? $this->connection : null; } diff --git a/src/Dibi/Drivers/FirebirdResult.php b/src/Dibi/Drivers/FirebirdResult.php index 8a07778c9..979960be0 100644 --- a/src/Dibi/Drivers/FirebirdResult.php +++ b/src/Dibi/Drivers/FirebirdResult.php @@ -102,7 +102,7 @@ public function free(): void * Returns the result set resource. * @return resource|null */ - public function getResultResource() + public function getResultResource(): mixed { $this->autoFree = false; return is_resource($this->resultSet) ? $this->resultSet : null; diff --git a/src/Dibi/Drivers/MySqliDriver.php b/src/Dibi/Drivers/MySqliDriver.php index 11337314e..e3cf83250 100644 --- a/src/Dibi/Drivers/MySqliDriver.php +++ b/src/Dibi/Drivers/MySqliDriver.php @@ -156,10 +156,7 @@ public function query(string $sql): ?Dibi\ResultDriver } - /** - * @param int|string $code - */ - public static function createException(string $message, $code, string $sql): Dibi\DriverException + public static function createException(string $message, int|string $code, string $sql): Dibi\DriverException { if (in_array($code, [1216, 1217, 1451, 1452, 1701], true)) { return new Dibi\ForeignKeyConstraintViolationException($message, $code, $sql); diff --git a/src/Dibi/Drivers/NoDataResult.php b/src/Dibi/Drivers/NoDataResult.php index 82c309222..932398c8e 100644 --- a/src/Dibi/Drivers/NoDataResult.php +++ b/src/Dibi/Drivers/NoDataResult.php @@ -60,7 +60,7 @@ public function getResultColumns(): array } - public function getResultResource() + public function getResultResource(): mixed { return null; } diff --git a/src/Dibi/Drivers/OdbcDriver.php b/src/Dibi/Drivers/OdbcDriver.php index 9a998e955..4f5064f5f 100644 --- a/src/Dibi/Drivers/OdbcDriver.php +++ b/src/Dibi/Drivers/OdbcDriver.php @@ -167,7 +167,7 @@ public function inTransaction(): bool * Returns the connection resource. * @return resource|null */ - public function getResource() + public function getResource(): mixed { return is_resource($this->connection) ? $this->connection : null; } diff --git a/src/Dibi/Drivers/OdbcResult.php b/src/Dibi/Drivers/OdbcResult.php index 324d84b76..3aa5a79fc 100644 --- a/src/Dibi/Drivers/OdbcResult.php +++ b/src/Dibi/Drivers/OdbcResult.php @@ -122,7 +122,7 @@ public function getResultColumns(): array * Returns the result set resource. * @return resource|null */ - public function getResultResource() + public function getResultResource(): mixed { $this->autoFree = false; return is_resource($this->resultSet) ? $this->resultSet : null; diff --git a/src/Dibi/Drivers/OracleDriver.php b/src/Dibi/Drivers/OracleDriver.php index 70cb5424f..5fb2a2987 100644 --- a/src/Dibi/Drivers/OracleDriver.php +++ b/src/Dibi/Drivers/OracleDriver.php @@ -183,7 +183,7 @@ public function rollback(string $savepoint = null): void * Returns the connection resource. * @return resource|null */ - public function getResource() + public function getResource(): mixed { return is_resource($this->connection) ? $this->connection : null; } diff --git a/src/Dibi/Drivers/OracleResult.php b/src/Dibi/Drivers/OracleResult.php index bcff77993..e45637565 100644 --- a/src/Dibi/Drivers/OracleResult.php +++ b/src/Dibi/Drivers/OracleResult.php @@ -107,7 +107,7 @@ public function getResultColumns(): array * Returns the result set resource. * @return resource|null */ - public function getResultResource() + public function getResultResource(): mixed { $this->autoFree = false; return is_resource($this->resultSet) ? $this->resultSet : null; diff --git a/src/Dibi/Drivers/PostgreDriver.php b/src/Dibi/Drivers/PostgreDriver.php index dd1f2a2c8..6ec04aa14 100644 --- a/src/Dibi/Drivers/PostgreDriver.php +++ b/src/Dibi/Drivers/PostgreDriver.php @@ -224,7 +224,7 @@ public function inTransaction(): bool * Returns the connection resource. * @return resource|null */ - public function getResource() + public function getResource(): mixed { return is_resource($this->connection) ? $this->connection : null; } diff --git a/src/Dibi/Drivers/PostgreResult.php b/src/Dibi/Drivers/PostgreResult.php index db159e612..f6c23016d 100644 --- a/src/Dibi/Drivers/PostgreResult.php +++ b/src/Dibi/Drivers/PostgreResult.php @@ -109,7 +109,7 @@ public function getResultColumns(): array * Returns the result set resource. * @return resource|null */ - public function getResultResource() + public function getResultResource(): mixed { $this->autoFree = false; return is_resource($this->resultSet) ? $this->resultSet : null; diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index d5fe653f5..7619232f0 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -163,7 +163,7 @@ public function rollback(string $savepoint = null): void * Returns the connection resource. * @return resource|null */ - public function getResource() + public function getResource(): mixed { return is_resource($this->connection) ? $this->connection : null; } diff --git a/src/Dibi/Drivers/SqlsrvResult.php b/src/Dibi/Drivers/SqlsrvResult.php index 21b4b523e..819a9d75b 100644 --- a/src/Dibi/Drivers/SqlsrvResult.php +++ b/src/Dibi/Drivers/SqlsrvResult.php @@ -103,7 +103,7 @@ public function getResultColumns(): array * Returns the result set resource. * @return resource|null */ - public function getResultResource() + public function getResultResource(): mixed { $this->autoFree = false; return is_resource($this->resultSet) ? $this->resultSet : null; diff --git a/src/Dibi/Event.php b/src/Dibi/Event.php index c3b9de089..5e4bdf1f3 100644 --- a/src/Dibi/Event.php +++ b/src/Dibi/Event.php @@ -75,10 +75,7 @@ public function __construct(Connection $connection, int $type, string $sql = nul } - /** - * @param Result|DriverException|null $result - */ - public function done($result = null): self + public function done(Result|DriverException $result = null): static { $this->result = $result; try { diff --git a/src/Dibi/Fluent.php b/src/Dibi/Fluent.php index cfb2113f8..7f955789b 100644 --- a/src/Dibi/Fluent.php +++ b/src/Dibi/Fluent.php @@ -120,7 +120,7 @@ public function __construct(Connection $connection) /** * Appends new argument to the clause. */ - public function __call(string $clause, array $args): self + public function __call(string $clause, array $args): static { $clause = self::$normalizer->$clause; @@ -206,7 +206,7 @@ public function __call(string $clause, array $args): self /** * Switch to a clause. */ - public function clause(string $clause): self + public function clause(string $clause): static { $this->cursor = &$this->clauses[self::$normalizer->$clause]; if ($this->cursor === null) { @@ -220,7 +220,7 @@ public function clause(string $clause): self /** * Removes a clause. */ - public function removeClause(string $clause): self + public function removeClause(string $clause): static { $this->clauses[self::$normalizer->$clause] = null; return $this; @@ -230,7 +230,7 @@ public function removeClause(string $clause): self /** * Change a SQL flag. */ - public function setFlag(string $flag, bool $value = true): self + public function setFlag(string $flag, bool $value = true): static { $flag = strtoupper($flag); if ($value) { @@ -269,7 +269,7 @@ final public function getConnection(): Connection /** * Adds Result setup. */ - public function setupResult(string $method): self + public function setupResult(string $method): static { $this->setups[] = func_get_args(); return $this; @@ -281,10 +281,10 @@ public function setupResult(string $method): self /** * Generates and executes SQL query. - * @return Result|int|null result set or number of affected rows + * Returns result set or number of affected rows * @throws Exception */ - public function execute(string $return = null) + public function execute(string $return = null): Result|int|null { $res = $this->query($this->_export()); switch ($return) { @@ -300,9 +300,8 @@ public function execute(string $return = null) /** * Generates, executes SQL query and fetches the single row. - * @return Row|array|null */ - public function fetch() + public function fetch(): Row|array|null { return $this->command === 'SELECT' && !$this->clauses['LIMIT'] ? $this->query($this->_export(null, ['%lmt', 1]))->fetch() @@ -312,9 +311,9 @@ public function fetch() /** * Like fetch(), but returns only first field. - * @return mixed value on success, null if no next record + * Returns value on success, null if no next record */ - public function fetchSingle() + public function fetchSingle(): mixed { return $this->command === 'SELECT' && !$this->clauses['LIMIT'] ? $this->query($this->_export(null, ['%lmt', 1]))->fetchSingle() diff --git a/src/Dibi/Helpers.php b/src/Dibi/Helpers.php index e208309ec..3c99ac3af 100644 --- a/src/Dibi/Helpers.php +++ b/src/Dibi/Helpers.php @@ -19,9 +19,8 @@ class Helpers /** * Prints out a syntax highlighted version of the SQL command or Result. - * @param string|Result $sql */ - public static function dump($sql = null, bool $return = false): ?string + public static function dump(string|Result $sql = null, bool $return = false): ?string { ob_start(); if ($sql instanceof Result && PHP_SAPI === 'cli') { @@ -229,7 +228,7 @@ public static function alias(array &$config, string $key, string $alias): void /** * Import SQL dump from file. - * @return int count of sql commands + * Returns count of sql commands */ public static function loadFromFile(Connection $connection, string $file, callable $onProgress = null): int { @@ -277,14 +276,14 @@ public static function loadFromFile(Connection $connection, string $file, callab /** @internal */ - public static function false2Null($val) + public static function false2Null(mixed $val): mixed { return $val === false ? null : $val; } /** @internal */ - public static function intVal($value): int + public static function intVal(mixed $value): int { if (is_int($value)) { return $value; diff --git a/src/Dibi/Reflection/Column.php b/src/Dibi/Reflection/Column.php index 0019c2b1d..fb52b68fa 100644 --- a/src/Dibi/Reflection/Column.php +++ b/src/Dibi/Reflection/Column.php @@ -108,15 +108,13 @@ public function isAutoIncrement(): bool } - /** @return mixed */ - public function getDefault() + public function getDefault(): mixed { return $this->info['default'] ?? null; } - /** @return mixed */ - public function getVendorInfo(string $key) + public function getVendorInfo(string $key): mixed { return $this->info['vendor'][$key] ?? null; } diff --git a/src/Dibi/Result.php b/src/Dibi/Result.php index 41cecc1e4..29d365abf 100644 --- a/src/Dibi/Result.php +++ b/src/Dibi/Result.php @@ -130,7 +130,7 @@ final public function getColumnCount(): int /** * Set fetched object class. This class should extend the Row class. */ - public function setRowClass(?string $class): self + public function setRowClass(?string $class): static { $this->rowClass = $class; return $this; @@ -149,7 +149,7 @@ public function getRowClass(): ?string /** * Set a factory to create fetched object instances. These should extend the Row class. */ - public function setRowFactory(callable $callback): self + public function setRowFactory(callable $callback): static { $this->rowFactory = $callback; return $this; @@ -159,9 +159,8 @@ public function setRowFactory(callable $callback): self /** * Fetches the row at current position, process optional type conversion. * and moves the internal cursor to the next position - * @return Row|array|null */ - final public function fetch() + final public function fetch(): Row|array|null { $row = $this->getResultDriver()->fetch(true); if ($row === null) { @@ -180,9 +179,9 @@ final public function fetch() /** * Like fetch(), but returns only first field. - * @return mixed value on success, null if no next record + * Returns value on success, null if no next record */ - final public function fetchSingle() + final public function fetchSingle(): mixed { $row = $this->getResultDriver()->fetch(true); if ($row === null) { @@ -522,7 +521,7 @@ private function normalize(array &$row): void * Define column type. * @param string|null $type use constant Type::* */ - final public function setType(string $column, ?string $type): self + final public function setType(string $column, ?string $type): static { $this->types[$column] = $type; return $this; @@ -550,7 +549,7 @@ final public function getTypes(): array /** * Sets type format. */ - final public function setFormat(string $type, ?string $format): self + final public function setFormat(string $type, ?string $format): static { $this->formats[$type] = $format; return $this; @@ -560,7 +559,7 @@ final public function setFormat(string $type, ?string $format): self /** * Sets type formats. */ - final public function setFormats(array $formats): self + final public function setFormats(array $formats): static { $this->formats = $formats; return $this; diff --git a/src/Dibi/ResultIterator.php b/src/Dibi/ResultIterator.php index 3c23e6c3a..2f3f5c763 100644 --- a/src/Dibi/ResultIterator.php +++ b/src/Dibi/ResultIterator.php @@ -43,9 +43,8 @@ public function rewind(): void /** * Returns the key of the current element. - * @return mixed */ - public function key() + public function key(): mixed { return $this->pointer; } @@ -53,9 +52,8 @@ public function key() /** * Returns the current element. - * @return mixed */ - public function current() + public function current(): mixed { return $this->row; } diff --git a/src/Dibi/Row.php b/src/Dibi/Row.php index f367fd456..b4676aadb 100644 --- a/src/Dibi/Row.php +++ b/src/Dibi/Row.php @@ -31,9 +31,8 @@ public function toArray(): array /** * Converts value to DateTime object. - * @return DateTime|string|null */ - public function asDateTime(string $key, string $format = null) + public function asDateTime(string $key, string $format = null): DateTime|string|null { $time = $this[$key]; if (!$time instanceof DateTime) { diff --git a/src/Dibi/Translator.php b/src/Dibi/Translator.php index 097354822..b28229888 100644 --- a/src/Dibi/Translator.php +++ b/src/Dibi/Translator.php @@ -159,9 +159,8 @@ public function translate(array $args): string /** * Apply modifier to single value. - * @param mixed $value */ - public function formatValue($value, ?string $modifier): string + public function formatValue(mixed $value, ?string $modifier): string { if ($this->comment) { return '...'; diff --git a/src/Dibi/dibi.php b/src/Dibi/dibi.php index cad0c815b..80380ebbf 100644 --- a/src/Dibi/dibi.php +++ b/src/Dibi/dibi.php @@ -88,7 +88,7 @@ final public function __construct() * @param array $config connection parameters * @throws Dibi\Exception */ - public static function connect($config = [], string $name = '0'): Dibi\Connection + public static function connect(array $config = [], string $name = '0'): Dibi\Connection { return self::$connection = self::$registry[$name] = new Dibi\Connection($config, $name); } @@ -151,10 +151,9 @@ public static function __callStatic(string $name, array $args) /** * Prints out a syntax highlighted version of the SQL command or Result. - * @param string|Dibi\Result $sql * @param bool $return return output instead of printing it? */ - public static function dump($sql = null, bool $return = false): ?string + public static function dump(string|Dibi\Result $sql = null, bool $return = false): ?string { return Dibi\Helpers::dump($sql, $return); } diff --git a/src/Dibi/exceptions.php b/src/Dibi/exceptions.php index 48b78c022..e6312f01b 100644 --- a/src/Dibi/exceptions.php +++ b/src/Dibi/exceptions.php @@ -18,11 +18,12 @@ class Exception extends \Exception private ?string $sql; - /** - * @param int|string $code - */ - public function __construct(string $message = '', $code = 0, string $sql = null, \Throwable $previous = null) - { + public function __construct( + string $message = '', + int|string $code = 0, + string $sql = null, + \Throwable $previous = null, + ) { parent::__construct($message, 0, $previous); $this->code = $code; $this->sql = $sql; diff --git a/src/Dibi/interfaces.php b/src/Dibi/interfaces.php index 9f6b21223..bb0db7e21 100644 --- a/src/Dibi/interfaces.php +++ b/src/Dibi/interfaces.php @@ -67,9 +67,8 @@ function rollback(string $savepoint = null): void; /** * Returns the connection resource. - * @return mixed */ - function getResource(); + function getResource(): mixed; /** * Returns the connection reflector. @@ -117,7 +116,6 @@ function getRowCount(): int; /** * Moves cursor position without fetching row. - * @return bool true on success, false if unable to seek to specified record * @throws Exception */ function seek(int $row): bool; @@ -142,9 +140,8 @@ function getResultColumns(): array; /** * Returns the result set resource. - * @return mixed */ - function getResultResource(); + function getResultResource(): mixed; /** * Decodes data from result set. From 48845839d1ee1201c5997e4170d849d1d7aa4af9 Mon Sep 17 00:00:00 2001 From: jaf2bj Date: Wed, 26 May 2021 14:48:00 +0200 Subject: [PATCH 09/21] sqlsrv_configure after sqlsrv_errors --- src/Dibi/Drivers/SqlsrvDriver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index 7619232f0..7e5de720d 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -63,13 +63,15 @@ public function __construct(array $config) sqlsrv_configure('WarningsReturnAsErrors', 0); $this->connection = sqlsrv_connect($config['host'], $options); - sqlsrv_configure('WarningsReturnAsErrors', 1); } if (!is_resource($this->connection)) { $info = sqlsrv_errors(SQLSRV_ERR_ERRORS); throw new Dibi\DriverException($info[0]['message'], $info[0]['code']); } + if (!isset($config['resource'])) { + sqlsrv_configure('WarningsReturnAsErrors', 1); + } $this->version = sqlsrv_server_info($this->connection)['SQLServerVersion']; } From c3b365e59986662633219708e5f0e5a894c5925d Mon Sep 17 00:00:00 2001 From: jaf2bj Date: Wed, 26 May 2021 14:51:37 +0200 Subject: [PATCH 10/21] sqlsrv_configure after sqlsrv_errors --- src/Dibi/Drivers/SqlsrvDriver.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index 7e5de720d..29d4ccad8 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -69,9 +69,9 @@ public function __construct(array $config) $info = sqlsrv_errors(SQLSRV_ERR_ERRORS); throw new Dibi\DriverException($info[0]['message'], $info[0]['code']); } - if (!isset($config['resource'])) { - sqlsrv_configure('WarningsReturnAsErrors', 1); - } + if (!isset($config['resource'])) { + sqlsrv_configure('WarningsReturnAsErrors', 1); + } $this->version = sqlsrv_server_info($this->connection)['SQLServerVersion']; } From 35a8ee7bf18d58729404036c994f4f980f2dbaf1 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Tue, 22 Jun 2021 15:16:02 -0700 Subject: [PATCH 11/21] Sqlsrv driver parameterized query support --- src/Dibi/Drivers/DummyDriver.php | 2 +- src/Dibi/Drivers/FirebirdDriver.php | 1 + src/Dibi/Drivers/MySqliDriver.php | 1 + src/Dibi/Drivers/NoParameterizedQueries.php | 63 +++++++++++++++++++++ src/Dibi/Drivers/OdbcDriver.php | 1 + src/Dibi/Drivers/OracleDriver.php | 1 + src/Dibi/Drivers/PdoDriver.php | 1 + src/Dibi/Drivers/PostgreDriver.php | 1 + src/Dibi/Drivers/SqliteDriver.php | 1 + src/Dibi/Drivers/SqlsrvDriver.php | 49 +++++++++++++++- src/Dibi/QueryParameter.php | 30 ++++++++++ src/Dibi/Translator.php | 12 ++++ src/Dibi/interfaces.php | 18 ++++++ tests/dibi/Sqlsrv.params.phpt | 39 +++++++++++++ tests/dibi/data/sqlsrv.sql | 2 +- 15 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 src/Dibi/Drivers/NoParameterizedQueries.php create mode 100644 src/Dibi/QueryParameter.php create mode 100644 tests/dibi/Sqlsrv.params.phpt diff --git a/src/Dibi/Drivers/DummyDriver.php b/src/Dibi/Drivers/DummyDriver.php index 523179a46..f1e331297 100644 --- a/src/Dibi/Drivers/DummyDriver.php +++ b/src/Dibi/Drivers/DummyDriver.php @@ -18,6 +18,7 @@ class DummyDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector { use Dibi\Strict; + use NoParameterizedQueries; public function disconnect(): void { @@ -129,7 +130,6 @@ public function escapeLike(string $value, int $pos): string return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'"); } - /** * Injects LIMIT/OFFSET to the SQL query. */ diff --git a/src/Dibi/Drivers/FirebirdDriver.php b/src/Dibi/Drivers/FirebirdDriver.php index e1f8c69fc..793a4df69 100644 --- a/src/Dibi/Drivers/FirebirdDriver.php +++ b/src/Dibi/Drivers/FirebirdDriver.php @@ -27,6 +27,7 @@ class FirebirdDriver implements Dibi\Driver { use Dibi\Strict; + use NoParameterizedQueries; public const ERROR_EXCEPTION_THROWN = -836; diff --git a/src/Dibi/Drivers/MySqliDriver.php b/src/Dibi/Drivers/MySqliDriver.php index d9dede68b..75a952342 100644 --- a/src/Dibi/Drivers/MySqliDriver.php +++ b/src/Dibi/Drivers/MySqliDriver.php @@ -33,6 +33,7 @@ class MySqliDriver implements Dibi\Driver { use Dibi\Strict; + use NoParameterizedQueries; public const ERROR_ACCESS_DENIED = 1045; diff --git a/src/Dibi/Drivers/NoParameterizedQueries.php b/src/Dibi/Drivers/NoParameterizedQueries.php new file mode 100644 index 000000000..09799546b --- /dev/null +++ b/src/Dibi/Drivers/NoParameterizedQueries.php @@ -0,0 +1,63 @@ +connection); // @ - connection can be already disconnected } - /** * Executes the SQL query. * @throws Dibi\DriverException @@ -92,7 +93,8 @@ public function disconnect(): void public function query(string $sql): ?Dibi\ResultDriver { $this->affectedRows = null; - $res = sqlsrv_query($this->connection, $sql); + $res = sqlsrv_query($this->connection, $sql, $this->paramValues); // TODO Change this to include bound parameters + $this->paramValues = []; if ($res === false) { $info = sqlsrv_errors(); @@ -248,6 +250,47 @@ public function escapeLike(string $value, int $pos): string return ($pos & 1 ? "'%" : "'") . $value . ($pos & 2 ? "%'" : "'"); } + public function addParameter(QueryParameter $param) : void { + // https://www.php.net/manual/en/sqlsrv.constants.php + $this->paramValues[] = [ + $param->value, + \SQLSRV_PARAM_IN, + $param->phpType, + $param->sqlType, + ]; + } + + function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_VARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + } + + function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_NVARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + } + + function bindIdentifier(?string $value): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_UNIQUEIDENTIFIER, \SQLSRV_PHPTYPE_STRING('UTF-8')); + } + + function bindInt(?int $value): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_INT, \SQLSRV_PHPTYPE_INT); + } + + function bindNumeric(?float $value, string $precision, string $scale): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_NUMERIC($precision, $scale), \SQLSRV_PHPTYPE_FLOAT); + } + + function bindDate(?\DateTimeInterface $value): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_DATE, \SQLSRV_PHPTYPE_DATETIME); + } + + function bindDateTime(?\DateTimeInterface $value): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIME2, \SQLSRV_PHPTYPE_DATETIME); + } + + function bindDateInterval(?\DateInterval $value): QueryParameter { + return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIMEOFFSET, \SQLSRV_PHPTYPE_STRING('UTF-8')); + } /** * Injects LIMIT/OFFSET to the SQL query. diff --git a/src/Dibi/QueryParameter.php b/src/Dibi/QueryParameter.php new file mode 100644 index 000000000..068549e12 --- /dev/null +++ b/src/Dibi/QueryParameter.php @@ -0,0 +1,30 @@ +sqlType = $sqlType; + $this->phpType = $phpType; + $this->value = $value; + } + + public function __toString() : string + { + return "QueryParameter Value={$this->value} SqlType:{$this->sqlType} PhpType:{$this->phpType}"; + } +} diff --git a/src/Dibi/Translator.php b/src/Dibi/Translator.php index 1a7852e0a..6627115dd 100644 --- a/src/Dibi/Translator.php +++ b/src/Dibi/Translator.php @@ -128,6 +128,11 @@ public function translate(array $args): string $arg = iterator_to_array($arg); } + if ($arg instanceof QueryParameter) { + $this->driver->addParameter($arg); + continue; + } + if (is_array($arg) && is_string(key($arg))) { // associative array -> autoselect between SET or VALUES & LIST if ($commandIns === null) { @@ -598,6 +603,13 @@ private function cb(array $matches): string } return ''; + } elseif ($mod === 'tsql') { // parameterized query + if ($this->comment) { + return "parameterized query"; + } else { + + } + return '?'; } else { // default processing $cursor++; return $this->formatValue($this->args[$cursor - 1], $mod); diff --git a/src/Dibi/interfaces.php b/src/Dibi/interfaces.php index 9f6b21223..14887add7 100644 --- a/src/Dibi/interfaces.php +++ b/src/Dibi/interfaces.php @@ -98,6 +98,24 @@ function escapeDateInterval(\DateInterval $value): string; */ function escapeLike(string $value, int $pos): string; + function addParameter(QueryParameter $param) : void; + + function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter; + + function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter; + + function bindIdentifier(?string $value): QueryParameter; + + function bindInt(?int $value): QueryParameter; + + function bindNumeric(?float $value, string $precision, string $scale): QueryParameter; + + function bindDate(?\DateTimeInterface $value): QueryParameter; + + function bindDateTime(?\DateTimeInterface $value): QueryParameter; + + function bindDateInterval(?\DateInterval $value): QueryParameter; + /** * Injects LIMIT/OFFSET to the SQL query. */ diff --git a/tests/dibi/Sqlsrv.params.phpt b/tests/dibi/Sqlsrv.params.phpt new file mode 100644 index 000000000..1b6ad5bc5 --- /dev/null +++ b/tests/dibi/Sqlsrv.params.phpt @@ -0,0 +1,39 @@ +getDriver(); + + Assert::equal('hello', $conn->query('SELECT %tsql', $driver->bindAsciiText('hello', '20'))->fetchSingle()); + + Assert::equal(1, $conn->query('INSERT INTO Customers ([name]) VALUES (%tsql)', $driver->bindText('❤️‍🔥'))->getRowCount()); + Assert::equal('❤️‍🔥', $conn->fetchSingle('SELECT [name] FROM Customers WHERE [name] = %tsql', $driver->bindText('❤️‍🔥'))); + + $param = $driver->bindText('testing', '20', 'UTF-8'); + Assert::equal(\SQLSRV_SQLTYPE_NVARCHAR('20'), $param->sqlType); + Assert::equal('testing', $param->value); + Assert::equal(\SQLSRV_PHPTYPE_STRING('UTF-8'), $param->phpType); + + Assert::equal('?????', $conn->query('SELECT %tsql', $driver->bindAsciiText('❤️‍🔥'))->fetchSingle()); + + Assert::equal('❤️‍🔥', $conn->query('SELECT %tsql', $driver->bindText('❤️‍🔥'))->fetchSingle()); + + Assert::equal(42, $conn->query('SELECT %tsql', $driver->bindInt(42))->fetchSingle()); + + Assert::equal(null, $conn->query('SELECT %tsql', $driver->bindText(null))->fetchSingle()); +}; + +$conn = new Dibi\Connection($config); +$conn->loadFile(__DIR__ . "/data/$config[system].sql"); + +$tests($conn); diff --git a/tests/dibi/data/sqlsrv.sql b/tests/dibi/data/sqlsrv.sql index 9be70d6ee..71f4df428 100644 --- a/tests/dibi/data/sqlsrv.sql +++ b/tests/dibi/data/sqlsrv.sql @@ -18,7 +18,7 @@ SET IDENTITY_INSERT products OFF; CREATE TABLE customers ( customer_id int NOT NULL IDENTITY(11,1), - name varchar(50) NOT NULL, + name nvarchar(50) NOT NULL, PRIMARY KEY(customer_id) ); From 32a675f36cf42b96805924411c2f3eb7c8b78954 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Thu, 24 Jun 2021 09:17:48 -0700 Subject: [PATCH 12/21] Changing %tsql to %pq for parameterized query substitution --- src/Dibi/Drivers/PdoDriver.php | 66 +++++++++++++++++++++++++++++- src/Dibi/Translator.php | 4 +- tests/dibi/Connection.connect.phpt | 21 ++++++++++ tests/dibi/DateTime.phpt | 7 ++-- tests/dibi/Sqlsrv.params.phpt | 14 +++---- 5 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/Dibi/Drivers/PdoDriver.php b/src/Dibi/Drivers/PdoDriver.php index 3ed1eaf89..3ec7dcab1 100644 --- a/src/Dibi/Drivers/PdoDriver.php +++ b/src/Dibi/Drivers/PdoDriver.php @@ -11,6 +11,7 @@ use Dibi; use Dibi\Helpers; +use Dibi\QueryParameter; use PDO; @@ -28,7 +29,6 @@ class PdoDriver implements Dibi\Driver { use Dibi\Strict; - use NoParameterizedQueries; /** @var PDO|null Connection resource */ private $connection; @@ -42,6 +42,8 @@ class PdoDriver implements Dibi\Driver /** @var string */ private $serverVersion = ''; + /** @var array */ + private $paramValues = []; /** @throws Dibi\NotSupportedException */ public function __construct(array $config) @@ -94,6 +96,21 @@ public function disconnect(): void */ public function query(string $sql): ?Dibi\ResultDriver { + if (count($this->paramValues) > 0) { + $res = $this->connection->prepare($sql, $this->paramValues); + if ($res) { + $count = count($this->paramValues); + for ($index = 0; $index < $count && $res; $index++) { + $success = $res->bindParam($index+1, $this->paramValues[$index]['var'], $this->paramValues[$index]['type']); + if (!$success) { + $res = false; + } + } + if ($res) { + $res->execute(); + } + } + } $res = $this->connection->query($sql); if ($res) { $this->affectedRows = $res->rowCount(); @@ -350,6 +367,53 @@ public function escapeLike(string $value, int $pos): string } } + public function addParameter(QueryParameter $param) : void { + // https://www.php.net/manual/en/sqlsrv.constants.php + $this->paramValues[] = [ + 'var' => $param->value, + 'type' => $param->sqlType + ]; + } + + function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_VARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_NVARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindIdentifier(?string $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_UNIQUEIDENTIFIER, \SQLSRV_PHPTYPE_STRING('UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindInt(?int $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_INT, \SQLSRV_PHPTYPE_INT); + return new QueryParameter($value, PDO::PARAM_INT, null); + } + + function bindNumeric(?float $value, string $precision, string $scale): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_NUMERIC($precision, $scale), \SQLSRV_PHPTYPE_FLOAT); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindDate(?\DateTimeInterface $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATE, \SQLSRV_PHPTYPE_DATETIME); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindDateTime(?\DateTimeInterface $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIME2, \SQLSRV_PHPTYPE_DATETIME); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindDateInterval(?\DateInterval $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIMEOFFSET, \SQLSRV_PHPTYPE_STRING('UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } /** * Injects LIMIT/OFFSET to the SQL query. diff --git a/src/Dibi/Translator.php b/src/Dibi/Translator.php index 6627115dd..a7d026cac 100644 --- a/src/Dibi/Translator.php +++ b/src/Dibi/Translator.php @@ -603,11 +603,9 @@ private function cb(array $matches): string } return ''; - } elseif ($mod === 'tsql') { // parameterized query + } elseif ($mod === 'pq') { // parameterized query if ($this->comment) { return "parameterized query"; - } else { - } return '?'; } else { // default processing diff --git a/tests/dibi/Connection.connect.phpt b/tests/dibi/Connection.connect.phpt index fbc7501a1..8e27e6e54 100644 --- a/tests/dibi/Connection.connect.phpt +++ b/tests/dibi/Connection.connect.phpt @@ -62,6 +62,27 @@ test('', function () use ($config) { Assert::equal('hello', $conn->query('SELECT %s', 'hello')->fetchSingle()); }); +test('Binding to int Query Parameters', function () use ($config) { + $conn = new Connection($config); + $driver = $conn->getDriver(); + try { + Assert::equal(PHP_INT_MAX, $conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle()); + Assert::null($conn->query('SELECT %pq', $driver->bindInt(null))->fetchSingle()); + } catch (Dibi\NotSupportedException $_) { + } +}); + +test('Binding to Text Query Parameters', function () use ($config) { + $conn = new Connection($config); + $driver = $conn->getDriver(); + try { + Assert::equal('hello', $conn->query('SELECT %pq', $driver->bindAsciiText('hello'))->fetchSingle()); + Assert::equal('hello', $conn->query('SELECT %pq', $driver->bindText('hello'))->fetchSingle()); + Assert::null($conn->query('SELECT %pq', $driver->bindText(null))->fetchSingle()); + Assert::null($conn->query('SELECT %pq', $driver->bindAsciiText(null))->fetchSingle()); + } catch (Dibi\NotSupportedException $_) { + } +}); test('', function () use ($config) { Assert::exception(function () use ($config) { diff --git a/tests/dibi/DateTime.phpt b/tests/dibi/DateTime.phpt index 5621c9b0f..efc525fd6 100644 --- a/tests/dibi/DateTime.phpt +++ b/tests/dibi/DateTime.phpt @@ -7,7 +7,6 @@ use Tester\Assert; require __DIR__ . '/bootstrap.php'; - date_default_timezone_set('Europe/Prague'); Assert::same('1978-01-23 11:40:00.000000', (string) new DateTime(254400000)); @@ -15,7 +14,9 @@ Assert::same('1978-01-23 11:40:00.000000', (string) (new DateTime)->setTimestamp 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 +if (is_int(2544000000)) { + Assert::same('2050-08-13 11:40:00.000000', (string) (new DateTime)->setTimestamp(2544000000)); // 64 bit only +} +Assert::same(is_int(2544000000) ? 2544000000 : false, (new DateTime(2544000000))->getTimestamp()); // 64 bit Assert::same('1978-05-05 00:00:00.000000', (string) new DateTime('1978-05-05')); diff --git a/tests/dibi/Sqlsrv.params.phpt b/tests/dibi/Sqlsrv.params.phpt index 1b6ad5bc5..5656b5920 100644 --- a/tests/dibi/Sqlsrv.params.phpt +++ b/tests/dibi/Sqlsrv.params.phpt @@ -14,23 +14,23 @@ require __DIR__ . '/bootstrap.php'; $tests = function ($conn) { $driver = $conn->getDriver(); - Assert::equal('hello', $conn->query('SELECT %tsql', $driver->bindAsciiText('hello', '20'))->fetchSingle()); + Assert::equal('hello', $conn->query('SELECT %pq', $driver->bindAsciiText('hello', '20'))->fetchSingle()); - Assert::equal(1, $conn->query('INSERT INTO Customers ([name]) VALUES (%tsql)', $driver->bindText('❤️‍🔥'))->getRowCount()); - Assert::equal('❤️‍🔥', $conn->fetchSingle('SELECT [name] FROM Customers WHERE [name] = %tsql', $driver->bindText('❤️‍🔥'))); + Assert::equal(1, $conn->query('INSERT INTO Customers ([name]) VALUES (%pq)', $driver->bindText('❤️‍🔥'))->getRowCount()); + Assert::equal('❤️‍🔥', $conn->fetchSingle('SELECT [name] FROM Customers WHERE [name] = %pq', $driver->bindText('❤️‍🔥'))); $param = $driver->bindText('testing', '20', 'UTF-8'); Assert::equal(\SQLSRV_SQLTYPE_NVARCHAR('20'), $param->sqlType); Assert::equal('testing', $param->value); Assert::equal(\SQLSRV_PHPTYPE_STRING('UTF-8'), $param->phpType); - Assert::equal('?????', $conn->query('SELECT %tsql', $driver->bindAsciiText('❤️‍🔥'))->fetchSingle()); + Assert::equal('?????', $conn->query('SELECT %pq', $driver->bindAsciiText('❤️‍🔥'))->fetchSingle()); - Assert::equal('❤️‍🔥', $conn->query('SELECT %tsql', $driver->bindText('❤️‍🔥'))->fetchSingle()); + Assert::equal('❤️‍🔥', $conn->query('SELECT %pq', $driver->bindText('❤️‍🔥'))->fetchSingle()); - Assert::equal(42, $conn->query('SELECT %tsql', $driver->bindInt(42))->fetchSingle()); + Assert::equal(42, $conn->query('SELECT %pq', $driver->bindInt(42))->fetchSingle()); - Assert::equal(null, $conn->query('SELECT %tsql', $driver->bindText(null))->fetchSingle()); + Assert::equal(null, $conn->query('SELECT %pq', $driver->bindText(null))->fetchSingle()); }; $conn = new Dibi\Connection($config); From 2ad35926c021e75536f977cd50b0c0a4a2c1081d Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Thu, 24 Jun 2021 10:19:20 -0700 Subject: [PATCH 13/21] Fix PDO usage and be sure to reset query params between queries --- src/Dibi/Drivers/PdoDriver.php | 12 +++++++++--- tests/dibi/Connection.connect.phpt | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Dibi/Drivers/PdoDriver.php b/src/Dibi/Drivers/PdoDriver.php index 3ec7dcab1..da3013de4 100644 --- a/src/Dibi/Drivers/PdoDriver.php +++ b/src/Dibi/Drivers/PdoDriver.php @@ -97,7 +97,7 @@ public function disconnect(): void public function query(string $sql): ?Dibi\ResultDriver { if (count($this->paramValues) > 0) { - $res = $this->connection->prepare($sql, $this->paramValues); + $res = $this->connection->prepare($sql); if ($res) { $count = count($this->paramValues); for ($index = 0; $index < $count && $res; $index++) { @@ -107,11 +107,17 @@ public function query(string $sql): ?Dibi\ResultDriver } } if ($res) { - $res->execute(); + $success = $res->execute(); + if (!$success) { + $res = false; + } } } + $this->paramValues = []; + } else { + $res = $this->connection->query($sql); } - $res = $this->connection->query($sql); + if ($res) { $this->affectedRows = $res->rowCount(); return $res->columnCount() ? $this->createResultDriver($res) : null; diff --git a/tests/dibi/Connection.connect.phpt b/tests/dibi/Connection.connect.phpt index 8e27e6e54..00da0dd0c 100644 --- a/tests/dibi/Connection.connect.phpt +++ b/tests/dibi/Connection.connect.phpt @@ -66,7 +66,8 @@ test('Binding to int Query Parameters', function () use ($config) { $conn = new Connection($config); $driver = $conn->getDriver(); try { - Assert::equal(PHP_INT_MAX, $conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle()); + Assert::equal(PHP_INT_MAX, intval($conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle())); + Assert::equal(42, intval($conn->query("SELECT 42;")->fetchSingle())); // Some PDO drivers will convert to string types even when bound to non string values Assert::null($conn->query('SELECT %pq', $driver->bindInt(null))->fetchSingle()); } catch (Dibi\NotSupportedException $_) { } From a138466b097a09f522e7c40d22b0033cef6c9da6 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Thu, 24 Jun 2021 16:44:25 -0700 Subject: [PATCH 14/21] Code formatting / cleanup --- src/Dibi/Drivers/NoParameterizedQueries.php | 56 ++++++++++----------- src/Dibi/Drivers/SqlsrvDriver.php | 2 +- tests/dibi/Connection.connect.phpt | 3 +- tests/dibi/DateTime.phpt | 2 +- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/Dibi/Drivers/NoParameterizedQueries.php b/src/Dibi/Drivers/NoParameterizedQueries.php index 09799546b..306c06e78 100644 --- a/src/Dibi/Drivers/NoParameterizedQueries.php +++ b/src/Dibi/Drivers/NoParameterizedQueries.php @@ -17,47 +17,47 @@ */ trait NoParameterizedQueries { - public function addParameter(QueryParameter $param) : void { - throw new NotSupportedException('Parameterized queries unsupported'); - } + public function addParameter(QueryParameter $param) : void { + throw new NotSupportedException('Parameterized queries unsupported'); + } - public function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + public function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindIdentifier(?string $value): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindInt(?int $value): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindNumeric(?float $value, string $precision, string $scale): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindDate(?\DateTimeInterface $value): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindDateTime(?\DateTimeInterface $value): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } public function bindDateInterval(?\DateInterval $value): QueryParameter - { - throw new NotSupportedException('Parameterized queries unsupported'); - } + { + throw new NotSupportedException('Parameterized queries unsupported'); + } } diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index 7e0e8d395..f941aabc1 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -257,7 +257,7 @@ public function addParameter(QueryParameter $param) : void { \SQLSRV_PARAM_IN, $param->phpType, $param->sqlType, - ]; + ]; } function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { diff --git a/tests/dibi/Connection.connect.phpt b/tests/dibi/Connection.connect.phpt index 00da0dd0c..e64a2467e 100644 --- a/tests/dibi/Connection.connect.phpt +++ b/tests/dibi/Connection.connect.phpt @@ -66,7 +66,8 @@ test('Binding to int Query Parameters', function () use ($config) { $conn = new Connection($config); $driver = $conn->getDriver(); try { - Assert::equal(PHP_INT_MAX, intval($conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle())); + // TODO: Not working on postgre pdo driver: + // Assert::equal(PHP_INT_MAX, intval($conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle())); Assert::equal(42, intval($conn->query("SELECT 42;")->fetchSingle())); // Some PDO drivers will convert to string types even when bound to non string values Assert::null($conn->query('SELECT %pq', $driver->bindInt(null))->fetchSingle()); } catch (Dibi\NotSupportedException $_) { diff --git a/tests/dibi/DateTime.phpt b/tests/dibi/DateTime.phpt index efc525fd6..df1f11661 100644 --- a/tests/dibi/DateTime.phpt +++ b/tests/dibi/DateTime.phpt @@ -15,7 +15,7 @@ Assert::same(254400000, (new DateTime(254400000))->getTimestamp()); Assert::same('2050-08-13 11:40:00.000000', (string) new DateTime(2544000000)); if (is_int(2544000000)) { - Assert::same('2050-08-13 11:40:00.000000', (string) (new DateTime)->setTimestamp(2544000000)); // 64 bit only + Assert::same('2050-08-13 11:40:00.000000', (string) (new DateTime)->setTimestamp(2544000000)); // 64 bit only } Assert::same(is_int(2544000000) ? 2544000000 : false, (new DateTime(2544000000))->getTimestamp()); // 64 bit From 63a7076eef5657bc328bb62a64a4daed5693be93 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Thu, 24 Jun 2021 17:00:09 -0700 Subject: [PATCH 15/21] Fixes code checker errors --- src/Dibi/Drivers/NoParameterizedQueries.php | 10 +++++++++- src/Dibi/QueryParameter.php | 16 ++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Dibi/Drivers/NoParameterizedQueries.php b/src/Dibi/Drivers/NoParameterizedQueries.php index 306c06e78..c379aa099 100644 --- a/src/Dibi/Drivers/NoParameterizedQueries.php +++ b/src/Dibi/Drivers/NoParameterizedQueries.php @@ -17,45 +17,53 @@ */ trait NoParameterizedQueries { - public function addParameter(QueryParameter $param) : void { + public function addParameter(QueryParameter $param): void { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindIdentifier(?string $value): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindInt(?int $value): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindNumeric(?float $value, string $precision, string $scale): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindDate(?\DateTimeInterface $value): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindDateTime(?\DateTimeInterface $value): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); } + public function bindDateInterval(?\DateInterval $value): QueryParameter { throw new NotSupportedException('Parameterized queries unsupported'); diff --git a/src/Dibi/QueryParameter.php b/src/Dibi/QueryParameter.php index 068549e12..eeb84d20f 100644 --- a/src/Dibi/QueryParameter.php +++ b/src/Dibi/QueryParameter.php @@ -10,18 +10,18 @@ namespace Dibi; class QueryParameter { - use Strict; + use Strict; public $sqlType; - public $phpType; + public $phpType; public $value; - public function __construct($value, $sqlType, $phpType) - { - $this->sqlType = $sqlType; - $this->phpType = $phpType; - $this->value = $value; - } + public function __construct($value, $sqlType, $phpType) + { + $this->sqlType = $sqlType; + $this->phpType = $phpType; + $this->value = $value; + } public function __toString() : string { From 06dc27335ad30dcbfbfdbd069153f60d1809edea Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Thu, 24 Jun 2021 17:18:56 -0700 Subject: [PATCH 16/21] Temporarily removing query parameter support for pdo driver --- src/Dibi/Drivers/PdoDriver.php | 75 +----------------------------- tests/dibi/Connection.connect.phpt | 5 +- 2 files changed, 4 insertions(+), 76 deletions(-) diff --git a/src/Dibi/Drivers/PdoDriver.php b/src/Dibi/Drivers/PdoDriver.php index da3013de4..1c89b8938 100644 --- a/src/Dibi/Drivers/PdoDriver.php +++ b/src/Dibi/Drivers/PdoDriver.php @@ -29,6 +29,7 @@ class PdoDriver implements Dibi\Driver { use Dibi\Strict; + use NoParameterizedQueries; /** @var PDO|null Connection resource */ private $connection; @@ -42,9 +43,6 @@ class PdoDriver implements Dibi\Driver /** @var string */ private $serverVersion = ''; - /** @var array */ - private $paramValues = []; - /** @throws Dibi\NotSupportedException */ public function __construct(array $config) { @@ -96,28 +94,7 @@ public function disconnect(): void */ public function query(string $sql): ?Dibi\ResultDriver { - if (count($this->paramValues) > 0) { - $res = $this->connection->prepare($sql); - if ($res) { - $count = count($this->paramValues); - for ($index = 0; $index < $count && $res; $index++) { - $success = $res->bindParam($index+1, $this->paramValues[$index]['var'], $this->paramValues[$index]['type']); - if (!$success) { - $res = false; - } - } - if ($res) { - $success = $res->execute(); - if (!$success) { - $res = false; - } - } - } - $this->paramValues = []; - } else { - $res = $this->connection->query($sql); - } - + $res = $this->connection->query($sql); if ($res) { $this->affectedRows = $res->rowCount(); return $res->columnCount() ? $this->createResultDriver($res) : null; @@ -373,54 +350,6 @@ public function escapeLike(string $value, int $pos): string } } - public function addParameter(QueryParameter $param) : void { - // https://www.php.net/manual/en/sqlsrv.constants.php - $this->paramValues[] = [ - 'var' => $param->value, - 'type' => $param->sqlType - ]; - } - - function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_VARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - - function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_NVARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - - function bindIdentifier(?string $value): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_UNIQUEIDENTIFIER, \SQLSRV_PHPTYPE_STRING('UTF-8')); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - - function bindInt(?int $value): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_INT, \SQLSRV_PHPTYPE_INT); - return new QueryParameter($value, PDO::PARAM_INT, null); - } - - function bindNumeric(?float $value, string $precision, string $scale): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_NUMERIC($precision, $scale), \SQLSRV_PHPTYPE_FLOAT); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - - function bindDate(?\DateTimeInterface $value): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATE, \SQLSRV_PHPTYPE_DATETIME); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - - function bindDateTime(?\DateTimeInterface $value): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIME2, \SQLSRV_PHPTYPE_DATETIME); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - - function bindDateInterval(?\DateInterval $value): QueryParameter { - // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIMEOFFSET, \SQLSRV_PHPTYPE_STRING('UTF-8')); - return new QueryParameter($value, PDO::PARAM_STR, null); - } - /** * Injects LIMIT/OFFSET to the SQL query. */ diff --git a/tests/dibi/Connection.connect.phpt b/tests/dibi/Connection.connect.phpt index e64a2467e..2977c8b17 100644 --- a/tests/dibi/Connection.connect.phpt +++ b/tests/dibi/Connection.connect.phpt @@ -66,9 +66,8 @@ test('Binding to int Query Parameters', function () use ($config) { $conn = new Connection($config); $driver = $conn->getDriver(); try { - // TODO: Not working on postgre pdo driver: - // Assert::equal(PHP_INT_MAX, intval($conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle())); - Assert::equal(42, intval($conn->query("SELECT 42;")->fetchSingle())); // Some PDO drivers will convert to string types even when bound to non string values + Assert::equal(PHP_INT_MAX, intval($conn->query('SELECT %pq', $driver->bindInt(PHP_INT_MAX))->fetchSingle())); + Assert::equal(42, intval($conn->query("SELECT %pq;", $driver->bindInt(42))->fetchSingle())); // Some PDO drivers will convert to string types even when bound to non string values Assert::null($conn->query('SELECT %pq', $driver->bindInt(null))->fetchSingle()); } catch (Dibi\NotSupportedException $_) { } From 493eec8c8f2bbce4e5d63919d18f25da167eaab3 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Thu, 24 Jun 2021 17:30:26 -0700 Subject: [PATCH 17/21] Updating appveyor to PHP 7.4 to support MS 5.9 libraries --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a4330dcf6..ac9a83a7c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,17 +15,17 @@ init: - SET ANSICON=121x90 (121x90) install: - # Install PHP 7.2 + # Install PHP 7.4 - 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 curl https://windows.php.net/downloads/releases/archives/php-7.2.18-Win32-VC15-x64.zip --output php.zip + - IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-7.4.19-Win32-vc15-x64.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 curl https://github.com/microsoft/msphpsql/releases/download/v5.8.0/Windows-7.2.zip -L --output sqlsrv.zip + - IF %PHP%==1 curl https://github.com/microsoft/msphpsql/releases/download/v5.9.0/Windows-7.4.zip -L --output sqlsrv.zip - IF %PHP%==1 7z x sqlsrv.zip >nul - - IF %PHP%==1 copy Windows-7.2\x64\php_sqlsrv_72_ts.dll ext\php_sqlsrv_ts.dll + - IF %PHP%==1 copy Windows-7.4\x64\php_sqlsrv_74_ts.dll ext\php_sqlsrv_ts.dll - IF %PHP%==1 del /Q *.zip # Install Microsoft Access Database Engine x64 From 62d8706d04b4dceae364162b993eb6695aa8f7b3 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Mon, 28 Jun 2021 12:59:42 -0700 Subject: [PATCH 18/21] Updating ODBC Driver install for appveyor and referencing "function-like" SQL server constants reliably --- appveyor.yml | 4 ++++ composer.json | 3 ++- src/Dibi/Drivers/SqlsrvDriver.php | 23 +++++++++++++++++------ tests/dibi/Sqlsrv.params.phpt | 6 ++++-- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ac9a83a7c..329c96866 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,6 +32,10 @@ install: - IF %PHP%==1 curl https://download.microsoft.com/download/2/4/3/24375141-E08D-4803-AB0E-10F2E3A07AAA/AccessDatabaseEngine_X64.exe --output AccessDatabaseEngine_X64.exe - cmd /c start /wait AccessDatabaseEngine_X64.exe /passive + # Install ODBC Driver for SQL Server x64 Version 17.7.2 + - IF %PHP%==1 curl curl -L -v https://go.microsoft.com/fwlink/?linkid=2156851 --output msodbcsql.msi + - cmd /c start /wait msiexec /qn /passive /i msodbcsql.msi + # Install Nette Tester - cd c:\projects\dibi - appveyor DownloadFile https://getcomposer.org/composer.phar diff --git a/composer.json b/composer.json index d94135ceb..c66c6b1cb 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "tracy/tracy": "~2.2", "nette/tester": "~2.0", "nette/di": "^3.0", - "phpstan/phpstan": "^0.12" + "phpstan/phpstan": "^0.12", + "nette/code-checker": "^3.2" }, "replace": { "dg/dibi": "*" diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index f941aabc1..66a8457b9 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -29,6 +29,9 @@ class SqlsrvDriver implements Dibi\Driver { use Dibi\Strict; + // https://docs.microsoft.com/en-us/sql/t-sql/data-types/int-bigint-smallint-and-tinyint-transact-sql?view=sql-server-ver15 + private const SQLSERVER_MAX_INT = 2147483647; + /** @var resource */ private $connection; @@ -261,23 +264,30 @@ public function addParameter(QueryParameter $param) : void { } function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { - return new QueryParameter($value, \SQLSRV_SQLTYPE_VARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + $phpType = \SQLSRV_PHPTYPE_STRING($encoding ?: 'UTF-8'); + $sqlType = \SQLSRV_SQLTYPE_VARCHAR($length ?: 'max'); + return new QueryParameter($value, $sqlType, $phpType); } function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { - return new QueryParameter($value, \SQLSRV_SQLTYPE_NVARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + $phpType = \SQLSRV_PHPTYPE_STRING($encoding ?: 'UTF-8'); + $sqlType = \SQLSRV_SQLTYPE_NVARCHAR($length ?: 'max'); + return new QueryParameter($value, $sqlType, $phpType); } function bindIdentifier(?string $value): QueryParameter { - return new QueryParameter($value, \SQLSRV_SQLTYPE_UNIQUEIDENTIFIER, \SQLSRV_PHPTYPE_STRING('UTF-8')); + $phpType = \SQLSRV_PHPTYPE_STRING('UTF-8'); + return new QueryParameter($value, \SQLSRV_SQLTYPE_UNIQUEIDENTIFIER, $phpType); } function bindInt(?int $value): QueryParameter { - return new QueryParameter($value, \SQLSRV_SQLTYPE_INT, \SQLSRV_PHPTYPE_INT); + $sqlType = ($value == null || $value <= self::SQLSERVER_MAX_INT) ? \SQLSRV_SQLTYPE_INT : \SQLSRV_SQLTYPE_BIGINT; + return new QueryParameter($value, $sqlType, \SQLSRV_PHPTYPE_INT); } function bindNumeric(?float $value, string $precision, string $scale): QueryParameter { - return new QueryParameter($value, \SQLSRV_SQLTYPE_NUMERIC($precision, $scale), \SQLSRV_PHPTYPE_FLOAT); + $sqlType = \SQLSRV_SQLTYPE_NUMERIC($precision, $scale); + return new QueryParameter($value, $sqlType, \SQLSRV_PHPTYPE_FLOAT); } function bindDate(?\DateTimeInterface $value): QueryParameter { @@ -289,7 +299,8 @@ function bindDateTime(?\DateTimeInterface $value): QueryParameter { } function bindDateInterval(?\DateInterval $value): QueryParameter { - return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIMEOFFSET, \SQLSRV_PHPTYPE_STRING('UTF-8')); + $phpType = \SQLSRV_PHPTYPE_STRING('UTF-8'); + return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIMEOFFSET, $phpType); } /** diff --git a/tests/dibi/Sqlsrv.params.phpt b/tests/dibi/Sqlsrv.params.phpt index 5656b5920..4802feb8f 100644 --- a/tests/dibi/Sqlsrv.params.phpt +++ b/tests/dibi/Sqlsrv.params.phpt @@ -20,9 +20,11 @@ $tests = function ($conn) { Assert::equal('❤️‍🔥', $conn->fetchSingle('SELECT [name] FROM Customers WHERE [name] = %pq', $driver->bindText('❤️‍🔥'))); $param = $driver->bindText('testing', '20', 'UTF-8'); - Assert::equal(\SQLSRV_SQLTYPE_NVARCHAR('20'), $param->sqlType); + $expectedSqlType = \SQLSRV_SQLTYPE_NVARCHAR('20'); + $expectedPhpType = \SQLSRV_PHPTYPE_STRING('UTF-8'); + Assert::equal($expectedSqlType, $param->sqlType); Assert::equal('testing', $param->value); - Assert::equal(\SQLSRV_PHPTYPE_STRING('UTF-8'), $param->phpType); + Assert::equal($expectedPhpType, $param->phpType); Assert::equal('?????', $conn->query('SELECT %pq', $driver->bindAsciiText('❤️‍🔥'))->fetchSingle()); From 57af572e243be3199cd707c620fda816631dc297 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Mon, 28 Jun 2021 17:11:12 -0700 Subject: [PATCH 19/21] updating curl command --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 329c96866..18da63d00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,7 @@ install: - cmd /c start /wait AccessDatabaseEngine_X64.exe /passive # Install ODBC Driver for SQL Server x64 Version 17.7.2 - - IF %PHP%==1 curl curl -L -v https://go.microsoft.com/fwlink/?linkid=2156851 --output msodbcsql.msi + - IF %PHP%==1 curl --silent --location --output msodbcsql.msi https://go.microsoft.com/fwlink/?linkid=2156851 - cmd /c start /wait msiexec /qn /passive /i msodbcsql.msi # Install Nette Tester From 41fdfbd1dcd823e6e86487c0e775636a034c1624 Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Tue, 29 Jun 2021 16:36:39 -0700 Subject: [PATCH 20/21] Re-adding support for PdoDriver query parameter support. Updating Appveyor SqlServer runtime Updated sql server runtime to 2016 since that's the currently oldest supported version. https://docs.microsoft.com/en-us/sql/sql-server/end-of-support/sql-server-end-of-life-overview?view=sql-server-ver15 --- .gitignore | 1 + appveyor.yml | 3 +- readme.md | 10 +++++ src/Dibi/Drivers/PdoDriver.php | 75 +++++++++++++++++++++++++++++++++- tests/databases.appveyor.ini | 22 ++++++---- 5 files changed, 101 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index de4a392c3..ba0d2a307 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /vendor /composer.lock +/.vscode \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 18da63d00..ace08b6e6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,8 +6,9 @@ cache: clone_folder: c:\projects\dibi services: - - mssql2012sp1 +# - mssql2012sp1 # - mssql2014 + - mssql2016 - mysql init: diff --git a/readme.md b/readme.md index 997b3c415..edc764df1 100644 --- a/readme.md +++ b/readme.md @@ -176,6 +176,7 @@ In addition to the `?` wildcard char, we can also use modifiers: | %ex | SQL expression or array of expressions | %lmt | special - adds LIMIT to the query | %ofs | special - adds OFFSET to the query +| %pq | special - sends the parameterized query down to the underlying DB driver for binding Example: @@ -202,6 +203,15 @@ $result = $database->query('SELECT * FROM %n WHERE %n = ?', $table, $column, $va // SELECT * FROM `blog`.`users` WHERE `name` = 'Jim' ``` +The modifier `%pq` inserts a `?` into the query sent to the underlying database driver and allows the caller to bind the parameterized query values to the positional modifiers. + +Example: + +```php +$result = $database->query('SELECT * FROM users WHERE name = %pq', $database->getDriver()->bindText($name)); +// SELECT * FROM `users` WHERE `name` = ? +``` + Three special modifiers are available for LIKE: | modifier | description diff --git a/src/Dibi/Drivers/PdoDriver.php b/src/Dibi/Drivers/PdoDriver.php index 1c89b8938..da3013de4 100644 --- a/src/Dibi/Drivers/PdoDriver.php +++ b/src/Dibi/Drivers/PdoDriver.php @@ -29,7 +29,6 @@ class PdoDriver implements Dibi\Driver { use Dibi\Strict; - use NoParameterizedQueries; /** @var PDO|null Connection resource */ private $connection; @@ -43,6 +42,9 @@ class PdoDriver implements Dibi\Driver /** @var string */ private $serverVersion = ''; + /** @var array */ + private $paramValues = []; + /** @throws Dibi\NotSupportedException */ public function __construct(array $config) { @@ -94,7 +96,28 @@ public function disconnect(): void */ public function query(string $sql): ?Dibi\ResultDriver { - $res = $this->connection->query($sql); + if (count($this->paramValues) > 0) { + $res = $this->connection->prepare($sql); + if ($res) { + $count = count($this->paramValues); + for ($index = 0; $index < $count && $res; $index++) { + $success = $res->bindParam($index+1, $this->paramValues[$index]['var'], $this->paramValues[$index]['type']); + if (!$success) { + $res = false; + } + } + if ($res) { + $success = $res->execute(); + if (!$success) { + $res = false; + } + } + } + $this->paramValues = []; + } else { + $res = $this->connection->query($sql); + } + if ($res) { $this->affectedRows = $res->rowCount(); return $res->columnCount() ? $this->createResultDriver($res) : null; @@ -350,6 +373,54 @@ public function escapeLike(string $value, int $pos): string } } + public function addParameter(QueryParameter $param) : void { + // https://www.php.net/manual/en/sqlsrv.constants.php + $this->paramValues[] = [ + 'var' => $param->value, + 'type' => $param->sqlType + ]; + } + + function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_VARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_NVARCHAR($length ?? 'max'), \SQLSRV_PHPTYPE_STRING($encoding ?? 'UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindIdentifier(?string $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_UNIQUEIDENTIFIER, \SQLSRV_PHPTYPE_STRING('UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindInt(?int $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_INT, \SQLSRV_PHPTYPE_INT); + return new QueryParameter($value, PDO::PARAM_INT, null); + } + + function bindNumeric(?float $value, string $precision, string $scale): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_NUMERIC($precision, $scale), \SQLSRV_PHPTYPE_FLOAT); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindDate(?\DateTimeInterface $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATE, \SQLSRV_PHPTYPE_DATETIME); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindDateTime(?\DateTimeInterface $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIME2, \SQLSRV_PHPTYPE_DATETIME); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + + function bindDateInterval(?\DateInterval $value): QueryParameter { + // return new QueryParameter($value, \SQLSRV_SQLTYPE_DATETIMEOFFSET, \SQLSRV_PHPTYPE_STRING('UTF-8')); + return new QueryParameter($value, PDO::PARAM_STR, null); + } + /** * Injects LIMIT/OFFSET to the SQL query. */ diff --git a/tests/databases.appveyor.ini b/tests/databases.appveyor.ini index 0e8c92437..cd2c46066 100644 --- a/tests/databases.appveyor.ini +++ b/tests/databases.appveyor.ini @@ -50,13 +50,13 @@ system = odbc ;password = "Password12!" ;system = sqlsrv -[sqlsrv 2012] -driver = sqlsrv -host = "(local)\SQL2012SP1" -database = master -username = sa -password = "Password12!" -system = sqlsrv +; [sqlsrv 2012] +; driver = sqlsrv +; host = "(local)\SQL2012SP1" +; database = master +; username = sa +; password = "Password12!" +; system = sqlsrv ;[sqlsrv 2012-pdo] ;driver = pdo @@ -79,3 +79,11 @@ system = sqlsrv ;username = sa ;password = "Password12!" ;system = sqlsrv + +[sqlsrv 2016] +driver = sqlsrv +host = "(local)\SQL2016" +database = master +username = sa +password = "Password12!" +system = sqlsrv From 77adc8cf92c5177c63e73e8f474c6517c068605b Mon Sep 17 00:00:00 2001 From: Gabe Martin Date: Tue, 29 Jun 2021 16:50:33 -0700 Subject: [PATCH 21/21] Attempt to fix broken test related to SQL server drivers 'function like' constants --- src/Dibi/Drivers/SqlsrvDriver.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Dibi/Drivers/SqlsrvDriver.php b/src/Dibi/Drivers/SqlsrvDriver.php index 66a8457b9..214725b03 100644 --- a/src/Dibi/Drivers/SqlsrvDriver.php +++ b/src/Dibi/Drivers/SqlsrvDriver.php @@ -264,14 +264,18 @@ public function addParameter(QueryParameter $param) : void { } function bindAsciiText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { - $phpType = \SQLSRV_PHPTYPE_STRING($encoding ?: 'UTF-8'); - $sqlType = \SQLSRV_SQLTYPE_VARCHAR($length ?: 'max'); + $encoding = $encoding ?: 'UTF-8'; + $length = $length ?: 'max'; + $phpType = \SQLSRV_PHPTYPE_STRING($encoding); + $sqlType = \SQLSRV_SQLTYPE_VARCHAR($length); return new QueryParameter($value, $sqlType, $phpType); } function bindText(?string $value, ?string $length = null, ?string $encoding = null): QueryParameter { - $phpType = \SQLSRV_PHPTYPE_STRING($encoding ?: 'UTF-8'); - $sqlType = \SQLSRV_SQLTYPE_NVARCHAR($length ?: 'max'); + $encoding = $encoding ?: 'UTF-8'; + $length = $length ?: 'max'; + $phpType = \SQLSRV_PHPTYPE_STRING($encoding); + $sqlType = \SQLSRV_SQLTYPE_NVARCHAR($length); return new QueryParameter($value, $sqlType, $phpType); }