From 40faab75531691cc9949aa056b77cf3216b76bdf Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 17 Sep 2020 21:43:52 +0100 Subject: [PATCH 01/11] Test and implement inner join --- composer.json | 2 +- composer.lock | 4 +- src/Query/SelectQuery.php | 43 +++++++++++++++++++ src/Query/SqlQuery.php | 21 +++++++++ .../Helper/Query/SelectExampleExtendWhere.php | 2 +- .../Helper/Query/SelectExampleInnerJoin.php | 21 +++++++++ test/phpunit/Query/SelectQueryTest.php | 16 ++++--- test/phpunit/Query/SqlQueryTest.php | 4 +- test/phpunit/QueryTestCase.php | 12 ++++++ 9 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 test/phpunit/Helper/Query/SelectExampleInnerJoin.php create mode 100644 test/phpunit/QueryTestCase.php diff --git a/composer.json b/composer.json index 2f86272..852366e 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Object oriented representation of SQL queries.", "require": { - "php": "^7.2" + "php": "^7.4" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 6901832..9b710cf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c68c0328eba354bf6046fd54cdc0df5d", + "content-hash": "fa8ef213c8901d3ee7fa6c4ebc36142a", "packages": [], "packages-dev": [ { @@ -1794,7 +1794,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.2" + "php": "^7.4" }, "platform-dev": [] } diff --git a/src/Query/SelectQuery.php b/src/Query/SelectQuery.php index 61a9227..38b1879 100644 --- a/src/Query/SelectQuery.php +++ b/src/Query/SelectQuery.php @@ -7,6 +7,14 @@ public function __toString():string { self::PRE_QUERY_COMMENT => $this->preQuery(), "select" => $this->select(), "from" => $this->from(), + "inner join" => $this->innerJoin(), + "cross join" => $this->crossJoin(), + // The underscore is not a typo (https://dev.mysql.com/doc/refman/8.0/en/join.html) + "straight_join" => $this->straightJoin(), + "left join" => $this->leftJoin(), + "left outer join" => $this->leftOuterJoin(), + "right join" => $this->rightJoin(), + "right outer join" => $this->rightOuterJoin(), "where" => $this->where(), "group by" => $this->groupBy(), "having" => $this->having(), @@ -26,6 +34,41 @@ public function from():array { return []; } + /** @return string[] */ + public function innerJoin():array { + return []; + } + + /** @return string[] */ + public function crossJoin():array { + return []; + } + + /** @return string[] */ + public function straightJoin():array { + return []; + } + + /** @return string[] */ + public function leftJoin():array { + return []; + } + + /** @return string[] */ + public function leftOuterJoin():array { + return []; + } + + /** @return string[] */ + public function rightJoin():array { + return []; + } + + /** @return string[] */ + public function rightOuterJoin():array { + return []; + } + public function where():array { return []; } diff --git a/src/Query/SqlQuery.php b/src/Query/SqlQuery.php index 0547b76..491dd56 100644 --- a/src/Query/SqlQuery.php +++ b/src/Query/SqlQuery.php @@ -33,6 +33,12 @@ protected function processClauseList(array $clauses):string { $parts ); } + elseif(strstr($name, "join")) { + $query .= $this->processJoinClause( + $name, + $parts + ); + } else { $query .= $this->processClause( $name, @@ -92,4 +98,19 @@ protected function processWhereClause( $query .= "\n\n"; return $query; } + + private function processJoinClause( + string $name, + array $parts + ):string { + $query = ""; + + foreach($parts as $i => $part) { + $query .= $name . " "; + $part = str_replace(["\n", "\t"], " ", $part); + $query .= $part . PHP_EOL; + } + + return $query; + } } \ No newline at end of file diff --git a/test/phpunit/Helper/Query/SelectExampleExtendWhere.php b/test/phpunit/Helper/Query/SelectExampleExtendWhere.php index 91fac94..8d54492 100644 --- a/test/phpunit/Helper/Query/SelectExampleExtendWhere.php +++ b/test/phpunit/Helper/Query/SelectExampleExtendWhere.php @@ -4,7 +4,7 @@ class SelectExampleExtendWhere extends SelectExample { public function where():array { return array_merge(parent::where(), [ - "test = 0", + "test = 123", ]); } } \ No newline at end of file diff --git a/test/phpunit/Helper/Query/SelectExampleInnerJoin.php b/test/phpunit/Helper/Query/SelectExampleInnerJoin.php new file mode 100644 index 0000000..425f858 --- /dev/null +++ b/test/phpunit/Helper/Query/SelectExampleInnerJoin.php @@ -0,0 +1,21 @@ + Date: Thu, 17 Sep 2020 22:16:56 +0100 Subject: [PATCH 02/11] Test subquery --- src/Query/SelectQuery.php | 21 ++++++++++------ src/Query/SqlQuery.php | 6 +++++ .../Helper/Query/SelectExampleSubquery.php | 11 +++++++++ .../Query/SelectExampleUsedAsSubquery.php | 24 +++++++++++++++++++ test/phpunit/Query/SelectQueryTest.php | 8 ++++++- 5 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 test/phpunit/Helper/Query/SelectExampleSubquery.php create mode 100644 test/phpunit/Helper/Query/SelectExampleUsedAsSubquery.php diff --git a/src/Query/SelectQuery.php b/src/Query/SelectQuery.php index 38b1879..5eea9be 100644 --- a/src/Query/SelectQuery.php +++ b/src/Query/SelectQuery.php @@ -3,7 +3,7 @@ class SelectQuery extends SqlQuery { public function __toString():string { - return $this->processClauseList([ + $query = $this->processClauseList([ self::PRE_QUERY_COMMENT => $this->preQuery(), "select" => $this->select(), "from" => $this->from(), @@ -18,18 +18,24 @@ public function __toString():string { "where" => $this->where(), "group by" => $this->groupBy(), "having" => $this->having(), - "window" => $this->window(), "order by" => $this->orderBy(), "limit" => $this->limit(), self::POST_QUERY_COMMENT => $this->postQuery(), ]); + + if($this->subQuery) { + $query = "( $query )"; + } + + return $query; } - /** @return string[]|SqlQuery[] */ + /** @return string[] */ public function select():array { return []; } + /** @return string[]|SqlQuery[] */ public function from():array { return []; } @@ -69,26 +75,27 @@ public function rightOuterJoin():array { return []; } + /** @return string[]|SqlQuery[] */ public function where():array { return []; } + /** @return string[]|SqlQuery[] */ public function groupBy():array { return []; } + /** @return string[]|SqlQuery[] */ public function having():array { return []; } - public function window():array { - return []; - } - + /** @return string[] */ public function orderBy():array { return []; } + /** @return string[] */ public function limit():array { return []; } diff --git a/src/Query/SqlQuery.php b/src/Query/SqlQuery.php index 491dd56..6fbe0c5 100644 --- a/src/Query/SqlQuery.php +++ b/src/Query/SqlQuery.php @@ -9,6 +9,12 @@ abstract class SqlQuery { const POST_QUERY_COMMENT = "/* postQuery */"; const WHERE_CLAUSES = ["where", "having"]; + protected bool $subQuery; + + public function __construct(bool $subQuery = false) { + $this->subQuery = $subQuery; + } + abstract public function __toString():string; public function preQuery():string { diff --git a/test/phpunit/Helper/Query/SelectExampleSubquery.php b/test/phpunit/Helper/Query/SelectExampleSubquery.php new file mode 100644 index 0000000..267a971 --- /dev/null +++ b/test/phpunit/Helper/Query/SelectExampleSubquery.php @@ -0,0 +1,11 @@ + " . new SelectExampleUsedAsSubquery(true), + ]; + } +} \ No newline at end of file diff --git a/test/phpunit/Helper/Query/SelectExampleUsedAsSubquery.php b/test/phpunit/Helper/Query/SelectExampleUsedAsSubquery.php new file mode 100644 index 0000000..6148bdf --- /dev/null +++ b/test/phpunit/Helper/Query/SelectExampleUsedAsSubquery.php @@ -0,0 +1,24 @@ +where()); self::assertEmpty($sut->groupBy()); self::assertEmpty($sut->having()); - self::assertEmpty($sut->window()); self::assertEmpty($sut->orderBy()); self::assertEmpty($sut->limit()); } @@ -55,4 +55,10 @@ public function testSelectInnerJoin() { $sql = self::normalise($sut); self::assertEquals("select id, name, dateOfBirth, module.title from student inner join student_has_module shm on shm.studentId = student.id inner join module on shm.moduleId = module.id where deletedAt is null", $sql); } + + public function testSelectSubquery() { + $sut = new SelectExampleSubquery(); + $sql = self::normalise($sut); + self::assertEquals("select id, name, dateOfBirth from student where deletedAt is null and age > ( select minAge from consent where consent.district = student.district )", $sql); + } } \ No newline at end of file From cf540b17991379b37775a71587d001b74db22fd2 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 22 Sep 2020 15:51:45 +0100 Subject: [PATCH 03/11] Implement simple insert --- src/Query/InsertQuery.php | 47 +++++++++++++++++++++ src/Query/SqlQuery.php | 22 +++++++++- test/phpunit/Helper/Query/InsertExample.php | 21 +++++++++ test/phpunit/Query/InsertQueryTest.php | 13 ++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/Query/InsertQuery.php create mode 100644 test/phpunit/Helper/Query/InsertExample.php create mode 100644 test/phpunit/Query/InsertQueryTest.php diff --git a/src/Query/InsertQuery.php b/src/Query/InsertQuery.php new file mode 100644 index 0000000..120701c --- /dev/null +++ b/src/Query/InsertQuery.php @@ -0,0 +1,47 @@ +processClauseList([ + self::PRE_QUERY_COMMENT => $this->preQuery(), + "insert into" => $this->into(), + "set" => $this->normaliseSet($this->set()), + ]); + + if($this->subQuery) { + $query = "( $query )"; + } + + return $query; + } + + public function into():array { + return []; + } + + /** + * Return either an associative array where the keys are the column + * names and the values are the assignment values, or an indexed array + * where the values are the column names where the values will be + * inferred as the column name prefixed with the colon character. + */ + public function set():array { + return []; + } + + private function normaliseSet(array $setData):array { + reset($setData); + $firstKey = key($setData); + if(!is_int($firstKey)) { + return $setData; + } + + $normalised = []; + foreach($setData as $i => $name) { + $normalised[$name] = ":$name"; + } + + return $normalised; + } +} \ No newline at end of file diff --git a/src/Query/SqlQuery.php b/src/Query/SqlQuery.php index 6fbe0c5..4212ca3 100644 --- a/src/Query/SqlQuery.php +++ b/src/Query/SqlQuery.php @@ -39,6 +39,9 @@ protected function processClauseList(array $clauses):string { $parts ); } + elseif($name === "set") { + $query .= $this->processSetClause($parts); + } elseif(strstr($name, "join")) { $query .= $this->processJoinClause( $name, @@ -61,7 +64,7 @@ protected function processClause( array $parts, string $listChar = "," ):string { - if(empty($parts) || $parts[0] === "") { + if(empty($parts) || (isset($parts[0]) && $parts[0] === "")) { return ""; } @@ -119,4 +122,21 @@ private function processJoinClause( return $query; } + + private function processSetClause(array $parts):string { + $query = ""; + + foreach($parts as $key => $value) { + if(strlen($query) === 0) { + $query .= "set " . PHP_EOL; + } + else { + $query .= ", " . PHP_EOL; + } + + $query .= "$key = $value"; + } + + return $query; + } } \ No newline at end of file diff --git a/test/phpunit/Helper/Query/InsertExample.php b/test/phpunit/Helper/Query/InsertExample.php new file mode 100644 index 0000000..af0d8f0 --- /dev/null +++ b/test/phpunit/Helper/Query/InsertExample.php @@ -0,0 +1,21 @@ + ":name", + "dateOfBirth" => ":dateOfBirth", + ]; + } +} \ No newline at end of file diff --git a/test/phpunit/Query/InsertQueryTest.php b/test/phpunit/Query/InsertQueryTest.php new file mode 100644 index 0000000..a2d9673 --- /dev/null +++ b/test/phpunit/Query/InsertQueryTest.php @@ -0,0 +1,13 @@ + Date: Tue, 22 Sep 2020 15:53:43 +0100 Subject: [PATCH 04/11] Test inferred insert fields --- .../Query/InsertInferredPlaceholderExample.php | 17 +++++++++++++++++ test/phpunit/Query/InsertQueryTest.php | 7 +++++++ 2 files changed, 24 insertions(+) create mode 100644 test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php diff --git a/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php b/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php new file mode 100644 index 0000000..941ae62 --- /dev/null +++ b/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php @@ -0,0 +1,17 @@ + Date: Tue, 22 Sep 2020 16:04:50 +0100 Subject: [PATCH 05/11] Test mixing inferred with explicit insert fields --- src/Query/InsertQuery.php | 13 +++++------ .../InsertInferredPlaceholderExample.php | 4 +++- .../Query/InsertMixedPlaceholderExample.php | 22 +++++++++++++++++++ test/phpunit/Query/InsertQueryTest.php | 7 ++++++ 4 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 test/phpunit/Helper/Query/InsertMixedPlaceholderExample.php diff --git a/src/Query/InsertQuery.php b/src/Query/InsertQuery.php index 120701c..256e039 100644 --- a/src/Query/InsertQuery.php +++ b/src/Query/InsertQuery.php @@ -31,15 +31,14 @@ public function set():array { } private function normaliseSet(array $setData):array { - reset($setData); - $firstKey = key($setData); - if(!is_int($firstKey)) { - return $setData; - } - $normalised = []; foreach($setData as $i => $name) { - $normalised[$name] = ":$name"; + if(is_int($i)) { + $normalised[$name] = ":$name"; + } + else { + $normalised[$i] = $name; + } } return $normalised; diff --git a/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php b/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php index 941ae62..306b400 100644 --- a/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php +++ b/test/phpunit/Helper/Query/InsertInferredPlaceholderExample.php @@ -1,7 +1,9 @@ ":dateTimeNow", + "enabled" => 1, + "type", + ]; + } +} \ No newline at end of file diff --git a/test/phpunit/Query/InsertQueryTest.php b/test/phpunit/Query/InsertQueryTest.php index 4845fe5..f8f1e85 100644 --- a/test/phpunit/Query/InsertQueryTest.php +++ b/test/phpunit/Query/InsertQueryTest.php @@ -3,6 +3,7 @@ use Gt\SqlBuilder\Test\Helper\Query\InsertExample; use Gt\SqlBuilder\Test\Helper\Query\InsertInferredPlaceholderExample; +use Gt\SqlBuilder\Test\Helper\Query\InsertMixedPlaceholderExample; use Gt\SqlBuilder\Test\QueryTestCase; class InsertQueryTest extends QueryTestCase { @@ -17,4 +18,10 @@ public function testInsertInferredPlaceholder() { $sql = self::normalise($sut); self::assertEquals("insert into student set name = :name, dateOfBirth = :dateOfBirth", $sql); } + + public function testInsertMixedPlaceholder() { + $sut = new InsertMixedPlaceholderExample(); + $sql = self::normalise($sut); + self::assertEquals("insert into student set name = :name, dateOfBirth = :dateOfBirth, createdAt = :dateTimeNow, enabled = 1, type = :type", $sql); + } } \ No newline at end of file From 5e326c6dadb3389951c5537627e0f5b007a1ab82 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 22 Sep 2020 17:17:38 +0100 Subject: [PATCH 06/11] Implement insert ... on duplicate key update --- src/Query/InsertQuery.php | 11 +++++++++ src/Query/SqlQuery.php | 12 +++++++--- .../InsertOnDuplicateKeyUpdateExample.php | 23 +++++++++++++++++++ test/phpunit/Query/InsertQueryTest.php | 7 ++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test/phpunit/Helper/Query/InsertOnDuplicateKeyUpdateExample.php diff --git a/src/Query/InsertQuery.php b/src/Query/InsertQuery.php index 256e039..df15dde 100644 --- a/src/Query/InsertQuery.php +++ b/src/Query/InsertQuery.php @@ -7,6 +7,7 @@ public function __toString():string { self::PRE_QUERY_COMMENT => $this->preQuery(), "insert into" => $this->into(), "set" => $this->normaliseSet($this->set()), + "on duplicate key update" => $this->normaliseSet($this->onDuplicate()), ]); if($this->subQuery) { @@ -30,6 +31,16 @@ public function set():array { return []; } + /** + * Return an assignment list that matches the set() rules. It is often + * useful to return a call to set() directly, as it is usual to list the + * same assignments as part of the "on duplicate key update" section as + * in the "set" section. + */ + public function onDuplicate():array { + return []; + } + private function normaliseSet(array $setData):array { $normalised = []; foreach($setData as $i => $name) { diff --git a/src/Query/SqlQuery.php b/src/Query/SqlQuery.php index 4212ca3..7f50810 100644 --- a/src/Query/SqlQuery.php +++ b/src/Query/SqlQuery.php @@ -42,6 +42,9 @@ protected function processClauseList(array $clauses):string { elseif($name === "set") { $query .= $this->processSetClause($parts); } + elseif($name === "on duplicate key update") { + $query .= $this->processSetClause($parts, $name); + } elseif(strstr($name, "join")) { $query .= $this->processJoinClause( $name, @@ -123,12 +126,15 @@ private function processJoinClause( return $query; } - private function processSetClause(array $parts):string { + private function processSetClause( + array $parts, + string $prefix = "set" + ):string { $query = ""; foreach($parts as $key => $value) { if(strlen($query) === 0) { - $query .= "set " . PHP_EOL; + $query .= "$prefix " . PHP_EOL; } else { $query .= ", " . PHP_EOL; @@ -137,6 +143,6 @@ private function processSetClause(array $parts):string { $query .= "$key = $value"; } - return $query; + return $query . PHP_EOL; } } \ No newline at end of file diff --git a/test/phpunit/Helper/Query/InsertOnDuplicateKeyUpdateExample.php b/test/phpunit/Helper/Query/InsertOnDuplicateKeyUpdateExample.php new file mode 100644 index 0000000..8fcb5c0 --- /dev/null +++ b/test/phpunit/Helper/Query/InsertOnDuplicateKeyUpdateExample.php @@ -0,0 +1,23 @@ +set(); + } +} \ No newline at end of file diff --git a/test/phpunit/Query/InsertQueryTest.php b/test/phpunit/Query/InsertQueryTest.php index f8f1e85..c933a7b 100644 --- a/test/phpunit/Query/InsertQueryTest.php +++ b/test/phpunit/Query/InsertQueryTest.php @@ -4,6 +4,7 @@ use Gt\SqlBuilder\Test\Helper\Query\InsertExample; use Gt\SqlBuilder\Test\Helper\Query\InsertInferredPlaceholderExample; use Gt\SqlBuilder\Test\Helper\Query\InsertMixedPlaceholderExample; +use Gt\SqlBuilder\Test\Helper\Query\InsertOnDuplicateKeyUpdateExample; use Gt\SqlBuilder\Test\QueryTestCase; class InsertQueryTest extends QueryTestCase { @@ -24,4 +25,10 @@ public function testInsertMixedPlaceholder() { $sql = self::normalise($sut); self::assertEquals("insert into student set name = :name, dateOfBirth = :dateOfBirth, createdAt = :dateTimeNow, enabled = 1, type = :type", $sql); } + + public function testInsertOnDuplicateKeyUpdate() { + $sut = new InsertOnDuplicateKeyUpdateExample(); + $sql = self::normalise($sut); + self::assertEquals("insert into student set id = :id, name = :name on duplicate key update id = :id, name = :name", $sql); + } } \ No newline at end of file From 66053ca4a56fc46bc3de538ac618eb5428df5f70 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 22 Sep 2020 17:35:23 +0100 Subject: [PATCH 07/11] Implement missing insert into partition functionality --- src/Query/InsertQuery.php | 5 ++++ src/Query/SqlQuery.php | 11 ++++++++ .../Helper/Query/InsertPartitionExample.php | 25 +++++++++++++++++++ test/phpunit/Query/InsertQueryTest.php | 7 ++++++ 4 files changed, 48 insertions(+) create mode 100644 test/phpunit/Helper/Query/InsertPartitionExample.php diff --git a/src/Query/InsertQuery.php b/src/Query/InsertQuery.php index df15dde..a238d72 100644 --- a/src/Query/InsertQuery.php +++ b/src/Query/InsertQuery.php @@ -6,6 +6,7 @@ public function __toString():string { $query = $this->processClauseList([ self::PRE_QUERY_COMMENT => $this->preQuery(), "insert into" => $this->into(), + "partition" => $this->partition(), "set" => $this->normaliseSet($this->set()), "on duplicate key update" => $this->normaliseSet($this->onDuplicate()), ]); @@ -41,6 +42,10 @@ public function onDuplicate():array { return []; } + public function partition():array { + return []; + } + private function normaliseSet(array $setData):array { $normalised = []; foreach($setData as $i => $name) { diff --git a/src/Query/SqlQuery.php b/src/Query/SqlQuery.php index 7f50810..24da0bf 100644 --- a/src/Query/SqlQuery.php +++ b/src/Query/SqlQuery.php @@ -45,6 +45,9 @@ protected function processClauseList(array $clauses):string { elseif($name === "on duplicate key update") { $query .= $this->processSetClause($parts, $name); } + elseif($name === "partition") { + $query .= $this->processPartitionClause($parts); + } elseif(strstr($name, "join")) { $query .= $this->processJoinClause( $name, @@ -145,4 +148,12 @@ private function processSetClause( return $query . PHP_EOL; } + + private function processPartitionClause(array $parts):string { + return "partition ( " + . PHP_EOL + . implode(", " . PHP_EOL, $parts) + . " )" + . PHP_EOL; + } } \ No newline at end of file diff --git a/test/phpunit/Helper/Query/InsertPartitionExample.php b/test/phpunit/Helper/Query/InsertPartitionExample.php new file mode 100644 index 0000000..140c874 --- /dev/null +++ b/test/phpunit/Helper/Query/InsertPartitionExample.php @@ -0,0 +1,25 @@ + Date: Tue, 22 Sep 2020 17:42:02 +0100 Subject: [PATCH 08/11] Add failing tests for #6 replace --- test/phpunit/Query/ReplaceQueryTest.php | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/phpunit/Query/ReplaceQueryTest.php diff --git a/test/phpunit/Query/ReplaceQueryTest.php b/test/phpunit/Query/ReplaceQueryTest.php new file mode 100644 index 0000000..8f37134 --- /dev/null +++ b/test/phpunit/Query/ReplaceQueryTest.php @@ -0,0 +1,30 @@ + Date: Tue, 22 Sep 2020 17:52:33 +0100 Subject: [PATCH 09/11] Implement ReplaceQuery as base class for InsertQuery closes #6 --- src/Query/InsertQuery.php | 35 +------------ src/Query/ReplaceQuery.php | 52 +++++++++++++++++++ src/Query/SqlQuery.php | 4 ++ test/phpunit/Helper/Query/ReplaceExample.php | 21 ++++++++ .../ReplaceInferredPlaceholderExample.php | 19 +++++++ .../Query/ReplaceMixedPlaceholderExample.php | 22 ++++++++ .../Helper/Query/ReplacePartitionExample.php | 25 +++++++++ test/phpunit/Query/ReplaceQueryTest.php | 6 ++- 8 files changed, 150 insertions(+), 34 deletions(-) create mode 100644 src/Query/ReplaceQuery.php create mode 100644 test/phpunit/Helper/Query/ReplaceExample.php create mode 100644 test/phpunit/Helper/Query/ReplaceInferredPlaceholderExample.php create mode 100644 test/phpunit/Helper/Query/ReplaceMixedPlaceholderExample.php create mode 100644 test/phpunit/Helper/Query/ReplacePartitionExample.php diff --git a/src/Query/InsertQuery.php b/src/Query/InsertQuery.php index a238d72..8b40990 100644 --- a/src/Query/InsertQuery.php +++ b/src/Query/InsertQuery.php @@ -1,7 +1,7 @@ processClauseList([ self::PRE_QUERY_COMMENT => $this->preQuery(), @@ -9,6 +9,7 @@ public function __toString():string { "partition" => $this->partition(), "set" => $this->normaliseSet($this->set()), "on duplicate key update" => $this->normaliseSet($this->onDuplicate()), + self::POST_QUERY_COMMENT => $this->postQuery(), ]); if($this->subQuery) { @@ -18,20 +19,6 @@ public function __toString():string { return $query; } - public function into():array { - return []; - } - - /** - * Return either an associative array where the keys are the column - * names and the values are the assignment values, or an indexed array - * where the values are the column names where the values will be - * inferred as the column name prefixed with the colon character. - */ - public function set():array { - return []; - } - /** * Return an assignment list that matches the set() rules. It is often * useful to return a call to set() directly, as it is usual to list the @@ -41,22 +28,4 @@ public function set():array { public function onDuplicate():array { return []; } - - public function partition():array { - return []; - } - - private function normaliseSet(array $setData):array { - $normalised = []; - foreach($setData as $i => $name) { - if(is_int($i)) { - $normalised[$name] = ":$name"; - } - else { - $normalised[$i] = $name; - } - } - - return $normalised; - } } \ No newline at end of file diff --git a/src/Query/ReplaceQuery.php b/src/Query/ReplaceQuery.php new file mode 100644 index 0000000..81b11b7 --- /dev/null +++ b/src/Query/ReplaceQuery.php @@ -0,0 +1,52 @@ +processClauseList([ + self::PRE_QUERY_COMMENT => $this->preQuery(), + "replace into" => $this->into(), + "partition" => $this->partition(), + "set" => $this->normaliseSet($this->set()), + self::POST_QUERY_COMMENT => $this->postQuery(), + ]); + + if($this->subQuery) { + $query = "( $query )"; + } + + return $query; + } + + public function into():array { + return []; + } + + public function partition():array { + return []; + } + + /** + * Return either an associative array where the keys are the column + * names and the values are the assignment values, or an indexed array + * where the values are the column names where the values will be + * inferred as the column name prefixed with the colon character. + */ + public function set():array { + return []; + } + + protected function normaliseSet(array $setData):array { + $normalised = []; + foreach($setData as $i => $name) { + if(is_int($i)) { + $normalised[$name] = ":$name"; + } + else { + $normalised[$i] = $name; + } + } + + return $normalised; + } +} \ No newline at end of file diff --git a/src/Query/SqlQuery.php b/src/Query/SqlQuery.php index 24da0bf..45b5686 100644 --- a/src/Query/SqlQuery.php +++ b/src/Query/SqlQuery.php @@ -150,6 +150,10 @@ private function processSetClause( } private function processPartitionClause(array $parts):string { + if(empty($parts)) { + return ""; + } + return "partition ( " . PHP_EOL . implode(", " . PHP_EOL, $parts) diff --git a/test/phpunit/Helper/Query/ReplaceExample.php b/test/phpunit/Helper/Query/ReplaceExample.php new file mode 100644 index 0000000..52e8a08 --- /dev/null +++ b/test/phpunit/Helper/Query/ReplaceExample.php @@ -0,0 +1,21 @@ + ":name", + "dateOfBirth" => ":dateOfBirth", + ]; + } +} \ No newline at end of file diff --git a/test/phpunit/Helper/Query/ReplaceInferredPlaceholderExample.php b/test/phpunit/Helper/Query/ReplaceInferredPlaceholderExample.php new file mode 100644 index 0000000..636fc46 --- /dev/null +++ b/test/phpunit/Helper/Query/ReplaceInferredPlaceholderExample.php @@ -0,0 +1,19 @@ + ":dateTimeNow", + "enabled" => 1, + "type", + ]; + } +} \ No newline at end of file diff --git a/test/phpunit/Helper/Query/ReplacePartitionExample.php b/test/phpunit/Helper/Query/ReplacePartitionExample.php new file mode 100644 index 0000000..97ad20a --- /dev/null +++ b/test/phpunit/Helper/Query/ReplacePartitionExample.php @@ -0,0 +1,25 @@ + Date: Tue, 22 Sep 2020 21:02:04 +0100 Subject: [PATCH 10/11] Implement DeleteQuery closes #5 --- src/Query/DeleteQuery.php | 38 +++++++++++++++++++ test/phpunit/Helper/DeleteOrderByExample.php | 24 ++++++++++++ test/phpunit/Helper/Query/DeleteExample.php | 22 +++++++++++ .../Helper/Query/DeletePartitionExample.php | 26 +++++++++++++ test/phpunit/Query/DeleteQueryTest.php | 27 +++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 src/Query/DeleteQuery.php create mode 100644 test/phpunit/Helper/DeleteOrderByExample.php create mode 100644 test/phpunit/Helper/Query/DeleteExample.php create mode 100644 test/phpunit/Helper/Query/DeletePartitionExample.php create mode 100644 test/phpunit/Query/DeleteQueryTest.php diff --git a/src/Query/DeleteQuery.php b/src/Query/DeleteQuery.php new file mode 100644 index 0000000..2313483 --- /dev/null +++ b/src/Query/DeleteQuery.php @@ -0,0 +1,38 @@ +processClauseList([ + self::PRE_QUERY_COMMENT => $this->preQuery(), + "delete from" => $this->from(), + "partition" => $this->partition(), + "where" => $this->where(), + "order by" => $this->orderBy(), + "limit" => $this->limit(), + self::POST_QUERY_COMMENT => $this->postQuery(), + ]); + + return $query; + } + + public function from():array { + return []; + } + + public function partition():array { + return []; + } + + public function where():array { + return []; + } + + public function orderBy():array { + return []; + } + + public function limit():array { + return []; + } +} \ No newline at end of file diff --git a/test/phpunit/Helper/DeleteOrderByExample.php b/test/phpunit/Helper/DeleteOrderByExample.php new file mode 100644 index 0000000..8e0ec95 --- /dev/null +++ b/test/phpunit/Helper/DeleteOrderByExample.php @@ -0,0 +1,24 @@ + Date: Tue, 22 Sep 2020 21:14:26 +0100 Subject: [PATCH 11/11] Implement UpdateQuery closes #4 --- src/Query/DeleteQuery.php | 4 +- src/Query/UpdateQuery.php | 50 +++++++++++++++++++ test/phpunit/Helper/Query/UpdateExample.php | 18 +++++++ .../Helper/Query/UpdateExtendsExample.php | 11 ++++ test/phpunit/Query/UpdateQueryTest.php | 20 ++++++++ 5 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/Query/UpdateQuery.php create mode 100644 test/phpunit/Helper/Query/UpdateExample.php create mode 100644 test/phpunit/Helper/Query/UpdateExtendsExample.php create mode 100644 test/phpunit/Query/UpdateQueryTest.php diff --git a/src/Query/DeleteQuery.php b/src/Query/DeleteQuery.php index 2313483..29bea11 100644 --- a/src/Query/DeleteQuery.php +++ b/src/Query/DeleteQuery.php @@ -3,7 +3,7 @@ class DeleteQuery extends SqlQuery { public function __toString():string { - $query = $this->processClauseList([ + return $this->processClauseList([ self::PRE_QUERY_COMMENT => $this->preQuery(), "delete from" => $this->from(), "partition" => $this->partition(), @@ -12,8 +12,6 @@ public function __toString():string { "limit" => $this->limit(), self::POST_QUERY_COMMENT => $this->postQuery(), ]); - - return $query; } public function from():array { diff --git a/src/Query/UpdateQuery.php b/src/Query/UpdateQuery.php new file mode 100644 index 0000000..34c71fe --- /dev/null +++ b/src/Query/UpdateQuery.php @@ -0,0 +1,50 @@ +processClauseList([ + self::PRE_QUERY_COMMENT => $this->preQuery(), + "update" => $this->update(), + "set" => $this->normaliseSet($this->set()), + "where" => $this->where(), + "order by" => $this->orderBy(), + "limit" => $this->limit(), + self::POST_QUERY_COMMENT => $this->postQuery(), + ]); + } + + public function update():array { + return []; + } + + public function set():array { + return []; + } + + public function where():array { + return []; + } + + public function orderBy():array { + return []; + } + + public function limit():array { + return []; + } + + protected function normaliseSet(array $setData):array { + $normalised = []; + foreach($setData as $i => $name) { + if(is_int($i)) { + $normalised[$name] = ":$name"; + } + else { + $normalised[$i] = $name; + } + } + + return $normalised; + } +} \ No newline at end of file diff --git a/test/phpunit/Helper/Query/UpdateExample.php b/test/phpunit/Helper/Query/UpdateExample.php new file mode 100644 index 0000000..0a4c1cd --- /dev/null +++ b/test/phpunit/Helper/Query/UpdateExample.php @@ -0,0 +1,18 @@ + date_sub(now(), interval 30 day)" + ]; + } +} \ No newline at end of file diff --git a/test/phpunit/Query/UpdateQueryTest.php b/test/phpunit/Query/UpdateQueryTest.php new file mode 100644 index 0000000..2143c12 --- /dev/null +++ b/test/phpunit/Query/UpdateQueryTest.php @@ -0,0 +1,20 @@ + date_sub(now(), interval 30 day)", $sql); + } +} \ No newline at end of file