SelectSqlGenerationTest.php 31.5 KB
Newer Older
1
<?php
2 3 4

namespace Doctrine\Tests\ORM\Query;

5
use Doctrine\ORM\Query;
6

7
require_once __DIR__ . '/../../TestInit.php';
8 9

class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
10
{
11 12
    private $_em;

13 14
    protected function setUp()
    {
15 16 17
        $this->_em = $this->_getTestEntityManager();
    }

18
    public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed, array $queryHints = array())
19
    {
20
        try {
21
            $query = $this->_em->createQuery($dqlToBeTested);
22 23
            $query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
                    ->useQueryCache(false);
24
            
25 26 27
            foreach ($queryHints AS $name => $value) {
                $query->setHint($name, $value);
            }
28 29
            parent::assertEquals($sqlToBeConfirmed, $query->getSql());
            $query->free();
30
        } catch (\Exception $e) {
31 32 33 34
            $this->fail($e->getMessage());
        }
    }

35
    public function testSupportsSelectForAllFields()
36 37
    {
        $this->assertSqlGeneration(
38
            'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u',
39
            'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_'
40
        );
41
    }
42

43 44
    public function testSupportsSelectForOneField()
    {
45
        $this->assertSqlGeneration(
46
            'SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u',
47
            'SELECT c0_.id AS id0 FROM cms_users c0_'
48 49
        );
    }
50

51 52 53 54 55 56 57
    public function testSupportsSelectForOneNestedField()
    {
        $this->assertSqlGeneration(
            'SELECT a.user.id FROM Doctrine\Tests\Models\CMS\CmsArticle a',
            'SELECT c0_.id AS id0 FROM cms_articles c1_ INNER JOIN cms_users c0_ ON c1_.user_id = c0_.id'
        );
    }
58

59 60 61 62
    public function testSupportsSelectForAllNestedField()
    {
        $this->assertSqlGeneration(
            'SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a ORDER BY a.user.name ASC',
63
            'SELECT c0_.id AS id0, c0_.topic AS topic1, c0_.text AS text2, c0_.version AS version3 FROM cms_articles c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id ORDER BY c1_.name ASC'
64 65
        );
    }
66

67
    public function testSupportsSelectForMultipleColumnsOfASingleComponent()
68
    {
69
        $this->assertSqlGeneration(
70
            'SELECT u.username, u.name FROM Doctrine\Tests\Models\CMS\CmsUser u',
71
            'SELECT c0_.username AS username0, c0_.name AS name1 FROM cms_users c0_'
72
        );
73 74
    }

75
    public function testSupportsSelectWithCollectionAssociationJoin()
76 77
    {
        $this->assertSqlGeneration(
78
            'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.phonenumbers p',
79
            'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.phonenumber AS phonenumber4 FROM cms_users c0_ INNER JOIN cms_phonenumbers c1_ ON c0_.id = c1_.user_id'
80 81 82
        );
    }

83
    public function testSupportsSelectWithSingleValuedAssociationJoin()
84 85
    {
        $this->assertSqlGeneration(
86
            'SELECT u, a FROM Doctrine\Tests\Models\Forum\ForumUser u JOIN u.avatar a',
87
            'SELECT f0_.id AS id0, f0_.username AS username1, f1_.id AS id2 FROM forum_users f0_ INNER JOIN forum_avatars f1_ ON f0_.avatar_id = f1_.id'
88 89
        );
    }
90

91 92 93 94
    public function testSupportsOrderByWithAscAsDefault()
    {
        $this->assertSqlGeneration(
            'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id',
95
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id ASC'
96 97 98 99 100 101 102
        );
    }

    public function testSupportsOrderByAsc()
    {
        $this->assertSqlGeneration(
            'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id asc',
103
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id ASC'
104 105 106 107 108 109
        );
    }
    public function testSupportsOrderByDesc()
    {
        $this->assertSqlGeneration(
            'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id desc',
110
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id DESC'
111 112 113
        );
    }

114
    public function testSupportsSelectDistinct()
115 116
    {
        $this->assertSqlGeneration(
117
            'SELECT DISTINCT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u',
118
            'SELECT DISTINCT c0_.name AS name0 FROM cms_users c0_'
119 120 121
        );
    }

122
    public function testSupportsAggregateFunctionInSelectedFields()
123 124
    {
        $this->assertSqlGeneration(
125
            'SELECT COUNT(u.id) FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id',
126
            'SELECT COUNT(c0_.id) AS sclr0 FROM cms_users c0_ GROUP BY c0_.id'
127 128 129
        );
    }

