From 37b3bdcd22334ec0184e18764622730ae4159d50 Mon Sep 17 00:00:00 2001 From: Julian Vennen Date: Mon, 15 Jul 2024 16:10:20 +0200 Subject: [PATCH 1/4] Format Select query params --- src/Query/SelectQuery.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Query/SelectQuery.php b/src/Query/SelectQuery.php index 3f15748..c845c14 100644 --- a/src/Query/SelectQuery.php +++ b/src/Query/SelectQuery.php @@ -28,7 +28,7 @@ public function __construct(null|WhereCondition|array|WhereGroup $where = null, null|array $order = null, null|array $fields = null, null|Limit|array|int $limit = null, - null|array $group = null) + null|array $group = null) { if ($where) { $this->where($where); From f29023c54808f7a110644aca662c13adb4b966cf Mon Sep 17 00:00:00 2001 From: Julian Vennen Date: Mon, 15 Jul 2024 16:10:46 +0200 Subject: [PATCH 2/4] Replace != with IS NOT when comparing to null --- src/Query/Generator/SQL.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Query/Generator/SQL.php b/src/Query/Generator/SQL.php index 4f8e443..2f8586e 100644 --- a/src/Query/Generator/SQL.php +++ b/src/Query/Generator/SQL.php @@ -118,8 +118,12 @@ private function generateWhere(Query $query, WhereCondition|WhereGroup $where = $where = $query->getWhere(); } if ($where instanceof WhereCondition) { - if ($where->value === null && $where->operator === "=") { - $where->operator = "IS"; + if ($where->value === null) { + if ($where->operator === "=") { + $where->operator = "IS"; + } elseif ($where->operator === "!=") { + $where->operator = "IS NOT"; + } } $value = $where->value; From 6fb4a4b6a123020f40c27b2153c2e6172493f905 Mon Sep 17 00:00:00 2001 From: Julian Vennen Date: Mon, 15 Jul 2024 16:11:24 +0200 Subject: [PATCH 3/4] Add spacing in update queries to match where conditions --- src/Query/Generator/SQL.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Query/Generator/SQL.php b/src/Query/Generator/SQL.php index 2f8586e..88f0fad 100644 --- a/src/Query/Generator/SQL.php +++ b/src/Query/Generator/SQL.php @@ -237,7 +237,7 @@ private function generateFields(Query $query): string } } else if ($field instanceof UpdateField) { - $fieldStrings[] = $this->columnEnclosure . $field->key . $this->columnEnclosure . "=" . $this->generateValue($field->value); + $fieldStrings[] = $this->columnEnclosure . $field->key . $this->columnEnclosure . " = " . $this->generateValue($field->value); } } From d634eecafeb0ea7865684d492009a72c18bf5a18 Mon Sep 17 00:00:00 2001 From: Julian Vennen Date: Mon, 15 Jul 2024 16:11:41 +0200 Subject: [PATCH 4/4] Add tests for SQL codegen --- phpunit.xml | 5 + test/tests/SQLTest.php | 287 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 test/tests/SQLTest.php diff --git a/phpunit.xml b/phpunit.xml index ff9ee7c..a917a30 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,5 +1,10 @@ + + + src/ + + test/tests/ diff --git a/test/tests/SQLTest.php b/test/tests/SQLTest.php new file mode 100644 index 0000000..fa3cfc9 --- /dev/null +++ b/test/tests/SQLTest.php @@ -0,0 +1,287 @@ +sql = new SQL("addslashes"); + } + + public function testSelect() + { + $query = new SelectQuery(); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test`", $this->sql->generate($query)); + } + + public function testSelectWhereCondition() + { + $query = new SelectQuery( + new WhereCondition('text', 'value'), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`text` = 'value')", $this->sql->generate($query)); + } + + public function testSelectWhereConditionNumber() + { + $query = new SelectQuery( + new WhereCondition('number', 1), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` = 1)", $this->sql->generate($query)); + } + + public function testSelectWhereConditionFloat() + { + $query = new SelectQuery( + new WhereCondition('number', 1.5), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` = 1.5)", $this->sql->generate($query)); + } + + public function testSelectWhereConditionOperator() + { + $query = new SelectQuery( + new WhereCondition('text', 'value', '!='), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`text` != 'value')", $this->sql->generate($query)); + } + + public function testSelectWhereConditionNull() + { + $query = new SelectQuery( + new WhereCondition('text', null), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`text` IS NULL)", $this->sql->generate($query)); + } + + public function testSelectWhereConditionNotNull() + { + $query = new SelectQuery( + new WhereCondition('text', null, '!='), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`text` IS NOT NULL)", $this->sql->generate($query)); + } + + public function testSelectWhereConditionIN() + { + $query = new SelectQuery( + new WhereCondition('number', [1.5, 5, "a", ["b", "c", "d"]], 'IN'), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` IN (1.5, 5, 'a', ('b', 'c', 'd')))", $this->sql->generate($query)); + } + + public function testSelectWhereArray() + { + $query = new SelectQuery([ + 'number' => 1, + 'text' => 'value', + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` = 1 AND `text` = 'value')", $this->sql->generate($query)); + } + + public function testSelectWhereArrayOperator() + { + $query = new SelectQuery([ + ['number', 0.5], + ['number', '<', 1], + 'text' => 'value', + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` = 0.5 AND `number` < 1 AND `text` = 'value')", $this->sql->generate($query)); + } + + public function testSelectWhereGroup() + { + $query = new SelectQuery( + new WhereGroup([ + new WhereCondition('number', 1, '<'), + new WhereCondition('number', 0, '>'), + ]), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` < 1 AND `number` > 0)", $this->sql->generate($query)); + } + + public function testSelectWhereGroupOR() + { + $query = new SelectQuery( + new WhereGroup([ + new WhereCondition('number', 1, '>'), + new WhereCondition('number', 0, '<'), + ], WhereGroup::OR), + ); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` WHERE (`number` > 1 OR `number` < 0)", $this->sql->generate($query)); + } + + public function testSelectSingleField() + { + $query = new SelectQuery(fields: ['text']); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT `text` FROM `test`", $this->sql->generate($query)); + } + + public function testSelectSelectFields() + { + $query = new SelectQuery(fields: ['text', 'number']); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT `text`, `number` FROM `test`", $this->sql->generate($query)); + } + + public function testSelectOrder() + { + $query = new SelectQuery(order: [ + 'number' => 'ASC', + 'text' => 'DESC', + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` ORDER BY `number` ASC, `text` DESC", $this->sql->generate($query)); + } + + public function testSelectCount() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::COUNT), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT COUNT(`number`) FROM `test`", $this->sql->generate($query)); + } + + public function testSelectCountStar() + { + $query = new SelectQuery(fields: [ + (new SelectField('*'))->setFunction(SelectField::COUNT), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT COUNT(*) FROM `test`", $this->sql->generate($query)); + } + + public function testSelectSum() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::SUM), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT SUM(`number`) FROM `test`", $this->sql->generate($query)); + } + + public function testSelectSumAs() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::SUM)->setAlias('sum'), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT SUM(`number`) AS `sum` FROM `test`", $this->sql->generate($query)); + } + + public function testSelectAVG() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::AVERAGE), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT AVG(`number`) FROM `test`", $this->sql->generate($query)); + } + + public function testSelectLimitNumber() + { + $query = new SelectQuery(limit:100); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` LIMIT 0, 100", $this->sql->generate($query)); + } + + public function testSelectLimitArray() + { + $query = new SelectQuery(limit:[5, 100]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` LIMIT 5, 100", $this->sql->generate($query)); + } + + public function testSelectLimit() + { + $query = new SelectQuery(limit:new Limit(100, 5)); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` LIMIT 5, 100", $this->sql->generate($query)); + } + + public function testSelectGroup() + { + $query = new SelectQuery(group:['number', 'text']); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT * FROM `test` GROUP BY `number`, `text`", $this->sql->generate($query)); + } + + public function testDelete() + { + $query = new DeleteQuery(); + $query->modelClassName = TestModel::class; + + /** @noinspection SqlWithoutWhere */ + $this->assertEquals("DELETE FROM `test`", $this->sql->generate($query)); + } + + public function testDeleteLimit() + { + $query = new DeleteQuery(limit: 100); + $query->modelClassName = TestModel::class; + + /** @noinspection SqlWithoutWhere */ + $this->assertEquals("DELETE FROM `test` LIMIT 100", $this->sql->generate($query)); + } + + public function testUpdate() + { + $query = new UpdateQuery(['text' => 'value']); + $query->modelClassName = TestModel::class; + + /** @noinspection SqlWithoutWhere */ + $this->assertEquals("UPDATE `test` SET `text` = 'value'", $this->sql->generate($query)); + } +}