diff --git a/composer.json b/composer.json
index e5f63c3..a753655 100644
--- a/composer.json
+++ b/composer.json
@@ -30,17 +30,18 @@
}
},
"require": {
- "php": "~8.2.0 || ~8.3.0 || ~8.4.0",
- "php-db/phpdb": "^0.2.1"
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
+ "php-db/phpdb": "^0.4.1"
},
"require-dev": {
+ "ext-pdo_pgsql": "*",
+ "ext-pgsql": "*",
"laminas/laminas-coding-standard": "^3.0.1",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-phpunit": "^2.0",
- "phpunit/phpunit": "^11.5.15"
+ "phpunit/phpunit": "^11.5.42"
},
"suggest": {
- "ext-pdo": "*",
"ext-pdo_pgsql": "*",
"ext-pgsql": "*",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component"
@@ -53,13 +54,14 @@
"autoload-dev": {
"psr-4": {
"PhpDbTest\\Adapter\\Pgsql\\": "test/unit/",
+ "PhpDbTestAsset\\Pgsql\\": "test/asset/",
"PhpDbIntegrationTest\\Adapter\\Pgsql\\": "test/integration/"
}
},
"scripts": {
"check": [
"@cs-check",
- "@static-analysis",
+ "@sa",
"@test",
"@test-integration"
],
@@ -68,8 +70,9 @@
"test": "phpunit --colors=always --testsuite \"unit test\"",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"test-integration": "phpunit --colors=always --testsuite \"integration test\"",
- "static-analysis": "vendor/bin/phpstan analyse --memory-limit=256M",
+ "sa": "vendor/bin/phpstan analyse --memory-limit=256M",
"sa-generate-baseline": "vendor/bin/phpstan analyse --memory-limit=256M --generate-baseline",
+ "sa-verbose": "vendor/bin/phpstan analyse --memory-limit=256M -vv",
"upload-coverage": "coveralls -v"
}
}
diff --git a/composer.lock b/composer.lock
index 0413512..4461851 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,30 +4,30 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "93b90a40dd4fe8c39502da74c4585c56",
+ "content-hash": "5063e7391ca1bbb366715a6569a7af12",
"packages": [
{
"name": "brick/varexporter",
- "version": "0.5.0",
+ "version": "0.6.0",
"source": {
"type": "git",
"url": "https://github.com/brick/varexporter.git",
- "reference": "84b2a7a91f69aa5d079aec5a0a7256ebf2dceb6b"
+ "reference": "af98bfc2b702a312abbcaff37656dbe419cec5bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/varexporter/zipball/84b2a7a91f69aa5d079aec5a0a7256ebf2dceb6b",
- "reference": "84b2a7a91f69aa5d079aec5a0a7256ebf2dceb6b",
+ "url": "https://api.github.com/repos/brick/varexporter/zipball/af98bfc2b702a312abbcaff37656dbe419cec5bc",
+ "reference": "af98bfc2b702a312abbcaff37656dbe419cec5bc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^5.0",
- "php": "^7.4 || ^8.0"
+ "php": "^8.1"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^9.3",
- "psalm/phar": "5.21.1"
+ "phpunit/phpunit": "^10.5",
+ "vimeo/psalm": "6.8.4"
},
"type": "library",
"autoload": {
@@ -45,7 +45,7 @@
],
"support": {
"issues": "https://github.com/brick/varexporter/issues",
- "source": "https://github.com/brick/varexporter/tree/0.5.0"
+ "source": "https://github.com/brick/varexporter/tree/0.6.0"
},
"funding": [
{
@@ -53,26 +53,26 @@
"type": "github"
}
],
- "time": "2024-05-10T17:15:19+00:00"
+ "time": "2025-02-20T17:42:39+00:00"
},
{
"name": "laminas/laminas-servicemanager",
- "version": "4.4.0",
+ "version": "4.5.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
- "reference": "74da44d07e493b834347123242d0047976fb9932"
+ "reference": "a6996829c8ce55025cca1b57b1e8a8b165e3926c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/74da44d07e493b834347123242d0047976fb9932",
- "reference": "74da44d07e493b834347123242d0047976fb9932",
+ "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/a6996829c8ce55025cca1b57b1e8a8b165e3926c",
+ "reference": "a6996829c8ce55025cca1b57b1e8a8b165e3926c",
"shasum": ""
},
"require": {
- "brick/varexporter": "^0.3.8 || ^0.4.0 || ^0.5.0",
+ "brick/varexporter": "^0.3.8 || ^0.4.0 || ^0.5.0 || ^0.6.0",
"laminas/laminas-stdlib": "^3.19",
- "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"psr/container": "^1.1 || ^2.0"
},
"conflict": {
@@ -86,14 +86,14 @@
"composer/package-versions-deprecated": "^1.11.99.5",
"friendsofphp/proxy-manager-lts": "^1.0.18",
"laminas/laminas-cli": "^1.11",
- "laminas/laminas-coding-standard": "~3.0.1",
- "laminas/laminas-container-config-test": "^1.0",
+ "laminas/laminas-coding-standard": "~3.1.0",
+ "laminas/laminas-container-config-test": "^1.1",
"mikey179/vfsstream": "^1.6.12",
- "phpbench/phpbench": "^1.4.0",
- "phpunit/phpunit": "^10.5.44",
- "psalm/plugin-phpunit": "^0.19.2",
- "symfony/console": "^6.4.17 || ^7.0",
- "vimeo/psalm": "^6.2.0"
+ "phpbench/phpbench": "^1.4.1",
+ "phpunit/phpunit": "^10.5.58",
+ "psalm/plugin-phpunit": "^0.19.5",
+ "symfony/console": "^6.4.17 || ^7.3.4",
+ "vimeo/psalm": "^6.13.1"
},
"suggest": {
"friendsofphp/proxy-manager-lts": "To handle lazy initialization of services",
@@ -130,7 +130,7 @@
"chat": "https://laminas.dev/chat",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
- "source": "https://github.com/laminas/laminas-servicemanager/tree/4.4.0"
+ "source": "https://github.com/laminas/laminas-servicemanager/tree/4.5.0"
},
"funding": [
{
@@ -138,34 +138,34 @@
"type": "community_bridge"
}
],
- "time": "2025-02-04T06:13:50+00:00"
+ "time": "2025-10-14T09:41:04+00:00"
},
{
"name": "laminas/laminas-stdlib",
- "version": "3.20.0",
+ "version": "3.21.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
- "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4"
+ "reference": "b1c81514cfe158aadf724c42b34d3d0a8164c096"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/8974a1213be42c3e2f70b2c27b17f910291ab2f4",
- "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4",
+ "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/b1c81514cfe158aadf724c42b34d3d0a8164c096",
+ "reference": "b1c81514cfe158aadf724c42b34d3d0a8164c096",
"shasum": ""
},
"require": {
- "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
},
"conflict": {
"zendframework/zend-stdlib": "*"
},
"require-dev": {
- "laminas/laminas-coding-standard": "^3.0",
- "phpbench/phpbench": "^1.3.1",
- "phpunit/phpunit": "^10.5.38",
- "psalm/plugin-phpunit": "^0.19.0",
- "vimeo/psalm": "^5.26.1"
+ "laminas/laminas-coding-standard": "^3.1.0",
+ "phpbench/phpbench": "^1.4.1",
+ "phpunit/phpunit": "^11.5.42",
+ "psalm/plugin-phpunit": "^0.19.5",
+ "vimeo/psalm": "^6.13.1"
},
"type": "library",
"autoload": {
@@ -197,20 +197,20 @@
"type": "community_bridge"
}
],
- "time": "2024-10-29T13:46:07+00:00"
+ "time": "2025-10-11T18:13:12+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.6.1",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
- "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
@@ -253,28 +253,28 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
},
- "time": "2025-08-13T20:13:15+00:00"
+ "time": "2025-12-06T11:56:16+00:00"
},
{
"name": "php-db/phpdb",
- "version": "0.2.1",
+ "version": "0.4.x-dev",
"source": {
"type": "git",
"url": "https://github.com/php-db/phpdb.git",
- "reference": "d221b024cb3aea77992f41a962913918301dc92e"
+ "reference": "3cb7531b36bf37c42843bbe9dd05583d8d8f130e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-db/phpdb/zipball/d221b024cb3aea77992f41a962913918301dc92e",
- "reference": "d221b024cb3aea77992f41a962913918301dc92e",
+ "url": "https://api.github.com/repos/php-db/phpdb/zipball/3cb7531b36bf37c42843bbe9dd05583d8d8f130e",
+ "reference": "3cb7531b36bf37c42843bbe9dd05583d8d8f130e",
"shasum": ""
},
"require": {
- "laminas/laminas-servicemanager": "^4.0.0",
+ "laminas/laminas-servicemanager": "^3.0.0 || ^4.0.0",
"laminas/laminas-stdlib": "^3.20.0",
- "php": "~8.2.0 || ~8.3.0 || ~8.4.0"
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
},
"conflict": {
"laminas/laminas-db": "*",
@@ -283,6 +283,8 @@
"require-dev": {
"laminas/laminas-coding-standard": "^3.0.1",
"laminas/laminas-eventmanager": "^3.14.0",
+ "laminas/laminas-hydrator": "^4.6.0",
+ "phpbench/phpbench": "^1.4",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^11.5.15",
@@ -321,7 +323,7 @@
"issues": "https://github.com/php-db/phpdb/issues",
"source": "https://github.com/php-db/phpdb"
},
- "time": "2025-10-07T08:36:48+00:00"
+ "time": "2025-12-05T01:52:04+00:00"
},
{
"name": "psr/container",
@@ -380,29 +382,29 @@
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
- "version": "v1.1.2",
+ "version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/composer-installer.git",
- "reference": "e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1"
+ "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1",
- "reference": "e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1",
+ "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.2",
"php": ">=5.4",
- "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
+ "squizlabs/php_codesniffer": "^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "^2.2",
"ext-json": "*",
"ext-zip": "*",
"php-parallel-lint/php-parallel-lint": "^1.4.0",
- "phpcompatibility/php-compatibility": "^9.0",
+ "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev",
"yoast/phpunit-polyfills": "^1.0"
},
"type": "composer-plugin",
@@ -472,7 +474,7 @@
"type": "thanks_dev"
}
],
- "time": "2025-07-17T20:45:56+00:00"
+ "time": "2025-11-11T04:32:07+00:00"
},
{
"name": "laminas/laminas-coding-standard",
@@ -754,11 +756,11 @@
},
{
"name": "phpstan/phpstan",
- "version": "2.1.30",
+ "version": "2.1.33",
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a4a7f159927983dd4f7c8020ed227d80b7f39d7d",
- "reference": "a4a7f159927983dd4f7c8020ed227d80b7f39d7d",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f",
+ "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f",
"shasum": ""
},
"require": {
@@ -803,25 +805,25 @@
"type": "github"
}
],
- "time": "2025-10-02T16:07:52+00:00"
+ "time": "2025-12-05T10:24:31+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "2.0.7",
+ "version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "9a9b161baee88a5f5c58d816943cff354ff233dc"
+ "reference": "8d61a5854e7497d95bc85188e13537e99bd7aae7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/9a9b161baee88a5f5c58d816943cff354ff233dc",
- "reference": "9a9b161baee88a5f5c58d816943cff354ff233dc",
+ "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/8d61a5854e7497d95bc85188e13537e99bd7aae7",
+ "reference": "8d61a5854e7497d95bc85188e13537e99bd7aae7",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
- "phpstan/phpstan": "^2.1.18"
+ "phpstan/phpstan": "^2.1.32"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -854,9 +856,9 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
- "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.7"
+ "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.10"
},
- "time": "2025-07-13T11:31:46+00:00"
+ "time": "2025-12-06T11:15:39+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -1195,16 +1197,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.5.42",
+ "version": "11.5.46",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "1c6cb5dfe412af3d0dfd414cfd110e3b9cfdbc3c"
+ "reference": "75dfe79a2aa30085b7132bb84377c24062193f33"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1c6cb5dfe412af3d0dfd414cfd110e3b9cfdbc3c",
- "reference": "1c6cb5dfe412af3d0dfd414cfd110e3b9cfdbc3c",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/75dfe79a2aa30085b7132bb84377c24062193f33",
+ "reference": "75dfe79a2aa30085b7132bb84377c24062193f33",
"shasum": ""
},
"require": {
@@ -1276,7 +1278,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.42"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.46"
},
"funding": [
{
@@ -1300,7 +1302,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-28T12:09:13+00:00"
+ "time": "2025-12-06T08:01:15+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -2355,16 +2357,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.13.4",
+ "version": "3.13.5",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
- "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119"
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ad545ea9c1b7d270ce0fc9cbfb884161cd706119",
- "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
"shasum": ""
},
"require": {
@@ -2381,11 +2383,6 @@
"bin/phpcs"
],
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
- }
- },
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
@@ -2435,7 +2432,7 @@
"type": "thanks_dev"
}
],
- "time": "2025-09-05T05:47:09+00:00"
+ "time": "2025-11-04T16:30:35+00:00"
},
{
"name": "staabm/side-effects-detector",
@@ -2491,16 +2488,16 @@
},
{
"name": "theseer/tokenizer",
- "version": "1.2.3",
+ "version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
- "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
"shasum": ""
},
"require": {
@@ -2529,7 +2526,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
- "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
+ "source": "https://github.com/theseer/tokenizer/tree/1.3.1"
},
"funding": [
{
@@ -2537,7 +2534,7 @@
"type": "github"
}
],
- "time": "2024-03-03T12:36:25+00:00"
+ "time": "2025-11-17T20:03:58+00:00"
},
{
"name": "webimpress/coding-standard",
@@ -2601,11 +2598,14 @@
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
- "php": "~8.2.0 || ~8.3.0 || ~8.4.0"
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
+ },
+ "platform-dev": {
+ "ext-pdo_pgsql": "*",
+ "ext-pgsql": "*"
},
- "platform-dev": {},
"platform-overrides": {
"php": "8.2.99"
},
- "plugin-api-version": "2.6.0"
+ "plugin-api-version": "2.9.0"
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 97ae618..295633b 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -29,10 +29,10 @@
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Platform/Postgresql.php b/src/AdapterPlatform.php
similarity index 84%
rename from src/Platform/Postgresql.php
rename to src/AdapterPlatform.php
index 55fac46..9ba5f64 100644
--- a/src/Platform/Postgresql.php
+++ b/src/AdapterPlatform.php
@@ -2,46 +2,38 @@
declare(strict_types=1);
-namespace PhpDb\Adapter\Pgsql\Platform;
+namespace PhpDb\Adapter\Pgsql;
use Override;
use PDO;
use PgSql\Connection as PgSqlConnection;
-use PhpDb\Adapter\AdapterInterface;
use PhpDb\Adapter\Driver\DriverInterface;
use PhpDb\Adapter\Driver\PdoDriverInterface;
-use PhpDb\Adapter\Driver\Pgsql\Pgsql;
-use PhpDb\Adapter\Exception;
-use PhpDb\Adapter\Pgsql\Driver\Pdo\Pdo as PdoDriver;
use PhpDb\Adapter\Platform\AbstractPlatform;
use PhpDb\Sql\Platform\Platform as SqlPlatformDecorator;
use PhpDb\Sql\Platform\PlatformDecoratorInterface;
-use function get_resource_type;
use function implode;
-use function in_array;
use function is_resource;
use function pg_escape_string;
use function str_replace;
-class Postgresql extends AbstractPlatform
+class AdapterPlatform extends AbstractPlatform
{
public final const PLATFORM_NAME = 'PostgreSQL';
+
/**
* Overrides value from AbstractPlatform to use proper escaping for Postgres
- *
- * @var string
*/
- protected $quoteIdentifierTo = '""';
+ protected string $quoteIdentifierTo = '""';
/** @var string[] */
- private $knownPgsqlResources = [
+ private array $knownPgsqlResources = [
'pgsql link',
'pgsql link persistent',
];
public function __construct(
- //private readonly PDO|Pgsql|PdoDriver $driver
private readonly DriverInterface|PdoDriverInterface|PDO $driver,
) {
}
@@ -79,7 +71,6 @@ public function quoteValue($value): string
* {@inheritDoc}
*
* @param scalar $value
- * @return string
*/
#[Override]
public function quoteTrustedValue($value): string
diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php
index 19aa7af..be98388 100644
--- a/src/ConfigProvider.php
+++ b/src/ConfigProvider.php
@@ -6,28 +6,88 @@
use Laminas\ServiceManager\Factory\InvokableFactory;
use PhpDb\Adapter\AdapterInterface;
+use PhpDb\Adapter\Driver\ConnectionInterface;
use PhpDb\Adapter\Driver\DriverInterface;
+use PhpDb\Adapter\Driver\PdoConnectionInterface;
+use PhpDb\Adapter\Driver\PdoDriverInterface;
use PhpDb\Adapter\Platform\PlatformInterface;
+use PhpDb\Adapter\Pgsql\Pdo\Connection as PdoConnection;
+use PhpDb\Adapter\Pgsql\Pdo\Driver as PdoDriver;
+use PhpDb\Adapter\Profiler\Profiler;
+use PhpDb\Adapter\Profiler\ProfilerInterface;
+use PhpDb\Container\AdapterAbstractServiceFactory;
+use PhpDb\Metadata\MetadataInterface;
+use PhpDb\ResultSet\ResultSetInterface;
-readonly class ConfigProvider
+final readonly class ConfigProvider
{
public function __invoke(): array
{
return [
- 'dependencies' => $this->getDependencies(),
+ 'dependencies' => $this->getDependencies(),
+ AdapterInterface::class => $this->getAdapters(),
+ ];
+ }
+
+ public function getAdapters(): array
+ {
+ return [
+ 'adapters' => [
+ AdapterInterface::class => [
+ 'driver' => Driver::class,
+ 'connection' => [
+ 'host' => 'localhost',
+ 'port' => 5432,
+ 'username' => 'your_username',
+ 'password' => 'your_password',
+ 'database' => 'your_database',
+ ],
+ ],
+ ],
];
}
public function getDependencies(): array
{
return [
+ 'abstract_factories' => [
+ Container\AdapterAbstractServiceFactory::class,
+ ],
'aliases' => [
- PlatformInterface::class => Platform\Postgresql::class,
+ DriverInterface::class => Driver::class,
+ 'pgsql' => Driver::class,
+ 'PgSQL' => Driver::class,
+ 'Postgresql' => Driver::class,
+ 'PostgreSQL' => Driver::class,
+ PdoDriverInterface::class => PdoDriver::class,
+ 'pdo_pgsql' => PdoDriver::class,
+ 'PDO_pgsql' => PdoDriver::class,
+ 'PDO_PgSQL' => PdoDriver::class,
+ 'Pdo_PgSQL' => PdoDriver::class,
+ 'PDO_postgresql' => PdoDriver::class,
+ 'pdo_postgresql' => PdoDriver::class,
+ 'PDO_Postgresql' => PdoDriver::class,
+ 'Pdo_Postgresql' => PdoDriver::class,
+ 'PDO_PostgreSQL' => PdoDriver::class,
+ 'pdo_PostgreSQL' => PdoDriver::class,
+ ConnectionInterface::class => Connection::class,
+ MetadataInterface::class => Metadata\Source::class,
+ PdoConnectionInterface::class => PdoConnection::class,
+ PlatformInterface::class => AdapterPlatform::class,
],
'factories' => [
- AdapterInterface::class => Container\AdapterServiceFactory::class,
- DriverInterface::class => Container\PdoDriverInterfaceFactory::class,
- Platform\Postgresql::class => InvokableFactory::class,
+ //AdapterInterface::class => Container\AdapterInterfaceFactory::class,
+ AdapterPlatform::class => Container\PlatformInterfaceFactory::class,
+ Connection::class => Container\ConnectionInterfaceFactory::class,
+ Metadata\Source::class => Container\MetadataInterfaceFactory::class,
+ Statement::class => Container\StatementInterfaceFactory::class,
+ Driver::class => Container\DriverInterfaceFactory::class,
+ PdoConnection::class => Container\PdoConnectionInterfaceFactory::class,
+ PdoDriver::class => Container\PdoDriverInterfaceFactory::class,
+ // Provide the following if you wish to override the Profiler implementation
+ //ProfilerInterface::class => YourCustomProfilerFactory::class,
+ // Provide the following if you wish to override the ResultSet implementation
+ //ResultSetInterface::class => YourCustomResultSetFactory::class,
],
];
}
diff --git a/src/Driver/Pgsql/Connection.php b/src/Connection.php
similarity index 77%
rename from src/Driver/Pgsql/Connection.php
rename to src/Connection.php
index 03aba23..b058bc4 100644
--- a/src/Driver/Pgsql/Connection.php
+++ b/src/Connection.php
@@ -2,8 +2,9 @@
declare(strict_types=1);
-namespace PhpDb\Adapter\Pgsql\Driver\Pgsql;
+namespace PhpDb\Adapter\Pgsql;
+use Override;
use PgSql\Connection as PgSqlConnection;
use PhpDb\Adapter\Driver\AbstractConnection;
use PhpDb\Adapter\Driver\ConnectionInterface;
@@ -16,7 +17,7 @@
use function array_filter;
use function http_build_query;
use function is_array;
-use function is_resource;
+use function pg_close;
use function pg_connect;
use function pg_fetch_result;
use function pg_last_error;
@@ -26,48 +27,53 @@
use function set_error_handler;
use function sprintf;
use function str_replace;
+use function strtolower;
use function urldecode;
use const PGSQL_CONNECT_FORCE_NEW;
class Connection extends AbstractConnection implements DriverAwareInterface
{
- /** @var Pgsql */
- protected $driver;
+ protected Driver $driver;
+
+ /** @var PgSqlConnection|null */
+ protected $resource;
/** @var null|int PostgreSQL connection type */
protected ?int $type = null;
- public function __construct(PgSqlConnection|array|null $connectionInfo = null)
+ public function __construct(PgSqlConnection|array $connectionInfo)
{
if (is_array($connectionInfo)) {
$this->setConnectionParameters($connectionInfo);
- } elseif ($connectionInfo instanceof PgSqlConnection || is_resource($connectionInfo)) {
+ } else {
$this->setResource($connectionInfo);
}
}
- public function setResource(PgSqlConnection $resource): ConnectionInterface
- {
+ public function setResource(
+ PgSqlConnection $resource
+ ): ConnectionInterface&DriverAwareInterface {
$this->resource = $resource;
return $this;
}
- /**
- * old param type hint Pgsql $driver
- */
- public function setDriver(DriverInterface $driver): DriverAwareInterface
+ #[Override]
+ public function getResource(): ?PgSqlConnection
{
+ return $this->resource;
+ }
+
+ public function setDriver(
+ DriverInterface $driver
+ ): ConnectionInterface&DriverAwareInterface {
$this->driver = $driver;
return $this;
}
- /**
- * @return $this Provides a fluent interface
- */
- public function setType(?int $type): static
+ public function setType(?int $type): ConnectionInterface&DriverAwareInterface
{
$invalidConectionType = $type !== PGSQL_CONNECT_FORCE_NEW;
if ($invalidConectionType) {
@@ -80,12 +86,7 @@ public function setType(?int $type): static
return $this;
}
- /**
- * {@inheritDoc}
- *
- * @return null|string
- */
- public function getCurrentSchema(): bool|string
+ public function getCurrentSchema(): string|false
{
if (! $this->isConnected()) {
$this->connect();
@@ -157,7 +158,6 @@ public function isConnected(): bool
*/
public function disconnect(): static
{
- // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFallbackGlobalName
pg_close($this->resource);
return $this;
@@ -269,8 +269,32 @@ public function getLastGeneratedValue($name = null): bool|int|string|null
*/
private function getConnectionString(): string
{
- $connectionParameters = array_filter((new PgsqlConfig())($this->connectionParameters));
+ $parameters = $this->connectionParameters;
+ $conn = [];
+ foreach ($parameters as $name => $value) {
+ $name = match (strtolower($name)) {
+ 'host', 'hostname' => 'host',
+ 'user', 'username' => 'user',
+ 'password', 'passwd', 'pw' => 'password',
+ 'database', 'dbname', 'db', 'schema' => 'dbname',
+ 'port' => 'port',
+ 'socket' => 'socket',
+ default => throw new Exception\InvalidArgumentException(
+ 'Connection parameter "' . $name . '" is not valid for Pgsql adapter'
+ ),
+ };
+ if ($name === 'port' && $value !== null) {
+ $value = (int) $value;
+ }
+ $conn[$name] = $value;
+ }
- return urldecode(http_build_query($connectionParameters, '', ' '));
+ return urldecode(
+ http_build_query(
+ array_filter($conn),
+ '',
+ ' '
+ )
+ );
}
}
diff --git a/src/Container/AdapterAbstractServiceFactory.php b/src/Container/AdapterAbstractServiceFactory.php
new file mode 100644
index 0000000..f8f68b2
--- /dev/null
+++ b/src/Container/AdapterAbstractServiceFactory.php
@@ -0,0 +1,141 @@
+getConfig($container);
+ if ($config === []) {
+ return false;
+ }
+
+ return isset($config[$requestedName])
+ && is_array($config[$requestedName])
+ && ! empty($config[$requestedName]);
+ }
+
+ /**
+ * Create a DB adapter
+ *
+ * @param string $requestedName
+ */
+ public function __invoke(
+ ContainerInterface|ServiceManager $container,
+ $requestedName,
+ ?array $options = null
+ ): AdapterInterface&Adapter {
+ /** @var string|null $driverClass */
+ $driverClass = $this->config[$requestedName]['driver'] ?? null;
+ if ($driverClass === null) {
+ throw new ServiceNotCreatedException(
+ sprintf('Cannot create adapter "%s"; no driver configured', $requestedName)
+ );
+ }
+
+ /** @var DriverInterface|PdoDriverInterface $driver */
+ $driver = $container->build($driverClass, $this->config[$requestedName]);
+ /** @var PlatformInterface&Pgsql\AdapterPlatform $platform */
+ $platform = $container->build(PlatformInterface::class, ['driver' => $driver]);
+ /** @var ResultSetInterface|null $resultSet */
+ $resultSet = $container->has(ResultSetInterface::class)
+ ? $container->build(ResultSetInterface::class)
+ : null;
+ /** @var ProfilerInterface|null $profiler */
+ $profiler = $container->has(ProfilerInterface::class)
+ ? $container->build(ProfilerInterface::class)
+ : null;
+
+ return match(true) {
+ $resultSet !== null && $profiler !== null => new Adapter(
+ driver:$driver,
+ platform: $platform,
+ queryResultSetPrototype: $resultSet,
+ profiler: $profiler,
+ ),
+ $resultSet !== null => new Adapter(
+ driver:$driver,
+ platform: $platform,
+ queryResultSetPrototype: $resultSet,
+ ),
+ $profiler !== null => new Adapter(
+ driver:$driver,
+ platform: $platform,
+ profiler: $profiler,
+ ),
+ default => new Adapter(
+ driver:$driver,
+ platform: $platform,
+ ),
+ };
+ }
+
+ /**
+ * Get db configuration, if any
+ * todo: refactor to use PhpDb\ConfigProvider::ADAPTERS_CONFIG_KEY instead of hardcoding 'adapters'
+ */
+ protected function getConfig(ContainerInterface $container): array
+ {
+ if ($this->config !== null) {
+ return $this->config;
+ }
+
+ if (! $container->has('config')) {
+ $this->config = [];
+ return $this->config;
+ }
+
+ $config = $container->get('config');
+ if (
+ ! isset($config[AdapterInterface::class])
+ || ! is_array($config[AdapterInterface::class])
+ ) {
+ $this->config = [];
+ return $this->config;
+ }
+
+ $config = $config[AdapterInterface::class];
+ if (
+ ! isset($config['adapters'])
+ || ! is_array($config['adapters'])
+ ) {
+ $this->config = [];
+ return $this->config;
+ }
+
+ $this->config = $config['adapters'];
+ return $this->config;
+ }
+}
diff --git a/src/Container/AdapterInterfaceFactory.php b/src/Container/AdapterInterfaceFactory.php
index 602df73..1b3df2e 100644
--- a/src/Container/AdapterInterfaceFactory.php
+++ b/src/Container/AdapterInterfaceFactory.php
@@ -12,7 +12,6 @@
use PhpDb\Adapter\Exception\RuntimeException;
use PhpDb\Adapter\Platform\PlatformInterface;
use PhpDb\Adapter\Profiler\ProfilerInterface;
-use PhpDb\Container\AdapterManager;
use PhpDb\ResultSet\ResultSetInterface;
use Psr\Container\ContainerInterface;
@@ -20,25 +19,76 @@
class AdapterInterfaceFactory
{
- /**
- * Create db adapter service
- *
- * @param array|null $options
- * @throws ContainerExceptionInterface
- * @throws NotFoundExceptionInterface
- */
- public function __invoke(ContainerInterface $container): AdapterInterface {
- $resultSetPrototype = $container->has(ResultSetInterface::class)
- ? $container->get(ResultSetInterface::class)
+ public function __invoke(
+ ContainerInterface $container,
+ string $requestedName,
+ ): AdapterInterface {
+ if (! $container->has('config')) {
+ throw new ServiceNotFoundException(
+ sprintf(
+ 'Could not find service "config" in container %s',
+ $container::class
+ )
+ );
+ }
+
+ /** @var array $config */
+ $config = $container->get('config');
+
+ /** @var array $dbConfig */
+ $dbConfig = $config[AdapterInterface::class][$requestedName] ?? $config[AdapterInterface::class] ?? [];
+
+ if (! isset($dbConfig['driver'])) {
+ throw new RuntimeException(
+ 'Database configuration must contain a "driver" key'
+ );
+ }
+
+ /** @var string $driver */
+ $driver = $dbConfig['driver'];
+ if (! $container->has($driver)) {
+ throw new ServiceNotFoundException(
+ sprintf(
+ 'Could not find database driver service "%s" in container %s',
+ $driver,
+ $container::class
+ )
+ );
+ }
+ /** @var DriverInterface|PdoDriverInterface $driverInstance */
+ $driverInstance = $container->get($driver);
+
+ if (! $container->has(PlatformInterface::class)) {
+ throw new ServiceNotFoundException(
+ sprintf(
+ 'Could not find service "%s" in container %s',
+ PlatformInterface::class,
+ $container::class
+ )
+ );
+ }
+
+ /** @var PlatformInterface $adapterPlatform */
+ $adapterPlatform = $container->get(PlatformInterface::class);
+
+ /** @var ProfilerInterface|null $profilerInstanceOrNull */
+ $profilerInstanceOrNull = $container->has(ProfilerInterface::class)
+ ? $container->get(ProfilerInterface::class)
: null;
- $profiler = $container->get(ProfilerInterface::class);
+ if (! $container->has(ResultSetInterface::class)) {
+ return new $requestedName(
+ driver: $driverInstance,
+ platform: $adapterPlatform,
+ profiler: $profilerInstanceOrNull
+ );
+ }
- return new Adapter(
- $container->get(DriverInterface::class),
- $container->get(Platform\Postgresql::class),
- $resultSetPrototype,
- $profiler
+ return new $requestedName(
+ driver: $driverInstance,
+ platform: $adapterPlatform,
+ queryResultSetPrototype: $container->get(ResultSetInterface::class),
+ profiler: $profilerInstanceOrNull
);
}
}
diff --git a/src/Container/ConnectionInterfaceFactory.php b/src/Container/ConnectionInterfaceFactory.php
new file mode 100644
index 0000000..6b6e478
--- /dev/null
+++ b/src/Container/ConnectionInterfaceFactory.php
@@ -0,0 +1,31 @@
+get('config')[AdapterInterface::class]['adapters'][$requestedName]['connection']
+ ?? null;
+ if ($connectionInfo === null || ! is_array($connectionInfo) || $connectionInfo === []) {
+ throw new InvalidConnectionParametersException(
+ 'Connection configuration must be an array of parameters',
+ $connectionInfo
+ );
+ }
+ return new Connection($connectionInfo);
+ }
+}
diff --git a/src/Container/ConnectionInterfaceFactoryFactory.php b/src/Container/ConnectionInterfaceFactoryFactory.php
deleted file mode 100644
index 16b120f..0000000
--- a/src/Container/ConnectionInterfaceFactoryFactory.php
+++ /dev/null
@@ -1,10 +0,0 @@
-get('config')[AdapterInterface::class]['adapters'][$requestedName]['connection']
+ ?? [];
+ $connection = $container->build(Pgsql\Connection::class, ['connection' => $connectionParameters]);
+ return new Pgsql\Driver(
+ connection:$connection,
+ statementPrototype: $container->build(Pgsql\Statement::class, ['options' => $options['options'] ?? []]),
+ resultPrototype: new Pgsql\Result(),
+ );
+ }
+}
diff --git a/src/Container/DriverInterfaceFactoryFactory.php b/src/Container/DriverInterfaceFactoryFactory.php
deleted file mode 100644
index 72da1fa..0000000
--- a/src/Container/DriverInterfaceFactoryFactory.php
+++ /dev/null
@@ -1,10 +0,0 @@
-profiler = $profiler;
if ($this->connection instanceof ProfilerAwareInterface) {
$this->connection->setProfiler($profiler);
@@ -77,7 +76,7 @@ public function checkEnvironment(): bool
{
if (! extension_loaded('pgsql')) {
throw new Exception\RuntimeException(
- 'The PostgreSQL (pgsql) extension is required for this adapter but the extension is not loaded'
+ 'The PostgreSQL (pgsql) extension is required for this Driver but the extension is not loaded'
);
}
return true;
@@ -115,7 +114,7 @@ public function createStatement($sqlOrResource = null): StatementInterface&State
/**
* Create result
*
- * @param resource|PgSqlResult|PgSqlConnection $resource
+ * @param PgSqlResult $resource
*/
#[Override]
public function createResult($resource): ResultInterface&Result
diff --git a/src/Driver/DatabasePlatformNameTrait.php b/src/Driver/DatabasePlatformNameTrait.php
deleted file mode 100644
index a940404..0000000
--- a/src/Driver/DatabasePlatformNameTrait.php
+++ /dev/null
@@ -1,20 +0,0 @@
- $value) {
- $name = match (strtolower($name)) {
- 'host', 'hostname' => 'host',
- 'user', 'username' => 'user',
- 'password', 'passwd', 'pw' => 'password',
- 'database', 'dbname', 'db', 'schema' => 'dbname',
- 'port' => 'port',
- 'socket' => 'socket',
- default => throw new InvalidArgumentException(
- 'Unknown connection parameter "' . $name . '"'
- ),
- };
- $connectionParameters[$name] = $value;
- }
-
- $connectionFilters = [
- 'host' => [
- 'filter' => FILTER_SANITIZE_URL,
- 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_EMPTY_STRING_NULL,
- ],
- 'user' => [
- 'filter' => FILTER_SANITIZE_ENCODED,
- 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_EMPTY_STRING_NULL,
- ],
- 'password' => [
- 'filter' => FILTER_SANITIZE_ENCODED,
- 'flags' => FILTER_FLAG_EMPTY_STRING_NULL,
- ],
- 'database' => [
- 'filter' => FILTER_SANITIZE_ENCODED,
- 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_EMPTY_STRING_NULL,
- ],
- 'socket' => [
- 'filter' => FILTER_SANITIZE_ENCODED,
- 'flags' => FILTER_FLAG_EMPTY_STRING_NULL,
- ],
- 'port' => [
- 'filter' => FILTER_VALIDATE_INT,
- 'flags' => FILTER_NULL_ON_FAILURE,
- ],
- ];
-
- return filter_var_array($connectionParameters, $connectionFilters);
- }
-}
diff --git a/src/Driver/Pgsql/Result.php b/src/Driver/Pgsql/Result.php
deleted file mode 100644
index 92831c6..0000000
--- a/src/Driver/Pgsql/Result.php
+++ /dev/null
@@ -1,174 +0,0 @@
-resource = $resource;
- $this->count = pg_num_rows($this->resource);
- $this->generatedValue = $generatedValue;
- }
-
- /**
- * Current
- *
- * @return array|bool|mixed
- */
- #[ReturnTypeWillChange]
- public function current()
- {
- if ($this->count === 0) {
- return false;
- }
- return pg_fetch_assoc($this->resource, $this->position);
- }
-
- /**
- * Next
- *
- * @return void
- */
- #[ReturnTypeWillChange]
- public function next()
- {
- $this->position++;
- }
-
- /**
- * Key
- *
- * @return int|mixed
- */
- #[ReturnTypeWillChange]
- public function key()
- {
- return $this->position;
- }
-
- /**
- * Valid
- *
- * @return bool
- */
- #[ReturnTypeWillChange]
- public function valid()
- {
- return $this->position < $this->count;
- }
-
- /**
- * Rewind
- *
- * @return void
- */
- #[ReturnTypeWillChange]
- public function rewind()
- {
- $this->position = 0;
- }
-
- /** todo: track this */
- public function buffer(): void
- {
- }
-
- /**
- * Is buffered
- */
- public function isBuffered(): ?bool
- {
- return false;
- }
-
- public function isQueryResult(): bool
- {
- return pg_num_fields($this->resource) > 0;
- }
-
- /**
- * Get affected rows
- */
- public function getAffectedRows(): int
- {
- return pg_affected_rows($this->resource);
- }
-
- /**
- * Get generated value
- *
- * @return mixed|null
- */
- public function getGeneratedValue()
- {
- return $this->generatedValue;
- }
-
- /**
- * Get resource
- */
- public function getResource()
- {
- // TODO: Implement getResource() method.
- }
-
- /**
- * Count
- *
- * @return int The custom count as an integer.
- */
- #[ReturnTypeWillChange]
- public function count()
- {
- return $this->count;
- }
-
- /**
- * Get field count
- */
- public function getFieldCount(): int
- {
- return pg_num_fields($this->resource);
- }
-}
diff --git a/src/Exception/ContainerException.php b/src/Exception/ContainerException.php
new file mode 100644
index 0000000..639e953
--- /dev/null
+++ b/src/Exception/ContainerException.php
@@ -0,0 +1,25 @@
+data['schemas'])) {
return;
diff --git a/src/Driver/Pdo/Connection.php b/src/Pdo/Connection.php
similarity index 97%
rename from src/Driver/Pdo/Connection.php
rename to src/Pdo/Connection.php
index 3f5de24..e8597e0 100644
--- a/src/Driver/Pdo/Connection.php
+++ b/src/Pdo/Connection.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace PhpDb\Adapter\Pgsql\Driver\Pdo;
+namespace PhpDb\Adapter\Pgsql\Pdo;
use Override;
use PDO;
@@ -26,7 +26,7 @@ class Connection extends AbstractPdoConnection
* {@inheritDoc}
*/
#[Override]
- public function getCurrentSchema(): string|bool
+ public function getCurrentSchema(): string|false
{
if (! $this->isConnected()) {
$this->connect();
diff --git a/src/Driver/Pdo/Pdo.php b/src/Pdo/Driver.php
similarity index 81%
rename from src/Driver/Pdo/Pdo.php
rename to src/Pdo/Driver.php
index 1aee71d..48f21a2 100644
--- a/src/Driver/Pdo/Pdo.php
+++ b/src/Pdo/Driver.php
@@ -2,16 +2,16 @@
declare(strict_types=1);
-namespace PhpDb\Adapter\Pgsql\Driver\Pdo;
+namespace PhpDb\Adapter\Pgsql\Pdo;
use Override;
use PDOStatement;
use PhpDb\Adapter\Driver\Pdo\AbstractPdo;
use PhpDb\Adapter\Driver\Pdo\Result;
use PhpDb\Adapter\Driver\ResultInterface;
-use PhpDb\Adapter\Pgsql\Driver\DatabasePlatformNameTrait;
+use PhpDb\Adapter\Pgsql\DatabasePlatformNameTrait;
-class Pdo extends AbstractPdo
+class Driver extends AbstractPdo
{
use DatabasePlatformNameTrait;
diff --git a/src/Result.php b/src/Result.php
new file mode 100644
index 0000000..9f71e89
--- /dev/null
+++ b/src/Result.php
@@ -0,0 +1,116 @@
+resource = $resource;
+ $this->count = pg_num_rows($this->resource);
+ $this->generatedValue = $generatedValue;
+ }
+
+ #[Override]
+ public function current(): array|false
+ {
+ if ($this->count === 0) {
+ return false;
+ }
+ return pg_fetch_assoc($this->resource, $this->position);
+ }
+
+ #[Override]
+ public function next(): void
+ {
+ $this->position++;
+ }
+
+ #[Override]
+ public function key(): int
+ {
+ return $this->position;
+ }
+
+ #[Override]
+ public function valid(): bool
+ {
+ return $this->position < $this->count;
+ }
+
+ #[Override]
+ public function rewind(): void
+ {
+ $this->position = 0;
+ }
+
+ #[Override]
+ public function buffer(): void
+ {
+ }
+
+ #[Override]
+ public function isBuffered(): false
+ {
+ return false;
+ }
+
+ #[Override]
+ public function isQueryResult(): bool
+ {
+ return pg_num_fields($this->resource) > 0;
+ }
+
+ #[Override]
+ public function getAffectedRows(): int
+ {
+ return pg_affected_rows($this->resource);
+ }
+
+ #[Override]
+ public function getGeneratedValue(): mixed
+ {
+ return $this->generatedValue;
+ }
+
+ /**
+ * Get resource
+ */
+ public function getResource(): PgSqlResult
+ {
+ return $this->resource;
+ }
+
+ #[Override]
+ public function count(): int
+ {
+ return $this->count;
+ }
+
+ #[Override]
+ public function getFieldCount(): int
+ {
+ return pg_num_fields($this->resource);
+ }
+}
diff --git a/src/Driver/Pgsql/Statement.php b/src/Statement.php
similarity index 51%
rename from src/Driver/Pgsql/Statement.php
rename to src/Statement.php
index fcb26f1..8ea3752 100644
--- a/src/Driver/Pgsql/Statement.php
+++ b/src/Statement.php
@@ -2,151 +2,123 @@
declare(strict_types=1);
-namespace PhpDb\Adapter\Pgsql\Driver\Pgsql;
+namespace PhpDb\Adapter\Pgsql;
+use Override;
+use PgSql\Connection as PgSqlConnection;
+use PgSql\Result as PgSqlResult;
+use PhpDb\Adapter\Driver\DriverAwareInterface;
+use PhpDb\Adapter\Driver\DriverInterface;
use PhpDb\Adapter\Driver\ResultInterface;
use PhpDb\Adapter\Driver\StatementInterface;
use PhpDb\Adapter\Exception;
use PhpDb\Adapter\ParameterContainer;
-use PhpDb\Adapter\Pgsql\Connection as PgSqlConnection;
-use PhpDb\Adapter\Profiler;
+use PhpDb\Adapter\Profiler\ProfilerAwareInterface;
+use PhpDb\Adapter\Profiler\ProfilerInterface;
-use function get_resource_type;
use function is_array;
-use function is_resource;
use function pg_execute;
use function pg_last_error;
use function pg_prepare;
use function preg_replace_callback;
-use function sprintf;
-class Statement implements StatementInterface, Profiler\ProfilerAwareInterface
+class Statement implements
+ StatementInterface,
+ DriverAwareInterface,
+ ProfilerAwareInterface
{
+ protected bool $bufferResults = false;
+
protected static int $statementIndex = 0;
- protected string $statementName = '';
+ protected string $statementName = 'statement';
- protected Pgsql $driver;
+ protected Driver $driver;
- protected Profiler\ProfilerInterface $profiler;
+ protected ProfilerInterface $profiler;
- /** @var resource */
- protected $pgsql;
+ protected PgSqlConnection $pgsql;
- /** @var resource */
- protected $resource;
+ protected PgSqlResult|false $resource;
protected string $sql;
- protected ParameterContainer $parameterContainer;
+ public function __construct(
+ protected ParameterContainer $parameterContainer = new ParameterContainer(),
+ array|bool $options = false
+ ) {
+ if (is_array($options)) {
+ $this->bufferResults = $options['buffer_results'] ?? false;
+ } else {
+ $this->bufferResults = $options;
+ }
+ }
- /**
- * @return $this Provides a fluent interface
- */
- public function setDriver(Pgsql $driver): static
- {
+ #[Override]
+ public function setDriver(
+ DriverInterface $driver
+ ): StatementInterface&DriverAwareInterface&ProfilerAwareInterface {
$this->driver = $driver;
return $this;
}
- /**
- * @return $this Provides a fluent interface
- */
- public function setProfiler(Profiler\ProfilerInterface $profiler): static
- {
+ #[Override]
+ public function setProfiler(
+ ProfilerInterface $profiler
+ ): StatementInterface&DriverAwareInterface&ProfilerAwareInterface {
$this->profiler = $profiler;
return $this;
}
- public function getProfiler(): ?Profiler\ProfilerInterface
+ public function getProfiler(): (StatementInterface&ProfilerInterface)|null
{
return $this->profiler;
}
- /**
- * Initialize
- *
- * @param resource $pgsql
- * @throws Exception\RuntimeException For invalid or missing postgresql connection.
- */
- public function initialize($pgsql): void
+ public function initialize(PgSqlConnection $pgsql): void
{
- if (
- ! $pgsql instanceof PgSqlConnection
- && (
- ! is_resource($pgsql)
- || 'pgsql link' !== get_resource_type($pgsql)
- )
- ) {
- throw new Exception\RuntimeException(sprintf(
- '%s: Invalid or missing postgresql connection; received "%s"',
- __METHOD__,
- get_resource_type($pgsql)
- ));
- }
-
$this->pgsql = $pgsql;
}
- /**
- * Get resource
- *
- * @todo Implement this method
- * phpcs:ignore Squiz.Commenting.FunctionComment.InvalidNoReturn
- * @return resource
- */
- public function getResource()
+ #[Override]
+ public function getResource(): PgSqlResult|false
{
return $this->resource;
}
- /**
- * Set sql
- *
- * @param string $sql
- * @return $this Provides a fluent interface
- */
- public function setSql($sql): static
- {
+ #[Override]
+ public function setSql(
+ ?string $sql
+ ): StatementInterface&DriverAwareInterface&ProfilerAwareInterface {
$this->sql = $sql;
return $this;
}
- /**
- * Get sql
- */
+ #[Override]
public function getSql(): ?string
{
return $this->sql;
}
- /**
- * Set parameter container
- *
- * @return $this Provides a fluent interface
- */
- public function setParameterContainer(ParameterContainer $parameterContainer): static
- {
+ #[Override]
+ public function setParameterContainer(
+ ParameterContainer $parameterContainer
+ ): StatementInterface&DriverAwareInterface&ProfilerAwareInterface {
$this->parameterContainer = $parameterContainer;
return $this;
}
- /**
- * Get parameter container
- */
+ #[Override]
public function getParameterContainer(): ParameterContainer
{
return $this->parameterContainer;
}
- /**
- * Prepare
- *
- * @param string $sql
- */
- public function prepare($sql = null): StatementInterface
- {
- $sql = $sql ?: $this->sql;
+ #[Override]
+ public function prepare(
+ ?string $sql = null
+ ): StatementInterface&DriverAwareInterface&ProfilerAwareInterface {
+ $sql = $sql ?? $this->sql;
$pCount = 1;
$sql = preg_replace_callback(
@@ -157,14 +129,13 @@ function () use (&$pCount) {
$sql
);
- $this->sql = $sql;
- $this->statementName = 'statement' . ++static::$statementIndex;
- $this->resource = pg_prepare($this->pgsql, $this->statementName, $sql);
+ $this->sql = $sql;
+ $this->statementName .= ++static::$statementIndex;
+ $this->resource = pg_prepare($this->pgsql, $this->statementName, $sql);
+ return $this;
}
- /**
- * Is prepared
- */
+ #[Override]
public function isPrepared(): bool
{
return isset($this->resource);
@@ -174,8 +145,8 @@ public function isPrepared(): bool
* Execute
*
* @throws Exception\InvalidQueryException
- * @return Result
*/
+ #[Override]
public function execute(ParameterContainer|array|null $parameters = null): ?ResultInterface
{
if (! $this->isPrepared()) {
diff --git a/test/asset/SetupTrait.php b/test/asset/SetupTrait.php
new file mode 100644
index 0000000..e6ba423
--- /dev/null
+++ b/test/asset/SetupTrait.php
@@ -0,0 +1,152 @@
+getAdapter();
+ parent::setUp();
+ }
+
+ public function getAdapter(string $adapter = self::NATIVE_ADAPTER): AdapterInterface
+ {
+ $serviceManagerConfig = ArrayUtils::merge(
+ (new Pgsql\ConfigProvider())()['dependencies'],
+ [
+ 'services' => [
+ 'config' => $this->getTestConfig(),
+ ],
+ ]
+ );
+ $this->serviceManager = new ServiceManager($serviceManagerConfig);
+ return $this->serviceManager->get($adapter);
+ }
+
+ public function getTestConfig(): array
+ {
+ return [
+ AdapterInterface::class => [
+ 'adapters' => [
+ self::NATIVE_ADAPTER => [
+ 'driver' => Pgsql\Driver::class,
+ 'connection' => [
+ 'host' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME'),
+ 'port' => 5432,
+ 'username' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_USERNAME'),
+ 'password' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_PASSWORD'),
+ 'database' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
+ ],
+ ],
+ self::PDO_ADAPTER => [
+ 'driver' => Pgsql\Pdo\Driver::class,
+ 'connection' => [
+ 'host' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME'),
+ 'port' => 5432,
+ 'username' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_USERNAME'),
+ 'password' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_PASSWORD'),
+ 'database' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
+ ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function getMockedAdapter(string $adapter = self::NATIVE_ADAPTER): AdapterInterface
+ {
+ $driverMock = $this->getMockBuilder(DriverInterface::class)->getMock();
+ $pdoDriverMock = $this->getMockBuilder(PdoDriverInterface::class)->getMock();
+ $testConfig = [
+ AdapterInterface::class => [
+ 'adapters' => [
+ self::NATIVE_ADAPTER => [
+ 'driver' => Pgsql\Driver::class,
+ 'connection' => [
+ 'host' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME'),
+ 'port' => 5432,
+ 'username' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_USERNAME'),
+ 'password' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_PASSWORD'),
+ 'database' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
+ ],
+ ],
+ self::PDO_ADAPTER => [
+ 'driver' => Pgsql\Pdo\Driver::class,
+ 'connection' => [
+ 'host' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME'),
+ 'port' => 5432,
+ 'username' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_USERNAME'),
+ 'password' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_PASSWORD'),
+ 'database' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
+ ],
+ ],
+ ],
+ ],
+ 'dependencies' => [
+ 'abstract_factories' => [
+ Pgsql\Container\AdapterAbstractServiceFactory::class,
+ ],
+ 'aliases' => [
+ DriverInterface::class => Pgsql\Driver::class,
+ 'pgsql' => Pgsql\Driver::class,
+ 'PgSQL' => Pgsql\Driver::class,
+ 'Postgresql' => Pgsql\Driver::class,
+ 'PostgreSQL' => Pgsql\Driver::class,
+ PdoDriverInterface::class => Pgsql\Pdo\Driver::class,
+ 'pdo_pgsql' => Pgsql\Pdo\Driver::class,
+ 'PDO_pgsql' => Pgsql\Pdo\Driver::class,
+ 'PDO_PgSQL' => Pgsql\Pdo\Driver::class,
+ 'Pdo_PgSQL' => Pgsql\Pdo\Driver::class,
+ 'PDO_postgresql' => Pgsql\Pdo\Driver::class,
+ 'pdo_postgresql' => Pgsql\Pdo\Driver::class,
+ 'PDO_Postgresql' => Pgsql\Pdo\Driver::class,
+ 'Pdo_Postgresql' => Pgsql\Pdo\Driver::class,
+ 'PDO_PostgreSQL' => Pgsql\Pdo\Driver::class,
+ 'pdo_PostgreSQL' => Pgsql\Pdo\Driver::class,
+ ConnectionInterface::class => Pgsql\Connection::class,
+ PdoConnectionInterface::class => Pgsql\Pdo\Connection::class,
+ PlatformInterface::class => Pgsql\AdapterPlatform::class,
+ ],
+ 'factories' => [
+ Pgsql\Driver::class => function (ContainerInterface $container) use ($driverMock) {
+ return $driverMock;
+ },
+ Pgsql\Pdo\Driver::class => function (ContainerInterface $container) use ($pdoDriverMock) {
+ return $pdoDriverMock;
+ },
+ ],
+ ],
+ ];
+
+ $libConfig = (new Pgsql\ConfigProvider())();
+ $config = ArrayUtils::merge($libConfig, $testConfig);
+ $serviceManagerConfig = ArrayUtils::merge(
+ $config['dependencies'],
+ [
+ 'services' => [
+ 'config' => $config,
+ ],
+ ]
+ );
+
+ $this->serviceManager = new ServiceManager($serviceManagerConfig);
+ return $this->serviceManager->get($adapter);
+ }
+}
diff --git a/test/integration/Adapter/Driver/Pdo/Postgresql/AdapterTest.php b/test/integration/Adapter/Driver/Pdo/Postgresql/AdapterTest.php
deleted file mode 100644
index 7604764..0000000
--- a/test/integration/Adapter/Driver/Pdo/Postgresql/AdapterTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-markTestSkipped('pdo_pgsql integration tests are not enabled!');
- }
-
- $this->adapter = new Adapter([
- 'driver' => 'pdo_pgsql',
- 'database' => (string) getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_DATABASE'),
- 'hostname' => (string) getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_HOSTNAME'),
- 'username' => (string) getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_USERNAME'),
- 'password' => (string) getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_PASSWORD'),
- ]);
-
- $this->hostname = (string) getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_HOSTNAME');
- }
-}
diff --git a/test/integration/Adapter/Platform/PostgresqlTest.php b/test/integration/AdapterPlatformTest.php
similarity index 74%
rename from test/integration/Adapter/Platform/PostgresqlTest.php
rename to test/integration/AdapterPlatformTest.php
index 7bec9ab..759d5f6 100644
--- a/test/integration/Adapter/Platform/PostgresqlTest.php
+++ b/test/integration/AdapterPlatformTest.php
@@ -1,12 +1,12 @@
*/
public array|\PDO $adapters = [];
@@ -25,23 +25,23 @@ final class PostgresqlTest extends TestCase
#[Override]
protected function setUp(): void
{
- if (! getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL')) {
+ if (! getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL')) {
$this->markTestSkipped(self::class . ' integration tests are not enabled!');
}
if (extension_loaded('pgsql')) {
$this->adapters['pgsql'] = pg_connect(
- 'host=' . getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_HOSTNAME')
- . ' dbname=' . getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_DATABASE')
- . ' user=' . getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_USERNAME')
- . ' password=' . getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_PASSWORD')
+ 'host=' . getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_HOSTNAME')
+ . ' dbname=' . getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_DATABASE')
+ . ' user=' . getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_USERNAME')
+ . ' password=' . getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_PASSWORD')
);
}
if (extension_loaded('pdo')) {
$this->adapters['pdo_pgsql'] = new \PDO(
- 'pgsql:host=' . getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_HOSTNAME') . ';dbname='
- . getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_DATABASE'),
- getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_USERNAME'),
- getenv('TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL_PASSWORD')
+ 'pgsql:host=' . getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_HOSTNAME') . ';dbname='
+ . getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_DATABASE'),
+ getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_USERNAME'),
+ getenv('TESTS_LAMINAS_DB_ADAPTER_PGSQL_PASSWORD')
);
}
}
@@ -60,11 +60,11 @@ public function testQuoteValueWithPgsql()
) {
$this->markTestSkipped('Postgres (pgsql) not configured in unit test configuration file');
}
- $pgsql = new Postgresql($this->adapters['pgsql']);
+ $pgsql = new AdapterPlatform($this->adapters['pgsql']);
$value = $pgsql->quoteValue('value');
self::assertEquals('\'value\'', $value);
- $pgsql = new Postgresql(new Pgsql\Pgsql(new Pgsql\Connection($this->adapters['pgsql'])));
+ $pgsql = new AdapterPlatform(new Driver(new PgSqlConnection($this->adapters['pgsql'])));
$value = $pgsql->quoteValue('value');
self::assertEquals('\'value\'', $value);
}
diff --git a/test/integration/Extension/IntegrationTestStartedListener.php b/test/integration/Extension/IntegrationTestStartedListener.php
new file mode 100644
index 0000000..b3dc4c3
--- /dev/null
+++ b/test/integration/Extension/IntegrationTestStartedListener.php
@@ -0,0 +1,44 @@
+testSuite()->name() !== 'integration test') {
+ return;
+ }
+
+ if (getenv('TESTS_PHPDB_ADAPTER_MYSQL')) {
+ $this->fixtureLoaders[] = new PgsqlFixtureLoader();
+ }
+
+ if (empty($this->fixtureLoaders)) {
+ return;
+ }
+
+ printf("\nIntegration test started.\n");
+
+ foreach ($this->fixtureLoaders as $fixtureLoader) {
+ $fixtureLoader->createDatabase();
+ }
+ }
+}
diff --git a/test/integration/Extension/IntegrationTestStoppedListener.php b/test/integration/Extension/IntegrationTestStoppedListener.php
new file mode 100644
index 0000000..dcf1b9f
--- /dev/null
+++ b/test/integration/Extension/IntegrationTestStoppedListener.php
@@ -0,0 +1,33 @@
+testSuite()->name() !== 'integration test'
+ || empty($this->fixtureLoaders)
+ ) {
+ return;
+ }
+
+ printf("\nIntegration test ended.\n");
+
+ foreach ($this->fixtureLoaders as $fixtureLoader) {
+ $fixtureLoader->dropDatabase();
+ }
+ }
+}
diff --git a/test/integration/Extension/ListenerExtension.php b/test/integration/Extension/ListenerExtension.php
new file mode 100644
index 0000000..9f0f171
--- /dev/null
+++ b/test/integration/Extension/ListenerExtension.php
@@ -0,0 +1,24 @@
+registerSubscribers(
+ new IntegrationTestStartedListener(),
+ new IntegrationTestStoppedListener(),
+ );
+ }
+}
diff --git a/test/integration/FixtureLoader/PgsqlFixtureLoader.php b/test/integration/FixtureLoader/PgsqlFixtureLoader.php
index f2cd5d6..c54a7c5 100644
--- a/test/integration/FixtureLoader/PgsqlFixtureLoader.php
+++ b/test/integration/FixtureLoader/PgsqlFixtureLoader.php
@@ -34,12 +34,12 @@ public function createDatabase(): void
if (
false === $this->pdo->exec(sprintf(
"CREATE DATABASE %s",
- getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_DATABASE')
+ getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE')
))
) {
throw new Exception(sprintf(
"I cannot create the PostgreSQL %s test database: %s",
- getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_DATABASE'),
+ getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
print_r($this->pdo->errorInfo(), true)
));
}
@@ -52,7 +52,7 @@ public function createDatabase(): void
if (false === $this->pdo->exec(file_get_contents($this->fixtureFile))) {
throw new Exception(sprintf(
"I cannot create the table for %s database. Check the %s file. %s ",
- getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_DATABASE'),
+ getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
$this->fixtureFile,
print_r($this->pdo->errorInfo(), true)
));
@@ -75,7 +75,7 @@ public function dropDatabase(): void
$this->pdo->exec(sprintf(
"DROP DATABASE IF EXISTS %s",
- getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_DATABASE')
+ getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE')
));
$this->disconnect();
@@ -86,16 +86,16 @@ public function dropDatabase(): void
*/
protected function connect(bool $useDb = false): void
{
- $dsn = 'pgsql:host=' . getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_HOSTNAME');
+ $dsn = 'pgsql:host=' . getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME');
if ($useDb) {
- $dsn .= ';dbname=' . getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_DATABASE');
+ $dsn .= ';dbname=' . getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE');
}
$this->pdo = new PDO(
$dsn,
- getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_USERNAME'),
- getenv('TESTS_PHPDB_ADAPTER_DRIVER_PGSQL_PASSWORD')
+ getenv('TESTS_PHPDB_ADAPTER_PGSQL_USERNAME'),
+ getenv('TESTS_PHPDB_ADAPTER_PGSQL_PASSWORD')
);
}
diff --git a/test/integration/Pdo/AdapterTest.php b/test/integration/Pdo/AdapterTest.php
new file mode 100644
index 0000000..2710453
--- /dev/null
+++ b/test/integration/Pdo/AdapterTest.php
@@ -0,0 +1,84 @@
+getAdapter()->getDriver()->getConnection();
+ $this->assertInstanceOf(ConnectionInterface::class, $connection);
+ }
+
+ public function testGetCurrentSchema(): void
+ {
+ /** @var AdapterInterface&SchemaAwareInterface&Adapter $adapter */
+ $adapter = $this->getAdapter();
+ $schema = $adapter->getCurrentSchema();
+ self::assertIsString($schema);
+ self::assertNotEmpty($schema);
+ }
+
+ public function testDriverDisconnectAfterQuoteWithPlatform(): void
+ {
+ $isTcpConnection = $this->isTcpConnection();
+
+ /** @var AdapterInterface&Adapter $adapter */
+ $adapter = $this->getAdapter([
+ 'db' => [
+ 'driver' => Driver::class,
+ ],
+ ]);
+ $adapter->getDriver()->getConnection()->connect();
+ self::assertTrue($adapter->getDriver()->getConnection()->isConnected());
+ if ($isTcpConnection) {
+ self::assertTrue($adapter->getDriver()->getConnection()->isConnected());
+ }
+
+ $adapter->getDriver()->getConnection()->disconnect();
+ self::assertFalse($adapter->getDriver()->getConnection()->isConnected());
+ if ($isTcpConnection) {
+ self::assertFalse($adapter->getDriver()->getConnection()->isConnected());
+ }
+
+ $adapter->getDriver()->getConnection()->connect();
+ self::assertTrue($adapter->getDriver()->getConnection()->isConnected());
+ if ($isTcpConnection) {
+ self::assertTrue($adapter->getDriver()->getConnection()->isConnected());
+ }
+
+ $adapter->getPlatform()->quoteValue('test');
+
+ $adapter->getDriver()->getConnection()->disconnect();
+
+ self::assertFalse($adapter->getDriver()->getConnection()->isConnected());
+ if ($isTcpConnection) {
+ self::assertFalse($adapter->getDriver()->getConnection()->isConnected());
+ }
+ }
+
+ protected function isTcpConnection(): bool
+ {
+ $hostName = $this->getHostname();
+ return $hostName !== 'localhost' && $hostName !== '127.0.0.1';
+ }
+}
diff --git a/test/integration/Pdo/SetupTrait.php b/test/integration/Pdo/SetupTrait.php
new file mode 100644
index 0000000..2918279
--- /dev/null
+++ b/test/integration/Pdo/SetupTrait.php
@@ -0,0 +1,66 @@
+markTestSkipped('pdo_pgsql integration tests are not enabled!');
+ }
+
+ $connectionParams = [
+ 'driver' => 'pdo_pgsql',
+ 'database' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_DATABASE'),
+ 'hostname' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME'),
+ 'username' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_USERNAME'),
+ 'password' => (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_PASSWORD'),
+ ];
+
+ $pdoDriver = new Driver(
+ new Connection($connectionParams),
+ new Statement(),
+ new Result()
+ );
+
+ $this->adapter = new Adapter(
+ $pdoDriver,
+ new AdapterPlatform($pdoDriver)
+ );
+
+ $this->hostname = (string) getenv('TESTS_PHPDB_ADAPTER_PGSQL_HOSTNAME');
+ }
+
+ public function getAdapter(): AdapterInterface
+ {
+ return $this->adapter;
+ }
+
+ public function getHostname(): string
+ {
+ return $this->hostname;
+ }
+}
diff --git a/test/integration/Adapter/Driver/Pdo/Postgresql/TableGatewayTest.php b/test/integration/Pdo/TableGatewayTest.php
similarity index 81%
rename from test/integration/Adapter/Driver/Pdo/Postgresql/TableGatewayTest.php
rename to test/integration/Pdo/TableGatewayTest.php
index 6d278a6..160ca49 100644
--- a/test/integration/Adapter/Driver/Pdo/Postgresql/TableGatewayTest.php
+++ b/test/integration/Pdo/TableGatewayTest.php
@@ -1,8 +1,9 @@
getDependencies();
- $config['services']['config'] = $dbConfig;
-
- return new ServiceManager($config);
- }
-
- #[Override]
- protected function setUp(): void
- {
- if (! extension_loaded('pdo_sqlite')) {
- $this->markTestSkipped('Adapter factory tests require pdo_sqlite');
- }
-
- $this->factory = new AdapterInterfaceFactory();
- }
-
- /**
- * @throws ContainerExceptionInterface
- * @throws NotFoundExceptionInterface
- */
- public function testV3FactoryReturnsDefaultAdapter(): void
- {
- $this->expectNotToPerformAssertions();
-
- $services = $this->createServiceManager([
- 'db' => [
- 'driver' => 'Pdo_Pgsql',
- 'database' => ':memory:',
- ],
- ]);
-
- $this->factory->__invoke($services, Adapter::class);
- }
-
- /**
- * @throws ContainerExceptionInterface
- * @throws NotFoundExceptionInterface
- */
- public function testV3FactoryReturnsDefaultAdapterWithDefaultProfiler(): void
- {
- $services = $this->createServiceManager([
- 'db' => [
- 'driver' => 'Pdo_Pgsql',
- 'database' => ':memory:',
- 'profiler' => true,
- ],
- ]);
-
- $adapter = $this->factory->__invoke($services, Adapter::class);
- self::assertInstanceOf(ProfilerInterface::class, $adapter->getProfiler());
- }
-
- /**
- * @throws ContainerExceptionInterface
- * @throws NotFoundExceptionInterface
- */
- public function testV3FactoryReturnsDefaultAdapterWithProfilerClassname(): void
- {
- $services = $this->createServiceManager([
- 'db' => [
- 'driver' => 'Pdo_Pgsql',
- 'database' => ':memory:',
- 'profiler' => Profiler::class,
- ],
- ]);
-
- $adapter = $this->factory->__invoke($services, Adapter::class);
- self::assertInstanceOf(ProfilerInterface::class, $adapter->getProfiler());
- }
-
- /**
- * @throws ContainerExceptionInterface
- * @throws NotFoundExceptionInterface
- */
- public function testV3FactoryReturnsDefaultAdapterWithProfilerInstance(): void
- {
- $services = $this->createServiceManager([
- 'db' => [
- 'driver' => 'Pdo_Pgsql',
- 'database' => ':memory:',
- 'profiler' => $this->getMockBuilder(ProfilerInterface::class)->getMock(),
- ],
- ]);
-
- $adapter = $this->factory->__invoke($services, Adapter::class);
- self::assertInstanceOf(ProfilerInterface::class, $adapter->getProfiler());
- }
-}
diff --git a/test/unit/Adapter/AdapterTest.php b/test/unit/Adapter/AdapterTest.php
index 0ee756b..cdfb8f0 100644
--- a/test/unit/Adapter/AdapterTest.php
+++ b/test/unit/Adapter/AdapterTest.php
@@ -12,12 +12,11 @@
use PhpDb\Adapter\Driver\ResultInterface;
use PhpDb\Adapter\Driver\StatementInterface;
use PhpDb\Adapter\ParameterContainer;
-use PhpDb\Adapter\Pgsql\Driver\Pdo\Pdo;
-use PhpDb\Adapter\Pgsql\Platform\Postgresql as PgsqlPlatform;
+use PhpDb\Adapter\Pgsql\AdapterPlatform;
+use PhpDb\Adapter\Pgsql\Pdo\Driver;
use PhpDb\Adapter\Profiler;
use PhpDb\ResultSet\ResultSet;
use PhpDb\ResultSet\ResultSetInterface;
-use PhpDbTest\TestAsset\TemporaryResultSet;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\TestDox;
@@ -40,7 +39,7 @@ final class AdapterTest extends TestCase
{
protected DriverInterface&MockObject $mockDriver;
- protected PgsqlPlatform $mockPlatform;
+ protected AdapterPlatform $mockPlatform;
protected ConnectionInterface&MockObject $mockConnection;
@@ -194,9 +193,6 @@ public function testQueryWhenExecutedProducesAResultSetObjectWhenResultIsQuery()
$r = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE);
self::assertInstanceOf(ResultSet::class, $r);
-
- $r = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE, new TemporaryResultSet());
- self::assertInstanceOf(TemporaryResultSet::class, $r);
}
#[TestDox('unit test: Test createStatement() produces a statement object')]
@@ -220,33 +216,33 @@ public function testMagicGet(): void
$this->adapter->foo;
}
- /**
- * @throws Exception
- */
- #[Override]
- protected function setUp(): void
- {
- $this->mockConnection = $this->createMock(ConnectionInterface::class);
- $this->mockPlatform = new PgsqlPlatform();
- $this->mockStatement = $this->getMockBuilder(Statement::class)->getMock();
- $this->mockDriver = $this->getMockBuilder(Pdo::class)
- ->setConstructorArgs([
- $this->mockConnection,
- $this->mockStatement,
- ])
- ->getMock();
-
- $this->mockResultSet = $this->getMockBuilder(ResultSetInterface::class)->getMock();
-
- $this->mockDriver->method('getDatabasePlatformName')->willReturn('Pgsql');
- $this->mockDriver->method('checkEnvironment')->willReturn(true);
- $this->mockDriver->method('getConnection')->willReturn($this->mockConnection);
- //$this->mockDriver->method('createStatement')->willReturn($this->mockStatement);
-
- $this->adapter = new Adapter(
- $this->mockDriver,
- $this->mockPlatform,
- $this->mockResultSet
- );
- }
+ // #[Override]
+ // protected function setUp(): void
+ // {
+ // $this->mockConnection = $this->createMock(ConnectionInterface::class);
+
+ // $this->mockStatement = $this->getMockBuilder(Statement::class)->getMock();
+
+ // $this->mockDriver = $this->getMockBuilder(Driver::class)
+ // ->setConstructorArgs([
+ // $this->mockConnection,
+ // $this->mockStatement,
+ // ])
+ // ->getMock();
+
+ // $this->mockDriver->method('getDatabasePlatformName')->willReturn('Pgsql');
+ // $this->mockDriver->method('checkEnvironment')->willReturn(true);
+ // $this->mockDriver->method('getConnection')->willReturn($this->mockConnection);
+ // $this->mockDriver->method('createStatement')->willReturn($this->mockStatement);
+
+ // $this->mockPlatform = new AdapterPlatform($this->mockDriver);
+
+ // $this->mockResultSet = $this->getMockBuilder(ResultSetInterface::class)->getMock();
+
+ // $this->adapter = new Adapter(
+ // $this->mockDriver,
+ // $this->mockPlatform,
+ // $this->mockResultSet
+ // );
+ // }
}
diff --git a/test/unit/Adapter/ConfigProviderTest.php b/test/unit/Adapter/ConfigProviderTest.php
index 4132144..8d1c86b 100644
--- a/test/unit/Adapter/ConfigProviderTest.php
+++ b/test/unit/Adapter/ConfigProviderTest.php
@@ -6,46 +6,70 @@
use Laminas\ServiceManager\Factory\InvokableFactory;
use PhpDb\Adapter\AdapterInterface;
+use PhpDb\Adapter\Driver\ConnectionInterface;
use PhpDb\Adapter\Driver\DriverInterface;
-use PhpDb\Adapter\Pgsql\ConfigProvider;
-use PhpDb\Adapter\Pgsql\Container\AdapterServiceFactory;
-use PhpDb\Adapter\Pgsql\Driver;
-use PhpDb\Adapter\Pgsql\Platform;
+use PhpDb\Adapter\Driver\PdoConnectionInterface;
+use PhpDb\Adapter\Driver\PdoDriverInterface;
+use PhpDb\Adapter\Pgsql;
use PhpDb\Adapter\Platform\PlatformInterface;
use PhpDb\Adapter\Profiler\Profiler;
use PhpDb\Adapter\Profiler\ProfilerInterface;
+use PhpDb\Container\AdapterAbstractServiceFactory;
+use PhpDb\Metadata\MetadataInterface;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
-#[CoversMethod(ConfigProvider::class, '__invoke')]
-#[CoversMethod(ConfigProvider::class, 'getDependencies')]
+#[CoversMethod(Pgsql\ConfigProvider::class, '__invoke')]
+#[CoversMethod(Pgsql\ConfigProvider::class, 'getDependencies')]
final class ConfigProviderTest extends TestCase
{
/** @var array> */
private array $config = [
'aliases' => [
- PlatformInterface::class => Platform\Postgresql::class,
- ProfilerInterface::class => Profiler::class,
+ DriverInterface::class => Pgsql\Driver::class,
+ 'pgsql' => Pgsql\Driver::class,
+ 'PgSQL' => Pgsql\Driver::class,
+ 'Postgresql' => Pgsql\Driver::class,
+ 'PostgreSQL' => Pgsql\Driver::class,
+ PdoDriverInterface::class => Pgsql\Pdo\Driver::class,
+ 'pdo_pgsql' => Pgsql\Pdo\Driver::class,
+ 'PDO_pgsql' => Pgsql\Pdo\Driver::class,
+ 'PDO_PgSQL' => Pgsql\Pdo\Driver::class,
+ 'Pdo_PgSQL' => Pgsql\Pdo\Driver::class,
+ 'PDO_postgresql' => Pgsql\Pdo\Driver::class,
+ 'pdo_postgresql' => Pgsql\Pdo\Driver::class,
+ 'PDO_Postgresql' => Pgsql\Pdo\Driver::class,
+ 'Pdo_Postgresql' => Pgsql\Pdo\Driver::class,
+ 'PDO_PostgreSQL' => Pgsql\Pdo\Driver::class,
+ 'pdo_PostgreSQL' => Pgsql\Pdo\Driver::class,
+ ConnectionInterface::class => Pgsql\Connection::class,
+ MetadataInterface::class => Pgsql\Metadata\Source::class,
+ PdoConnectionInterface::class => Pgsql\Pdo\Connection::class,
+ PlatformInterface::class => Pgsql\AdapterPlatform::class,
+ ProfilerInterface::class => Profiler::class,
],
'factories' => [
- AdapterInterface::class => AdapterServiceFactory::class,
- DriverInterface::class => Driver\Pdo\DriverFactory::class,
- Platform\Postgresql::class => InvokableFactory::class,
- Profiler::class => InvokableFactory::class,
+ AdapterInterface::class => Pgsql\Container\AdapterInterfaceFactory::class,
+ Pgsql\Driver::class => Pgsql\Container\DriverInterfaceFactory::class,
+ Pgsql\Pdo\Driver::class => Pgsql\Container\PdoDriverInterfaceFactory::class,
+ Pgsql\Connection::class => Pgsql\Container\ConnectionInterfaceFactory::class,
+ Pgsql\Pdo\Connection::class => Pgsql\Container\PdoConnectionInterfaceFactory::class,
+ Pgsql\AdapterPlatform::class => Pgsql\Container\PlatformInterfaceFactory::class,
+ Profiler::class => InvokableFactory::class,
],
];
- public function testProvidesExpectedConfiguration(): ConfigProvider
+ public function testProvidesExpectedConfiguration(): Pgsql\ConfigProvider
{
- $provider = new ConfigProvider();
+ $provider = new Pgsql\ConfigProvider();
self::assertEquals($this->config, $provider->getDependencies());
return $provider;
}
#[Depends('testProvidesExpectedConfiguration')]
- public function testInvocationProvidesDependencyConfiguration(ConfigProvider $provider): void
+ public function testInvocationProvidesDependencyConfiguration(Pgsql\ConfigProvider $provider): void
{
self::assertEquals(['dependencies' => $provider->getDependencies()], $provider());
}
diff --git a/test/unit/Adapter/SetupTest.php b/test/unit/Adapter/SetupTest.php
new file mode 100644
index 0000000..8ed8abf
--- /dev/null
+++ b/test/unit/Adapter/SetupTest.php
@@ -0,0 +1,20 @@
+getAdapter();
+ self::assertInstanceOf(AdapterInterface::class, $adapter);
+ }
+}