130
    public function testSupportsWhereClauseWithPositionalParameter()
131 132
    {
        $this->assertSqlGeneration(
133
            'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.id = ?1',
134
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.id = ?'
135 136
        );
    }
romanb's avatar
romanb committed
137

138
    public function testSupportsWhereClauseWithNamedParameter()
139 140
    {
        $this->assertSqlGeneration(
141
            'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.username = :name',
romanb's avatar
romanb committed
142
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.username = ?'
143 144 145
        );
    }

146
    public function testSupportsWhereAndClauseWithNamedParameters()
147 148
    {
        $this->assertSqlGeneration(
149
            'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.username = :name and u.username = :name2',
romanb's avatar
romanb committed
150
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.username = ? AND f0_.username = ?'
151 152
        );
    }
153

154
    public function testSupportsCombinedWhereClauseWithNamedParameter()
155 156
    {
        $this->assertSqlGeneration(
157
            'select u from Doctrine\Tests\Models\Forum\ForumUser u where (u.username = :name OR u.username = :name2) AND u.id = :id',
romanb's avatar
romanb committed
158
            'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE (f0_.username = ? OR f0_.username = ?) AND f0_.id = ?'
159 160 161
        );
    }

162
    public function testSupportsAggregateFunctionInASelectDistinct()
163 164
    {
        $this->assertSqlGeneration(
165
            'SELECT COUNT(DISTINCT u.name) FROM Doctrine\Tests\Models\CMS\CmsUser u',
166
            'SELECT COUNT(DISTINCT c0_.name) AS sclr0 FROM cms_users c0_'
167 168
        );
    }
169

170
    // Ticket #668
171
    public function testSupportsASqlKeywordInAStringLiteralParam()
172 173
    {
        $this->assertSqlGeneration(
174
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name LIKE '%foo OR bar%'",
175
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE c0_.name LIKE '%foo OR bar%'"
176 177 178
        );
    }

179
    public function testSupportsArithmeticExpressionsInWherePart()
180 181
    {
        $this->assertSqlGeneration(
182
            'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((u.id + 5000) * u.id + 3) < 10000000',
183
            'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (c0_.id + 5000) * c0_.id + 3 < 10000000'
184 185 186
        );
    }

187
    public function testSupportsMultipleEntitiesInFromClause()
188 189 190
    {
        $this->assertSqlGeneration(
            'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a WHERE u.id = a.user.id',
191
            'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.id AS id4, c1_.topic AS topic5, c1_.text AS text6, c1_.version AS version7 FROM cms_users c0_ INNER JOIN cms_users c2_ ON c1_.user_id = c2_.id WHERE c0_.id = c2_.id'
192 193 194
        );
    }

195
    public function testSupportsPlainJoinWithoutClause()
196 197
    {
        $this->assertSqlGeneration(
198
            'SELECT u.id, a.id from Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a',
199
            'SELECT c0_.id AS id0, c1_.id AS id1 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id'
200 201
        );
        $this->assertSqlGeneration(
202
            'SELECT u.id, a.id from Doctrine\Tests\Models\CMS\CmsUser u JOIN u.articles a',
203
            'SELECT c0_.id AS id0, c1_.id AS id1 FROM cms_users c0_ INNER JOIN cms_articles c1_ ON c0_.id = c1_.user_id'
204 205
        );
    }
206

207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
    /**
     * @group DDC-135
     */
    public function testSupportsJoinAndWithClauseRestriction()
    {
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a WITH a.topic LIKE '%foo%'",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ LEFT JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE '%foo%')"
        );
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a WITH a.topic LIKE '%foo%'",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ INNER JOIN cms_articles c1_ ON c0_.id = c1_.user_id AND (c1_.topic LIKE '%foo%')"
        );
    }

    /**
     * @group DDC-135
     * @group DDC-177
     */
    public function testJoinOnClause_NotYetSupported_ThrowsException()
    {
        $this->setExpectedException('Doctrine\ORM\Query\QueryException');

        $sql = $this->_em->createQuery(
            "SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a ON a.topic LIKE '%foo%'"
        )->getSql();
    }

235
    public function testSupportsMultipleJoins()
