Issues (119)

tests/Utils/BufferedQueryTest.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Tests\Utils;
6
7
use PhpMyAdmin\SqlParser\Tests\TestCase;
8
use PhpMyAdmin\SqlParser\Utils\BufferedQuery;
9
use PHPUnit\Framework\Attributes\DataProvider;
10
11
use function count;
12
use function is_string;
13
use function str_split;
14
15
class BufferedQueryTest extends TestCase
16
{
17
    /**
18
     * @param array<string, bool> $options
19
     * @param string[]            $expected
20
     * @psalm-param array{delimiter?: non-empty-string, parse_delimiter?: bool, add_delimiter?: bool} $options
21
     * @psalm-param positive-int $chunkSize
22
     */
23
    #[DataProvider('extractProvider')]
24
    public function testExtract(
25
        string $query,
26
        int $chunkSize,
27
        array $options,
28
        array $expected,
29
    ): void {
30
        $chunks = str_split($query, $chunkSize);
31
        $count = count($chunks);
0 ignored issues
show
It seems like $chunks can also be of type true; however, parameter $value of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

31
        $count = count(/** @scrutinizer ignore-type */ $chunks);
Loading history...
32
33
        /**
34
         * The array of extracted statements.
35
         */
36
        $statements = [];
37
38
        /**
39
         * The `BufferedQuery` instance used for extraction.
40
         */
41
        $bq = new BufferedQuery('', $options);
42
43
        // Feeding chunks and extracting queries.
44
        $i = 0;
45
        while ($i < $count) {
46
            $stmt = $bq->extract();
47
48
            if (is_string($stmt) && $stmt !== '') {
49
                $statements[] = $stmt;
50
            } else {
51
                $bq->query .= $chunks[$i++];
52
            }
53
        }
54
55
        // Feeding ended, extracting remaining queries.
56
        while ($stmt = $bq->extract(true)) {
57
            $statements[] = $stmt;
58
        }
59
60
        $this->assertEquals($expected, $statements);
61
    }
62
63
    /**
64
     * @return array<int, array<int, int|string|string[]|bool[]>>
65
     * @psalm-return list<array{string, positive-int, array{parse_delimiter: bool, add_delimiter: bool}, string[]}>
66
     */
67
    public static function extractProvider(): array
68
    {
69
        $query =
70
            '/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;' . "\n" .
71
            '/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;' . "\n" .
72
            '/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;' . "\n" .
73
            '/*!40101 SET NAMES utf8mb4 */;' . "\n" .
74
            '' . "\n" .
75
            'SET SQL_MODE = \'NO_AUTO_VALUE_ON_ZERO\';' . "\n" .
76
            'SET time_zone = "+00:00";' . "\n" .
77
            '' . "\n" .
78
            '/* a comment */ DELIMITER $$' . "\n" .
79
            '' . "\n" .
80
            '# Bash-like comment sytanx.' . "\n" .
81
            'CREATE DEFINER=`root`@`localhost` PROCEDURE `film_in_stock` (IN `p_film_id` ' .
82
            'INT, IN `p_store_id` INT, OUT `p_film_count` INT)  READS SQL DATA' . "\n" .
83
            'BEGIN' . "\n" .
84
            '     SELECT inventory_id' . "\n" .
85
            '     FROM inventory' . "\n" .
86
            '     WHERE film_id = p_film_id' . "\n" .
87
            '     AND store_id = p_store_id' . "\n" .
88
            '     AND inventory_in_stock(inventory_id);' . "\n" .
89
            '' . "\n" .
90
            '     SELECT FOUND_ROWS() INTO p_film_count;' . "\n" .
91
            'END$$' . "\n" .
92
            '' . "\n" .
93
            'DELIMITER ;' . "\n" .
94
            '' . "\n" .
95
            '-- --------------------------------------------------------' . "\n" .
96
            '' . "\n" .
97
            '--' . "\n" .
98
            '-- Table structure for `actor`' . "\n" .
99
            '--' . "\n" .
100
            '' . "\n" .
101
            '/* C-like comment syntax. */' . "\n" .
102
            'CREATE TABLE IF NOT EXISTS `actor` (' . "\n" .
103
            '`actor_id` SMALLINT(5) UNSIGNED NOT NULL,' . "\n" .
104
            '`first_name` VARCHAR(45) NOT NULL,' . "\n" .
105
            '`last_name` VARCHAR(45) NOT NULL,' . "\n" .
106
            '`last_update` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' . "\n" .
107
            ') ENGINE=InnoDB DEFAULT CHARSET=utf8;' . "\n" .
108
            '' . "\n" .
109
            '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;' . "\n" .
110
            '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;' . "\n" .
111
            '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */';
112
113
        return [
114
            [
115
                "SELECT '\'';\nSELECT '\'';",
116
                8,
117
                [
118
                    'parse_delimiter' => true,
119
                    'add_delimiter' => true,
120
                ],
121
                [
122
                    "SELECT '\'';",
123
                    "SELECT '\'';",
124
                ],
125
            ],
126
127
            [
128
                'SELECT \\',
129
                8,
130
                [
131
                    'parse_delimiter' => false,
132
                    'add_delimiter' => false,
133
                ],
134
                ['SELECT \\'],
135
            ],
136
137
            [
138
                "CREATE TABLE `test` (\n" .
139
                "  `txt` varchar(10)\n" .
140
                ");\n" .
141
                "INSERT INTO `test` (`txt`) VALUES('abc');\n" .
142
                "INSERT INTO `test` (`txt`) VALUES('\\\\');\n" .
143
                "INSERT INTO `test` (`txt`) VALUES('xyz');\n",
144
                8,
145
                [
146
                    'parse_delimiter' => true,
147
                    'add_delimiter' => true,
148
                ],
149
                [
150
                    "CREATE TABLE `test` (\n" .
151
                    "  `txt` varchar(10)\n" .
152
                    ');',
153
                    "INSERT INTO `test` (`txt`) VALUES('abc');",
154
                    "INSERT INTO `test` (`txt`) VALUES('\\\\');",
155
                    "INSERT INTO `test` (`txt`) VALUES('xyz');",
156
                ],
157
            ],
158
159
            [
160
                'SELECT """""""";' .
161
                'SELECT """\\\\"""',
162
                8,
163
                [
164
                    'parse_delimiter' => true,
165
                    'add_delimiter' => true,
166
                ],
167
                [
168
                    'SELECT """""""";',
169
                    'SELECT """\\\\"""',
170
                ],
171
            ],
172
173
            [
174
                'DELIMITER A_VERY_LONG_DEL' . "\n" .
175
                'SELECT 1 A_VERY_LONG_DEL' . "\n" .
176
                'DELIMITER ;',
177
                3,
178
                [
179
                    'parse_delimiter' => true,
180
                    'add_delimiter' => true,
181
                ],
182
                [
183
                    'DELIMITER A_VERY_LONG_DEL',
184
                    'SELECT 1 A_VERY_LONG_DEL',
185
                    'DELIMITER ;',
186
                ],
187
            ],
188
189
            [
190
                $query,
191
                32,
192
                [
193
                    'parse_delimiter' => false,
194
                    'add_delimiter' => false,
195
                ],
196
                [
197
                    '/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */',
198
199
                    '/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */',
200
201
                    '/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */',
202
203
                    '/*!40101 SET NAMES utf8mb4 */',
204
205
                    'SET SQL_MODE = \'NO_AUTO_VALUE_ON_ZERO\'',
206
207
                    'SET time_zone = "+00:00"',
208
209
                    '# Bash-like comment sytanx.' . "\n" .
210
                    'CREATE DEFINER=`root`@`localhost` PROCEDURE `film_in_stock` (IN `p_film_id` ' .
211
                    'INT, IN `p_store_id` INT, OUT `p_film_count` INT)  READS SQL DATA' . "\n" .
212
                    'BEGIN' . "\n" .
213
                    '     SELECT inventory_id' . "\n" .
214
                    '     FROM inventory' . "\n" .
215
                    '     WHERE film_id = p_film_id' . "\n" .
216
                    '     AND store_id = p_store_id' . "\n" .
217
                    '     AND inventory_in_stock(inventory_id);' . "\n" .
218
                    '' . "\n" .
219
                    '     SELECT FOUND_ROWS() INTO p_film_count;' . "\n" .
220
                    'END',
221
222
                    '-- --------------------------------------------------------' . "\n" .
223
                    '' . "\n" .
224
                    '--' . "\n" .
225
                    '-- Table structure for `actor`' . "\n" .
226
                    '--' . "\n" .
227
                    '' . "\n" .
228
                    '/* C-like comment syntax. */' . "\n" .
229
                    'CREATE TABLE IF NOT EXISTS `actor` (' . "\n" .
230
                    '`actor_id` SMALLINT(5) UNSIGNED NOT NULL,' . "\n" .
231
                    '`first_name` VARCHAR(45) NOT NULL,' . "\n" .
232
                    '`last_name` VARCHAR(45) NOT NULL,' . "\n" .
233
                    '`last_update` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' . "\n" .
234
                    ') ENGINE=InnoDB DEFAULT CHARSET=utf8',
235
236
                    '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */',
237
238
                    '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */',
239
240
                    '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */',
241
                ],
242
            ],
243
244
            [
245
                $query,
246
                32,
247
                [
248
                    'parse_delimiter' => true,
249
                    'add_delimiter' => false,
250
                ],
251
                [
252
                    '/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */',
253
254
                    '/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */',
255
256
                    '/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */',
257
258
                    '/*!40101 SET NAMES utf8mb4 */',
259
260
                    'SET SQL_MODE = \'NO_AUTO_VALUE_ON_ZERO\'',
261
262
                    'SET time_zone = "+00:00"',
263
264
                    '/* a comment */  DELIMITER $$',
265
266
                    '# Bash-like comment sytanx.' . "\n" .
267
                    'CREATE DEFINER=`root`@`localhost` PROCEDURE `film_in_stock` (IN `p_film_id` ' .
268
                    'INT, IN `p_store_id` INT, OUT `p_film_count` INT)  READS SQL DATA' . "\n" .
269
                    'BEGIN' . "\n" .
270
                    '     SELECT inventory_id' . "\n" .
271
                    '     FROM inventory' . "\n" .
272
                    '     WHERE film_id = p_film_id' . "\n" .
273
                    '     AND store_id = p_store_id' . "\n" .
274
                    '     AND inventory_in_stock(inventory_id);' . "\n" .
275
                    '' . "\n" .
276
                    '     SELECT FOUND_ROWS() INTO p_film_count;' . "\n" .
277
                    'END',
278
279
                    'DELIMITER ;',
280
281
                    '-- --------------------------------------------------------' . "\n" .
282
                    '' . "\n" .
283
                    '--' . "\n" .
284
                    '-- Table structure for `actor`' . "\n" .
285
                    '--' . "\n" .
286
                    '' . "\n" .
287
                    '/* C-like comment syntax. */' . "\n" .
288
                    'CREATE TABLE IF NOT EXISTS `actor` (' . "\n" .
289
                    '`actor_id` SMALLINT(5) UNSIGNED NOT NULL,' . "\n" .
290
                    '`first_name` VARCHAR(45) NOT NULL,' . "\n" .
291
                    '`last_name` VARCHAR(45) NOT NULL,' . "\n" .
292
                    '`last_update` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' . "\n" .
293
                    ') ENGINE=InnoDB DEFAULT CHARSET=utf8',
294
295
                    '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */',
296
297
                    '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */',
298
299
                    '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */',
300
                ],
301
            ],
302
303
            [
304
                $query,
305
                64,
306
                [
307
                    'parse_delimiter' => false,
308
                    'add_delimiter' => true,
309
                ],
310
                [
311
                    '/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;',
312
313
                    '/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;',
314
315
                    '/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;',
316
317
                    '/*!40101 SET NAMES utf8mb4 */;',
318
319
                    'SET SQL_MODE = \'NO_AUTO_VALUE_ON_ZERO\';',
320
321
                    'SET time_zone = "+00:00";',
322
323
                    '# Bash-like comment sytanx.' . "\n" .
324
                    'CREATE DEFINER=`root`@`localhost` PROCEDURE `film_in_stock` (IN `p_film_id` ' .
325
                    'INT, IN `p_store_id` INT, OUT `p_film_count` INT)  READS SQL DATA' . "\n" .
326
                    'BEGIN' . "\n" .
327
                    '     SELECT inventory_id' . "\n" .
328
                    '     FROM inventory' . "\n" .
329
                    '     WHERE film_id = p_film_id' . "\n" .
330
                    '     AND store_id = p_store_id' . "\n" .
331
                    '     AND inventory_in_stock(inventory_id);' . "\n" .
332
                    '' . "\n" .
333
                    '     SELECT FOUND_ROWS() INTO p_film_count;' . "\n" .
334
                    'END$$',
335
336
                    '-- --------------------------------------------------------' . "\n" .
337
                    '' . "\n" .
338
                    '--' . "\n" .
339
                    '-- Table structure for `actor`' . "\n" .
340
                    '--' . "\n" .
341
                    '' . "\n" .
342
                    '/* C-like comment syntax. */' . "\n" .
343
                    'CREATE TABLE IF NOT EXISTS `actor` (' . "\n" .
344
                    '`actor_id` SMALLINT(5) UNSIGNED NOT NULL,' . "\n" .
345
                    '`first_name` VARCHAR(45) NOT NULL,' . "\n" .
346
                    '`last_name` VARCHAR(45) NOT NULL,' . "\n" .
347
                    '`last_update` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' . "\n" .
348
                    ') ENGINE=InnoDB DEFAULT CHARSET=utf8;',
349
350
                    '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;',
351
352
                    '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;',
353
354
                    '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */',
355
                ],
356
            ],
357
        ];
358
    }
359
}
360