From 326175ecaf9d9bf55ce4891583a853929c8f50c9 Mon Sep 17 00:00:00 2001 From: "Arjay Q. Angeles" Date: Sun, 6 Dec 2020 21:12:48 +0800 Subject: [PATCH 1/3] Enhance pagination as suggested on #563. --- src/Oci8/Query/Grammars/OracleGrammar.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index 291b68b3..fd69bbc6 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -161,6 +161,12 @@ protected function compileTableExpression($sql, $constraint, $query) return "select * from ({$sql}) where rownum {$constraint}"; } + if (! is_null($query->limit && ! is_null($query->offset))) { + $start = $query->offset + 1; + $finish = $query->offset + $query->limit; + 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 03f9d2212865443d496426326422d7cf125be103 Mon Sep 17 00:00:00 2001 From: "Arjay Q. Angeles" Date: Sun, 6 Dec 2020 21:30:18 +0800 Subject: [PATCH 2/3] Fix pagination tests. --- tests/Database/Oci8QueryBuilderTest.php | 52 ++++++++++++++++--------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/tests/Database/Oci8QueryBuilderTest.php b/tests/Database/Oci8QueryBuilderTest.php index 4df48419..2771b335 100644 --- a/tests/Database/Oci8QueryBuilderTest.php +++ b/tests/Database/Oci8QueryBuilderTest.php @@ -267,8 +267,10 @@ public function testSubSelectWhereIns() $builder->select('*')->from('users')->whereIn('id', function ($q) { $q->select('id')->from('users')->where('age', '>', 25)->take(3); }); - $this->assertEquals('select * from "USERS" where "ID" in (select t2.* from ( select rownum AS "rn", t1.* from (select "ID" from "USERS" where "AGE" > ?) t1 ) t2 where t2."rn" between 1 and 3)', - $builder->toSql()); + $this->assertEquals( + 'select * from "USERS" where "ID" in (select t2.* from ( select rownum AS "rn", t1.* from (select "ID" from "USERS" where "AGE" > ?) t1 where rownum <= 3) t2 where t2."rn" >= 1)', + $builder->toSql() + ); $this->assertEquals([25], $builder->getBindings()); $builder = $this->getBuilder(); @@ -279,8 +281,10 @@ public function testSubSelectWhereIns() $builder->select('*')->from('users')->whereNotIn('id', function ($q) { $q->select('id')->from('users')->where('age', '>', 25)->take(3); }); - $this->assertEquals('select * from "USERS" where "ID" not in (select t2.* from ( select rownum AS "rn", t1.* from (select "ID" from "USERS" where "AGE" > ?) t1 ) t2 where t2."rn" between 1 and 3)', - $builder->toSql()); + $this->assertEquals( + 'select * from "USERS" where "ID" not in (select t2.* from ( select rownum AS "rn", t1.* from (select "ID" from "USERS" where "AGE" > ?) t1 where rownum <= 3) t2 where t2."rn" >= 1)', + $builder->toSql() + ); $this->assertEquals([25], $builder->getBindings()); } @@ -361,8 +365,10 @@ public function testOffset() $connection = $builder->getConnection(); $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->offset(10); - $this->assertEquals('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" >= 11', - $builder->toSql()); + $this->assertEquals( + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 10) t2 where t2."rn" >= 11', + $builder->toSql() + ); } public function testLimitsAndOffsets() @@ -371,36 +377,46 @@ public function testLimitsAndOffsets() $connection = $builder->getConnection(); $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->offset(5)->limit(10); - $this->assertEquals('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 6 and 15', - $builder->toSql()); + $this->assertEquals( + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 6', + $builder->toSql() + ); $builder = $this->getBuilder(); $connection = $builder->getConnection(); $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->skip(5)->take(10); - $this->assertEquals('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 6 and 15', - $builder->toSql()); + $this->assertEquals( + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 6', + $builder->toSql() + ); $builder = $this->getBuilder(); $connection = $builder->getConnection(); $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->skip(-5)->take(10); - $this->assertEquals('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 1 and 10', - $builder->toSql()); + $this->assertEquals( + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 10) t2 where t2."rn" >= 1', + $builder->toSql() + ); $builder = $this->getBuilder(); $connection = $builder->getConnection(); $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->forPage(2, 15); - $this->assertEquals('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 16 and 30', - $builder->toSql()); + $this->assertEquals( + '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(); $connection = $builder->getConnection(); $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->forPage(-2, 15); - $this->assertEquals('select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 1 and 15', - $builder->toSql()); + $this->assertEquals( + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 15) t2 where t2."rn" >= 1', + $builder->toSql() + ); } public function testLimitAndOffsetToPaginateOne() @@ -410,7 +426,7 @@ public function testLimitAndOffsetToPaginateOne() $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->offset(0)->limit(1); $this->assertEquals( - 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 1 and 1', + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 1) t2 where t2."rn" >= 1', $builder->toSql() ); @@ -419,7 +435,7 @@ public function testLimitAndOffsetToPaginateOne() $connection->shouldReceive('getConfig')->andReturn(''); $builder->select('*')->from('users')->offset(1)->limit(1); $this->assertEquals( - 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 ) t2 where t2."rn" between 2 and 2', + 'select t2.* from ( select rownum AS "rn", t1.* from (select * from "USERS") t1 where rownum <= 2) t2 where t2."rn" >= 2', $builder->toSql() ); } From a717c96d27809d46f344040df005af971830c363 Mon Sep 17 00:00:00 2001 From: "Arjay Q. Angeles" Date: Sun, 6 Dec 2020 21:40:38 +0800 Subject: [PATCH 3/3] Fix cs. --- src/Oci8/Query/Grammars/OracleGrammar.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Oci8/Query/Grammars/OracleGrammar.php b/src/Oci8/Query/Grammars/OracleGrammar.php index fd69bbc6..580a54fb 100644 --- a/src/Oci8/Query/Grammars/OracleGrammar.php +++ b/src/Oci8/Query/Grammars/OracleGrammar.php @@ -164,6 +164,7 @@ protected function compileTableExpression($sql, $constraint, $query) if (! is_null($query->limit && ! is_null($query->offset))) { $start = $query->offset + 1; $finish = $query->offset + $query->limit; + return "select t2.* from ( select rownum AS \"rn\", t1.* from ({$sql}) t1 where rownum <= {$finish}) t2 where t2.\"rn\" >= {$start}"; }