From 9d8280086ff4b90188092948ba619112fbaa5c18 Mon Sep 17 00:00:00 2001 From: Jakub Trmota Date: Mon, 18 Nov 2024 22:44:59 +0100 Subject: [PATCH] DB: use boolean parameters as a query parameter --- docs/fluent.md | 4 +- phpcs-ignores.neon | 10 +++- src/Db/SqlDefinition.php | 10 ++-- tests/Integration/FetchTest.php | 7 +-- ...st.php => FluentQueryExecuteFetchTest.php} | 4 +- tests/Integration/QueryTest.php | 50 +++++++++++++++++++ tests/Unit/QueryTest.php | 8 +++ 7 files changed, 78 insertions(+), 15 deletions(-) rename tests/Integration/{QueryExecuteFetchTest.php => FluentQueryExecuteFetchTest.php} (98%) create mode 100644 tests/Integration/QueryTest.php diff --git a/docs/fluent.md b/docs/fluent.md index 3059a5f..dca4f5c 100644 --- a/docs/fluent.md +++ b/docs/fluent.md @@ -356,7 +356,7 @@ $query = $connection 'phones' => Forrest79\PhPgSql\Db\Helper::createStringPgArray(['732123456', '736987654']), ]); -dump($query); // (Query) INSERT INTO users (nick, inserted_datetime, active, age, height_cm, phones) VALUES($1, now(), TRUE, $2, $3, $4) [Params: (array) ['James', 37, (NULL), '{\"732123456\",\"736987654\"}']] +dump($query); // (Query) INSERT INTO users (nick, inserted_datetime, active, age, height_cm, phones) VALUES($1, now(), $2, $3, $4, $5) [Params: (array) ['James', 't', 37, (NULL), '{\"732123456\",\"736987654\"}']] $result = $query->execute(); @@ -830,7 +830,7 @@ $query = $connection ->join('user_departments', 'ud', 'ud.department_id = au.id') ->where('ud.department_id IN (?)', Forrest79\PhPgSql\Db\Sql\Query::create('SELECT id FROM active_departments')); -dump($query); // (Query) WITH active_users AS (SELECT id, nick, age, height_cm FROM users WHERE active = TRUE), active_departments AS (SELECT id FROM departments WHERE active = TRUE) SELECT au.id, au.nick, au.age, au.height_cm FROM active_users AS au INNER JOIN user_departments AS ud ON ud.department_id = au.id WHERE ud.department_id IN (SELECT id FROM active_departments) +dump($query); // (Query) WITH active_users AS (SELECT id, nick, age, height_cm FROM users WHERE active = TRUE), active_departments AS (SELECT id FROM departments WHERE active = $1) SELECT au.id, au.nick, au.age, au.height_cm FROM active_users AS au INNER JOIN user_departments AS ud ON ud.department_id = au.id WHERE ud.department_id IN (SELECT id FROM active_departments) [Params: (array) ['t']] $query->execute(); ``` diff --git a/phpcs-ignores.neon b/phpcs-ignores.neon index cb2d3d9..9a95b55 100644 --- a/phpcs-ignores.neon +++ b/phpcs-ignores.neon @@ -473,6 +473,12 @@ ignoreErrors: count: 1 path: tests/Integration/FetchTest.php + - + sniff: PSR1.Files.SideEffects.FoundWithSymbols + message: 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line 15 and the first side effect is on line 9.' + count: 1 + path: tests/Integration/FluentQueryExecuteFetchTest.php + - sniff: PSR1.Files.SideEffects.FoundWithSymbols message: 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line 15 and the first side effect is on line 9.' @@ -517,9 +523,9 @@ ignoreErrors: - sniff: PSR1.Files.SideEffects.FoundWithSymbols - message: 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line 15 and the first side effect is on line 9.' + message: 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line 12 and the first side effect is on line 7.' count: 1 - path: tests/Integration/QueryExecuteFetchTest.php + path: tests/Integration/QueryTest.php - sniff: PSR1.Files.SideEffects.FoundWithSymbols diff --git a/src/Db/SqlDefinition.php b/src/Db/SqlDefinition.php index 668927e..b06136e 100644 --- a/src/Db/SqlDefinition.php +++ b/src/Db/SqlDefinition.php @@ -54,8 +54,6 @@ static function ($matches) use (&$params, &$parsedParams, &$origParamIndex, &$pa $parsedParams[] = ($value instanceof \BackedEnum) ? $value->value : $value; } return \implode(', ', $keys); - } else if (\is_bool($param)) { - return $param === TRUE ? 'TRUE' : 'FALSE'; // @todo as param } else if ($param instanceof Sql) { $subquerySql = self::processSqlDefinition($param->getSqlDefinition(), $paramIndex); $paramIndex += \count($subquerySql->params); @@ -63,7 +61,13 @@ static function ($matches) use (&$params, &$parsedParams, &$origParamIndex, &$pa return $subquerySql->sql; } - $parsedParams[] = ($param instanceof \BackedEnum) ? $param->value : $param; + if (\is_bool($param)) { + $parsedParams[] = $param ? 't' : 'f'; + } else if ($param instanceof \BackedEnum) { + $parsedParams[] = $param->value; + } else { + $parsedParams[] = $param; + } return '$' . ++$paramIndex; }, diff --git a/tests/Integration/FetchTest.php b/tests/Integration/FetchTest.php index e0be2f4..8079340 100644 --- a/tests/Integration/FetchTest.php +++ b/tests/Integration/FetchTest.php @@ -817,12 +817,7 @@ public function testRowValues(): void private function fetch(Db\Result $result): Db\Row { - $row = $result->fetch(); - if ($row === NULL) { - throw new \RuntimeException('No data from database were returned'); - } - - return $row; + return $result->fetch() ?? throw new \RuntimeException('No data from database were returned'); } diff --git a/tests/Integration/QueryExecuteFetchTest.php b/tests/Integration/FluentQueryExecuteFetchTest.php similarity index 98% rename from tests/Integration/QueryExecuteFetchTest.php rename to tests/Integration/FluentQueryExecuteFetchTest.php index 0399e73..3bc7995 100644 --- a/tests/Integration/QueryExecuteFetchTest.php +++ b/tests/Integration/FluentQueryExecuteFetchTest.php @@ -12,7 +12,7 @@ * @testCase * @property-read Fluent\Connection $connection */ -final class QueryExecuteFetchTest extends TestCase +final class FluentQueryExecuteFetchTest extends TestCase { public function testFetch(): void @@ -284,4 +284,4 @@ protected function createConnection(): Db\Connection } -(new QueryExecuteFetchTest())->run(); +(new FluentQueryExecuteFetchTest())->run(); diff --git a/tests/Integration/QueryTest.php b/tests/Integration/QueryTest.php new file mode 100644 index 0000000..91af2b7 --- /dev/null +++ b/tests/Integration/QueryTest.php @@ -0,0 +1,50 @@ +connection->query(' + CREATE TABLE test( + id integer, + bool_column bool + ); + '); + + $this->connection->query('INSERT INTO test(id, bool_column) VALUES(?, ?)', 1, TRUE); + $this->connection->query('INSERT INTO test(id, bool_column) VALUES(?, ?)', 2, FALSE); + + $resultTrue = $this->connection->query('SELECT id, bool_column FROM test WHERE bool_column = ?', TRUE); + + $rowTrue = $resultTrue->fetch() ?? throw new \RuntimeException('No data from database were returned'); + + Tester\Assert::same(1, $rowTrue->id); + Tester\Assert::true($rowTrue->bool_column); + + $resultTrue->free(); + + // --- + + $resultFalse = $this->connection->query('SELECT id, bool_column FROM test WHERE bool_column = ?', FALSE); + + $rowFalse = $resultFalse->fetch() ?? throw new \RuntimeException('No data from database were returned'); + + Tester\Assert::same(2, $rowFalse->id); + Tester\Assert::false($rowFalse->bool_column); + + $resultFalse->free(); + } + +} + +(new QueryTest())->run(); diff --git a/tests/Unit/QueryTest.php b/tests/Unit/QueryTest.php index 51f8a1c..bf62830 100644 --- a/tests/Unit/QueryTest.php +++ b/tests/Unit/QueryTest.php @@ -115,6 +115,14 @@ public function testPrepareQueryWithQuery(): void } + public function testPrepareQueryWithBool(): void + { + $query = Db\Sql\Query::create('SELECT * FROM table WHERE column1 = ? AND column2 = ?', TRUE, FALSE)->toDbQuery(); + Tester\Assert::same('SELECT * FROM table WHERE column1 = $1 AND column2 = $2', $query->sql); + Tester\Assert::same(['t', 'f'], $query->params); + } + + public function testPrepareQueryWithEnum(): void { $query = Db\Sql\Query::create('SELECT * FROM table WHERE column = ?', Tests\TestEnum::One)->toDbQuery();