236 237
    {
        $this->assertSqlGeneration(
238
            'SELECT u.id, a.id, p, c.id from Doctrine\Tests\Models\CMS\CmsUser u JOIN u.articles a JOIN u.phonenumbers p JOIN a.comments c',
239
            'SELECT c0_.id AS id0, c1_.id AS id1, c2_.phonenumber AS phonenumber2, c3_.id AS id3 FROM cms_users c0_ INNER JOIN cms_articles c1_ ON c0_.id = c1_.user_id INNER JOIN cms_phonenumbers c2_ ON c0_.id = c2_.user_id INNER JOIN cms_comments c3_ ON c1_.id = c3_.article_id'
240 241
        );
    }
242

243
    public function testSupportsTrimFunction()
244 245 246
    {
        $this->assertSqlGeneration(
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(TRAILING ' ' FROM u.name) = 'someone'",
247
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE TRIM(TRAILING ' ' FROM c0_.name) = 'someone'"
248 249
        );
    }
250

251
    // Ticket 894
252
    public function testSupportsBetweenClauseWithPositionalParameters()
253 254 255
    {
        $this->assertSqlGeneration(
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id BETWEEN ?1 AND ?2",
256
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE c0_.id BETWEEN ? AND ?"
257 258 259
        );
    }

260
    public function testSupportsFunctionalExpressionsInWherePart()
261 262
    {
        $this->assertSqlGeneration(
263
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(u.name) = 'someone'",
264 265
            // String quoting in the SQL usually depends on the database platform.
            // This test works with a mock connection which uses ' for string quoting.
266
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE TRIM(c0_.name) = 'someone'"
267
        );
268
    }
269

270
    // Ticket #973
271
    public function testSupportsSingleValuedInExpressionWithoutSpacesInWherePart()
272 273
    {
        $this->assertSqlGeneration(
274
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id IN(46)",
275
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE c0_.id IN (46)"
276 277 278
        );
    }

279
    public function testSupportsMultipleValuedInExpressionInWherePart()
280 281
    {
        $this->assertSqlGeneration(
282
            'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id IN (1, 2)',
283
            'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id IN (1, 2)'
284 285 286
        );
    }

287
    public function testSupportsNotInExpressionInWherePart()
288 289
    {
        $this->assertSqlGeneration(
290
            'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id NOT IN (1)',
291
            'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id NOT IN (1)'
292 293 294
        );
    }

295
    public function testSupportsConcatFunctionForMysqlAndPostgresql()
296
    {
297 298 299 300
        $connMock = $this->_em->getConnection();
        $orgPlatform = $connMock->getDatabasePlatform();

        $connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\MySqlPlatform);
301
        $this->assertSqlGeneration(
302
            "SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, 's') = ?1",
303
            "SELECT c0_.id AS id0 FROM cms_users c0_ WHERE CONCAT(c0_.name, 's') = ?"
304 305 306
        );
        $this->assertSqlGeneration(
            "SELECT CONCAT(u.id, u.name) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1",
307
            "SELECT CONCAT(c0_.id, c0_.name) AS sclr0 FROM cms_users c0_ WHERE c0_.id = ?"
308 309
        );

310 311 312
        $connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
        $this->assertSqlGeneration(
            "SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, 's') = ?1",
313
            "SELECT c0_.id AS id0 FROM cms_users c0_ WHERE c0_.name || 's' = ?"
314 315 316
        );
        $this->assertSqlGeneration(
            "SELECT CONCAT(u.id, u.name) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1",
317
            "SELECT c0_.id || c0_.name AS sclr0 FROM cms_users c0_ WHERE c0_.id = ?"
318 319 320 321
        );

        $connMock->setDatabasePlatform($orgPlatform);
    }
322

323
    public function testSupportsExistsExpressionInWherePartWithCorrelatedSubquery()
324 325 326 327 328 329
    {
        $this->assertSqlGeneration(
            'SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE EXISTS (SELECT p.phonenumber FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = u.id)',
            'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT c1_.phonenumber FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = c0_.id)'
        );
    }
330

331
    public function testSupportsMemberOfExpression()
