From e6db3fc89cbaf3fc81bfa6557c37abbdec44caa1 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Wed, 7 Feb 2024 23:05:25 +0800 Subject: [PATCH 01/15] fix: lock for update implementation fix: #819 fix: forPage SQL --- src/Oci8/Query/Grammars/OracleGrammar.php | 35 ++++++++++++----------- src/Oci8/Query/OracleBuilder.php | 18 ------------ tests/Database/Oci8QueryBuilderTest.php | 12 ++------ 3 files changed, 21 insertions(+), 44 deletions(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 0d2ceeec..c85edd98 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -70,7 +70,7 @@ public function compileExists(Builder $query) */ public function compileSelect(Builder $query) { - if ($query->unions && $query->aggregate) { + if (($query->unions || $query->havings) && $query->aggregate) { return $this->compileUnionAggregate($query); } @@ -83,24 +83,20 @@ public function compileSelect(Builder $query) $query->columns = ['*']; } - $components = $this->compileComponents($query); - // To compile the query, we'll spin through each component of the query and // see if that component exists. If it does we'll just call the compiler // function for the component which is responsible for making the SQL. + $components = $this->compileComponents($query); $sql = trim($this->concatenate($components)); - // If an offset is present on the query, we will need to wrap the query in - // a big "ANSI" offset syntax block. This is very nasty compared to the - // other database systems but is necessary for implementing features. - if ($this->isPaginationable($query, $components)) { - return $this->compileAnsiOffset($query, $components); - } - if ($query->unions) { $sql = $this->wrapUnion($sql).' '.$this->compileUnions($query); } + if (isset($query->limit) || isset($query->offset)) { + $sql = $this->compileAnsiOffset($query, $components); + } + $query->columns = $original; return $sql; @@ -177,7 +173,11 @@ protected function compileRowConstraint($query) */ protected function compileTableExpression($sql, $constraint, $query) { - if ($query->limit == 1 && is_null($query->offset)) { + if (isset($query->lock)) { + $constraint .= ' '.$this->compileLock($query, $query->lock); + } + + if (($query->limit == 1 && is_null($query->offset))) { return "select * from ({$sql}) where rownum {$constraint}"; } @@ -188,6 +188,7 @@ protected function compileTableExpression($sql, $constraint, $query) return "select t2.* from ( select rownum AS \"rn\", t1.* from ({$sql}) t1 where rownum <= {$finish}) t2 where t2.\"rn\" >= {$start}"; } + return "select t2.* from ( select rownum AS \"rn\", t1.* from ({$sql}) t1 ) t2 where t2.\"rn\" {$constraint}"; } @@ -455,7 +456,7 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, // create EMPTY_BLOB sql for each binary $binarySql = []; - foreach (explode(',', $binaryColumns) as $binary) { + foreach ((array) $binaryColumns as $binary) { $binarySql[] = "$binary = EMPTY_BLOB()"; } @@ -489,15 +490,15 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, */ protected function compileLock(Builder $query, $value) { - if (is_string($value)) { - return $value; + if (empty($query->wheres)) { + return ''; } - if ($value) { - return 'for update'; + if (is_string($value)) { + return $value; } - return ''; + return $value ? 'for update' : 'lock in share mode'; } /** diff --git a/src/Oci8/Query/OracleBuilder.php b/src/Oci8/Query/OracleBuilder.php index 2783a003..3b13ec73 100644 --- a/src/Oci8/Query/OracleBuilder.php +++ b/src/Oci8/Query/OracleBuilder.php @@ -141,24 +141,6 @@ public function whereIn($column, $values, $boolean = 'and', $not = false) return parent::whereIn($column, $values, $boolean, $not); } - /** - * Run the query as a "select" statement against the connection. - * - * @return array - */ - protected function runSelect() - { - if ($this->lock) { - $this->connection->beginTransaction(); - $result = $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); - $this->connection->commit(); - - return $result; - } - - return $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); - } - /** * Set the table which the query is targeting. * diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index 5635a5bf..e18d4175 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -1172,9 +1172,6 @@ public function testLimitAndOffsetToPaginateOne() ); } - /** - * @TODO: Review for page - */ public function testForPage() { $builder = $this->getBuilder(); @@ -1191,18 +1188,15 @@ public function testForPage() $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(2, 0); - // $this->assertSame('select * from "USERS" limit 0 offset 0', $builder->toSql()); - $this->assertSame('select * from "USERS"', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(0, 0); - // $this->assertSame('select * from "USERS" limit 0 offset 0', $builder->toSql()); - $this->assertSame('select * from "USERS"', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(-2, 0); - // $this->assertSame('select * from "USERS" limit 0 offset 0', $builder->toSql()); - $this->assertSame('select * from "USERS"', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', $builder->toSql()); } public function testGetCountForPaginationWithBindings() From a10c086b331921941e41be8a74d88956c9a98a67 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 7 Feb 2024 15:08:13 +0000 Subject: [PATCH 02/15] Apply fixes from StyleCI --- src/Oci8/Query/Grammars/OracleGrammar.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index c85edd98..918c3438 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -177,7 +177,7 @@ protected function compileTableExpression($sql, $constraint, $query) $constraint .= ' '.$this->compileLock($query, $query->lock); } - if (($query->limit == 1 && is_null($query->offset))) { + if ($query->limit == 1 && is_null($query->offset)) { return "select * from ({$sql}) where rownum {$constraint}"; } @@ -188,7 +188,6 @@ protected function compileTableExpression($sql, $constraint, $query) return "select t2.* from ( select rownum AS \"rn\", t1.* from ({$sql}) t1 where rownum <= {$finish}) t2 where t2.\"rn\" >= {$start}"; } - return "select t2.* from ( select rownum AS \"rn\", t1.* from ({$sql}) t1 ) t2 where t2.\"rn\" {$constraint}"; } From d25dff71d0f7e3d952083c18eb8c4a2449204873 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Wed, 7 Feb 2024 23:18:28 +0800 Subject: [PATCH 03/15] revert: multiple blob patch --- src/Oci8/Query/Grammars/OracleGrammar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 918c3438..82fe1150 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -455,7 +455,7 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, // create EMPTY_BLOB sql for each binary $binarySql = []; - foreach ((array) $binaryColumns as $binary) { + foreach (explode(',', $binaryColumns) as $binary) { $binarySql[] = "$binary = EMPTY_BLOB()"; } From a8a757d0841c8c4e0a1169e64bc87bef14a6d7de Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Wed, 7 Feb 2024 23:26:44 +0800 Subject: [PATCH 04/15] fix: use limit to skip --- src/Oci8/Query/Grammars/OracleGrammar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 82fe1150..1a39ee6f 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -489,7 +489,7 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, */ protected function compileLock(Builder $query, $value) { - if (empty($query->wheres)) { + if ($query->limit > 0) { return ''; } From 5198ea4f94a4d6ff49114c89786ff35b708a6e26 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Wed, 7 Feb 2024 23:58:45 +0800 Subject: [PATCH 05/15] test: enable lock tests --- tests/Database/Oci8QueryBuilderTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index e18d4175..187778b9 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -2508,15 +2508,12 @@ public function testOracleLock() $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); } catch (Oci8Exception $e) { // $this->assertEquals('select * from foo where bar = ? lock in share mode', $builder->toSql()); - $this->assertContains('Lock in share mode not yet supported!', $e->getMessage()); + $this->assertStringContainsString('Lock in share mode not yet supported!', $e->getMessage()); $this->assertEquals(['baz'], $builder->getBindings()); } } - /** - * @TODO: select with lock not yet supported. - */ - protected function testSelectWithLockUsesWritePdo() + public function testSelectWithLockUsesWritePdo() { $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once() From 82e9933c54d0dd06b380c551910afb234d4d3dd3 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 00:05:08 +0800 Subject: [PATCH 06/15] revert: transaction --- src/Oci8/Query/OracleBuilder.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Oci8/Query/OracleBuilder.php b/src/Oci8/Query/OracleBuilder.php index 3b13ec73..2783a003 100644 --- a/src/Oci8/Query/OracleBuilder.php +++ b/src/Oci8/Query/OracleBuilder.php @@ -141,6 +141,24 @@ public function whereIn($column, $values, $boolean = 'and', $not = false) return parent::whereIn($column, $values, $boolean, $not); } + /** + * Run the query as a "select" statement against the connection. + * + * @return array + */ + protected function runSelect() + { + if ($this->lock) { + $this->connection->beginTransaction(); + $result = $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); + $this->connection->commit(); + + return $result; + } + + return $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); + } + /** * Set the table which the query is targeting. * From 68be6389e707c1ab921a9825f85001deaedfcd99 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 01:46:51 +0800 Subject: [PATCH 07/15] fix: lock constraint --- src/Oci8/Query/Grammars/OracleGrammar.php | 39 +++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 1a39ee6f..d78c803d 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -93,7 +93,7 @@ public function compileSelect(Builder $query) $sql = $this->wrapUnion($sql).' '.$this->compileUnions($query); } - if (isset($query->limit) || isset($query->offset)) { + if ($this->isPaginationable($query, $components)) { $sql = $this->compileAnsiOffset($query, $components); } @@ -152,15 +152,21 @@ protected function compileRowConstraint($query) $start = $query->offset + 1; $finish = $query->offset + $query->limit; + $lock = ''; + + if (isset($query->lock)) { + $lock = ' '.$this->compileLock($query, $query->lock); + } + if ($query->limit == 1 && is_null($query->offset)) { - return '= 1'; + return '= 1'.$lock; } if ($query->offset && is_null($query->limit)) { - return ">= {$start}"; + return ">= {$start}".$lock;; } - return "between {$start} and {$finish}"; + return "between {$start} and {$finish}".$lock;; } /** @@ -173,10 +179,6 @@ protected function compileRowConstraint($query) */ protected function compileTableExpression($sql, $constraint, $query) { - if (isset($query->lock)) { - $constraint .= ' '.$this->compileLock($query, $query->lock); - } - if ($query->limit == 1 && is_null($query->offset)) { return "select * from ({$sql}) where rownum {$constraint}"; } @@ -489,15 +491,15 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, */ protected function compileLock(Builder $query, $value) { - if ($query->limit > 0) { - return ''; - } - if (is_string($value)) { return $value; } - return $value ? 'for update' : 'lock in share mode'; + if ($value) { + return 'for update'; + } + + return ''; } /** @@ -697,4 +699,15 @@ public function compileUpsert(Builder $query, array $values, array $uniqueBy, ar return $sql; } + + /** + * Compile the SQL statement to execute a savepoint rollback. + * + * @param string $name + * @return string + */ + public function compileSavepointRollBack($name) + { + return 'ROLLBACK TO '.$name; + } } From cfcfed3c6f823297f8ab19ca232958620cf84066 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 02:02:02 +0800 Subject: [PATCH 08/15] fix: do not apply lock when limit is set --- src/Oci8/Query/Grammars/OracleGrammar.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index d78c803d..43ae6e8d 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -93,7 +93,7 @@ public function compileSelect(Builder $query) $sql = $this->wrapUnion($sql).' '.$this->compileUnions($query); } - if ($this->isPaginationable($query, $components)) { + if (isset($query->limit) || isset($query->offset)) { $sql = $this->compileAnsiOffset($query, $components); } @@ -491,6 +491,10 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, */ protected function compileLock(Builder $query, $value) { + if ($query->limit > 0) { + return ''; + } + if (is_string($value)) { return $value; } From ae1770c394174317ca45565a4866a79fda3608bb Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 02:24:53 +0800 Subject: [PATCH 09/15] fix: move lock sql in compileSelect --- src/Oci8/Query/Grammars/OracleGrammar.php | 23 +- src/Oci8/Query/OracleBuilder.php | 18 - tests/Database/Oci8QueryBuilderTest.php | 888 ++++++++++++++-------- 3 files changed, 560 insertions(+), 369 deletions(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 43ae6e8d..917a408b 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -87,6 +87,7 @@ public function compileSelect(Builder $query) // see if that component exists. If it does we'll just call the compiler // function for the component which is responsible for making the SQL. $components = $this->compileComponents($query); + unset($components['lock']); $sql = trim($this->concatenate($components)); if ($query->unions) { @@ -97,6 +98,10 @@ public function compileSelect(Builder $query) $sql = $this->compileAnsiOffset($query, $components); } + if (isset($query->lock)) { + $sql .= ' '.$this->compileLock($query, $query->lock); + } + $query->columns = $original; return $sql; @@ -152,21 +157,15 @@ protected function compileRowConstraint($query) $start = $query->offset + 1; $finish = $query->offset + $query->limit; - $lock = ''; - - if (isset($query->lock)) { - $lock = ' '.$this->compileLock($query, $query->lock); - } - if ($query->limit == 1 && is_null($query->offset)) { - return '= 1'.$lock; + return '= 1'; } if ($query->offset && is_null($query->limit)) { - return ">= {$start}".$lock;; + return ">= {$start}"; } - return "between {$start} and {$finish}".$lock;; + return "between {$start} and {$finish}"; } /** @@ -491,15 +490,11 @@ public function compileUpdateLob(Builder $query, array $values, array $binaries, */ protected function compileLock(Builder $query, $value) { - if ($query->limit > 0) { - return ''; - } - if (is_string($value)) { return $value; } - if ($value) { + if (is_bool($value)) { return 'for update'; } diff --git a/src/Oci8/Query/OracleBuilder.php b/src/Oci8/Query/OracleBuilder.php index 2783a003..3b13ec73 100644 --- a/src/Oci8/Query/OracleBuilder.php +++ b/src/Oci8/Query/OracleBuilder.php @@ -141,24 +141,6 @@ public function whereIn($column, $values, $boolean = 'and', $not = false) return parent::whereIn($column, $values, $boolean, $not); } - /** - * Run the query as a "select" statement against the connection. - * - * @return array - */ - protected function runSelect() - { - if ($this->lock) { - $this->connection->beginTransaction(); - $result = $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); - $this->connection->commit(); - - return $result; - } - - return $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); - } - /** * Set the table which the query is targeting. * diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index 187778b9..58969d68 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -15,7 +15,6 @@ use Yajra\Oci8\Query\Grammars\OracleGrammar; use Yajra\Oci8\Query\OracleBuilder as Builder; use Yajra\Oci8\Query\Processors\OracleProcessor; -use Yajra\Pdo\Oci8\Exceptions\Oci8Exception; class Oci8QueryBuilderTest extends TestCase { @@ -31,6 +30,23 @@ public function testBasicSelect() $this->assertEquals('select * from "USERS"', $builder->toSql()); } + protected function getBuilder() + { + $grammar = new OracleGrammar; + $processor = m::mock(OracleProcessor::class); + + return new Builder($this->getConnection(), $grammar, $processor); + } + + protected function getConnection() + { + $connection = m::mock(ConnectionInterface::class); + $connection->shouldReceive('getConfig')->andReturn(''); + $connection->shouldReceive('getDatabaseName')->andReturn('database'); + + return $connection; + } + public function testBasicSelectWithGetColumns() { $builder = $this->getBuilder(); @@ -78,6 +94,14 @@ public function testBasicSelectUseWritePdo() $builder->select('*')->from('users')->get(); } + protected function getBuilderWithProcessor() + { + $grammar = new OracleGrammar; + $processor = new OracleProcessor; + + return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); + } + public function testBasicTableWrappingProtectsQuotationMarks() { $builder = $this->getBuilder(); @@ -160,7 +184,8 @@ public function testJoinAliasesWithPrefix() $builder = $this->getBuilder(); $builder->getGrammar()->setTablePrefix('prefix_'); $builder->select('*')->from('services')->join('translations AS t', 't.item_id', '=', 'services.id'); - $this->assertSame('select * from "PREFIX_SERVICES" inner join "PREFIX_TRANSLATIONS" t on "PREFIX_T"."ITEM_ID" = "PREFIX_SERVICES"."ID"', $builder->toSql()); + $this->assertSame('select * from "PREFIX_SERVICES" inner join "PREFIX_TRANSLATIONS" t on "PREFIX_T"."ITEM_ID" = "PREFIX_SERVICES"."ID"', + $builder->toSql()); } public function testBasicTableWrapping() @@ -386,15 +411,18 @@ public function testDateBasedOrWheresAcceptsTwoArguments() $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', 1)->orWhereDay('CREATED_AT', 1); - $this->assertSame('select * from "USERS" where "ID" = ? or extract (day from "CREATED_AT") = ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or extract (day from "CREATED_AT") = ?', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', 1)->orWhereMonth('CREATED_AT', 1); - $this->assertSame('select * from "USERS" where "ID" = ? or extract (month from "CREATED_AT") = ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or extract (month from "CREATED_AT") = ?', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', 1)->orWhereYear('created_at', 1); - $this->assertSame('select * from "USERS" where "ID" = ? or extract (year from "CREATED_AT") = ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or extract (year from "CREATED_AT") = ?', + $builder->toSql()); } public function testDateBasedWheresExpressionIsNotBound() @@ -440,7 +468,8 @@ public function testOrWhereDay() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereDay('created_at', '=', 1)->orWhereDay('created_at', '=', 2); - $this->assertSame('select * from "USERS" where extract (day from "CREATED_AT") = ? or extract (day from "CREATED_AT") = ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where extract (day from "CREATED_AT") = ? or extract (day from "CREATED_AT") = ?', + $builder->toSql()); $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); } @@ -456,7 +485,8 @@ public function testOrWhereMonth() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereMonth('created_at', '=', 5)->orWhereMonth('created_at', '=', 6); - $this->assertSame('select * from "USERS" where extract (month from "CREATED_AT") = ? or extract (month from "CREATED_AT") = ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where extract (month from "CREATED_AT") = ? or extract (month from "CREATED_AT") = ?', + $builder->toSql()); $this->assertEquals([0 => 5, 1 => 6], $builder->getBindings()); } @@ -472,7 +502,8 @@ public function testOrWhereYear() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereYear('created_at', '=', 2014)->orWhereYear('created_at', '=', 2015); - $this->assertSame('select * from "USERS" where extract (year from "CREATED_AT") = ? or extract (year from "CREATED_AT") = ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where extract (year from "CREATED_AT") = ? or extract (year from "CREATED_AT") = ?', + $builder->toSql()); $this->assertEquals([0 => 2014, 1 => 2015], $builder->getBindings()); } @@ -542,12 +573,14 @@ public function testWhereBetweenColumns() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereBetweenColumns('id', ['users.created_at', 'users.updated_at']); - $this->assertSame('select * from "USERS" where "ID" between "USERS"."CREATED_AT" and "USERS"."UPDATED_AT"', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" between "USERS"."CREATED_AT" and "USERS"."UPDATED_AT"', + $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereNotBetweenColumns('id', ['created_at', 'updated_at']); - $this->assertSame('select * from "USERS" where "ID" not between "CREATED_AT" and "UPDATED_AT"', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" not between "CREATED_AT" and "UPDATED_AT"', + $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); @@ -695,8 +728,12 @@ public function testEmptyWhereIntegerNotInRaw() public function testBasicWhereColumn() { $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereColumn('first_name', 'last_name')->orWhereColumn('first_name', 'middle_name'); - $this->assertSame('select * from "USERS" where "FIRST_NAME" = "LAST_NAME" or "FIRST_NAME" = "MIDDLE_NAME"', $builder->toSql()); + $builder->select('*') + ->from('users') + ->whereColumn('first_name', 'last_name') + ->orWhereColumn('first_name', 'middle_name'); + $this->assertSame('select * from "USERS" where "FIRST_NAME" = "LAST_NAME" or "FIRST_NAME" = "MIDDLE_NAME"', + $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); @@ -714,7 +751,8 @@ public function testArrayWhereColumn() $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereColumn($conditions); - $this->assertSame('select * from "USERS" where ("FIRST_NAME" = "LAST_NAME" and "UPDATED_AT" > "CREATED_AT")', $builder->toSql()); + $this->assertSame('select * from "USERS" where ("FIRST_NAME" = "LAST_NAME" and "UPDATED_AT" > "CREATED_AT")', + $builder->toSql()); $this->assertEquals([], $builder->getBindings()); } @@ -800,7 +838,8 @@ public function testUnionWithJoin() $join->on('dogs.breed_id', '=', 'breeds.id') ->where('breeds.is_native', '=', 1); })); - $this->assertSame('(select * from "USERS") union (select * from "DOGS" inner join "BREEDS" on "DOGS"."BREED_ID" = "BREEDS"."ID" and "BREEDS"."IS_NATIVE" = ?)', $builder->toSql()); + $this->assertSame('(select * from "USERS") union (select * from "DOGS" inner join "BREEDS" on "DOGS"."BREED_ID" = "BREEDS"."ID" and "BREEDS"."IS_NATIVE" = ?)', + $builder->toSql()); $this->assertEquals([0 => 1], $builder->getBindings()); } @@ -902,7 +941,8 @@ public function testArrayWhereNulls() $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', '=', 1)->orWhereNull(['id', 'expires_at']); - $this->assertSame('select * from "USERS" where "ID" = ? or "ID" is null or "EXPIRES_AT" is null', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or "ID" is null or "EXPIRES_AT" is null', + $builder->toSql()); $this->assertEquals([0 => 1], $builder->getBindings()); } @@ -923,12 +963,14 @@ public function testArrayWhereNotNulls() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereNotNull(['id', 'expires_at']); - $this->assertSame('select * from "USERS" where "ID" is not null and "EXPIRES_AT" is not null', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" is not null and "EXPIRES_AT" is not null', + $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', '>', 1)->orWhereNotNull(['id', 'expires_at']); - $this->assertSame('select * from "USERS" where "ID" > ? or "ID" is not null or "EXPIRES_AT" is not null', $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" > ? or "ID" is not null or "EXPIRES_AT" is not null', + $builder->toSql()); $this->assertEquals([0 => 1], $builder->getBindings()); } @@ -956,7 +998,9 @@ public function testGroupBys() $this->assertEquals(['foo'], $builder->getBindings()); $builder = $this->getBuilder(); - $builder->havingRaw('?', ['havingRawBinding'])->groupByRaw('?', ['groupByRawBinding'])->whereRaw('?', ['whereRawBinding']); + $builder->havingRaw('?', ['havingRawBinding']) + ->groupByRaw('?', ['groupByRawBinding']) + ->whereRaw('?', ['whereRawBinding']); $this->assertEquals(['whereRawBinding', 'groupByRawBinding', 'havingRawBinding'], $builder->getBindings()); } @@ -985,7 +1029,8 @@ public function testOrderBys() $builder->select('*')->from('posts')->where('public', 1) ->unionAll($this->getBuilder()->select('*')->from('videos')->where('public', 1)) ->orderByRaw('field(category, ?, ?) asc', ['news', 'opinion']); - $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by field(category, ?, ?) asc', $builder->toSql()); + $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by field(category, ?, ?) asc', + $builder->toSql()); $this->assertEquals([1, 1, 'news', 'opinion'], $builder->getBindings()); } @@ -1007,7 +1052,8 @@ public function testReorder() $builder->select('*')->from('first'); $builder->union($this->getBuilder()->select('*')->from('second')); $builder->orderBy('name'); - $this->assertSame('(select * from "FIRST") union (select * from "SECOND") order by "NAME" asc', $builder->toSql()); + $this->assertSame('(select * from "FIRST") union (select * from "SECOND") order by "NAME" asc', + $builder->toSql()); $builder->reorder(); $this->assertSame('(select * from "FIRST") union (select * from "SECOND")', $builder->toSql()); @@ -1038,7 +1084,8 @@ public function testOrderBySubQueries() $builder->select('*')->from('posts')->where('public', 1) ->unionAll($this->getBuilder()->select('*')->from('videos')->where('public', 1)) ->orderBy($this->getBuilder()->selectRaw('field(category, ?, ?)', ['news', 'opinion'])); - $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by (select field(category, ?, ?)) asc', $builder->toSql()); + $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by (select field(category, ?, ?)) asc', + $builder->toSql()); $this->assertEquals([1, 1, 'news', 'opinion'], $builder->getBindings()); } @@ -1076,23 +1123,39 @@ public function testHavingFollowedBySelectGet() { $builder = $this->getBuilder(); $query = 'select "CATEGORY", count(*) as "TOTAL" from "ITEM" where "DEPARTMENT" = ? group by "CATEGORY" having "TOTAL" > ?'; - $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular', 3], true)->andReturn([['category' => 'rock', 'total' => 5]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with($query, ['popular', 3], true) + ->andReturn([['category' => 'rock', 'total' => 5]]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); $builder->from('item'); - $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')])->where('department', '=', 'popular')->groupBy('category')->having('total', '>', 3)->get(); + $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')]) + ->where('department', '=', 'popular') + ->groupBy('category') + ->having('total', '>', 3) + ->get(); $this->assertEquals([['category' => 'rock', 'total' => 5]], $result->all()); // Using \Raw value $builder = $this->getBuilder(); $query = 'select "CATEGORY", count(*) as "TOTAL" from "ITEM" where "DEPARTMENT" = ? group by "CATEGORY" having "TOTAL" > 3'; - $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular'], true)->andReturn([['category' => 'rock', 'total' => 5]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with($query, ['popular'], true) + ->andReturn([['category' => 'rock', 'total' => 5]]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); $builder->from('item'); - $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')])->where('department', '=', 'popular')->groupBy('category')->having('total', '>', new Raw('3'))->get(); + $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')]) + ->where('department', '=', 'popular') + ->groupBy('category') + ->having('total', '>', new Raw('3')) + ->get(); $this->assertEquals([['category' => 'rock', 'total' => 5]], $result->all()); } @@ -1176,27 +1239,33 @@ public function testForPage() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(2, 15); - $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 30) t2 where t2."rn" >= 16', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 30) t2 where t2."rn" >= 16', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(0, 15); - $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 1', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 1', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(-2, 15); - $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 1', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 1', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(2, 0); - $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(0, 0); - $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->forPage(-2, 0); - $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', $builder->toSql()); + $this->assertSame('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 0) t2 where t2."rn" >= 1', + $builder->toSql()); } public function testGetCountForPaginationWithBindings() @@ -1206,7 +1275,11 @@ public function testGetCountForPaginationWithBindings() $q->select('body')->from('posts')->where('id', 4); }, 'post'); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select count(*) as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1222,7 +1295,11 @@ public function testGetCountForPaginationWithColumnAliases() $columns = ['body as post_body', 'teaser', 'posts.created as published']; $builder->from('posts')->select($columns); - $builder->getConnection()->shouldReceive('select')->once()->with('select count("BODY", "TEASER", "POSTS"."CREATED") as aggregate from "POSTS"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select count("BODY", "TEASER", "POSTS"."CREATED") as aggregate from "POSTS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1236,7 +1313,12 @@ public function testGetCountForPaginationWithUnion() $builder = $this->getBuilder(); $builder->from('posts')->select('id')->union($this->getBuilder()->from('videos')->select('id')); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "ID" from "POSTS") union (select "ID" from "VIDEOS")) "TEMP_TABLE"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select count(*) as aggregate from ((select "ID" from "POSTS") union (select "ID" from "VIDEOS")) "TEMP_TABLE"', + [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1337,17 +1419,17 @@ public function testBasicJoins() { $builder = $this->getBuilder(); $builder->select('*') - ->from('users') - ->join('contacts', 'users.id', '=', 'contacts.id') - ->leftJoin('photos', 'users.id', '=', 'photos.id'); + ->from('users') + ->join('contacts', 'users.id', '=', 'contacts.id') + ->leftJoin('photos', 'users.id', '=', 'photos.id'); $this->assertEquals('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" left join "PHOTOS" on "USERS"."ID" = "PHOTOS"."ID"', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*') - ->from('users') - ->leftJoinWhere('photos', 'users.id', '=', 'bar') - ->joinWhere('photos', 'users.id', '=', 'foo'); + ->from('users') + ->leftJoinWhere('photos', 'users.id', '=', 'bar') + ->joinWhere('photos', 'users.id', '=', 'foo'); $this->assertEquals('select * from "USERS" left join "PHOTOS" on "USERS"."ID" = ? inner join "PHOTOS" on "USERS"."ID" = ?', $builder->toSql()); $this->assertEquals(['bar', 'foo'], $builder->getBindings()); @@ -1356,8 +1438,11 @@ public function testBasicJoins() public function testCrossJoinSubs() { $builder = $this->getBuilder(); - $builder->selectRaw('(sale / overall.sales) * 100 AS percent_of_total')->from('sales')->crossJoinSub($this->getBuilder()->selectRaw('SUM(sale) AS sales')->from('sales'), 'overall'); - $this->assertSame('select (sale / overall.sales) * 100 AS percent_of_total from "SALES" cross join (select SUM(sale) AS sales from "SALES") "OVERALL"', $builder->toSql()); + $builder->selectRaw('(sale / overall.sales) * 100 AS percent_of_total') + ->from('sales') + ->crossJoinSub($this->getBuilder()->selectRaw('SUM(sale) AS sales')->from('sales'), 'overall'); + $this->assertSame('select (sale / overall.sales) * 100 AS percent_of_total from "SALES" cross join (select SUM(sale) AS sales from "SALES") "OVERALL"', + $builder->toSql()); } public function testComplexJoin() @@ -1384,13 +1469,15 @@ public function testJoinWhereNull() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is null', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is null', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is null', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is null', + $builder->toSql()); } public function testJoinWhereNotNull() @@ -1399,13 +1486,15 @@ public function testJoinWhereNotNull() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereNotNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is not null', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is not null', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereNotNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is not null', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is not null', + $builder->toSql()); } public function testJoinWhereIn() @@ -1414,14 +1503,16 @@ public function testJoinWhereIn() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (?, ?, ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (?, ?, ?)', + $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (?, ?, ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (?, ?, ?)', + $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); } @@ -1433,7 +1524,8 @@ public function testJoinWhereInSubquery() $q->select('name')->from('contacts')->where('name', 'baz'); $j->on('users.id', '=', 'contacts.id')->whereIn('contacts.name', $q); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', + $builder->toSql()); $this->assertEquals(['baz'], $builder->getBindings()); $builder = $this->getBuilder(); @@ -1442,7 +1534,8 @@ public function testJoinWhereInSubquery() $q->select('name')->from('contacts')->where('name', 'baz'); $j->on('users.id', '=', 'contacts.id')->orWhereIn('contacts.name', $q); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', + $builder->toSql()); $this->assertEquals(['baz'], $builder->getBindings()); } @@ -1452,14 +1545,16 @@ public function testJoinWhereNotIn() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereNotIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" not in (?, ?, ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" not in (?, ?, ?)', + $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereNotIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" not in (?, ?, ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" not in (?, ?, ?)', + $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); } @@ -1471,7 +1566,8 @@ public function testJoinsWithNestedConditions() $j->where('contacts.country', '=', 'US')->orWhere('contacts.is_partner', '=', 1); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" = ?)', $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" = ?)', + $builder->toSql()); $this->assertEquals(['US', 1], $builder->getBindings()); $builder = $this->getBuilder(); @@ -1484,7 +1580,8 @@ public function testJoinsWithNestedConditions() }); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."IS_ACTIVE" = ? or (("CONTACTS"."COUNTRY" = ? or "CONTACTS"."TYPE" = "USERS"."TYPE") and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" is null))', $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."IS_ACTIVE" = ? or (("CONTACTS"."COUNTRY" = ? or "CONTACTS"."TYPE" = "USERS"."TYPE") and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" is null))', + $builder->toSql()); $this->assertEquals([1, 'UK', 'US'], $builder->getBindings()); } @@ -1498,7 +1595,8 @@ public function testJoinsWithAdvancedConditions() ->orWhereRaw('year(contacts.created_at) = 2016'); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("ROLE" = ? or "CONTACTS"."DISABLED" is null or year(contacts.created_at) = 2016)', $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("ROLE" = ? or "CONTACTS"."DISABLED" is null or year(contacts.created_at) = 2016)', + $builder->toSql()); $this->assertEquals(['admin'], $builder->getBindings()); } @@ -1512,7 +1610,8 @@ public function testJoinsWithSubqueryCondition() ->whereNull('deleted_at'); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACT_TYPE_ID" in (select "ID" from "CONTACT_TYPES" where "CATEGORY_ID" = ? and "DELETED_AT" is null)', $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACT_TYPE_ID" in (select "ID" from "CONTACT_TYPES" where "CATEGORY_ID" = ? and "DELETED_AT" is null)', + $builder->toSql()); $this->assertEquals(['1'], $builder->getBindings()); $builder = $this->getBuilder(); @@ -1524,7 +1623,8 @@ public function testJoinsWithSubqueryCondition() ->whereNull('deleted_at'); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null)', $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null)', + $builder->toSql()); $this->assertEquals(['1'], $builder->getBindings()); } @@ -1543,55 +1643,66 @@ public function testJoinsWithAdvancedSubqueryCondition() }); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null and "LEVEL_ID" in (select "ID" from "LEVELS" where "IS_ACTIVE" = ?))', $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null and "LEVEL_ID" in (select "ID" from "LEVELS" where "IS_ACTIVE" = ?))', + $builder->toSql()); $this->assertEquals(['1', true], $builder->getBindings()); } public function testJoinsWithNestedJoins() { $builder = $this->getBuilder(); - $builder->select('users.id', 'contacts.id', 'contact_types.id')->from('users')->leftJoin('contacts', function ($j) { - $j->on('users.id', 'contacts.id')->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id'); - }); - $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID"', $builder->toSql()); + $builder->select('users.id', 'contacts.id', 'contact_types.id') + ->from('users') + ->leftJoin('contacts', function ($j) { + $j->on('users.id', 'contacts.id') + ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id'); + }); + $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID"', + $builder->toSql()); } public function testJoinsWithMultipleNestedJoins() { $builder = $this->getBuilder(); - $builder->select('users.id', 'contacts.id', 'contact_types.id', 'countrys.id', 'planets.id')->from('users')->leftJoin('contacts', function ($j) { - $j->on('users.id', 'contacts.id') - ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') - ->leftJoin('countrys', function ($q) { - $q->on('contacts.country', '=', 'countrys.country') - ->join('planets', function ($q) { - $q->on('countrys.planet_id', '=', 'planet.id') - ->where('planet.is_settled', '=', 1) - ->where('planet.population', '>=', 10000); - }); - }); - }); - $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID", "COUNTRYS"."ID", "PLANETS"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID" left join ("COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? and "PLANET"."POPULATION" >= ?) on "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY") on "USERS"."ID" = "CONTACTS"."ID"', $builder->toSql()); + $builder->select('users.id', 'contacts.id', 'contact_types.id', 'countrys.id', 'planets.id') + ->from('users') + ->leftJoin('contacts', function ($j) { + $j->on('users.id', 'contacts.id') + ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') + ->leftJoin('countrys', function ($q) { + $q->on('contacts.country', '=', 'countrys.country') + ->join('planets', function ($q) { + $q->on('countrys.planet_id', '=', 'planet.id') + ->where('planet.is_settled', '=', 1) + ->where('planet.population', '>=', 10000); + }); + }); + }); + $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID", "COUNTRYS"."ID", "PLANETS"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID" left join ("COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? and "PLANET"."POPULATION" >= ?) on "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY") on "USERS"."ID" = "CONTACTS"."ID"', + $builder->toSql()); $this->assertEquals(['1', 10000], $builder->getBindings()); } public function testJoinsWithNestedJoinWithAdvancedSubqueryCondition() { $builder = $this->getBuilder(); - $builder->select('users.id', 'contacts.id', 'contact_types.id')->from('users')->leftJoin('contacts', function ($j) { - $j->on('users.id', 'contacts.id') - ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') - ->whereExists(function ($q) { - $q->select('*')->from('countrys') - ->whereColumn('contacts.country', '=', 'countrys.country') - ->join('planets', function ($q) { - $q->on('countrys.planet_id', '=', 'planet.id') - ->where('planet.is_settled', '=', 1); - }) - ->where('planet.population', '>=', 10000); - }); - }); - $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID" and exists (select * from "COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? where "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY" and "PLANET"."POPULATION" >= ?)', $builder->toSql()); + $builder->select('users.id', 'contacts.id', 'contact_types.id') + ->from('users') + ->leftJoin('contacts', function ($j) { + $j->on('users.id', 'contacts.id') + ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') + ->whereExists(function ($q) { + $q->select('*')->from('countrys') + ->whereColumn('contacts.country', '=', 'countrys.country') + ->join('planets', function ($q) { + $q->on('countrys.planet_id', '=', 'planet.id') + ->where('planet.is_settled', '=', 1); + }) + ->where('planet.population', '>=', 10000); + }); + }); + $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID" and exists (select * from "COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? where "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY" and "PLANET"."POPULATION" >= ?)', + $builder->toSql()); $this->assertEquals(['1', 10000], $builder->getBindings()); } @@ -1622,8 +1733,8 @@ public function testJoinSub() $sub2 = $this->getBuilder()->from('contacts')->where('name', 'bar'); $sub2->getConnection()->shouldReceive('getDatabaseName')->andReturn('oracle'); $builder->from('users') - ->joinSub($sub1, 'sub1', 'users.id', '=', 1, 'inner', true) - ->joinSub($sub2, 'sub2', 'users.id', '=', 'sub2.user_id'); + ->joinSub($sub1, 'sub1', 'users.id', '=', 1, 'inner', true) + ->joinSub($sub2, 'sub2', 'users.id', '=', 'sub2.user_id'); $expected = 'select * from "USERS" '; $expected .= 'inner join (select * from "CONTACTS" where "NAME" = ?) "SUB1" on "USERS"."ID" = ? '; $expected .= 'inner join (select * from "CONTACTS" where "NAME" = ?) "SUB2" on "USERS"."ID" = "SUB2"."USER_ID"'; @@ -1640,7 +1751,8 @@ public function testJoinSubWithPrefix() $builder = $this->getBuilder(); $builder->getGrammar()->setTablePrefix('prefix_'); $builder->from('users')->joinSub('select * from "CONTACTS"', 'sub', 'users.id', '=', 'sub.id'); - $this->assertSame('select * from "PREFIX_USERS" inner join (select * from "CONTACTS") "PREFIX_SUB" on "PREFIX_USERS"."ID" = "PREFIX_SUB"."ID"', $builder->toSql()); + $this->assertSame('select * from "PREFIX_USERS" inner join (select * from "CONTACTS") "PREFIX_SUB" on "PREFIX_USERS"."ID" = "PREFIX_SUB"."ID"', + $builder->toSql()); } public function testLeftJoinSub() @@ -1682,18 +1794,18 @@ public function testFindReturnsFirstResultByID() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select * from (select * from "USERS" where "ID" = ?) where rownum = 1', - [1], true) - ->andReturn([['foo' => 'bar']]); + ->shouldReceive('select') + ->once() + ->with('select * from (select * from "USERS" where "ID" = ?) where rownum = 1', + [1], true) + ->andReturn([['foo' => 'bar']]); $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->find(1); $this->assertEquals(['foo' => 'bar'], $results); } @@ -1702,17 +1814,17 @@ public function testFirstMethodReturnsFirstResult() { $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select') - ->once() - ->with('select * from (select * from "USERS" where "ID" = ?) where rownum = 1', - [1], true) - ->andReturn([['foo' => 'bar']]); + ->once() + ->with('select * from (select * from "USERS" where "ID" = ?) where rownum = 1', + [1], true) + ->andReturn([['foo' => 'bar']]); $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->first(); $this->assertEquals(['foo' => 'bar'], $results); } @@ -1721,17 +1833,28 @@ public function testPluckMethodGetsCollectionOfColumnValues() { $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']])->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getProcessor() + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->pluck('foo'); $this->assertEquals(['bar', 'baz'], $results->all()); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->andReturn([['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']])->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getConnection()->shouldReceive('select')->once()->andReturn([ + ['id' => 1, 'foo' => 'bar'], + ['id' => 10, 'foo' => 'baz'], + ]); + $builder->getProcessor() + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->pluck('foo', 'id'); $this->assertEquals([1 => 'bar', 10 => 'baz'], $results->all()); } @@ -1741,18 +1864,26 @@ public function testImplode() // Test without glue. $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']])->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getProcessor() + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->implode('foo'); $this->assertSame('barbaz', $results); // Test with glue. $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']])->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getProcessor() + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->implode('foo', ','); $this->assertSame('bar,baz', $results); } @@ -1760,8 +1891,16 @@ public function testImplode() public function testValueMethodReturnsSingleColumn() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from (select "FOO" from "USERS" where "ID" = ?) where rownum = 1', [1], true)->andReturn([['foo' => 'bar']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturn([['foo' => 'bar']]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select * from (select "FOO" from "USERS" where "ID" = ?) where rownum = 1', [1], true) + ->andReturn([['foo' => 'bar']]); + $builder->getProcessor() + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar']]) + ->andReturn([['foo' => 'bar']]); $results = $builder->from('users')->where('id', '=', 1)->value('foo'); $this->assertSame('bar', $results); } @@ -1771,12 +1910,12 @@ public function testListMethodsGetsArrayOfColumnValues() $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->pluck('foo'); $this->assertEquals(['bar', 'baz'], $results->all()); @@ -1786,12 +1925,12 @@ public function testListMethodsGetsArrayOfColumnValues() ['id' => 10, 'foo' => 'baz'], ]); $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + ->shouldReceive('processSelect') + ->once() + ->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']]) + ->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->pluck('foo', 'id'); $this->assertEquals([1 => 'bar', 10 => 'baz'], $results->all()); } @@ -1799,7 +1938,11 @@ public function testListMethodsGetsArrayOfColumnValues() public function testAggregateFunctions() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select count(*) as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1807,17 +1950,29 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select 1 as "exists" from "USERS" where rownum = 1', [], true)->andReturn([['exists' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select 1 as "exists" from "USERS" where rownum = 1', [], true) + ->andReturn([['exists' => 1]]); $results = $builder->from('users')->exists(); $this->assertTrue($results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select 1 as "exists" from "USERS" where rownum = 1', [], true)->andReturn([['exists' => 0]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select 1 as "exists" from "USERS" where rownum = 1', [], true) + ->andReturn([['exists' => 0]]); $results = $builder->from('users')->doesntExist(); $this->assertTrue($results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select max("ID") as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select max("ID") as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1825,7 +1980,11 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select min("ID") as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select min("ID") as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1833,7 +1992,11 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select sum("ID") as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection() + ->shouldReceive('select') + ->once() + ->with('select sum("ID") as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1994,10 +2157,10 @@ public function testAggregateCountFunction() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select count(*) as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + ->shouldReceive('select') + ->once() + ->with('select count(*) as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2009,9 +2172,9 @@ public function testAggregateExistsFunction() { $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select') - ->once() - ->with('select 1 as "exists" from "USERS" where rownum = 1', [], true) - ->andReturn([['exists' => 1]]); + ->once() + ->with('select 1 as "exists" from "USERS" where rownum = 1', [], true) + ->andReturn([['exists' => 1]]); $results = $builder->from('users')->exists(); $this->assertTrue($results); } @@ -2020,10 +2183,10 @@ public function testAggregateMaxFunction() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select max("ID") as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + ->shouldReceive('select') + ->once() + ->with('select max("ID") as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2035,10 +2198,10 @@ public function testAggregateMinFunction() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select min("ID") as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + ->shouldReceive('select') + ->once() + ->with('select min("ID") as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2050,10 +2213,10 @@ public function testAggregateSumFunction() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select sum("ID") as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + ->shouldReceive('select') + ->once() + ->with('select sum("ID") as aggregate from "USERS"', [], true) + ->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2065,10 +2228,10 @@ public function testInsertMethod() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('insert') - ->once() - ->with('insert into "USERS" ("EMAIL") values (?)', ['foo']) - ->andReturn(true); + ->shouldReceive('insert') + ->once() + ->with('insert into "USERS" ("EMAIL") values (?)', ['foo']) + ->andReturn(true); $result = $builder->from('users')->insert(['email' => 'foo']); $this->assertTrue($result); } @@ -2076,7 +2239,11 @@ public function testInsertMethod() public function testInsertUsingMethod() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('affectingStatement')->once()->with('insert into "TABLE1" ("FOO") select "BAR" from "TABLE2" where "FOREIGN_ID" = ?', [5])->andReturn(1); + $builder->getConnection() + ->shouldReceive('affectingStatement') + ->once() + ->with('insert into "TABLE1" ("FOO") select "BAR" from "TABLE2" where "FOREIGN_ID" = ?', [5]) + ->andReturn(1); $result = $builder->from('table1')->insertUsing( ['foo'], @@ -2107,10 +2274,10 @@ public function testMultipleInsertMethod() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('insert') - ->once() - ->with('insert into "USERS" ("EMAIL") select ? from dual union all select ? from dual ', ['foo', 'foo']) - ->andReturn(true); + ->shouldReceive('insert') + ->once() + ->with('insert into "USERS" ("EMAIL") select ? from dual union all select ? from dual ', ['foo', 'foo']) + ->andReturn(true); $data[] = ['email' => 'foo']; $data[] = ['email' => 'foo']; $result = $builder->from('users')->insert($data); @@ -2121,10 +2288,10 @@ public function testInsertGetIdMethod() { $builder = $this->getBuilder(); $builder->getProcessor() - ->shouldReceive('processInsertGetId') - ->once() - ->with($builder, 'insert into "USERS" ("EMAIL") values (?) returning "ID" into ?', ['foo'], 'id') - ->andReturn(1); + ->shouldReceive('processInsertGetId') + ->once() + ->with($builder, 'insert into "USERS" ("EMAIL") values (?) returning "ID" into ?', ['foo'], 'id') + ->andReturn(1); $result = $builder->from('users')->insertGetId(['email' => 'foo'], 'id'); $this->assertEquals(1, $result); } @@ -2152,7 +2319,10 @@ public function testInsertGetIdMethodRemovesExpressions() public function testInsertGetIdWithEmptyValues() { $builder = $this->getBuilder(); - $builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'insert into "USERS" () values () returning "ID" into ?', [], null); + $builder->getProcessor() + ->shouldReceive('processInsertGetId') + ->once() + ->with($builder, 'insert into "USERS" () values () returning "ID" into ?', [], null); $builder->from('users')->insertGetId([]); } @@ -2175,8 +2345,16 @@ public function testInsertMethodRespectsRawBindings() public function testMultipleInsertsWithExpressionValues() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('insert')->once()->with('insert into "USERS" ("EMAIL") select UPPER\'Foo\' from dual union all select UPPER\'Foo\' from dual ', [])->andReturn(true); - $result = $builder->from('users')->insert([['email' => new Raw("UPPER('Foo')")], ['email' => new Raw("LOWER('Foo')")]]); + $builder->getConnection() + ->shouldReceive('insert') + ->once() + ->with('insert into "USERS" ("EMAIL") select UPPER\'Foo\' from dual union all select UPPER\'Foo\' from dual ', + []) + ->andReturn(true); + $result = $builder->from('users')->insert([ + ['email' => new Raw("UPPER('Foo')")], + ['email' => new Raw("LOWER('Foo')")], + ]); $this->assertTrue($result); } @@ -2184,12 +2362,12 @@ public function testInsertLobMethod() { $builder = $this->getBuilder(); $builder->getProcessor() - ->shouldReceive('saveLob') - ->once() - ->with($builder, - 'insert into "USERS" ("EMAIL", "MYBLOB") values (?, EMPTY_BLOB()) returning "MYBLOB", "ID" into ?, ?', - ['foo'], ['test data']) - ->andReturn(1); + ->shouldReceive('saveLob') + ->once() + ->with($builder, + 'insert into "USERS" ("EMAIL", "MYBLOB") values (?, EMPTY_BLOB()) returning "MYBLOB", "ID" into ?, ?', + ['foo'], ['test data']) + ->andReturn(1); $result = $builder->from('users')->insertLob(['email' => 'foo'], ['myblob' => 'test data'], 'id'); $this->assertEquals(1, $result); } @@ -2198,12 +2376,12 @@ public function testInsertOnlyLobMethod() { $builder = $this->getBuilder(); $builder->getProcessor() - ->shouldReceive('saveLob') - ->once() - ->with($builder, - 'insert into "USERS" ("MYBLOB") values (EMPTY_BLOB()) returning "MYBLOB", "ID" into ?, ?', [], - ['test data']) - ->andReturn(1); + ->shouldReceive('saveLob') + ->once() + ->with($builder, + 'insert into "USERS" ("MYBLOB") values (EMPTY_BLOB()) returning "MYBLOB", "ID" into ?, ?', [], + ['test data']) + ->andReturn(1); $result = $builder->from('users')->insertLob([], ['myblob' => 'test data'], 'id'); $this->assertEquals(1, $result); } @@ -2226,9 +2404,13 @@ public function testUpsertMethod() $builder->getConnection() ->shouldReceive('affectingStatement') ->once() - ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', ['foo', 'bar', 'foo2', 'bar2']) + ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', + ['foo', 'bar', 'foo2', 'bar2']) ->andReturn(2); - $result = $builder->from('users')->upsert([['email' => 'foo', 'name' => 'bar'], ['name' => 'bar2', 'email' => 'foo2']], 'email'); + $result = $builder->from('users')->upsert([ + ['email' => 'foo', 'name' => 'bar'], + ['name' => 'bar2', 'email' => 'foo2'], + ], 'email'); $this->assertEquals(2, $result); } @@ -2238,9 +2420,13 @@ public function testUpsertMethodWithUpdateColumns() $builder->getConnection() ->shouldReceive('affectingStatement') ->once() - ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', ['foo', 'bar', 'foo2', 'bar2']) + ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', + ['foo', 'bar', 'foo2', 'bar2']) ->andReturn(2); - $result = $builder->from('users')->upsert([['email' => 'foo', 'name' => 'bar'], ['name' => 'bar2', 'email' => 'foo2']], 'email', ['name']); + $result = $builder->from('users')->upsert([ + ['email' => 'foo', 'name' => 'bar'], + ['name' => 'bar2', 'email' => 'foo2'], + ], 'email', ['name']); $this->assertEquals(2, $result); } @@ -2248,16 +2434,16 @@ public function testUpdateLobMethod() { $builder = $this->getBuilder(); $builder->getProcessor() - ->shouldReceive('saveLob') - ->once() - ->with($builder, - 'update "USERS" set "EMAIL" = ?, "MYBLOB" = EMPTY_BLOB() where "ID" = ? returning "MYBLOB", "ID" into ?, ?', - ['foo', 1], - ['test data']) - ->andReturn(1); + ->shouldReceive('saveLob') + ->once() + ->with($builder, + 'update "USERS" set "EMAIL" = ?, "MYBLOB" = EMPTY_BLOB() where "ID" = ? returning "MYBLOB", "ID" into ?, ?', + ['foo', 1], + ['test data']) + ->andReturn(1); $result = $builder->from('users') - ->where('id', '=', 1) - ->updateLob(['email' => 'foo'], ['myblob' => 'test data'], 'id'); + ->where('id', '=', 1) + ->updateLob(['email' => 'foo'], ['myblob' => 'test data'], 'id'); $this->assertEquals(1, $result); } @@ -2265,16 +2451,16 @@ public function testUpdateOnlyLobMethod() { $builder = $this->getBuilder(); $builder->getProcessor() - ->shouldReceive('saveLob') - ->once() - ->with($builder, - 'update "USERS" set "MYBLOB" = EMPTY_BLOB() where "ID" = ? returning "MYBLOB", "ID" into ?, ?', - [1], - ['test data']) - ->andReturn(1); + ->shouldReceive('saveLob') + ->once() + ->with($builder, + 'update "USERS" set "MYBLOB" = EMPTY_BLOB() where "ID" = ? returning "MYBLOB", "ID" into ?, ?', + [1], + ['test data']) + ->andReturn(1); $result = $builder->from('users') - ->where('id', '=', 1) - ->updateLob([], ['myblob' => 'test data'], 'id'); + ->where('id', '=', 1) + ->updateLob([], ['myblob' => 'test data'], 'id'); $this->assertEquals(1, $result); } @@ -2282,15 +2468,15 @@ public function testUpdateMethodWithJoins() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('update') - ->once() - ->with('update "USERS" inner join "ORDERS" on "USERS"."ID" = "ORDERS"."USER_ID" set "EMAIL" = ?, "NAME" = ? where "USERS"."ID" = ?', - ['foo', 'bar', 1]) - ->andReturn(1); + ->shouldReceive('update') + ->once() + ->with('update "USERS" inner join "ORDERS" on "USERS"."ID" = "ORDERS"."USER_ID" set "EMAIL" = ?, "NAME" = ? where "USERS"."ID" = ?', + ['foo', 'bar', 1]) + ->andReturn(1); $result = $builder->from('users') - ->join('orders', 'users.id', '=', 'orders.user_id') - ->where('users.id', '=', 1) - ->update(['email' => 'foo', 'name' => 'bar']); + ->join('orders', 'users.id', '=', 'orders.user_id') + ->where('users.id', '=', 1) + ->update(['email' => 'foo', 'name' => 'bar']); $this->assertEquals(1, $result); } @@ -2298,10 +2484,10 @@ public function testUpdateMethodRespectsRaw() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('update') - ->once() - ->with('update "USERS" set "EMAIL" = foo, "NAME" = ? where "ID" = ?', ['bar', 1]) - ->andReturn(1); + ->shouldReceive('update') + ->once() + ->with('update "USERS" set "EMAIL" = foo, "NAME" = ? where "ID" = ?', ['bar', 1]) + ->andReturn(1); $result = $builder->from('users')->where('id', '=', 1)->update(['email' => new Raw('foo'), 'name' => 'bar']); $this->assertEquals(1, $result); } @@ -2353,59 +2539,23 @@ public function testDeleteMethod() { $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" where "EMAIL" = ?', ['foo']) - ->andReturn(1); + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" where "EMAIL" = ?', ['foo']) + ->andReturn(1); $result = $builder->from('users')->where('email', '=', 'foo')->delete(); $this->assertEquals(1, $result); $builder = $this->getBuilder(); $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" where "USERS"."ID" = ?', [1]) - ->andReturn(1); + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" where "USERS"."ID" = ?', [1]) + ->andReturn(1); $result = $builder->from('users')->delete(1); $this->assertEquals(1, $result); } - /** - * @TODO: fix delete with join sql. - */ - protected function testDeleteWithJoinMethod() - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."EMAIL" = ?)', ['foo'])->andReturn(1); - $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->where('users.email', '=', 'foo')->delete(); - $this->assertEquals(1, $result); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" as "a" where "CTID" in (select "a"."CTID" from "USERS" as "a" inner join "USERS" as "b" on "a"."ID" = "b"."user_id" where "EMAIL" = ? order by "ID" asc limit 1)', ['foo'])->andReturn(1); - $result = $builder->from('users AS a')->join('users AS b', 'a.id', '=', 'b.user_id')->where('email', '=', 'foo')->orderBy('id')->limit(1)->delete(); - $this->assertEquals(1, $result); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."ID" = ? order by "ID" asc limit 1)', [1])->andReturn(1); - $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->orderBy('id')->take(1)->delete(1); - $this->assertEquals(1, $result); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."user_id" and "USERS"."ID" = ? where "NAME" = ?)', [1, 'baz'])->andReturn(1); - $result = $builder->from('users') - ->join('contacts', function ($join) { - $join->on('users.id', '=', 'contacts.user_id') - ->where('users.id', '=', 1); - })->where('name', 'baz') - ->delete(); - $this->assertEquals(1, $result); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID")', [])->andReturn(1); - $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->delete(); - $this->assertEquals(1, $result); - } - public function testTruncateMethod() { $builder = $this->getBuilder(); @@ -2498,32 +2648,23 @@ public function testBuilderThrowsExpectedExceptionWithUndefinedMethod() public function testOracleLock() { + $builder = $this->getBuilder(); + $builder->select('*')->from('foo')->where('bar', '=', 'baz') + ->lockForUpdate() + ->limit(1); + $this->assertEquals('select * from (select * from "FOO" where "BAR" = ?) where rownum = 1 for update', $builder->toSql()); + $this->assertEquals(['baz'], $builder->getBindings()); + $builder = $this->getBuilder(); $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(); $this->assertEquals('select * from "FOO" where "BAR" = ? for update', $builder->toSql()); $this->assertEquals(['baz'], $builder->getBindings()); - $builder = $this->getBuilder(); - try { - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); - } catch (Oci8Exception $e) { - // $this->assertEquals('select * from foo where bar = ? lock in share mode', $builder->toSql()); - $this->assertStringContainsString('Lock in share mode not yet supported!', $e->getMessage()); - $this->assertEquals(['baz'], $builder->getBindings()); - } - } - public function testSelectWithLockUsesWritePdo() - { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once() - ->with(m::any(), m::any(), false); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock()->get(); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once() - ->with(m::any(), m::any(), false); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false)->get(); + $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); + $this->assertEquals('select * from "FOO" where "BAR" = ? for update', $builder->toSql()); + $this->assertEquals(['baz'], $builder->getBindings()); } public function testBindingOrder() @@ -2532,17 +2673,29 @@ public function testBindingOrder() $expectedBindings = ['foo', 1, 3, 'bar']; $builder = $this->getBuilder(); - $builder->select('*')->from('users')->join('othertable', function ($join) { - $join->where('bar', '=', 'foo'); - })->where('registered', 1)->groupBy('city')->having('population', '>', 3)->orderByRaw('match ("FOO") against(?)', ['bar']); + $builder->select('*') + ->from('users') + ->join('othertable', function ($join) { + $join->where('bar', '=', 'foo'); + }) + ->where('registered', 1) + ->groupBy('city') + ->having('population', '>', 3) + ->orderByRaw('match ("FOO") against(?)', ['bar']); $this->assertEquals($expectedSql, $builder->toSql()); $this->assertEquals($expectedBindings, $builder->getBindings()); // order of statements reversed $builder = $this->getBuilder(); - $builder->select('*')->from('users')->orderByRaw('match ("FOO") against(?)', ['bar'])->having('population', '>', 3)->groupBy('city')->where('registered', 1)->join('othertable', function ($join) { - $join->where('bar', '=', 'foo'); - }); + $builder->select('*') + ->from('users') + ->orderByRaw('match ("FOO") against(?)', ['bar']) + ->having('population', '>', 3) + ->groupBy('city') + ->where('registered', 1) + ->join('othertable', function ($join) { + $join->where('bar', '=', 'foo'); + }); $this->assertEquals($expectedSql, $builder->toSql()); $this->assertEquals($expectedBindings, $builder->getBindings()); } @@ -2670,6 +2823,18 @@ public function testChunkWithLastChunkComplete() }); } + /** + * @return m\MockInterface + */ + protected function getMockQueryBuilder() + { + return m::mock(Builder::class, [ + m::mock(ConnectionInterface::class), + new OracleGrammar, + m::mock(OracleProcessor::class), + ])->makePartial(); + } + public function testChunkWithLastChunkPartial() { $builder = $this->getMockQueryBuilder(); @@ -2930,8 +3095,10 @@ public function testWhereRowValues() $this->assertSame('select * from "ORDERS" where ("LAST_UPDATE", "ORDER_NUMBER") < (?, ?)', $builder->toSql()); $builder = $this->getBuilder(); - $builder->select('*')->from('orders')->where('company_id', 1)->orWhereRowValues(['last_update', 'order_number'], '<', [1, 2]); - $this->assertSame('select * from "ORDERS" where "COMPANY_ID" = ? or ("LAST_UPDATE", "ORDER_NUMBER") < (?, ?)', $builder->toSql()); + $builder->select('*')->from('orders')->where('company_id', 1)->orWhereRowValues(['last_update', 'order_number'], + '<', [1, 2]); + $this->assertSame('select * from "ORDERS" where "COMPANY_ID" = ? or ("LAST_UPDATE", "ORDER_NUMBER") < (?, ?)', + $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('orders')->whereRowValues(['last_update', 'order_number'], '<', [1, new Raw('2')]); @@ -2970,12 +3137,17 @@ public function testWhereJsonContains() $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereJsonContains('users.options->languages', ['en']); - $this->assertSame('select * from "USERS" where ("USERS"."OPTIONS"->\'languages\')::jsonb @> ?', $builder->toSql()); + $this->assertSame('select * from "USERS" where ("USERS"."OPTIONS"->\'languages\')::jsonb @> ?', + $builder->toSql()); $this->assertEquals(['["en"]'], $builder->getBindings()); $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereJsonContains('options->languages', new Raw("'[\"en\"]'")); - $this->assertSame('select * from "USERS" where "id" = ? or ("OPTIONS"->\'languages\')::jsonb @> \'["en"]\'', $builder->toSql()); + $builder->select('*') + ->from('users') + ->where('id', '=', 1) + ->orWhereJsonContains('options->languages', new Raw("'[\"en\"]'")); + $this->assertSame('select * from "USERS" where "id" = ? or ("OPTIONS"->\'languages\')::jsonb @> \'["en"]\'', + $builder->toSql()); $this->assertEquals([1], $builder->getBindings()); } @@ -2985,7 +3157,8 @@ public function testFromSub() $builder->fromSub(function ($query) { $query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions')->where('foo', '=', '1'); }, 'sessions')->where('bar', '<', '10'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS" where "FOO" = ?) "SESSIONS" where "BAR" < ?', $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS" where "FOO" = ?) "SESSIONS" where "BAR" < ?', + $builder->toSql()); $this->assertEquals(['1', '10'], $builder->getBindings()); $this->expectException(InvalidArgumentException::class); @@ -3000,7 +3173,8 @@ public function testFromSubWithPrefix() $builder->fromSub(function ($query) { $query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions')->where('foo', '=', '1'); }, 'sessions')->where('bar', '<', '10'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "PREFIX_USER_SESSIONS" where "FOO" = ?) "PREFIX_SESSIONS" where "BAR" < ?', $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "PREFIX_USER_SESSIONS" where "FOO" = ?) "PREFIX_SESSIONS" where "BAR" < ?', + $builder->toSql()); $this->assertEquals(['1', '10'], $builder->getBindings()); } @@ -3010,7 +3184,8 @@ public function testFromSubWithoutBindings() $builder->fromSub(function ($query) { $query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions'); }, 'sessions'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS") "SESSIONS"', $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS") "SESSIONS"', + $builder->toSql()); $this->expectException(InvalidArgumentException::class); $builder = $this->getBuilder(); @@ -3021,14 +3196,17 @@ public function testFromRaw() { $builder = $this->getBuilder(); $builder->fromRaw(new Raw('(select max(last_seen_at) as last_seen_at from "user_sessions") as "sessions"')); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "user_sessions") as "sessions"', $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "user_sessions") as "sessions"', + $builder->toSql()); } public function testFromRawWithWhereOnTheMainQuery() { $builder = $this->getBuilder(); - $builder->fromRaw(new Raw('(select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at"'))->where('last_seen_at', '>', '1520652582'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at" where "LAST_SEEN_AT" > ?', $builder->toSql()); + $builder->fromRaw(new Raw('(select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at"')) + ->where('last_seen_at', '>', '1520652582'); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at" where "LAST_SEEN_AT" > ?', + $builder->toSql()); $this->assertEquals(['1520652582'], $builder->getBindings()); } @@ -3075,40 +3253,76 @@ public function testRandomOrder() $this->assertEquals([0 => 'foo'], $builder->getBindings()); } - protected function getConnection() - { - $connection = m::mock(ConnectionInterface::class); - $connection->shouldReceive('getConfig')->andReturn(''); - $connection->shouldReceive('getDatabaseName')->andReturn('database'); - - return $connection; - } - - protected function getBuilder() - { - $grammar = new OracleGrammar; - $processor = m::mock(OracleProcessor::class); - - return new Builder($this->getConnection(), $grammar, $processor); - } - /** - * @return m\MockInterface + * @TODO: fix delete with join sql. */ - protected function getMockQueryBuilder() + protected function testDeleteWithJoinMethod() { - return m::mock(Builder::class, [ - m::mock(ConnectionInterface::class), - new OracleGrammar, - m::mock(OracleProcessor::class), - ])->makePartial(); - } + $builder = $this->getBuilder(); + $builder->getConnection() + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."EMAIL" = ?)', + ['foo']) + ->andReturn(1); + $result = $builder->from('users') + ->join('contacts', 'users.id', '=', 'contacts.id') + ->where('users.email', '=', 'foo') + ->delete(); + $this->assertEquals(1, $result); - protected function getBuilderWithProcessor() - { - $grammar = new OracleGrammar; - $processor = new OracleProcessor; + $builder = $this->getBuilder(); + $builder->getConnection() + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" as "a" where "CTID" in (select "a"."CTID" from "USERS" as "a" inner join "USERS" as "b" on "a"."ID" = "b"."user_id" where "EMAIL" = ? order by "ID" asc limit 1)', + ['foo']) + ->andReturn(1); + $result = $builder->from('users AS a') + ->join('users AS b', 'a.id', '=', 'b.user_id') + ->where('email', '=', 'foo') + ->orderBy('id') + ->limit(1) + ->delete(); + $this->assertEquals(1, $result); - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); + $builder = $this->getBuilder(); + $builder->getConnection() + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."ID" = ? order by "ID" asc limit 1)', + [1]) + ->andReturn(1); + $result = $builder->from('users') + ->join('contacts', 'users.id', '=', 'contacts.id') + ->orderBy('id') + ->take(1) + ->delete(1); + $this->assertEquals(1, $result); + + $builder = $this->getBuilder(); + $builder->getConnection() + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."user_id" and "USERS"."ID" = ? where "NAME" = ?)', + [1, 'baz']) + ->andReturn(1); + $result = $builder->from('users') + ->join('contacts', function ($join) { + $join->on('users.id', '=', 'contacts.user_id') + ->where('users.id', '=', 1); + })->where('name', 'baz') + ->delete(); + $this->assertEquals(1, $result); + + $builder = $this->getBuilder(); + $builder->getConnection() + ->shouldReceive('delete') + ->once() + ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID")', + []) + ->andReturn(1); + $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->delete(); + $this->assertEquals(1, $result); } } From fa4e1eab1bb96743154310842cad8d3bd47f2376 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 7 Feb 2024 18:27:30 +0000 Subject: [PATCH 10/15] Apply fixes from StyleCI --- tests/Database/Oci8QueryBuilderTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index 58969d68..2afba430 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -2660,7 +2660,6 @@ public function testOracleLock() $this->assertEquals('select * from "FOO" where "BAR" = ? for update', $builder->toSql()); $this->assertEquals(['baz'], $builder->getBindings()); - $builder = $this->getBuilder(); $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); $this->assertEquals('select * from "FOO" where "BAR" = ? for update', $builder->toSql()); From 2c321d2a2ca5b3456fdee9127a670c50a13ac3eb Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 02:26:51 +0800 Subject: [PATCH 11/15] fix: phpunit config error --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 88d7c307..bc604df2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,5 +1,5 @@ - + ./tests From 2fe80a3faa00dafbfaf8cd9554c80de868860393 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 02:28:39 +0800 Subject: [PATCH 12/15] chore: remove unused method --- src/Oci8/Query/Grammars/OracleGrammar.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 917a408b..cf8a6585 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -107,16 +107,6 @@ public function compileSelect(Builder $query) return $sql; } - /** - * @param Builder $query - * @param array $components - * @return bool - */ - protected function isPaginationable(Builder $query, array $components) - { - return ($query->limit > 0 || $query->offset > 0) && ! array_key_exists('lock', $components); - } - /** * Create a full ANSI offset clause for the query. * From fc52a8a575ae51dc7bec25ea6372d545f2c5f583 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 02:40:48 +0800 Subject: [PATCH 13/15] fix: use transaction when in lock mode --- src/Oci8/Query/OracleBuilder.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Oci8/Query/OracleBuilder.php b/src/Oci8/Query/OracleBuilder.php index 3b13ec73..f06d0813 100644 --- a/src/Oci8/Query/OracleBuilder.php +++ b/src/Oci8/Query/OracleBuilder.php @@ -141,6 +141,24 @@ public function whereIn($column, $values, $boolean = 'and', $not = false) return parent::whereIn($column, $values, $boolean, $not); } + /** + * Run the query as a "select" statement against the connection. + * + * @return array + */ + protected function runSelect() + { + if (isset($this->lock)) { + $this->connection->beginTransaction(); + $result = $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); + $this->connection->commit(); + + return $result; + } + + return $this->connection->select($this->toSql(), $this->getBindings(), ! $this->useWritePdo); + } + /** * Set the table which the query is targeting. * From 904efa426fa7aa9ba59d55aaccf351da4fc4b232 Mon Sep 17 00:00:00 2001 From: Arjay Angeles Date: Thu, 8 Feb 2024 17:41:38 +0800 Subject: [PATCH 14/15] revert: cs changes --- tests/Database/Oci8QueryBuilderTest.php | 597 ++++++++---------------- 1 file changed, 190 insertions(+), 407 deletions(-) diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index 2afba430..464b23bb 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -15,6 +15,7 @@ use Yajra\Oci8\Query\Grammars\OracleGrammar; use Yajra\Oci8\Query\OracleBuilder as Builder; use Yajra\Oci8\Query\Processors\OracleProcessor; +use Yajra\Pdo\Oci8\Exceptions\Oci8Exception; class Oci8QueryBuilderTest extends TestCase { @@ -30,23 +31,6 @@ public function testBasicSelect() $this->assertEquals('select * from "USERS"', $builder->toSql()); } - protected function getBuilder() - { - $grammar = new OracleGrammar; - $processor = m::mock(OracleProcessor::class); - - return new Builder($this->getConnection(), $grammar, $processor); - } - - protected function getConnection() - { - $connection = m::mock(ConnectionInterface::class); - $connection->shouldReceive('getConfig')->andReturn(''); - $connection->shouldReceive('getDatabaseName')->andReturn('database'); - - return $connection; - } - public function testBasicSelectWithGetColumns() { $builder = $this->getBuilder(); @@ -94,14 +78,6 @@ public function testBasicSelectUseWritePdo() $builder->select('*')->from('users')->get(); } - protected function getBuilderWithProcessor() - { - $grammar = new OracleGrammar; - $processor = new OracleProcessor; - - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - public function testBasicTableWrappingProtectsQuotationMarks() { $builder = $this->getBuilder(); @@ -184,8 +160,7 @@ public function testJoinAliasesWithPrefix() $builder = $this->getBuilder(); $builder->getGrammar()->setTablePrefix('prefix_'); $builder->select('*')->from('services')->join('translations AS t', 't.item_id', '=', 'services.id'); - $this->assertSame('select * from "PREFIX_SERVICES" inner join "PREFIX_TRANSLATIONS" t on "PREFIX_T"."ITEM_ID" = "PREFIX_SERVICES"."ID"', - $builder->toSql()); + $this->assertSame('select * from "PREFIX_SERVICES" inner join "PREFIX_TRANSLATIONS" t on "PREFIX_T"."ITEM_ID" = "PREFIX_SERVICES"."ID"', $builder->toSql()); } public function testBasicTableWrapping() @@ -411,18 +386,15 @@ public function testDateBasedOrWheresAcceptsTwoArguments() $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', 1)->orWhereDay('CREATED_AT', 1); - $this->assertSame('select * from "USERS" where "ID" = ? or extract (day from "CREATED_AT") = ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or extract (day from "CREATED_AT") = ?', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', 1)->orWhereMonth('CREATED_AT', 1); - $this->assertSame('select * from "USERS" where "ID" = ? or extract (month from "CREATED_AT") = ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or extract (month from "CREATED_AT") = ?', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', 1)->orWhereYear('created_at', 1); - $this->assertSame('select * from "USERS" where "ID" = ? or extract (year from "CREATED_AT") = ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or extract (year from "CREATED_AT") = ?', $builder->toSql()); } public function testDateBasedWheresExpressionIsNotBound() @@ -468,8 +440,7 @@ public function testOrWhereDay() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereDay('created_at', '=', 1)->orWhereDay('created_at', '=', 2); - $this->assertSame('select * from "USERS" where extract (day from "CREATED_AT") = ? or extract (day from "CREATED_AT") = ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where extract (day from "CREATED_AT") = ? or extract (day from "CREATED_AT") = ?', $builder->toSql()); $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); } @@ -485,8 +456,7 @@ public function testOrWhereMonth() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereMonth('created_at', '=', 5)->orWhereMonth('created_at', '=', 6); - $this->assertSame('select * from "USERS" where extract (month from "CREATED_AT") = ? or extract (month from "CREATED_AT") = ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where extract (month from "CREATED_AT") = ? or extract (month from "CREATED_AT") = ?', $builder->toSql()); $this->assertEquals([0 => 5, 1 => 6], $builder->getBindings()); } @@ -502,8 +472,7 @@ public function testOrWhereYear() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereYear('created_at', '=', 2014)->orWhereYear('created_at', '=', 2015); - $this->assertSame('select * from "USERS" where extract (year from "CREATED_AT") = ? or extract (year from "CREATED_AT") = ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where extract (year from "CREATED_AT") = ? or extract (year from "CREATED_AT") = ?', $builder->toSql()); $this->assertEquals([0 => 2014, 1 => 2015], $builder->getBindings()); } @@ -573,14 +542,12 @@ public function testWhereBetweenColumns() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereBetweenColumns('id', ['users.created_at', 'users.updated_at']); - $this->assertSame('select * from "USERS" where "ID" between "USERS"."CREATED_AT" and "USERS"."UPDATED_AT"', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" between "USERS"."CREATED_AT" and "USERS"."UPDATED_AT"', $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereNotBetweenColumns('id', ['created_at', 'updated_at']); - $this->assertSame('select * from "USERS" where "ID" not between "CREATED_AT" and "UPDATED_AT"', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" not between "CREATED_AT" and "UPDATED_AT"', $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); @@ -728,12 +695,8 @@ public function testEmptyWhereIntegerNotInRaw() public function testBasicWhereColumn() { $builder = $this->getBuilder(); - $builder->select('*') - ->from('users') - ->whereColumn('first_name', 'last_name') - ->orWhereColumn('first_name', 'middle_name'); - $this->assertSame('select * from "USERS" where "FIRST_NAME" = "LAST_NAME" or "FIRST_NAME" = "MIDDLE_NAME"', - $builder->toSql()); + $builder->select('*')->from('users')->whereColumn('first_name', 'last_name')->orWhereColumn('first_name', 'middle_name'); + $this->assertSame('select * from "USERS" where "FIRST_NAME" = "LAST_NAME" or "FIRST_NAME" = "MIDDLE_NAME"', $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); @@ -751,8 +714,7 @@ public function testArrayWhereColumn() $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereColumn($conditions); - $this->assertSame('select * from "USERS" where ("FIRST_NAME" = "LAST_NAME" and "UPDATED_AT" > "CREATED_AT")', - $builder->toSql()); + $this->assertSame('select * from "USERS" where ("FIRST_NAME" = "LAST_NAME" and "UPDATED_AT" > "CREATED_AT")', $builder->toSql()); $this->assertEquals([], $builder->getBindings()); } @@ -838,8 +800,7 @@ public function testUnionWithJoin() $join->on('dogs.breed_id', '=', 'breeds.id') ->where('breeds.is_native', '=', 1); })); - $this->assertSame('(select * from "USERS") union (select * from "DOGS" inner join "BREEDS" on "DOGS"."BREED_ID" = "BREEDS"."ID" and "BREEDS"."IS_NATIVE" = ?)', - $builder->toSql()); + $this->assertSame('(select * from "USERS") union (select * from "DOGS" inner join "BREEDS" on "DOGS"."BREED_ID" = "BREEDS"."ID" and "BREEDS"."IS_NATIVE" = ?)', $builder->toSql()); $this->assertEquals([0 => 1], $builder->getBindings()); } @@ -941,8 +902,7 @@ public function testArrayWhereNulls() $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', '=', 1)->orWhereNull(['id', 'expires_at']); - $this->assertSame('select * from "USERS" where "ID" = ? or "ID" is null or "EXPIRES_AT" is null', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" = ? or "ID" is null or "EXPIRES_AT" is null', $builder->toSql()); $this->assertEquals([0 => 1], $builder->getBindings()); } @@ -963,14 +923,12 @@ public function testArrayWhereNotNulls() { $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereNotNull(['id', 'expires_at']); - $this->assertSame('select * from "USERS" where "ID" is not null and "EXPIRES_AT" is not null', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" is not null and "EXPIRES_AT" is not null', $builder->toSql()); $this->assertEquals([], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('id', '>', 1)->orWhereNotNull(['id', 'expires_at']); - $this->assertSame('select * from "USERS" where "ID" > ? or "ID" is not null or "EXPIRES_AT" is not null', - $builder->toSql()); + $this->assertSame('select * from "USERS" where "ID" > ? or "ID" is not null or "EXPIRES_AT" is not null', $builder->toSql()); $this->assertEquals([0 => 1], $builder->getBindings()); } @@ -998,9 +956,7 @@ public function testGroupBys() $this->assertEquals(['foo'], $builder->getBindings()); $builder = $this->getBuilder(); - $builder->havingRaw('?', ['havingRawBinding']) - ->groupByRaw('?', ['groupByRawBinding']) - ->whereRaw('?', ['whereRawBinding']); + $builder->havingRaw('?', ['havingRawBinding'])->groupByRaw('?', ['groupByRawBinding'])->whereRaw('?', ['whereRawBinding']); $this->assertEquals(['whereRawBinding', 'groupByRawBinding', 'havingRawBinding'], $builder->getBindings()); } @@ -1029,8 +985,7 @@ public function testOrderBys() $builder->select('*')->from('posts')->where('public', 1) ->unionAll($this->getBuilder()->select('*')->from('videos')->where('public', 1)) ->orderByRaw('field(category, ?, ?) asc', ['news', 'opinion']); - $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by field(category, ?, ?) asc', - $builder->toSql()); + $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by field(category, ?, ?) asc', $builder->toSql()); $this->assertEquals([1, 1, 'news', 'opinion'], $builder->getBindings()); } @@ -1052,8 +1007,7 @@ public function testReorder() $builder->select('*')->from('first'); $builder->union($this->getBuilder()->select('*')->from('second')); $builder->orderBy('name'); - $this->assertSame('(select * from "FIRST") union (select * from "SECOND") order by "NAME" asc', - $builder->toSql()); + $this->assertSame('(select * from "FIRST") union (select * from "SECOND") order by "NAME" asc', $builder->toSql()); $builder->reorder(); $this->assertSame('(select * from "FIRST") union (select * from "SECOND")', $builder->toSql()); @@ -1084,8 +1038,7 @@ public function testOrderBySubQueries() $builder->select('*')->from('posts')->where('public', 1) ->unionAll($this->getBuilder()->select('*')->from('videos')->where('public', 1)) ->orderBy($this->getBuilder()->selectRaw('field(category, ?, ?)', ['news', 'opinion'])); - $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by (select field(category, ?, ?)) asc', - $builder->toSql()); + $this->assertSame('(select * from "POSTS" where "PUBLIC" = ?) union all (select * from "VIDEOS" where "PUBLIC" = ?) order by (select field(category, ?, ?)) asc', $builder->toSql()); $this->assertEquals([1, 1, 'news', 'opinion'], $builder->getBindings()); } @@ -1123,39 +1076,23 @@ public function testHavingFollowedBySelectGet() { $builder = $this->getBuilder(); $query = 'select "CATEGORY", count(*) as "TOTAL" from "ITEM" where "DEPARTMENT" = ? group by "CATEGORY" having "TOTAL" > ?'; - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with($query, ['popular', 3], true) - ->andReturn([['category' => 'rock', 'total' => 5]]); + $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular', 3], true)->andReturn([['category' => 'rock', 'total' => 5]]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); $builder->from('item'); - $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')]) - ->where('department', '=', 'popular') - ->groupBy('category') - ->having('total', '>', 3) - ->get(); + $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')])->where('department', '=', 'popular')->groupBy('category')->having('total', '>', 3)->get(); $this->assertEquals([['category' => 'rock', 'total' => 5]], $result->all()); // Using \Raw value $builder = $this->getBuilder(); $query = 'select "CATEGORY", count(*) as "TOTAL" from "ITEM" where "DEPARTMENT" = ? group by "CATEGORY" having "TOTAL" > 3'; - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with($query, ['popular'], true) - ->andReturn([['category' => 'rock', 'total' => 5]]); + $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular'], true)->andReturn([['category' => 'rock', 'total' => 5]]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); $builder->from('item'); - $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')]) - ->where('department', '=', 'popular') - ->groupBy('category') - ->having('total', '>', new Raw('3')) - ->get(); + $result = $builder->select(['category', new Raw('count(*) as "TOTAL"')])->where('department', '=', 'popular')->groupBy('category')->having('total', '>', new Raw('3'))->get(); $this->assertEquals([['category' => 'rock', 'total' => 5]], $result->all()); } @@ -1275,11 +1212,7 @@ public function testGetCountForPaginationWithBindings() $q->select('body')->from('posts')->where('id', 4); }, 'post'); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select count(*) as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1295,11 +1228,7 @@ public function testGetCountForPaginationWithColumnAliases() $columns = ['body as post_body', 'teaser', 'posts.created as published']; $builder->from('posts')->select($columns); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select count("BODY", "TEASER", "POSTS"."CREATED") as aggregate from "POSTS"', [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count("BODY", "TEASER", "POSTS"."CREATED") as aggregate from "POSTS"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1313,12 +1242,7 @@ public function testGetCountForPaginationWithUnion() $builder = $this->getBuilder(); $builder->from('posts')->select('id')->union($this->getBuilder()->from('videos')->select('id')); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select count(*) as aggregate from ((select "ID" from "POSTS") union (select "ID" from "VIDEOS")) "TEMP_TABLE"', - [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "ID" from "POSTS") union (select "ID" from "VIDEOS")) "TEMP_TABLE"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1438,11 +1362,8 @@ public function testBasicJoins() public function testCrossJoinSubs() { $builder = $this->getBuilder(); - $builder->selectRaw('(sale / overall.sales) * 100 AS percent_of_total') - ->from('sales') - ->crossJoinSub($this->getBuilder()->selectRaw('SUM(sale) AS sales')->from('sales'), 'overall'); - $this->assertSame('select (sale / overall.sales) * 100 AS percent_of_total from "SALES" cross join (select SUM(sale) AS sales from "SALES") "OVERALL"', - $builder->toSql()); + $builder->selectRaw('(sale / overall.sales) * 100 AS percent_of_total')->from('sales')->crossJoinSub($this->getBuilder()->selectRaw('SUM(sale) AS sales')->from('sales'), 'overall'); + $this->assertSame('select (sale / overall.sales) * 100 AS percent_of_total from "SALES" cross join (select SUM(sale) AS sales from "SALES") "OVERALL"', $builder->toSql()); } public function testComplexJoin() @@ -1469,15 +1390,13 @@ public function testJoinWhereNull() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is null', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is null', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is null', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is null', $builder->toSql()); } public function testJoinWhereNotNull() @@ -1486,15 +1405,13 @@ public function testJoinWhereNotNull() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereNotNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is not null', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."DELETED_AT" is not null', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereNotNull('contacts.deleted_at'); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is not null', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."DELETED_AT" is not null', $builder->toSql()); } public function testJoinWhereIn() @@ -1503,16 +1420,14 @@ public function testJoinWhereIn() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (?, ?, ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (?, ?, ?)', $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (?, ?, ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (?, ?, ?)', $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); } @@ -1524,8 +1439,7 @@ public function testJoinWhereInSubquery() $q->select('name')->from('contacts')->where('name', 'baz'); $j->on('users.id', '=', 'contacts.id')->whereIn('contacts.name', $q); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', $builder->toSql()); $this->assertEquals(['baz'], $builder->getBindings()); $builder = $this->getBuilder(); @@ -1534,8 +1448,7 @@ public function testJoinWhereInSubquery() $q->select('name')->from('contacts')->where('name', 'baz'); $j->on('users.id', '=', 'contacts.id')->orWhereIn('contacts.name', $q); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" in (select "NAME" from "CONTACTS" where "NAME" = ?)', $builder->toSql()); $this->assertEquals(['baz'], $builder->getBindings()); } @@ -1545,16 +1458,14 @@ public function testJoinWhereNotIn() $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->whereNotIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" not in (?, ?, ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."NAME" not in (?, ?, ?)', $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->join('contacts', function ($j) { $j->on('users.id', '=', 'contacts.id')->orWhereNotIn('contacts.name', [48, 'baz', null]); }); - $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" not in (?, ?, ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" or "CONTACTS"."NAME" not in (?, ?, ?)', $builder->toSql()); $this->assertEquals([48, 'baz', null], $builder->getBindings()); } @@ -1566,8 +1477,7 @@ public function testJoinsWithNestedConditions() $j->where('contacts.country', '=', 'US')->orWhere('contacts.is_partner', '=', 1); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" = ?)', - $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" = ?)', $builder->toSql()); $this->assertEquals(['US', 1], $builder->getBindings()); $builder = $this->getBuilder(); @@ -1580,8 +1490,7 @@ public function testJoinsWithNestedConditions() }); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."IS_ACTIVE" = ? or (("CONTACTS"."COUNTRY" = ? or "CONTACTS"."TYPE" = "USERS"."TYPE") and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" is null))', - $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACTS"."IS_ACTIVE" = ? or (("CONTACTS"."COUNTRY" = ? or "CONTACTS"."TYPE" = "USERS"."TYPE") and ("CONTACTS"."COUNTRY" = ? or "CONTACTS"."IS_PARTNER" is null))', $builder->toSql()); $this->assertEquals([1, 'UK', 'US'], $builder->getBindings()); } @@ -1595,8 +1504,7 @@ public function testJoinsWithAdvancedConditions() ->orWhereRaw('year(contacts.created_at) = 2016'); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("ROLE" = ? or "CONTACTS"."DISABLED" is null or year(contacts.created_at) = 2016)', - $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and ("ROLE" = ? or "CONTACTS"."DISABLED" is null or year(contacts.created_at) = 2016)', $builder->toSql()); $this->assertEquals(['admin'], $builder->getBindings()); } @@ -1610,8 +1518,7 @@ public function testJoinsWithSubqueryCondition() ->whereNull('deleted_at'); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACT_TYPE_ID" in (select "ID" from "CONTACT_TYPES" where "CATEGORY_ID" = ? and "DELETED_AT" is null)', - $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and "CONTACT_TYPE_ID" in (select "ID" from "CONTACT_TYPES" where "CATEGORY_ID" = ? and "DELETED_AT" is null)', $builder->toSql()); $this->assertEquals(['1'], $builder->getBindings()); $builder = $this->getBuilder(); @@ -1623,8 +1530,7 @@ public function testJoinsWithSubqueryCondition() ->whereNull('deleted_at'); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null)', - $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null)', $builder->toSql()); $this->assertEquals(['1'], $builder->getBindings()); } @@ -1643,66 +1549,55 @@ public function testJoinsWithAdvancedSubqueryCondition() }); }); }); - $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null and "LEVEL_ID" in (select "ID" from "LEVELS" where "IS_ACTIVE" = ?))', - $builder->toSql()); + $this->assertSame('select * from "USERS" left join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" and exists (select 1 from "CONTACT_TYPES" where contact_types.id = contacts.contact_type_id and "CATEGORY_ID" = ? and "DELETED_AT" is null and "LEVEL_ID" in (select "ID" from "LEVELS" where "IS_ACTIVE" = ?))', $builder->toSql()); $this->assertEquals(['1', true], $builder->getBindings()); } public function testJoinsWithNestedJoins() { $builder = $this->getBuilder(); - $builder->select('users.id', 'contacts.id', 'contact_types.id') - ->from('users') - ->leftJoin('contacts', function ($j) { - $j->on('users.id', 'contacts.id') - ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id'); - }); - $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID"', - $builder->toSql()); + $builder->select('users.id', 'contacts.id', 'contact_types.id')->from('users')->leftJoin('contacts', function ($j) { + $j->on('users.id', 'contacts.id')->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id'); + }); + $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID"', $builder->toSql()); } public function testJoinsWithMultipleNestedJoins() { $builder = $this->getBuilder(); - $builder->select('users.id', 'contacts.id', 'contact_types.id', 'countrys.id', 'planets.id') - ->from('users') - ->leftJoin('contacts', function ($j) { - $j->on('users.id', 'contacts.id') - ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') - ->leftJoin('countrys', function ($q) { - $q->on('contacts.country', '=', 'countrys.country') - ->join('planets', function ($q) { - $q->on('countrys.planet_id', '=', 'planet.id') - ->where('planet.is_settled', '=', 1) - ->where('planet.population', '>=', 10000); - }); - }); - }); - $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID", "COUNTRYS"."ID", "PLANETS"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID" left join ("COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? and "PLANET"."POPULATION" >= ?) on "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY") on "USERS"."ID" = "CONTACTS"."ID"', - $builder->toSql()); + $builder->select('users.id', 'contacts.id', 'contact_types.id', 'countrys.id', 'planets.id')->from('users')->leftJoin('contacts', function ($j) { + $j->on('users.id', 'contacts.id') + ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') + ->leftJoin('countrys', function ($q) { + $q->on('contacts.country', '=', 'countrys.country') + ->join('planets', function ($q) { + $q->on('countrys.planet_id', '=', 'planet.id') + ->where('planet.is_settled', '=', 1) + ->where('planet.population', '>=', 10000); + }); + }); + }); + $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID", "COUNTRYS"."ID", "PLANETS"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID" left join ("COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? and "PLANET"."POPULATION" >= ?) on "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY") on "USERS"."ID" = "CONTACTS"."ID"', $builder->toSql()); $this->assertEquals(['1', 10000], $builder->getBindings()); } public function testJoinsWithNestedJoinWithAdvancedSubqueryCondition() { $builder = $this->getBuilder(); - $builder->select('users.id', 'contacts.id', 'contact_types.id') - ->from('users') - ->leftJoin('contacts', function ($j) { - $j->on('users.id', 'contacts.id') - ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') - ->whereExists(function ($q) { - $q->select('*')->from('countrys') - ->whereColumn('contacts.country', '=', 'countrys.country') - ->join('planets', function ($q) { - $q->on('countrys.planet_id', '=', 'planet.id') - ->where('planet.is_settled', '=', 1); - }) - ->where('planet.population', '>=', 10000); - }); - }); - $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID" and exists (select * from "COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? where "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY" and "PLANET"."POPULATION" >= ?)', - $builder->toSql()); + $builder->select('users.id', 'contacts.id', 'contact_types.id')->from('users')->leftJoin('contacts', function ($j) { + $j->on('users.id', 'contacts.id') + ->join('contact_types', 'contacts.contact_type_id', '=', 'contact_types.id') + ->whereExists(function ($q) { + $q->select('*')->from('countrys') + ->whereColumn('contacts.country', '=', 'countrys.country') + ->join('planets', function ($q) { + $q->on('countrys.planet_id', '=', 'planet.id') + ->where('planet.is_settled', '=', 1); + }) + ->where('planet.population', '>=', 10000); + }); + }); + $this->assertSame('select "USERS"."ID", "CONTACTS"."ID", "CONTACT_TYPES"."ID" from "USERS" left join ("CONTACTS" inner join "CONTACT_TYPES" on "CONTACTS"."CONTACT_TYPE_ID" = "CONTACT_TYPES"."ID") on "USERS"."ID" = "CONTACTS"."ID" and exists (select * from "COUNTRYS" inner join "PLANETS" on "COUNTRYS"."PLANET_ID" = "PLANET"."ID" and "PLANET"."IS_SETTLED" = ? where "CONTACTS"."COUNTRY" = "COUNTRYS"."COUNTRY" and "PLANET"."POPULATION" >= ?)', $builder->toSql()); $this->assertEquals(['1', 10000], $builder->getBindings()); } @@ -1751,8 +1646,7 @@ public function testJoinSubWithPrefix() $builder = $this->getBuilder(); $builder->getGrammar()->setTablePrefix('prefix_'); $builder->from('users')->joinSub('select * from "CONTACTS"', 'sub', 'users.id', '=', 'sub.id'); - $this->assertSame('select * from "PREFIX_USERS" inner join (select * from "CONTACTS") "PREFIX_SUB" on "PREFIX_USERS"."ID" = "PREFIX_SUB"."ID"', - $builder->toSql()); + $this->assertSame('select * from "PREFIX_USERS" inner join (select * from "CONTACTS") "PREFIX_SUB" on "PREFIX_USERS"."ID" = "PREFIX_SUB"."ID"', $builder->toSql()); } public function testLeftJoinSub() @@ -1833,28 +1727,17 @@ public function testPluckMethodGetsCollectionOfColumnValues() { $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']])->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->pluck('foo'); $this->assertEquals(['bar', 'baz'], $results->all()); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->andReturn([ - ['id' => 1, 'foo' => 'bar'], - ['id' => 10, 'foo' => 'baz'], - ]); - $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getConnection()->shouldReceive('select')->once()->andReturn([['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']]); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']])->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->pluck('foo', 'id'); $this->assertEquals([1 => 'bar', 10 => 'baz'], $results->all()); } @@ -1864,26 +1747,18 @@ public function testImplode() // Test without glue. $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']])->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->implode('foo'); $this->assertSame('barbaz', $results); // Test with glue. $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar'], ['foo' => 'baz']]) - ->andReturnUsing(function ($query, $results) { - return $results; - }); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']])->andReturnUsing(function ($query, $results) { + return $results; + }); $results = $builder->from('users')->where('id', '=', 1)->implode('foo', ','); $this->assertSame('bar,baz', $results); } @@ -1891,16 +1766,8 @@ public function testImplode() public function testValueMethodReturnsSingleColumn() { $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select * from (select "FOO" from "USERS" where "ID" = ?) where rownum = 1', [1], true) - ->andReturn([['foo' => 'bar']]); - $builder->getProcessor() - ->shouldReceive('processSelect') - ->once() - ->with($builder, [['foo' => 'bar']]) - ->andReturn([['foo' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from (select "FOO" from "USERS" where "ID" = ?) where rownum = 1', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturn([['foo' => 'bar']]); $results = $builder->from('users')->where('id', '=', 1)->value('foo'); $this->assertSame('bar', $results); } @@ -1938,11 +1805,7 @@ public function testListMethodsGetsArrayOfColumnValues() public function testAggregateFunctions() { $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select count(*) as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1950,29 +1813,17 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select 1 as "exists" from "USERS" where rownum = 1', [], true) - ->andReturn([['exists' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select 1 as "exists" from "USERS" where rownum = 1', [], true)->andReturn([['exists' => 1]]); $results = $builder->from('users')->exists(); $this->assertTrue($results); $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select 1 as "exists" from "USERS" where rownum = 1', [], true) - ->andReturn([['exists' => 0]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select 1 as "exists" from "USERS" where rownum = 1', [], true)->andReturn([['exists' => 0]]); $results = $builder->from('users')->doesntExist(); $this->assertTrue($results); $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select max("ID") as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select max("ID") as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1980,11 +1831,7 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select min("ID") as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select min("ID") as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -1992,11 +1839,7 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('select') - ->once() - ->with('select sum("ID") as aggregate from "USERS"', [], true) - ->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select sum("ID") as aggregate from "USERS"', [], true)->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2239,11 +2082,7 @@ public function testInsertMethod() public function testInsertUsingMethod() { $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('affectingStatement') - ->once() - ->with('insert into "TABLE1" ("FOO") select "BAR" from "TABLE2" where "FOREIGN_ID" = ?', [5]) - ->andReturn(1); + $builder->getConnection()->shouldReceive('affectingStatement')->once()->with('insert into "TABLE1" ("FOO") select "BAR" from "TABLE2" where "FOREIGN_ID" = ?', [5])->andReturn(1); $result = $builder->from('table1')->insertUsing( ['foo'], @@ -2319,10 +2158,7 @@ public function testInsertGetIdMethodRemovesExpressions() public function testInsertGetIdWithEmptyValues() { $builder = $this->getBuilder(); - $builder->getProcessor() - ->shouldReceive('processInsertGetId') - ->once() - ->with($builder, 'insert into "USERS" () values () returning "ID" into ?', [], null); + $builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'insert into "USERS" () values () returning "ID" into ?', [], null); $builder->from('users')->insertGetId([]); } @@ -2345,16 +2181,8 @@ public function testInsertMethodRespectsRawBindings() public function testMultipleInsertsWithExpressionValues() { $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('insert') - ->once() - ->with('insert into "USERS" ("EMAIL") select UPPER\'Foo\' from dual union all select UPPER\'Foo\' from dual ', - []) - ->andReturn(true); - $result = $builder->from('users')->insert([ - ['email' => new Raw("UPPER('Foo')")], - ['email' => new Raw("LOWER('Foo')")], - ]); + $builder->getConnection()->shouldReceive('insert')->once()->with('insert into "USERS" ("EMAIL") select UPPER\'Foo\' from dual union all select UPPER\'Foo\' from dual ', [])->andReturn(true); + $result = $builder->from('users')->insert([['email' => new Raw("UPPER('Foo')")], ['email' => new Raw("LOWER('Foo')")]]); $this->assertTrue($result); } @@ -2404,13 +2232,9 @@ public function testUpsertMethod() $builder->getConnection() ->shouldReceive('affectingStatement') ->once() - ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', - ['foo', 'bar', 'foo2', 'bar2']) + ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', ['foo', 'bar', 'foo2', 'bar2']) ->andReturn(2); - $result = $builder->from('users')->upsert([ - ['email' => 'foo', 'name' => 'bar'], - ['name' => 'bar2', 'email' => 'foo2'], - ], 'email'); + $result = $builder->from('users')->upsert([['email' => 'foo', 'name' => 'bar'], ['name' => 'bar2', 'email' => 'foo2']], 'email'); $this->assertEquals(2, $result); } @@ -2420,13 +2244,9 @@ public function testUpsertMethodWithUpdateColumns() $builder->getConnection() ->shouldReceive('affectingStatement') ->once() - ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', - ['foo', 'bar', 'foo2', 'bar2']) + ->with('merge into "USERS" using (select ? as "EMAIL", ? as "NAME" from dual union all select ? as "EMAIL", ? as "NAME" from dual) "LARAVEL_SOURCE" on ("LARAVEL_SOURCE"."EMAIL" = "USERS"."EMAIL") when matched then update set "NAME" = "LARAVEL_SOURCE"."NAME" when not matched then insert ("EMAIL", "NAME") values ("LARAVEL_SOURCE"."EMAIL", "LARAVEL_SOURCE"."NAME")', ['foo', 'bar', 'foo2', 'bar2']) ->andReturn(2); - $result = $builder->from('users')->upsert([ - ['email' => 'foo', 'name' => 'bar'], - ['name' => 'bar2', 'email' => 'foo2'], - ], 'email', ['name']); + $result = $builder->from('users')->upsert([['email' => 'foo', 'name' => 'bar'], ['name' => 'bar2', 'email' => 'foo2']], 'email', ['name']); $this->assertEquals(2, $result); } @@ -2556,6 +2376,42 @@ public function testDeleteMethod() $this->assertEquals(1, $result); } + /** + * @TODO: fix delete with join sql. + */ + protected function testDeleteWithJoinMethod() + { + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."EMAIL" = ?)', ['foo'])->andReturn(1); + $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->where('users.email', '=', 'foo')->delete(); + $this->assertEquals(1, $result); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" as "a" where "CTID" in (select "a"."CTID" from "USERS" as "a" inner join "USERS" as "b" on "a"."ID" = "b"."user_id" where "EMAIL" = ? order by "ID" asc limit 1)', ['foo'])->andReturn(1); + $result = $builder->from('users AS a')->join('users AS b', 'a.id', '=', 'b.user_id')->where('email', '=', 'foo')->orderBy('id')->limit(1)->delete(); + $this->assertEquals(1, $result); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."ID" = ? order by "ID" asc limit 1)', [1])->andReturn(1); + $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->orderBy('id')->take(1)->delete(1); + $this->assertEquals(1, $result); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."user_id" and "USERS"."ID" = ? where "NAME" = ?)', [1, 'baz'])->andReturn(1); + $result = $builder->from('users') + ->join('contacts', function ($join) { + $join->on('users.id', '=', 'contacts.user_id') + ->where('users.id', '=', 1); + })->where('name', 'baz') + ->delete(); + $this->assertEquals(1, $result); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID")', [])->andReturn(1); + $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->delete(); + $this->assertEquals(1, $result); + } + public function testTruncateMethod() { $builder = $this->getBuilder(); @@ -2672,29 +2528,17 @@ public function testBindingOrder() $expectedBindings = ['foo', 1, 3, 'bar']; $builder = $this->getBuilder(); - $builder->select('*') - ->from('users') - ->join('othertable', function ($join) { - $join->where('bar', '=', 'foo'); - }) - ->where('registered', 1) - ->groupBy('city') - ->having('population', '>', 3) - ->orderByRaw('match ("FOO") against(?)', ['bar']); + $builder->select('*')->from('users')->join('othertable', function ($join) { + $join->where('bar', '=', 'foo'); + })->where('registered', 1)->groupBy('city')->having('population', '>', 3)->orderByRaw('match ("FOO") against(?)', ['bar']); $this->assertEquals($expectedSql, $builder->toSql()); $this->assertEquals($expectedBindings, $builder->getBindings()); // order of statements reversed $builder = $this->getBuilder(); - $builder->select('*') - ->from('users') - ->orderByRaw('match ("FOO") against(?)', ['bar']) - ->having('population', '>', 3) - ->groupBy('city') - ->where('registered', 1) - ->join('othertable', function ($join) { - $join->where('bar', '=', 'foo'); - }); + $builder->select('*')->from('users')->orderByRaw('match ("FOO") against(?)', ['bar'])->having('population', '>', 3)->groupBy('city')->where('registered', 1)->join('othertable', function ($join) { + $join->where('bar', '=', 'foo'); + }); $this->assertEquals($expectedSql, $builder->toSql()); $this->assertEquals($expectedBindings, $builder->getBindings()); } @@ -2822,18 +2666,6 @@ public function testChunkWithLastChunkComplete() }); } - /** - * @return m\MockInterface - */ - protected function getMockQueryBuilder() - { - return m::mock(Builder::class, [ - m::mock(ConnectionInterface::class), - new OracleGrammar, - m::mock(OracleProcessor::class), - ])->makePartial(); - } - public function testChunkWithLastChunkPartial() { $builder = $this->getMockQueryBuilder(); @@ -3094,10 +2926,8 @@ public function testWhereRowValues() $this->assertSame('select * from "ORDERS" where ("LAST_UPDATE", "ORDER_NUMBER") < (?, ?)', $builder->toSql()); $builder = $this->getBuilder(); - $builder->select('*')->from('orders')->where('company_id', 1)->orWhereRowValues(['last_update', 'order_number'], - '<', [1, 2]); - $this->assertSame('select * from "ORDERS" where "COMPANY_ID" = ? or ("LAST_UPDATE", "ORDER_NUMBER") < (?, ?)', - $builder->toSql()); + $builder->select('*')->from('orders')->where('company_id', 1)->orWhereRowValues(['last_update', 'order_number'], '<', [1, 2]); + $this->assertSame('select * from "ORDERS" where "COMPANY_ID" = ? or ("LAST_UPDATE", "ORDER_NUMBER") < (?, ?)', $builder->toSql()); $builder = $this->getBuilder(); $builder->select('*')->from('orders')->whereRowValues(['last_update', 'order_number'], '<', [1, new Raw('2')]); @@ -3136,17 +2966,12 @@ public function testWhereJsonContains() $builder = $this->getBuilder(); $builder->select('*')->from('users')->whereJsonContains('users.options->languages', ['en']); - $this->assertSame('select * from "USERS" where ("USERS"."OPTIONS"->\'languages\')::jsonb @> ?', - $builder->toSql()); + $this->assertSame('select * from "USERS" where ("USERS"."OPTIONS"->\'languages\')::jsonb @> ?', $builder->toSql()); $this->assertEquals(['["en"]'], $builder->getBindings()); $builder = $this->getBuilder(); - $builder->select('*') - ->from('users') - ->where('id', '=', 1) - ->orWhereJsonContains('options->languages', new Raw("'[\"en\"]'")); - $this->assertSame('select * from "USERS" where "id" = ? or ("OPTIONS"->\'languages\')::jsonb @> \'["en"]\'', - $builder->toSql()); + $builder->select('*')->from('users')->where('id', '=', 1)->orWhereJsonContains('options->languages', new Raw("'[\"en\"]'")); + $this->assertSame('select * from "USERS" where "id" = ? or ("OPTIONS"->\'languages\')::jsonb @> \'["en"]\'', $builder->toSql()); $this->assertEquals([1], $builder->getBindings()); } @@ -3156,8 +2981,7 @@ public function testFromSub() $builder->fromSub(function ($query) { $query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions')->where('foo', '=', '1'); }, 'sessions')->where('bar', '<', '10'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS" where "FOO" = ?) "SESSIONS" where "BAR" < ?', - $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS" where "FOO" = ?) "SESSIONS" where "BAR" < ?', $builder->toSql()); $this->assertEquals(['1', '10'], $builder->getBindings()); $this->expectException(InvalidArgumentException::class); @@ -3172,8 +2996,7 @@ public function testFromSubWithPrefix() $builder->fromSub(function ($query) { $query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions')->where('foo', '=', '1'); }, 'sessions')->where('bar', '<', '10'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "PREFIX_USER_SESSIONS" where "FOO" = ?) "PREFIX_SESSIONS" where "BAR" < ?', - $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "PREFIX_USER_SESSIONS" where "FOO" = ?) "PREFIX_SESSIONS" where "BAR" < ?', $builder->toSql()); $this->assertEquals(['1', '10'], $builder->getBindings()); } @@ -3183,8 +3006,7 @@ public function testFromSubWithoutBindings() $builder->fromSub(function ($query) { $query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions'); }, 'sessions'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS") "SESSIONS"', - $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "USER_SESSIONS") "SESSIONS"', $builder->toSql()); $this->expectException(InvalidArgumentException::class); $builder = $this->getBuilder(); @@ -3195,17 +3017,14 @@ public function testFromRaw() { $builder = $this->getBuilder(); $builder->fromRaw(new Raw('(select max(last_seen_at) as last_seen_at from "user_sessions") as "sessions"')); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "user_sessions") as "sessions"', - $builder->toSql()); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "user_sessions") as "sessions"', $builder->toSql()); } public function testFromRawWithWhereOnTheMainQuery() { $builder = $this->getBuilder(); - $builder->fromRaw(new Raw('(select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at"')) - ->where('last_seen_at', '>', '1520652582'); - $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at" where "LAST_SEEN_AT" > ?', - $builder->toSql()); + $builder->fromRaw(new Raw('(select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at"'))->where('last_seen_at', '>', '1520652582'); + $this->assertSame('select * from (select max(last_seen_at) as last_seen_at from "sessions") as "last_seen_at" where "LAST_SEEN_AT" > ?', $builder->toSql()); $this->assertEquals(['1520652582'], $builder->getBindings()); } @@ -3252,76 +3071,40 @@ public function testRandomOrder() $this->assertEquals([0 => 'foo'], $builder->getBindings()); } - /** - * @TODO: fix delete with join sql. - */ - protected function testDeleteWithJoinMethod() + protected function getConnection() { - $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."EMAIL" = ?)', - ['foo']) - ->andReturn(1); - $result = $builder->from('users') - ->join('contacts', 'users.id', '=', 'contacts.id') - ->where('users.email', '=', 'foo') - ->delete(); - $this->assertEquals(1, $result); + $connection = m::mock(ConnectionInterface::class); + $connection->shouldReceive('getConfig')->andReturn(''); + $connection->shouldReceive('getDatabaseName')->andReturn('database'); - $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" as "a" where "CTID" in (select "a"."CTID" from "USERS" as "a" inner join "USERS" as "b" on "a"."ID" = "b"."user_id" where "EMAIL" = ? order by "ID" asc limit 1)', - ['foo']) - ->andReturn(1); - $result = $builder->from('users AS a') - ->join('users AS b', 'a.id', '=', 'b.user_id') - ->where('email', '=', 'foo') - ->orderBy('id') - ->limit(1) - ->delete(); - $this->assertEquals(1, $result); + return $connection; + } - $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID" where "USERS"."ID" = ? order by "ID" asc limit 1)', - [1]) - ->andReturn(1); - $result = $builder->from('users') - ->join('contacts', 'users.id', '=', 'contacts.id') - ->orderBy('id') - ->take(1) - ->delete(1); - $this->assertEquals(1, $result); + protected function getBuilder() + { + $grammar = new OracleGrammar; + $processor = m::mock(OracleProcessor::class); - $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."user_id" and "USERS"."ID" = ? where "NAME" = ?)', - [1, 'baz']) - ->andReturn(1); - $result = $builder->from('users') - ->join('contacts', function ($join) { - $join->on('users.id', '=', 'contacts.user_id') - ->where('users.id', '=', 1); - })->where('name', 'baz') - ->delete(); - $this->assertEquals(1, $result); + return new Builder($this->getConnection(), $grammar, $processor); + } - $builder = $this->getBuilder(); - $builder->getConnection() - ->shouldReceive('delete') - ->once() - ->with('delete from "USERS" where "CTID" in (select "USERS"."CTID" from "USERS" inner join "CONTACTS" on "USERS"."ID" = "CONTACTS"."ID")', - []) - ->andReturn(1); - $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->delete(); - $this->assertEquals(1, $result); + /** + * @return m\MockInterface + */ + protected function getMockQueryBuilder() + { + return m::mock(Builder::class, [ + m::mock(ConnectionInterface::class), + new OracleGrammar, + m::mock(OracleProcessor::class), + ])->makePartial(); + } + + protected function getBuilderWithProcessor() + { + $grammar = new OracleGrammar; + $processor = new OracleProcessor; + + return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); } } From b894fa601a1932ea871a652fe41e8483f53d65ae Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 8 Feb 2024 09:43:03 +0000 Subject: [PATCH 15/15] Apply fixes from StyleCI --- tests/Database/Oci8QueryBuilderTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index 464b23bb..6081e56b 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -15,7 +15,6 @@ use Yajra\Oci8\Query\Grammars\OracleGrammar; use Yajra\Oci8\Query\OracleBuilder as Builder; use Yajra\Oci8\Query\Processors\OracleProcessor; -use Yajra\Pdo\Oci8\Exceptions\Oci8Exception; class Oci8QueryBuilderTest extends TestCase {