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

Michael Moravec's avatar
Michael Moravec committed
3 4
declare(strict_types=1);

5 6
namespace Doctrine\Tests\DBAL\Query\Expression;

Sergei Morozov's avatar
Sergei Morozov committed
7
use Doctrine\DBAL\Connection;
jeroendedauw's avatar
jeroendedauw committed
8 9
use Doctrine\DBAL\Query\Expression\CompositeExpression;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
Sergei Morozov's avatar
Sergei Morozov committed
10
use Doctrine\Tests\DbalTestCase;
11

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

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

24
        $this->expr = new ExpressionBuilder($conn);
25

26 27 28 29
        $conn->expects($this->any())
             ->method('getExpressionBuilder')
             ->will($this->returnValue($this->expr));
    }
30

31
    /**
32 33
     * @param string[]|CompositeExpression[] $parts
     *
34 35
     * @dataProvider provideDataForAndX
     */
36
    public function testAndX(array $parts, string $expected) : void
37 38
    {
        $composite = $this->expr->andX();
39

40 41 42
        foreach ($parts as $part) {
            $composite->add($part);
        }
43

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

47 48 49 50
    /**
     * @return mixed[][]
     */
    public static function provideDataForAndX() : iterable
51
    {
Sergei Morozov's avatar
Sergei Morozov committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
        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)',
            ],
            [
                [
71
                    'u.user = 1',
72 73
                    new CompositeExpression(
                        CompositeExpression::TYPE_OR,
Sergei Morozov's avatar
Sergei Morozov committed
74 75 76 77 78 79 80
                        ['u.group_id = 1', 'u.group_id = 2']
                    ),
                ],
                '(u.user = 1) AND ((u.group_id = 1) OR (u.group_id = 2))',
            ],
            [
                [
81
                    'u.group_id = 1',
82 83
                    new CompositeExpression(
                        CompositeExpression::TYPE_AND,
Sergei Morozov's avatar
Sergei Morozov committed
84 85 86 87 88 89
                        ['u.user = 1', 'u.group_id = 2']
                    ),
                ],
                '(u.group_id = 1) AND ((u.user = 1) AND (u.group_id = 2))',
            ],
        ];
90
    }
91

92
    /**
93 94
     * @param string[]|CompositeExpression[] $parts
     *
95 96
     * @dataProvider provideDataForOrX
     */
97
    public function testOrX(array $parts, string $expected) : void
98 99
    {
        $composite = $this->expr->orX();
100

101 102 103
        foreach ($parts as $part) {
            $composite->add($part);
        }
104

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

108 109 110 111
    /**
     * @return mixed[][]
     */
    public static function provideDataForOrX() : iterable
112
    {
Sergei Morozov's avatar
Sergei Morozov committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
        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)',
            ],
            [
                [
132
                    'u.user = 1',
133 134
                    new CompositeExpression(
                        CompositeExpression::TYPE_OR,
Sergei Morozov's avatar
Sergei Morozov committed
135 136 137 138 139 140 141
                        ['u.group_id = 1', 'u.group_id = 2']
                    ),
                ],
                '(u.user = 1) OR ((u.group_id = 1) OR (u.group_id = 2))',
            ],
            [
                [
142
                    'u.group_id = 1',
143 144
                    new CompositeExpression(
                        CompositeExpression::TYPE_AND,
Sergei Morozov's avatar
Sergei Morozov committed
145 146 147 148 149 150
                        ['u.user = 1', 'u.group_id = 2']
                    ),
                ],
                '(u.group_id = 1) OR ((u.user = 1) AND (u.group_id = 2))',
            ],
        ];
151
    }
152

153 154 155
    /**
     * @dataProvider provideDataForComparison
     */
156
    public function testComparison(string $leftExpr, string $operator, string $rightExpr, string $expected) : void
157 158
    {
        $part = $this->expr->comparison($leftExpr, $operator, $rightExpr);
159

160
        self::assertEquals($expected, (string) $part);
161
    }
162

163 164 165 166
    /**
     * @return mixed[][]
     */
    public static function provideDataForComparison() : iterable
167
    {
Sergei Morozov's avatar
Sergei Morozov committed
168 169 170 171 172 173 174 175
        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'],
        ];
176
    }
177

178
    public function testEq() : void
179
    {
180
        self::assertEquals('u.user_id = 1', $this->expr->eq('u.user_id', '1'));
181
    }
182

183
    public function testNeq() : void
184
    {
185
        self::assertEquals('u.user_id <> 1', $this->expr->neq('u.user_id', '1'));
186
    }
187

188
    public function testLt() : void
189
    {
190
        self::assertEquals('u.salary < 10000', $this->expr->lt('u.salary', '10000'));
191
    }
192

193
    public function testLte() : void
194
    {
195
        self::assertEquals('u.salary <= 10000', $this->expr->lte('u.salary', '10000'));
196
    }
197

198
    public function testGt() : void
199
    {
200
        self::assertEquals('u.salary > 10000', $this->expr->gt('u.salary', '10000'));
201
    }
202

203
    public function testGte() : void
204
    {
205
        self::assertEquals('u.salary >= 10000', $this->expr->gte('u.salary', '10000'));
206
    }
207

208
    public function testIsNull() : void
209
    {
210
        self::assertEquals('u.deleted IS NULL', $this->expr->isNull('u.deleted'));
211
    }
212

213
    public function testIsNotNull() : void
214
    {
215
        self::assertEquals('u.updated IS NOT NULL', $this->expr->isNotNull('u.updated'));
216
    }
217

218
    public function testIn() : void
219
    {
220
        self::assertEquals('u.groups IN (1, 3, 4, 7)', $this->expr->in('u.groups', ['1', '3', '4', '7']));
221 222
    }

223
    public function testInWithPlaceholder() : void
224
    {
225
        self::assertEquals('u.groups IN (?)', $this->expr->in('u.groups', '?'));
226 227
    }

228
    public function testNotIn() : void
229
    {
230
        self::assertEquals('u.groups NOT IN (1, 3, 4, 7)', $this->expr->notIn('u.groups', ['1', '3', '4', '7']));
231
    }
232

233
    public function testNotInWithPlaceholder() : void
234
    {
235
        self::assertEquals('u.groups NOT IN (:values)', $this->expr->notIn('u.groups', ':values'));
236
    }
237

238
    public function testLikeWithoutEscape() : void
239 240 241 242
    {
        self::assertEquals("a.song LIKE 'a virgin'", $this->expr->like('a.song', "'a virgin'"));
    }

243
    public function testLikeWithEscape() : void
244 245 246
    {
        self::assertEquals(
            "a.song LIKE 'a virgin' ESCAPE '💩'",
247
            $this->expr->like('a.song', "'a virgin'", "'💩'")
248 249 250
        );
    }

251
    public function testNotLikeWithoutEscape() : void
252 253 254 255 256 257 258
    {
        self::assertEquals(
            "s.last_words NOT LIKE 'this'",
            $this->expr->notLike('s.last_words', "'this'")
        );
    }

259
    public function testNotLikeWithEscape() : void
260 261 262
    {
        self::assertEquals(
            "p.description NOT LIKE '20💩%' ESCAPE '💩'",
263
            $this->expr->notLike('p.description', "'20💩%'", "'💩'")
264 265
        );
    }
266
}