Passed
Push — master ( 6186c3...2d1efd )
by William
02:54 queued 11s
created

CreateStatementTest::testBuilderCreateProcedure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 44
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 27
nc 1
nop 0
dl 0
loc 44
rs 9.488
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Tests\Builder;
6
7
use PhpMyAdmin\SqlParser\Components\CreateDefinition;
8
use PhpMyAdmin\SqlParser\Components\DataType;
9
use PhpMyAdmin\SqlParser\Components\Expression;
10
use PhpMyAdmin\SqlParser\Components\Key;
11
use PhpMyAdmin\SqlParser\Components\OptionsArray;
12
use PhpMyAdmin\SqlParser\Components\ParameterDefinition;
13
use PhpMyAdmin\SqlParser\Parser;
14
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
15
use PhpMyAdmin\SqlParser\Tests\TestCase;
16
use PhpMyAdmin\SqlParser\TokensList;
17
18
class CreateStatementTest extends TestCase
19
{
20
    public function testBuilder(): void
21
    {
22
        $parser = new Parser('CREATE USER "jeffrey"@"localhost" IDENTIFIED BY "mypass"');
23
        $stmt = $parser->statements[0];
24
        $this->assertEquals(
25
            'CREATE USER "jeffrey"@"localhost" IDENTIFIED BY "mypass"',
26
            $stmt->build()
27
        );
28
    }
29
30
    public function testBuilderDatabase(): void
31
    {
32
        // CREATE DATABASE ...
33
        $parser = new Parser(
34
            'CREATE DATABASE `mydb` ' .
35
            'DEFAULT CHARACTER SET = utf8 DEFAULT COLLATE = utf8_general_ci'
36
        );
37
        $stmt = $parser->statements[0];
38
39
        $this->assertEquals(
40
            'CREATE DATABASE `mydb` ' .
41
            'DEFAULT CHARACTER SET=utf8 DEFAULT COLLATE=utf8_general_ci',
42
            $stmt->build()
43
        );
44
45
        // CREATE SCHEMA ...
46
        $parser = new Parser('CREATE SCHEMA `mydb` DEFAULT CHARACTER SET = utf8 DEFAULT COLLATE = utf8_general_ci');
47
        $stmt = $parser->statements[0];
48
49
        $this->assertEquals(
50
            'CREATE SCHEMA `mydb` ' .
51
            'DEFAULT CHARACTER SET=utf8 DEFAULT COLLATE=utf8_general_ci',
52
            $stmt->build()
53
        );
54
    }
55
56
    public function testBuilderDefaultInt(): void
57
    {
58
        $parser = new Parser(
59
            'CREATE TABLE IF NOT EXISTS t1 (' .
60
            " c1 int(11) NOT NULL DEFAULT '0' COMMENT 'xxx'" .
61
            ') ENGINE=MyISAM'
62
        );
63
        $stmt = $parser->statements[0];
64
65
        $this->assertEquals(
66
            "CREATE TABLE IF NOT EXISTS t1 (\n" .
67
            "  `c1` int(11) NOT NULL DEFAULT '0' COMMENT 'xxx'\n" .
68
            ') ENGINE=MyISAM',
69
            $stmt->build()
70
        );
71
    }
72
73
    public function testBuilderCollate(): void
74
    {
75
        $parser = new Parser(
76
            'CREATE TABLE IF NOT EXISTS t1 (' .
77
            " c1 varchar(11) NOT NULL DEFAULT '0' COLLATE 'utf8_czech_ci' COMMENT 'xxx'" .
78
            ') ENGINE=MyISAM'
79
        );
80
        $stmt = $parser->statements[0];
81
82
        $this->assertEquals(
83
            "CREATE TABLE IF NOT EXISTS t1 (\n" .
84
            "  `c1` varchar(11) NOT NULL DEFAULT '0' COLLATE 'utf8_czech_ci' COMMENT 'xxx'\n" .
85
            ') ENGINE=MyISAM',
86
            $stmt->build()
87
        );
88
    }
89
90
    public function testBuilderDefaultComment(): void
91
    {
92
        $parser = new Parser(
93
            'CREATE TABLE `wp_audio` (' .
94
            " `somedata` int(11) DEFAULT NULL COMMENT 'ma data', " .
95
            " `someinfo` int(11) DEFAULT NULL COMMENT 'ma info' " .
96
            ' )'
97
        );
98
        $stmt = $parser->statements[0];
99
100
        $this->assertEquals(
101
            "CREATE TABLE `wp_audio` (\n" .
102
            "  `somedata` int(11) DEFAULT NULL COMMENT 'ma data',\n" .
103
            "  `someinfo` int(11) DEFAULT NULL COMMENT 'ma info'\n" .
104
            ') ',
105
            $stmt->build()
106
        );
107
    }
108
109
    public function testBuilderTable(): void
110
    {
111
        /* Assertion 1 */
112
        $stmt = new CreateStatement();
113
114
        $stmt->name = new Expression('', 'test', '');
115
        $stmt->options = new OptionsArray(['TABLE']);
116
        $stmt->fields = [
117
            new CreateDefinition(
118
                'id',
119
                new OptionsArray(['NOT NULL', 'AUTO_INCREMENT']),
120
                new DataType('INT', [11], new OptionsArray(['UNSIGNED']))
121
            ),
122
            new CreateDefinition(
123
                '',
124
                null,
125
                new Key('', [['name' => 'id']], 'PRIMARY KEY')
126
            ),
127
        ];
128
129
        $this->assertEquals(
130
            "CREATE TABLE `test` (\n" .
131
            "  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,\n" .
132
            "  PRIMARY KEY (`id`)\n" .
133
            ') ',
134
            $stmt->build()
135
        );
136
137
        /* Assertion 2 */
138
        $query =
139
            "CREATE TABLE `jos_core_acl_aro` (\n" .
140
            "  `id` int(11) NOT NULL,\n" .
141
            "  `section_value` varchar(240) NOT NULL DEFAULT '0',\n" .
142
            "  `value` varchar(240) NOT NULL DEFAULT '',\n" .
143
            "  `order_value` int(11) NOT NULL DEFAULT '0',\n" .
144
            "  `name` varchar(255) NOT NULL DEFAULT '',\n" .
145
            "  `hidden` int(11) NOT NULL DEFAULT '0',\n" .
146
            "  PRIMARY KEY (`id`),\n" .
147
            "  UNIQUE KEY `jos_section_value_value_aro` (`section_value`(100),`value`(15)) USING BTREE,\n" .
148
            "  KEY `jos_gacl_hidden_aro` (`hidden`)\n" .
149
            ') ENGINE=InnoDB DEFAULT CHARSET=latin1';
150
        $parser = new Parser($query);
151
        $this->assertEquals($query, $parser->statements[0]->build());
152
153
        /* Assertion 3 */
154
        $query = 'CREATE TABLE `table_copy` LIKE `old_table`';
155
        $parser = new Parser($query);
156
        $this->assertEquals($query, $parser->statements[0]->build());
157
158
        /* Assertion 4 */
159
        $query =
160
            "CREATE TABLE `aa` (\n" .
161
            "  `id` int(11) NOT NULL,\n" .
162
            "  `rTime` timestamp(3) NOT NULL DEFAULT '0000-00-00 00:00:00.000' ON UPDATE CURRENT_TIMESTAMP(3),\n" .
163
            "  PRIMARY KEY (`id`)\n" .
164
            ') ENGINE=InnoDB DEFAULT CHARSET=latin1';
165
        $parser = new Parser($query);
166
        $this->assertEquals($query, $parser->statements[0]->build());
167
    }
168
169
    public function testBuilderPartitions(): void
170
    {
171
        /* Assertion 1 */
172
        $query = 'CREATE TABLE ts (' . "\n"
173
            . '  `id` int,' . "\n"
174
            . '  `purchased` date' . "\n"
175
            . ') ' . "\n"
176
            . 'PARTITION BY RANGE(YEAR(purchased))' . "\n"
177
            . 'PARTITIONS 3' . "\n"
178
            . 'SUBPARTITION BY HASH(TO_DAYS(purchased))' . "\n"
179
            . 'SUBPARTITIONS 2' . "\n"
180
            . '(' . "\n"
181
            . 'PARTITION p0 VALUES LESS THAN (1990)  (' . "\n"
182
            . 'SUBPARTITION s0,' . "\n"
183
            . 'SUBPARTITION s1' . "\n"
184
            . '),' . "\n"
185
            . 'PARTITION p1 VALUES LESS THAN (2000)  (' . "\n"
186
            . 'SUBPARTITION s2,' . "\n"
187
            . 'SUBPARTITION s3' . "\n"
188
            . '),' . "\n"
189
            . 'PARTITION p2 VALUES LESS THAN MAXVALUE  (' . "\n"
190
            . 'SUBPARTITION s4,' . "\n"
191
            . 'SUBPARTITION s5' . "\n"
192
            . ')' . "\n"
193
            . ')';
194
        $parser = new Parser($query);
195
        $this->assertEquals($query, $parser->statements[0]->build());
196
197
        /* Assertion 2 */
198
        $query = 'CREATE TABLE `pma_test` (' . "\n"
199
            . '  `test_id` int(32) NOT NULL,' . "\n"
200
            . '  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP' . "\n"
201
            . ') ENGINE=InnoDB DEFAULT CHARSET=utf8' . "\n"
202
            . 'PARTITION BY RANGE (test_id)' . "\n"
203
            . '(' . "\n"
204
            . 'PARTITION p0 VALUES LESS THAN (250000) ENGINE=InnoDB,' . "\n"
205
            . 'PARTITION p1 VALUES LESS THAN (500000) ENGINE=InnoDB,' . "\n"
206
            . 'PARTITION p2 VALUES LESS THAN (750000) ENGINE=InnoDB,' . "\n"
207
            . 'PARTITION p3 VALUES LESS THAN (1000000) ENGINE=InnoDB,' . "\n"
208
            . 'PARTITION p4 VALUES LESS THAN (1250000) ENGINE=InnoDB,' . "\n"
209
            . 'PARTITION p5 VALUES LESS THAN (1500000) ENGINE=InnoDB,' . "\n"
210
            . 'PARTITION p6 VALUES LESS THAN MAXVALUE ENGINE=InnoDB' . "\n"
211
            . ')';
212
        $parser = new Parser($query);
213
        $this->assertEquals($query, $parser->statements[0]->build());
214
    }
215
216
    public function partitionQueriesProvider(): array
217
    {
218
        return [
219
            [
220
                'subparts' => <<<EOT
221
CREATE TABLE `ts` (
222
  `id` int(11) DEFAULT NULL,
223
  `purchased` date DEFAULT NULL
224
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
225
PARTITION BY RANGE (YEAR(purchased))
226
SUBPARTITION BY HASH (TO_DAYS(purchased))
227
(
228
PARTITION p0 VALUES LESS THAN (1990)  (
229
SUBPARTITION s0 ENGINE=InnoDB,
230
SUBPARTITION s1 ENGINE=InnoDB
231
),
232
PARTITION p1 VALUES LESS THAN (2000)  (
233
SUBPARTITION s2 ENGINE=InnoDB,
234
SUBPARTITION s3 ENGINE=InnoDB
235
),
236
PARTITION p2 VALUES LESS THAN MAXVALUE  (
237
SUBPARTITION s4 ENGINE=InnoDB,
238
SUBPARTITION s5 ENGINE=InnoDB
239
)
240
)
241
EOT
242
            ,
243
            ],
244
            [
245
                'parts' => <<<EOT
246
CREATE TABLE ptest (
247
  `event_date` date NOT NULL
248
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
249
PARTITION BY HASH (TO_DAYS(event_date))
250
(
251
PARTITION p0 ENGINE=InnoDB,
252
PARTITION p1 ENGINE=InnoDB,
253
PARTITION p2 ENGINE=InnoDB,
254
PARTITION p3 ENGINE=InnoDB,
255
PARTITION p4 ENGINE=InnoDB
256
)
257
EOT
258
            ,
259
            ],
260
        ];
261
    }
262
263
    /**
264
     * @dataProvider partitionQueriesProvider
265
     */
266
    public function testBuilderPartitionsEngine(string $query): void
267
    {
268
        $parser = new Parser($query);
269
        $stmt = $parser->statements[0];
270
271
        $this->assertEquals($query, $stmt->build());
272
    }
273
274
    public function testBuilderView(): void
275
    {
276
        $parser = new Parser(
277
            'CREATE VIEW myView (vid, vfirstname) AS ' .
278
            'SELECT id, first_name FROM employee WHERE id = 1'
279
        );
280
        $stmt = $parser->statements[0];
281
282
        $this->assertEquals(
283
            'CREATE VIEW myView (vid, vfirstname) AS  ' .
284
            'SELECT id, first_name FROM employee WHERE id = 1 ',
285
            $stmt->build()
286
        );
287
288
        $parser = new Parser(
289
            'CREATE OR REPLACE VIEW myView (vid, vfirstname) AS ' .
290
            'SELECT id, first_name FROM employee WHERE id = 1'
291
        );
292
        $stmt = $parser->statements[0];
293
294
        $this->assertEquals(
295
            'CREATE OR REPLACE VIEW myView (vid, vfirstname) AS  ' .
296
            'SELECT id, first_name FROM employee WHERE id = 1 ',
297
            $stmt->build()
298
        );
299
300
        // Assert the builder can build wrong syntax select expressions
301
        $parser = new Parser(
302
            'CREATE OR REPLACE VIEW myView (vid, vfirstname) AS ' .
303
            'SELECT id, first_name, FROMzz employee WHERE id = 1'
304
        );
305
        $stmt = $parser->statements[0];
306
        $this->assertEquals(
307
            'CREATE OR REPLACE VIEW myView (vid, vfirstname) AS  ' .
308
            'SELECT id, first_name, FROMzz employee WHERE id = 1 ',
309
            $stmt->build()
310
        );
311
312
        $parser = new Parser(
313
            'CREATE OR REPLACE VIEW myView (vid, vfirstname) AS ' .
314
            'SELECT id, first_name, FROMzz employee WHERE id = 1 ' .
315
            'UNION ' .
316
            'SELECT id, first_name, FROMzz employee WHERE id = 2 '
317
        );
318
        $stmt = $parser->statements[0];
319
320
        $this->assertEquals(
321
            'CREATE OR REPLACE VIEW myView (vid, vfirstname) AS  ' .
322
            'SELECT id, first_name, FROMzz employee WHERE id = 1 ' .
323
            'UNION ' .
324
            'SELECT id, first_name, FROMzz employee WHERE id = 2  ',
325
            $stmt->build()
326
        );
327
    }
328
329
    public function testBuilderViewComplex(): void
330
    {
331
        $parser = new Parser(
332
            'CREATE VIEW withclause AS' . "\n"
333
            . "\n"
334
            . 'WITH cte AS (' . "\n"
335
                . 'SELECT p.name, p.shape' . "\n"
336
                . 'FROM gis_all as p' . "\n"
337
            . ')' . "\n"
338
            . "\n"
339
            . 'SELECT cte.*' . "\n"
340
            . 'FROM cte' . "\n"
341
            . 'CROSS JOIN gis_all;'
342
        );
343
        $stmt = $parser->statements[0];
344
345
        $this->assertEquals(
346
            'CREATE VIEW withclause  AS ' . "\n"
347
            . "\n"
348
            . 'WITH cte AS (' . "\n"
349
                . 'SELECT p.name, p.shape' . "\n"
350
                . 'FROM gis_all as p' . "\n"
351
            . ')' . "\n"
352
            . "\n"
353
            . 'SELECT cte.*' . "\n"
354
            . 'FROM cte' . "\n"
355
            . 'CROSS JOIN gis_all ',
356
            $stmt->build()
357
        );
358
        $parser = new Parser(
359
            'CREATE VIEW withclause2 AS' . "\n"
360
            . "\n"
361
            . 'WITH cte AS (' . "\n"
362
                . "\t" . 'SELECT p.name, p.shape' . "\n"
363
                . "\t" . 'FROM gis_all as p' . "\n"
364
            . '), cte2 AS (' . "\n"
365
                . "\t" . 'SELECT p.name as n2, p.shape as sh2' . "\n"
366
                . "\t" . 'FROM gis_all as p' . "\n"
367
            . ')' . "\n"
368
            . "\n"
369
            . 'SELECT cte.*,cte2.*' . "\n"
370
            . 'FROM cte,cte2' . "\n"
371
            . 'CROSS JOIN gis_all;'
372
        );
373
        $stmt = $parser->statements[0];
374
375
        $this->assertEquals(
376
            'CREATE VIEW withclause2  AS ' . "\n"
377
            . "\n"
378
            . 'WITH cte AS (' . "\n"
379
                . "\t" . 'SELECT p.name, p.shape' . "\n"
380
                . "\t" . 'FROM gis_all as p' . "\n"
381
            . '), cte2 AS (' . "\n"
382
                . "\t" . 'SELECT p.name as n2, p.shape as sh2' . "\n"
383
                . "\t" . 'FROM gis_all as p' . "\n"
384
            . ')' . "\n"
385
            . "\n"
386
            . 'SELECT cte.*,cte2.*' . "\n"
387
            . 'FROM cte,cte2' . "\n"
388
            . 'CROSS JOIN gis_all ',
389
            $stmt->build()
390
        );
391
    }
392
393
    public function testBuilderCreateProcedure(): void
394
    {
395
        $parser = new Parser(
396
            'CREATE DEFINER=`root`@`%`'
397
            . ' PROCEDURE `test2`(IN `_var` INT) NOT DETERMINISTIC NO SQL'
398
            . ' SQL SECURITY INVOKER NO SQL SQL SECURITY INVOKER SELECT _var'
399
        );
400
401
        /** @var CreateStatement $stmt */
402
        $stmt = $parser->statements[0];
403
404
        $this->assertSame(
405
            'CREATE DEFINER=`root`@`%`'
406
            . ' PROCEDURE `test2` (IN `_var` INT)  NOT DETERMINISTIC NO SQL'
407
            . ' SQL SECURITY INVOKER NO SQL SQL SECURITY INVOKER SELECT _var',
408
            $stmt->build()
409
        );
410
411
        $this->assertTrue($stmt->entityOptions->isEmpty());
412
        $this->assertFalse($stmt->options->isEmpty());
413
414
        $this->assertSame(
415
            'DEFINER=`root`@`%` PROCEDURE',
416
            $stmt->options->__toString()
417
        );
418
419
        $this->assertSame(
420
            '`test2`',
421
            $stmt->name->__toString()
422
        );
423
424
        $this->assertSame(
425
            '(IN `_var` INT)',
426
            ParameterDefinition::build($stmt->parameters)
427
        );
428
429
        $this->assertSame(
430
            '',
431
            $stmt->entityOptions->__toString()
432
        );
433
434
        $this->assertSame(
435
            'NOT DETERMINISTIC NO SQL SQL SECURITY INVOKER NO SQL SQL SECURITY INVOKER SELECT _var',
436
            TokensList::build($stmt->body)
437
        );
438
    }
439
440
    public function testBuilderCreateFunction(): void
441
    {
442
        $parser = new Parser(
443
            'CREATE DEFINER=`root`@`localhost`'
444
            . ' FUNCTION `inventory_in_stock`(`p_inventory_id` INT) RETURNS tinyint(1)'
445
            . ' READS SQL DATA' . "\n"
446
            . ' COMMENT \'My best function written by a friend\'\'s friend' . "\n"
447
            . 'BEGIN' . "\n"
448
            . '    DECLARE v_rentals INT;' . "\n"
449
            . '    DECLARE v_out     INT;' . "\n"
450
            . "\n"
451
            . '    ' . "\n"
452
            . '    ' . "\n"
453
            . "\n"
454
            . '    SELECT COUNT(*) INTO v_rentals' . "\n"
455
            . '    FROM rental' . "\n"
456
            . '    WHERE inventory_id = p_inventory_id;' . "\n"
457
            . "\n"
458
            . '    IF v_rentals = 0 THEN' . "\n"
459
            . '      RETURN TRUE;' . "\n"
460
            . '    END IF;' . "\n"
461
            . "\n"
462
            . '    SELECT COUNT(rental_id) INTO v_out' . "\n"
463
            . '    FROM inventory LEFT JOIN rental USING(inventory_id)' . "\n"
464
            . '    WHERE inventory.inventory_id = p_inventory_id' . "\n"
465
            . '    AND rental.return_date IS NULL;' . "\n"
466
            . "\n"
467
            . '    IF v_out > 0 THEN' . "\n"
468
            . '      RETURN FALSE;' . "\n"
469
            . '    ELSE' . "\n"
470
            . '      RETURN TRUE;' . "\n"
471
            . '    END IF;' . "\n"
472
            . 'END'
473
        );
474
475
        /** @var CreateStatement $stmt */
476
        $stmt = $parser->statements[0];
477
478
        $this->assertSame(
479
            'CREATE DEFINER=`root`@`localhost`'
480
            . ' FUNCTION `inventory_in_stock` (`p_inventory_id` INT) RETURNS TINYINT(1)'
481
            . ' READS SQL DATA' . "\n"
482
            . ' COMMENT \'My best function written by a friend\'\'s friend' . "\n"
483
            . 'BEGIN' . "\n"
484
            . '    DECLARE v_rentals INT;' . "\n"
485
            . '    DECLARE v_out     INT;' . "\n"
486
            . "\n"
487
            . '    ' . "\n"
488
            . '    ' . "\n"
489
            . "\n"
490
            . '    SELECT COUNT(*) INTO v_rentals' . "\n"
491
            . '    FROM rental' . "\n"
492
            . '    WHERE inventory_id = p_inventory_id;' . "\n"
493
            . "\n"
494
            . '    IF v_rentals = 0 THEN' . "\n"
495
            . '      RETURN TRUE;' . "\n"
496
            . '    END IF;' . "\n"
497
            . "\n"
498
            . '    SELECT COUNT(rental_id) INTO v_out' . "\n"
499
            . '    FROM inventory LEFT JOIN rental USING(inventory_id)' . "\n"
500
            . '    WHERE inventory.inventory_id = p_inventory_id' . "\n"
501
            . '    AND rental.return_date IS NULL;' . "\n"
502
            . "\n"
503
            . '    IF v_out > 0 THEN' . "\n"
504
            . '      RETURN FALSE;' . "\n"
505
            . '    ELSE' . "\n"
506
            . '      RETURN TRUE;' . "\n"
507
            . '    END IF;' . "\n"
508
            . 'END',
509
            $stmt->build()
510
        );
511
512
        $this->assertTrue($stmt->entityOptions->isEmpty());
513
        $this->assertFalse($stmt->options->isEmpty());
514
515
        $this->assertSame(
516
            'DEFINER=`root`@`localhost` FUNCTION',
517
            $stmt->options->__toString()
518
        );
519
520
        $this->assertSame(
521
            '`inventory_in_stock`',
522
            $stmt->name->__toString()
523
        );
524
525
        $this->assertSame(
526
            '(`p_inventory_id` INT)',
527
            ParameterDefinition::build($stmt->parameters)
528
        );
529
530
        $this->assertSame(
531
            '',
532
            $stmt->entityOptions->__toString()
533
        );
534
535
        $this->assertSame(
536
            'READS SQL DATA' . "\n"
537
            . ' COMMENT \'My best function written by a friend\'\'s friend' . "\n"
538
            . 'BEGIN' . "\n"
539
            . '    DECLARE v_rentals INT;' . "\n"
540
            . '    DECLARE v_out     INT;' . "\n"
541
            . "\n"
542
            . '    ' . "\n"
543
            . '    ' . "\n"
544
            . "\n"
545
            . '    SELECT COUNT(*) INTO v_rentals' . "\n"
546
            . '    FROM rental' . "\n"
547
            . '    WHERE inventory_id = p_inventory_id;' . "\n"
548
            . "\n"
549
            . '    IF v_rentals = 0 THEN' . "\n"
550
            . '      RETURN TRUE;' . "\n"
551
            . '    END IF;' . "\n"
552
            . "\n"
553
            . '    SELECT COUNT(rental_id) INTO v_out' . "\n"
554
            . '    FROM inventory LEFT JOIN rental USING(inventory_id)' . "\n"
555
            . '    WHERE inventory.inventory_id = p_inventory_id' . "\n"
556
            . '    AND rental.return_date IS NULL;' . "\n"
557
            . "\n"
558
            . '    IF v_out > 0 THEN' . "\n"
559
            . '      RETURN FALSE;' . "\n"
560
            . '    ELSE' . "\n"
561
            . '      RETURN TRUE;' . "\n"
562
            . '    END IF;' . "\n"
563
            . 'END',
564
            TokensList::build($stmt->body)
565
        );
566
    }
567
568
    public function testBuilderTrigger(): void
569
    {
570
        $stmt = new CreateStatement();
571
572
        $stmt->options = new OptionsArray(['TRIGGER']);
573
        $stmt->name = new Expression('ins_sum');
574
        $stmt->entityOptions = new OptionsArray(['BEFORE', 'INSERT']);
575
        $stmt->table = new Expression('account');
576
        $stmt->body = 'SET @sum = @sum + NEW.amount';
577
578
        $this->assertEquals(
579
            'CREATE TRIGGER ins_sum BEFORE INSERT ON account ' .
580
            'FOR EACH ROW SET @sum = @sum + NEW.amount',
581
            $stmt->build()
582
        );
583
    }
584
585
    public function testBuilderRoutine(): void
586
    {
587
        $parser = new Parser(
588
            'CREATE FUNCTION test (IN `i` INT) RETURNS VARCHAR ' .
589
            'BEGIN ' .
590
            'DECLARE name VARCHAR DEFAULT ""; ' .
591
            'SELECT name INTO name FROM employees WHERE id = i; ' .
592
            'RETURN name; ' .
593
            'END'
594
        );
595
        $stmt = $parser->statements[0];
596
597
        $this->assertEquals(
598
            'CREATE FUNCTION test (IN `i` INT) RETURNS VARCHAR ' .
599
            'BEGIN ' .
600
            'DECLARE name VARCHAR DEFAULT ""; ' .
601
            'SELECT name INTO name FROM employees WHERE id = i; ' .
602
            'RETURN name; ' .
603
            'END',
604
            $stmt->build()
605
        );
606
    }
607
608
    public function testBuildSelect(): void
609
    {
610
        $parser = new Parser('CREATE TABLE new_tbl SELECT * FROM orig_tbl');
611
        $this->assertEquals(
612
            'CREATE TABLE new_tbl SELECT * FROM orig_tbl',
613
            $parser->statements[0]->build()
614
        );
615
    }
616
}
617