romanb's avatar
romanb committed
332 333 334
    {
        // "Get all users who have $phone as a phonenumber." (*cough* doesnt really make sense...)
        $q1 = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
335
        $q1->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
336

romanb's avatar
romanb committed
337 338 339
        $phone = new \Doctrine\Tests\Models\CMS\CmsPhonenumber;
        $phone->phonenumber = 101;
        $q1->setParameter('param', $phone);
340

romanb's avatar
romanb committed
341 342 343 344
        $this->assertEquals(
            'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_phonenumbers c1_ WHERE c0_.id = c1_.user_id AND c1_.phonenumber = ?)',
            $q1->getSql()
        );
345

romanb's avatar
romanb committed
346 347
        // "Get all users who are members of $group."
        $q2 = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.groups');
348
        $q2->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
349

romanb's avatar
romanb committed
350 351 352
        $group = new \Doctrine\Tests\Models\CMS\CmsGroup;
        $group->id = 101;
        $q2->setParameter('param', $group);
353

romanb's avatar
romanb committed
354
        $this->assertEquals(
romanb's avatar
romanb committed
355
            'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_users_groups c1_ INNER JOIN cms_groups c2_ ON c1_.group_id = c2_.id WHERE c1_.user_id = c0_.id AND c2_.id = ?)',
romanb's avatar
romanb committed
356 357
            $q2->getSql()
        );
358

romanb's avatar
romanb committed
359 360
        // "Get all persons who have $person as a friend."
        // Tough one: Many-many self-referencing ("friends") with class table inheritance
361
        $q3 = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p WHERE :param MEMBER OF p.friends');
romanb's avatar
romanb committed
362 363 364 365
        $person = new \Doctrine\Tests\Models\Company\CompanyPerson;
        $this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, 101);
        $q3->setParameter('param', $person);
        $this->assertEquals(
romanb's avatar
romanb committed
366
            'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.friend_id = c4_.id WHERE c3_.person_id = c0_.id AND c4_.id = ?)',
romanb's avatar
romanb committed
367 368 369
            $q3->getSql()
        );
    }
370

371
    public function testSupportsCurrentDateFunction()
372
    {
373 374
        $q = $this->_em->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.datetime > current_date()');
        $q->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
375
        $this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_DATE', $q->getSql());
376 377
    }

378
    public function testSupportsCurrentTimeFunction()
379
    {
380 381
        $q = $this->_em->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.time > current_time()');
        $q->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
382
        $this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.col_time > CURRENT_TIME', $q->getSql());
383 384
    }

385
    public function testSupportsCurrentTimestampFunction()
386
    {
387 388
        $q = $this->_em->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.datetime > current_timestamp()');
        $q->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
389
        $this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_TIMESTAMP', $q->getSql());
390 391
    }

392
    public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
    {
        $this->assertSqlGeneration(
            // DQL
            // The result of this query consists of all employees whose spouses are also employees.
            'SELECT DISTINCT emp FROM Doctrine\Tests\Models\CMS\CmsEmployee emp
                WHERE EXISTS (
                    SELECT spouseEmp
                    FROM Doctrine\Tests\Models\CMS\CmsEmployee spouseEmp
                    WHERE spouseEmp = emp.spouse)',
            // SQL
            'SELECT DISTINCT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_'
                . ' WHERE EXISTS ('
                    . 'SELECT c1_.id FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
                    . ')'

        );
409
    }
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426

    public function testLimitFromQueryClass()
    {
        $q = $this->_em
            ->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u')
            ->setMaxResults(10);

        $this->assertEquals('SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ LIMIT 10', $q->getSql());
    }

    public function testLimitAndOffsetFromQueryClass()
    {
        $q = $this->_em
            ->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u')
            ->setMaxResults(10)
            ->setFirstResult(0);

427
        $this->assertEquals('SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ LIMIT 10 OFFSET 0', $q->getSql());
428
    }
429

430 431 432 433
    public function testSizeFunction()
    {
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE SIZE(u.phonenumbers) > 1",
434
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) > 1"
435 436
        );
    }
437

438 439 440 441
    public function testSizeFunctionSupportsManyToMany()
    {
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE SIZE(u.groups) > 1",
442
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_users_groups c1_ WHERE c1_.user_id = c0_.id) > 1"
443 444 445
        );
    }

446 447 448 449
    public function testEmptyCollectionComparisonExpression()
    {
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.phonenumbers IS EMPTY",
450
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) = 0"
451 452 453
        );
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.phonenumbers IS NOT EMPTY",
454
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (SELECT COUNT(*) FROM cms_phonenumbers c1_ WHERE c1_.user_id = c0_.id) > 0"
455 456
        );
    }
457

458 459 460 461
    public function testNestedExpressions()
    {
        $this->assertSqlGeneration(
            "select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id > 10 and u.id < 42 and ((u.id * 2) > 5)",
462
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id > 10 AND c0_.id < 42 AND (c0_.id * 2 > 5)"
463 464
        );
    }
