Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit d9b1af5

Browse files
committed
Merge branch 'FuelMedical-master' into develop
2 parents e01d2b2 + 81168db commit d9b1af5

File tree

3 files changed

+89
-9
lines changed

3 files changed

+89
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ All notable changes to this project will be documented in this file, in reverse
2323

2424
### Fixed
2525

26-
- Nothing.
26+
- [#329](https://github.com/zendframework/zend-db/pull/329) fix Exception
27+
thrown when calling prepareStatementForSqlObject on a Select with a
28+
sub-Select that has limit and/or offset set
2729

2830
## 2.9.3 - 2018-04-09
2931

src/Sql/Platform/Mysql/SelectDecorator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protected function processLimit(
5252
if ($parameterContainer) {
5353
$paramPrefix = $this->processInfo['paramPrefix'];
5454
$parameterContainer->offsetSet($paramPrefix . 'limit', $this->limit, ParameterContainer::TYPE_INTEGER);
55-
return [$driver->formatParameterName('limit')];
55+
return [$driver->formatParameterName($paramPrefix . 'limit')];
5656
}
5757

5858
return [$this->limit];
@@ -69,7 +69,7 @@ protected function processOffset(
6969
if ($parameterContainer) {
7070
$paramPrefix = $this->processInfo['paramPrefix'];
7171
$parameterContainer->offsetSet($paramPrefix . 'offset', $this->offset, ParameterContainer::TYPE_INTEGER);
72-
return [$driver->formatParameterName('offset')];
72+
return [$driver->formatParameterName($paramPrefix . 'offset')];
7373
}
7474

7575
return [$this->offset];

test/unit/Sql/Platform/Mysql/SelectDecoratorTest.php

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
namespace ZendTest\Db\Sql\Platform\Mysql;
1111

1212
use PHPUnit\Framework\TestCase;
13+
use Zend\Db\Adapter\Driver\Mysqli\Connection;
14+
use ZendTest\Db\TestAsset\TrustingMysqlPlatform;
1315
use Zend\Db\Adapter\ParameterContainer;
1416
use Zend\Db\Adapter\Platform\Mysql as MysqlPlatform;
1517
use Zend\Db\Sql\Expression;
18+
use Zend\Db\Sql\Sql;
1619
use Zend\Db\Sql\Platform\Mysql\SelectDecorator;
1720
use Zend\Db\Sql\Select;
1821

@@ -54,6 +57,40 @@ public function testPrepareStatement(Select $select, $expectedSql, $expectedPara
5457
self::assertEquals($expectedParams, $parameterContainer->getNamedArray());
5558
}
5659

60+
/**
61+
* @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare
62+
* a proper limit/offset sql statement
63+
* @covers \Zend\Db\Sql\Platform\Mysql\SelectDecorator::prepareStatement
64+
* @covers \Zend\Db\Sql\Platform\Mysql\SelectDecorator::processLimit
65+
* @covers \Zend\Db\Sql\Platform\Mysql\SelectDecorator::processOffset
66+
* @dataProvider dataProvider
67+
*/
68+
public function testPrepareStatementForSqlObject(
69+
Select $select,
70+
$ignore,
71+
$expectedParams,
72+
$alsoIgnore,
73+
$expectedPdoSql
74+
) {
75+
// mock the adapter, driver, and parts
76+
$newStatement = new \Zend\Db\Adapter\Driver\Mysqli\Statement();
77+
$driver = new \Zend\Db\Adapter\Driver\Pdo\Pdo(new \Zend\Db\Adapter\Driver\Pdo\Connection());
78+
$mockAdapter = $this->getMockBuilder('Zend\Db\Adapter\Adapter')
79+
->setConstructorArgs([$driver, new TrustingMysqlPlatform()])
80+
->getMock();
81+
$trustingPlatform = new TrustingMysqlPlatform();
82+
$mockAdapter->expects($this->any())->method('getPlatform')->will($this->returnValue($trustingPlatform));
83+
$mockAdapter->expects($this->any())->method('getDriver')->will($this->returnValue($driver));
84+
// setup mock adapter
85+
$this->mockAdapter = $mockAdapter;
86+
87+
$this->sql = new Sql($this->mockAdapter, 'foo');
88+
$selectDecorator = new SelectDecorator;
89+
$selectDecorator->setSubject($select);
90+
$statement = $this->sql->prepareStatementForSqlObject($select, $newStatement);
91+
self::assertEquals($expectedPdoSql, $statement->getSql());
92+
}
93+
5794
/**
5895
* @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare
5996
* a proper limit/offset sql statement
@@ -71,28 +108,31 @@ public function testGetSqlString(Select $select, $ignore, $alsoIgnore, $expected
71108

72109
$selectDecorator = new SelectDecorator;
73110
$selectDecorator->setSubject($select);
74-
self::assertEquals($expectedSql, $selectDecorator->getSqlString(new MysqlPlatform));
111+
self::assertEquals($expectedSql, $selectDecorator->getSqlString(new TrustingMysqlPlatform));
75112
}
76113

77114
public function dataProvider()
78115
{
79116
$select0 = new Select;
80117
$select0->from('foo')->limit(5)->offset(10);
81118
$expectedPrepareSql0 = 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?';
119+
$expectedPrepareObjectSql0 = 'SELECT `foo`.* FROM `foo` LIMIT :limit OFFSET :offset';
82120
$expectedParams0 = ['offset' => 10, 'limit' => 5];
83121
$expectedSql0 = 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10';
84122

85123
// offset without limit
86124
$select1 = new Select;
87125
$select1->from('foo')->offset(10);
88126
$expectedPrepareSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?';
127+
$expectedPrepareObjectSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET :offset';
89128
$expectedParams1 = ['offset' => 10];
90129
$expectedSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10';
91130

92131
// offset and limit are not type casted when injected into parameter container
93132
$select2 = new Select;
94133
$select2->from('foo')->limit('5')->offset('10000000000000000000');
95134
$expectedPrepareSql2 = 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?';
135+
$expectedPrepareObjectSql2 = 'SELECT `foo`.* FROM `foo` LIMIT :limit OFFSET :offset';
96136
$expectedParams2 = ['offset' => '10000000000000000000', 'limit' => '5'];
97137
$expectedSql2 = 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10000000000000000000';
98138

@@ -113,6 +153,9 @@ public function dataProvider()
113153
$expectedPrepareSql3 =
114154
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` LIMIT ? OFFSET ?) AS `res`"
115155
. " FROM `foo` LIMIT ? OFFSET ?";
156+
$expectedPrepareObjectSql3 =
157+
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` LIMIT :subselect1limit OFFSET :subselect1offset) AS `res`"
158+
. " FROM `foo` LIMIT :limit OFFSET :offset";
116159
$expectedParams3 = [
117160
'subselect1limit' => 100,
118161
'subselect1offset' => 500,
@@ -148,6 +191,10 @@ public function dataProvider()
148191
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` LIMIT ? OFFSET ?) AS `res`,"
149192
. " (SELECT count(foo2.id) AS `cnt` FROM `foo2` LIMIT ? OFFSET ?) AS `res0`"
150193
. " FROM `foo` LIMIT ? OFFSET ?";
194+
$expectedPrepareObjectSql4 =
195+
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` LIMIT :subselect1limit OFFSET :subselect1offset)"
196+
. " AS `res`, (SELECT count(foo2.id) AS `cnt` FROM `foo2` LIMIT :subselect2limit OFFSET :subselect2offset)"
197+
. " AS `res0` FROM `foo` LIMIT :limit OFFSET :offset";
151198
$expectedParams4 = [
152199
'subselect1limit' => 100,
153200
'subselect1offset' => 500,
@@ -160,12 +207,43 @@ public function dataProvider()
160207
. " (SELECT count(foo2.id) AS `cnt` FROM `foo2` LIMIT 50 OFFSET 101) AS `res0`"
161208
. " FROM `foo` LIMIT 10 OFFSET 5";
162209

210+
// nested limit in field param, no limit in containing select
211+
$nestedSelect0 = new Select;
212+
$nestedSelect0->from('foo1')
213+
->columns([
214+
'cnt' => new Expression('count(foo1.id)')
215+
]);
216+
$nestedSelect0->where->equalTo('foo2', 'ab');
217+
$nestedSelect0->limit(1);
218+
219+
$select5 = new Select;
220+
$select5->from('foo')
221+
->columns([
222+
'res' => $nestedSelect0,
223+
]);
224+
225+
$expectedPrepareSql5 =
226+
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` WHERE `foo2` = ? LIMIT ?) AS `res`"
227+
. " FROM `foo`";
228+
$expectedPrepareObjectSql5 =
229+
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` WHERE `foo2` = :subselect1where1 LIMIT"
230+
. " :subselect1limit) AS `res` FROM `foo`";
231+
$expectedParams5 = [
232+
'subselect1limit' => 1,
233+
'subselect1where1' => 'ab'
234+
];
235+
$expectedSql5 = "SELECT (SELECT count(foo1.id) AS `cnt`"
236+
. " FROM `foo1` WHERE `foo2` = 'ab' LIMIT 1) AS `res`"
237+
. " FROM `foo`";
238+
239+
163240
return [
164-
[$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0],
165-
[$select1, $expectedPrepareSql1, $expectedParams1, $expectedSql1],
166-
[$select2, $expectedPrepareSql2, $expectedParams2, $expectedSql2],
167-
[$select3, $expectedPrepareSql3, $expectedParams3, $expectedSql3],
168-
[$select4, $expectedPrepareSql4, $expectedParams4, $expectedSql4],
241+
[$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0, $expectedPrepareObjectSql0],
242+
[$select1, $expectedPrepareSql1, $expectedParams1, $expectedSql1, $expectedPrepareObjectSql1],
243+
[$select2, $expectedPrepareSql2, $expectedParams2, $expectedSql2, $expectedPrepareObjectSql2],
244+
[$select3, $expectedPrepareSql3, $expectedParams3, $expectedSql3, $expectedPrepareObjectSql3],
245+
[$select4, $expectedPrepareSql4, $expectedParams4, $expectedSql4, $expectedPrepareObjectSql4],
246+
[$select5, $expectedPrepareSql5, $expectedParams5, $expectedSql5, $expectedPrepareObjectSql5],
169247
];
170248
}
171249
}

0 commit comments

Comments
 (0)