phpmyadmin /
sql-parser
| 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
Bug
introduced
by
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 |