ExpressionBuilderTest.php 7.78 KB
Newer Older
1 2
<?php

3
namespace Doctrine\DBAL\Tests\Query\Expression;
4

Sergei Morozov's avatar
Sergei Morozov committed
5
use Doctrine\DBAL\Connection;
jeroendedauw's avatar
jeroendedauw committed
6 7
use Doctrine\DBAL\Query\Expression\CompositeExpression;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
8
use PHPUnit\Framework\TestCase;
9

10 11 12
/**
 * @group DBAL-12
 */
13
class ExpressionBuilderTest extends TestCase
14
{
Sergei Morozov's avatar
Sergei Morozov committed
15
    /** @var ExpressionBuilder */
16
    protected $expr;
17

18
    protected function setUp() : void
19
    {
Sergei Morozov's avatar
Sergei Morozov committed
20
        $conn = $this->createMock(Connection::class);
21

22
        $this->expr = new ExpressionBuilder($conn);
23

24
        $conn->expects(self::any())
25
             ->method('getExpressionBuilder')
26
             ->will(self::returnValue($this->expr));
27
    }
28

29
    /**
30 31
     * @param string[]|CompositeExpression[] $parts
     *
32
     * @dataProvider provideDataForAnd
33
     */
34
    public function testAnd(array $parts, string $expected) : void
35
    {
36 37 38 39 40 41 42 43 44 45 46 47 48
        $composite = $this->expr->and(...$parts);

        self::assertEquals($expected, (string) $composite);
    }

    /**
     * @param string[]|CompositeExpression[] $parts
     *
     * @dataProvider provideDataForAnd
     */
    public function testAndX(array $parts, string $expected) : void
    {
        $composite = $this->expr->andX();
49

50 51 52
        foreach ($parts as $part) {
            $composite->add($part);
        }
53

54
        self::assertEquals($expected, (string) $composite);
55
    }
56

57 58 59
    /**
     * @return mixed[][]
     */
60
    public static function provideDataForAnd() : iterable
61
    {
Sergei Morozov's avatar
Sergei Morozov committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
        return [
            [
                ['u.user = 1'],
                'u.user = 1',
            ],
            [
                ['u.user = 1', 'u.group_id = 1'],
                '(u.user = 1) AND (u.group_id = 1)',
            ],
            [
                ['u.user = 1'],
                'u.user = 1',
            ],
            [
                ['u.group_id = 1', 'u.group_id = 2'],
                '(u.group_id = 1) AND (u.group_id = 2)',
            ],
            [
                [
81
                    'u.user = 1',
82 83 84
                    CompositeExpression::or(
                        'u.group_id = 1',
                        'u.group_id = 2'
Sergei Morozov's avatar
Sergei Morozov committed
85 86 87 88 89 90
                    ),
                ],
                '(u.user = 1) AND ((u.group_id = 1) OR (u.group_id = 2))',
            ],
            [
                [
91
                    'u.group_id = 1',
92 93 94
                    CompositeExpression::and(
                        'u.user = 1',
                        'u.group_id = 2'
Sergei Morozov's avatar
Sergei Morozov committed
95 96 97 98 99
                    ),
                ],
                '(u.group_id = 1) AND ((u.user = 1) AND (u.group_id = 2))',
            ],
        ];
100
    }
101

102
    /**
103 104
     * @param string[]|CompositeExpression[] $parts
     *
105
     * @dataProvider provideDataForOr
106
     */
107
    public function testOr(array $parts, string $expected) : void
108
    {
109 110 111 112 113 114 115 116 117 118 119 120 121
        $composite = $this->expr->or(...$parts);

        self::assertEquals($expected, (string) $composite);
    }

    /**
     * @param string[]|CompositeExpression[] $parts
     *
     * @dataProvider provideDataForOr
     */
    public function testOrX(array $parts, string $expected) : void
    {
        $composite = $this->expr->orX();
122

123 124 125
        foreach ($parts as $part) {
            $composite->add($part);
        }
126

127
        self::assertEquals($expected, (string) $composite);
128
    }
129

130 131 132
    /**
     * @return mixed[][]
     */
133
    public static function provideDataForOr() : iterable
134
    {
Sergei Morozov's avatar
Sergei Morozov committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
        return [
            [
                ['u.user = 1'],
                'u.user = 1',
            ],
            [
                ['u.user = 1', 'u.group_id = 1'],
                '(u.user = 1) OR (u.group_id = 1)',
            ],
            [
                ['u.user = 1'],
                'u.user = 1',
            ],
            [
                ['u.group_id = 1', 'u.group_id = 2'],
                '(u.group_id = 1) OR (u.group_id = 2)',
            ],
            [
                [
154
                    'u.user = 1',
155 156 157
                    CompositeExpression::or(
                        'u.group_id = 1',
                        'u.group_id = 2'
Sergei Morozov's avatar
Sergei Morozov committed
158 159 160 161 162 163
                    ),
                ],
                '(u.user = 1) OR ((u.group_id = 1) OR (u.group_id = 2))',
            ],
            [
                [
164
                    'u.group_id = 1',
165 166 167
                    CompositeExpression::and(
                        'u.user = 1',
                        'u.group_id = 2'
Sergei Morozov's avatar
Sergei Morozov committed
168 169 170 171 172
                    ),
                ],
                '(u.group_id = 1) OR ((u.user = 1) AND (u.group_id = 2))',
            ],
        ];
173
    }
174

175 176 177
    /**
     * @dataProvider provideDataForComparison
     */
178
    public function testComparison(string $leftExpr, string $operator, string $rightExpr, string $expected) : void
179 180
    {
        $part = $this->expr->comparison($leftExpr, $operator, $rightExpr);
181

182
        self::assertEquals($expected, $part);
183
    }
184

185 186 187 188
    /**
     * @return mixed[][]
     */
    public static function provideDataForComparison() : iterable
189
    {
Sergei Morozov's avatar
Sergei Morozov committed
190 191 192 193 194 195 196 197
        return [
            ['u.user_id', ExpressionBuilder::EQ, '1', 'u.user_id = 1'],
            ['u.user_id', ExpressionBuilder::NEQ, '1', 'u.user_id <> 1'],
            ['u.salary', ExpressionBuilder::LT, '10000', 'u.salary < 10000'],
            ['u.salary', ExpressionBuilder::LTE, '10000', 'u.salary <= 10000'],
            ['u.salary', ExpressionBuilder::GT, '10000', 'u.salary > 10000'],
            ['u.salary', ExpressionBuilder::GTE, '10000', 'u.salary >= 10000'],
        ];
198
    }
199

200
    public function testEq() : void
201
    {
202
        self::assertEquals('u.user_id = 1', $this->expr->eq('u.user_id', '1'));
203
    }
204

205
    public function testNeq() : void
206
    {
207
        self::assertEquals('u.user_id <> 1', $this->expr->neq('u.user_id', '1'));
208
    }
209

210
    public function testLt() : void
211
    {
212
        self::assertEquals('u.salary < 10000', $this->expr->lt('u.salary', '10000'));
213
    }
214

215
    public function testLte() : void
216
    {
217
        self::assertEquals('u.salary <= 10000', $this->expr->lte('u.salary', '10000'));
218
    }
219

220
    public function testGt() : void
221
    {
222
        self::assertEquals('u.salary > 10000', $this->expr->gt('u.salary', '10000'));
223
    }
224

225
    public function testGte() : void
226
    {
227
        self::assertEquals('u.salary >= 10000', $this->expr->gte('u.salary', '10000'));
228
    }
229

230
    public function testIsNull() : void
231
    {
232
        self::assertEquals('u.deleted IS NULL', $this->expr->isNull('u.deleted'));
233
    }
234

235
    public function testIsNotNull() : void
236
    {
237
        self::assertEquals('u.updated IS NOT NULL', $this->expr->isNotNull('u.updated'));
238
    }
239

240
    public function testIn() : void
241
    {
Sergei Morozov's avatar
Sergei Morozov committed
242
        self::assertEquals('u.groups IN (1, 3, 4, 7)', $this->expr->in('u.groups', [1, 3, 4, 7]));
243 244
    }

245
    public function testInWithPlaceholder() : void
246
    {
247
        self::assertEquals('u.groups IN (?)', $this->expr->in('u.groups', '?'));
248 249
    }

250
    public function testNotIn() : void
251
    {
Sergei Morozov's avatar
Sergei Morozov committed
252
        self::assertEquals('u.groups NOT IN (1, 3, 4, 7)', $this->expr->notIn('u.groups', [1, 3, 4, 7]));
253
    }
254

255
    public function testNotInWithPlaceholder() : void
256
    {
257
        self::assertEquals('u.groups NOT IN (:values)', $this->expr->notIn('u.groups', ':values'));
258
    }
259

260
    public function testLikeWithoutEscape() : void
261 262 263 264
    {
        self::assertEquals("a.song LIKE 'a virgin'", $this->expr->like('a.song', "'a virgin'"));
    }

265
    public function testLikeWithEscape() : void
266 267 268
    {
        self::assertEquals(
            "a.song LIKE 'a virgin' ESCAPE '💩'",
269
            $this->expr->like('a.song', "'a virgin'", "'💩'")
270 271 272
        );
    }

273
    public function testNotLikeWithoutEscape() : void
274 275 276 277 278 279 280
    {
        self::assertEquals(
            "s.last_words NOT LIKE 'this'",
            $this->expr->notLike('s.last_words', "'this'")
        );
    }

281
    public function testNotLikeWithEscape() : void
282 283 284
    {
        self::assertEquals(
            "p.description NOT LIKE '20💩%' ESCAPE '💩'",
285
            $this->expr->notLike('p.description', "'20💩%'", "'💩'")
286 287
        );
    }
288
}