10
10
namespace ZendTest \Db \Sql \Platform \Mysql ;
11
11
12
12
use PHPUnit \Framework \TestCase ;
13
+ use Zend \Db \Adapter \Driver \Mysqli \Connection ;
14
+ use ZendTest \Db \TestAsset \TrustingMysqlPlatform ;
13
15
use Zend \Db \Adapter \ParameterContainer ;
14
16
use Zend \Db \Adapter \Platform \Mysql as MysqlPlatform ;
15
17
use Zend \Db \Sql \Expression ;
18
+ use Zend \Db \Sql \Sql ;
16
19
use Zend \Db \Sql \Platform \Mysql \SelectDecorator ;
17
20
use Zend \Db \Sql \Select ;
18
21
@@ -54,6 +57,40 @@ public function testPrepareStatement(Select $select, $expectedSql, $expectedPara
54
57
self ::assertEquals ($ expectedParams , $ parameterContainer ->getNamedArray ());
55
58
}
56
59
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
+
57
94
/**
58
95
* @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare
59
96
* a proper limit/offset sql statement
@@ -71,28 +108,31 @@ public function testGetSqlString(Select $select, $ignore, $alsoIgnore, $expected
71
108
72
109
$ selectDecorator = new SelectDecorator ;
73
110
$ selectDecorator ->setSubject ($ select );
74
- self ::assertEquals ($ expectedSql , $ selectDecorator ->getSqlString (new MysqlPlatform ));
111
+ self ::assertEquals ($ expectedSql , $ selectDecorator ->getSqlString (new TrustingMysqlPlatform ));
75
112
}
76
113
77
114
public function dataProvider ()
78
115
{
79
116
$ select0 = new Select ;
80
117
$ select0 ->from ('foo ' )->limit (5 )->offset (10 );
81
118
$ expectedPrepareSql0 = 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ? ' ;
119
+ $ expectedPrepareObjectSql0 = 'SELECT `foo`.* FROM `foo` LIMIT :limit OFFSET :offset ' ;
82
120
$ expectedParams0 = ['offset ' => 10 , 'limit ' => 5 ];
83
121
$ expectedSql0 = 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10 ' ;
84
122
85
123
// offset without limit
86
124
$ select1 = new Select ;
87
125
$ select1 ->from ('foo ' )->offset (10 );
88
126
$ expectedPrepareSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ? ' ;
127
+ $ expectedPrepareObjectSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET :offset ' ;
89
128
$ expectedParams1 = ['offset ' => 10 ];
90
129
$ expectedSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10 ' ;
91
130
92
131
// offset and limit are not type casted when injected into parameter container
93
132
$ select2 = new Select ;
94
133
$ select2 ->from ('foo ' )->limit ('5 ' )->offset ('10000000000000000000 ' );
95
134
$ expectedPrepareSql2 = 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ? ' ;
135
+ $ expectedPrepareObjectSql2 = 'SELECT `foo`.* FROM `foo` LIMIT :limit OFFSET :offset ' ;
96
136
$ expectedParams2 = ['offset ' => '10000000000000000000 ' , 'limit ' => '5 ' ];
97
137
$ expectedSql2 = 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10000000000000000000 ' ;
98
138
@@ -113,6 +153,9 @@ public function dataProvider()
113
153
$ expectedPrepareSql3 =
114
154
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` LIMIT ? OFFSET ?) AS `res` "
115
155
. " 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 " ;
116
159
$ expectedParams3 = [
117
160
'subselect1limit ' => 100 ,
118
161
'subselect1offset ' => 500 ,
@@ -148,6 +191,10 @@ public function dataProvider()
148
191
"SELECT (SELECT count(foo1.id) AS `cnt` FROM `foo1` LIMIT ? OFFSET ?) AS `res`, "
149
192
. " (SELECT count(foo2.id) AS `cnt` FROM `foo2` LIMIT ? OFFSET ?) AS `res0` "
150
193
. " 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 " ;
151
198
$ expectedParams4 = [
152
199
'subselect1limit ' => 100 ,
153
200
'subselect1offset ' => 500 ,
@@ -160,12 +207,43 @@ public function dataProvider()
160
207
. " (SELECT count(foo2.id) AS `cnt` FROM `foo2` LIMIT 50 OFFSET 101) AS `res0` "
161
208
. " FROM `foo` LIMIT 10 OFFSET 5 " ;
162
209
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
+
163
240
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 ],
169
247
];
170
248
}
171
249
}
0 commit comments