465

466 467 468 469
    public function testNestedExpressions2()
    {
        $this->assertSqlGeneration(
            "select u from Doctrine\Tests\Models\CMS\CmsUser u where (u.id > 10) and (u.id < 42 and ((u.id * 2) > 5)) or u.id <> 42",
470
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (c0_.id > 10) AND (c0_.id < 42 AND (c0_.id * 2 > 5)) OR c0_.id <> 42"
471 472
        );
    }
473

474 475 476 477 478 479 480
    public function testNestedExpressions3()
    {
        $this->assertSqlGeneration(
            "select u from Doctrine\Tests\Models\CMS\CmsUser u where (u.id > 10) and (u.id between 1 and 10 or u.id in (1, 2, 3, 4, 5))",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (c0_.id > 10) AND (c0_.id BETWEEN 1 AND 10 OR c0_.id IN (1, 2, 3, 4, 5))"
        );
    }
481

482 483 484 485
    public function testOrderByCollectionAssociationSize()
    {
        $this->assertSqlGeneration(
            "select u, size(u.articles) as numArticles from Doctrine\Tests\Models\CMS\CmsUser u order by numArticles",
486
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, (SELECT COUNT(*) FROM cms_articles c1_ WHERE c1_.user_id = c0_.id) AS sclr4 FROM cms_users c0_ ORDER BY sclr4 ASC"
487 488
        );
    }
489

romanb's avatar
romanb committed
490 491 492 493
    public function testBooleanLiteralInWhereOnSqlite()
    {
        $oldPlat = $this->_em->getConnection()->getDatabasePlatform();
        $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\SqlitePlatform);
494

romanb's avatar
romanb committed
495 496 497 498
        $this->assertSqlGeneration(
            "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true",
            "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 1"
        );
499

romanb's avatar
romanb committed
500 501 502 503
        $this->assertSqlGeneration(
            "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false",
            "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 0"
        );
504

romanb's avatar
romanb committed
505 506
        $this->_em->getConnection()->setDatabasePlatform($oldPlat);
    }
507

romanb's avatar
romanb committed
508 509 510 511
    public function testBooleanLiteralInWhereOnPostgres()
    {
        $oldPlat = $this->_em->getConnection()->getDatabasePlatform();
        $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
512

romanb's avatar
romanb committed
513 514 515 516
        $this->assertSqlGeneration(
            "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true",
            "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 'true'"
        );
517

romanb's avatar
romanb committed
518 519 520 521
        $this->assertSqlGeneration(
            "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false",
            "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 'false'"
        );
522

romanb's avatar
romanb committed
523 524
        $this->_em->getConnection()->setDatabasePlatform($oldPlat);
    }
romanb's avatar
romanb committed
525

526 527
    public function testSingleValuedAssociationFieldInWhere()
    {
romanb's avatar
romanb committed
528
        $this->assertSqlGeneration(
529
            "SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.user = ?1",
romanb's avatar
romanb committed
530
            "SELECT c0_.phonenumber AS phonenumber0 FROM cms_phonenumbers c0_ WHERE c0_.user_id = ?"
531
        );
532
    }
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551

    public function testSingleValuedAssociationNullCheckOnOwningSide()
    {
        $this->assertSqlGeneration(
            "SELECT a FROM Doctrine\Tests\Models\CMS\CmsAddress a WHERE a.user IS NULL",
            "SELECT c0_.id AS id0, c0_.country AS country1, c0_.zip AS zip2, c0_.city AS city3 FROM cms_addresses c0_ WHERE c0_.user_id IS NULL"
        );
    }

    // Null check on inverse side has to happen through explicit JOIN.
    // "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.address IS NULL"
    // where the CmsUser is the inverse side is not supported.
    public function testSingleValuedAssociationNullCheckOnInverseSide()
    {
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.address a WHERE a.id IS NULL",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON c0_.id = c1_.user_id WHERE c1_.id IS NULL"
        );
    }
552

romanb's avatar
romanb committed
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
    /**
     * @group DDC-339
     */
    public function testStringFunctionLikeExpression()
    {
        $this->assertSqlGeneration(
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE LOWER(u.name) LIKE '%foo OR bar%'",
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE LOWER(c0_.name) LIKE '%foo OR bar%'"
        );
        $this->assertSqlGeneration(
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE LOWER(u.name) LIKE :str",
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE LOWER(c0_.name) LIKE ?"
        );
        $this->assertSqlGeneration(
            "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(UPPER(u.name), '_moo') LIKE :str",
            "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE UPPER(c0_.name) || '_moo' LIKE ?"
        );
    }
571 572 573 574 575 576 577 578 579 580 581 582

    /**
     * @group DDC-338
     */
    public function testOrderedCollectionFetchJoined()
    {
        $this->assertSqlGeneration(
            "SELECT r, l FROM Doctrine\Tests\Models\Routing\RoutingRoute r JOIN r.legs l",
            "SELECT r0_.id AS id0, r1_.id AS id1, r1_.departureDate AS departureDate2, r1_.arrivalDate AS arrivalDate3 FROM RoutingRoute r0_ INNER JOIN RoutingRouteLegs r2_ ON r0_.id = r2_.route_id INNER JOIN RoutingLeg r1_ ON r1_.id = r2_.leg_id ".
            "ORDER BY r1_.departureDate ASC"
        );
    }
583 584 585 586 587

    public function testSubselectInSelect()
    {
        $this->assertSqlGeneration(
            "SELECT u.name, (SELECT COUNT(p.phonenumber) FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234) pcount FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'",
588
            "SELECT c0_.name AS name0, (SELECT COUNT(c1_.phonenumber) AS dctrn__1 FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = 1234) AS sclr1 FROM cms_users c0_ WHERE c0_.name = 'jon'"
589 590
        );
    }
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605

    /**
     * @group locking
     * @group DDC-178
     */
    public function testPessimisticWriteLockQueryHint()
    {
        if ($this->_em->getConnection()->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) {
            $this->markTestSkipped('SqLite does not support Row locking at all.');
        }

        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 ".
            "FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
606
            array(Query::HINT_LOCK_MODE => \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
        );
    }

    /**
     * @group locking
     * @group DDC-178
     */
    public function testPessimisticReadLockQueryHintPostgreSql()
    {
        $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);

        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 ".
            "FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR SHARE",
622
            array(Query::HINT_LOCK_MODE => \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)
623 624 625 626 627
                );
    }

    /**
     * @group DDC-430
628 629 630 631 632 633
     */
    public function testSupportSelectWithMoreThan10InputParameters()
    {
        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1 OR u.id = ?2 OR u.id = ?3 OR u.id = ?4 OR u.id = ?5 OR u.id = ?6 OR u.id = ?7 OR u.id = ?8 OR u.id = ?9 OR u.id = ?10 OR u.id = ?11",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ?"
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
        );
    }

    /**
     * @group locking
     * @group DDC-178
     */
    public function testPessimisticReadLockQueryHintMySql()
    {
        $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\MySqlPlatform);

        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 ".
            "FROM cms_users c0_ WHERE c0_.username = 'gblanco' LOCK IN SHARE MODE",
649
            array(Query::HINT_LOCK_MODE => \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
        );
    }

    /**
     * @group locking
     * @group DDC-178
     */
    public function testPessimisticReadLockQueryHintOracle()
    {
        $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);

        $this->assertSqlGeneration(
            "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
            "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 ".
            "FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
665
            array(Query::HINT_LOCK_MODE => \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)
666 667
        );
    }
668 669 670

    /**
     * @group DDC-431
671 672 673 674 675 676 677 678 679 680 681
     */
    public function testSupportToCustomDQLFunctions()
    {
        $config = $this->_em->getConfiguration();
        $config->addCustomNumericFunction('MYABS', 'Doctrine\Tests\ORM\Query\MyAbsFunction');

        $this->assertSqlGeneration(
            'SELECT MYABS(p.phonenumber) FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p',
            'SELECT ABS(c0_.phonenumber) AS sclr0 FROM cms_phonenumbers c0_'
        );

682
        $config->setCustomNumericFunctions(array());
683
    }
684
}
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715


class MyAbsFunction extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
{
    public $simpleArithmeticExpression;

    /**
     * @override
     */
    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'ABS(' . $sqlWalker->walkSimpleArithmeticExpression(
            $this->simpleArithmeticExpression
        ) . ')';
    }

    /**
     * @override
     */
    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $lexer = $parser->getLexer();

        $parser->match(\Doctrine\ORM\Query\Lexer::T_IDENTIFIER);
        $parser->match(\Doctrine\ORM\Query\Lexer::T_OPEN_PARENTHESIS);

        $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
        
        $parser->match(\Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS);
    }
}