‪TYPO3CMS  10.4
Parser.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Schema\Table;
65 
70 class ‪Parser
71 {
77  protected ‪$lexer;
78 
84  protected ‪$statement;
85 
91  public function ‪__construct(string ‪$statement)
92  {
93  $this->statement = ‪$statement;
94  $this->lexer = new ‪Lexer(‪$statement);
95  }
96 
102  public function ‪getLexer(): ‪Lexer
103  {
104  return ‪$this->lexer;
105  }
106 
113  public function ‪getAST(): ‪AbstractCreateStatement
114  {
115  // Parse & build AST
116  return $this->‪queryLanguage();
117  }
118 
130  public function ‪match($token)
131  {
132  $lookaheadType = $this->lexer->lookahead['type'];
133 
134  // Short-circuit on first condition, usually types match
135  if ($lookaheadType !== $token) {
136  // If parameter is not identifier (1-99) must be exact match
137  if ($token < ‪Lexer::T_IDENTIFIER) {
138  $this->‪syntaxError((string)$this->lexer->getLiteral($token));
139  }
140 
141  // If parameter is keyword (200+) must be exact match
142  if ($token > ‪Lexer::T_IDENTIFIER) {
143  $this->‪syntaxError((string)$this->lexer->getLiteral($token));
144  }
145 
146  // If parameter is MATCH then FULL, PARTIAL or SIMPLE must follow
147  if ($token === ‪Lexer::T_MATCH
148  && $lookaheadType !== ‪Lexer::T_FULL
149  && $lookaheadType !== ‪Lexer::T_PARTIAL
150  && $lookaheadType !== ‪Lexer::T_SIMPLE
151  ) {
152  $this->‪syntaxError((string)$this->lexer->getLiteral($token));
153  }
154 
155  if ($token === ‪Lexer::T_ON && $lookaheadType !== ‪Lexer::T_DELETE && $lookaheadType !== ‪Lexer::T_UPDATE) {
156  $this->‪syntaxError((string)$this->lexer->getLiteral($token));
157  }
158  }
159 
160  $this->lexer->moveNext();
161  }
162 
169  public function ‪free($deep = false, $position = 0)
170  {
171  // WARNING! Use this method with care. It resets the scanner!
172  $this->lexer->resetPosition($position);
173 
174  // Deep = true cleans peek and also any previously defined errors
175  if ($deep) {
176  $this->lexer->resetPeek();
177  }
178 
179  $this->lexer->token = null;
180  $this->lexer->lookahead = null;
181  }
182 
192  public function ‪parse(): array
193  {
194  $ast = $this->‪getAST();
195 
196  if (!$ast instanceof ‪CreateTableStatement) {
197  return [];
198  }
199 
200  $tableBuilder = new ‪TableBuilder();
201  $table = $tableBuilder->create($ast);
202 
203  return [$table];
204  }
205 
215  public function ‪syntaxError($expected = '', $token = null)
216  {
217  if ($token === null) {
218  $token = $this->lexer->lookahead;
219  }
220 
221  $tokenPos = $token['position'] ?? '-1';
222 
223  $message = "line 0, col {$tokenPos}: Error: ";
224  $message .= ($expected !== '') ? "Expected {$expected}, got " : 'Unexpected ';
225  $message .= ($this->lexer->lookahead === null) ? 'end of string.' : "'{$token['value']}'";
226 
227  throw ‪StatementException::syntaxError($message, ‪StatementException::sqlError($this->statement));
228  }
229 
239  public function ‪semanticalError($message = '', $token = null)
240  {
241  if ($token === null) {
242  $token = $this->lexer->lookahead ?? [];
243  }
244 
245  // Minimum exposed chars ahead of token
246  $distance = 12;
247 
248  // Find a position of a final word to display in error string
249  $createTableStatement = ‪$this->statement;
250  $length = strlen($createTableStatement);
251  $pos = $token['position'] + $distance;
252  $pos = strpos($createTableStatement, ' ', ($length > $pos) ? $pos : $length);
253  $length = ($pos !== false) ? $pos - $token['position'] : $distance;
254 
255  $tokenPos = array_key_exists('position', $token) && $token['position'] > 0 ? $token['position'] : '-1';
256  $tokenStr = substr($createTableStatement, $token['position'], $length);
257 
258  // Building informative message
259  $message = 'line 0, col ' . $tokenPos . " near '" . $tokenStr . "': Error: " . $message;
260 
262  }
263 
271  protected function ‪peekBeyondClosingParenthesis($resetPeek = true)
272  {
273  $token = $this->lexer->peek();
274  $numUnmatched = 1;
275 
276  while ($numUnmatched > 0 && $token !== null) {
277  switch ($token['type']) {
279  ++$numUnmatched;
280  break;
282  --$numUnmatched;
283  break;
284  default:
285  // Do nothing
286  }
287 
288  $token = $this->lexer->peek();
289  }
290 
291  if ($resetPeek) {
292  $this->lexer->resetPeek();
293  }
294 
295  return $token;
296  }
297 
305  {
306  $this->lexer->moveNext();
307 
308  if ($this->lexer->lookahead['type'] !== ‪Lexer::T_CREATE) {
309  $this->‪syntaxError('CREATE');
310  }
311 
312  $statement = $this->‪createStatement();
313 
314  // Check for end of string
315  if ($this->lexer->lookahead !== null) {
316  $this->‪syntaxError('end of string');
317  }
318 
319  return ‪$statement;
320  }
321 
330  {
331  ‪$statement = null;
333 
334  switch ($this->lexer->lookahead['type']) {
336  // Intentional fall-through
337  case ‪Lexer::T_TABLE:
339  break;
340  default:
341  $this->‪syntaxError('TEMPORARY or TABLE');
342  break;
343  }
344 
346 
347  return ‪$statement;
348  }
349 
356  {
357  $createTableStatement = new ‪CreateTableStatement($this->‪createTableClause(), $this->‪createDefinition());
358 
359  if (!$this->lexer->isNextToken(‪Lexer::T_SEMICOLON)) {
360  $createTableStatement->tableOptions = $this->‪tableOptions();
361  }
362  return $createTableStatement;
363  }
364 
371  protected function ‪createTableClause(): ‪CreateTableClause
372  {
373  $isTemporary = false;
374  // Check for TEMPORARY
375  if ($this->lexer->isNextToken(‪Lexer::T_TEMPORARY)) {
377  $isTemporary = true;
378  }
379 
380  $this->‪match(‪Lexer::T_TABLE);
381 
382  // Check for IF NOT EXISTS
383  if ($this->lexer->isNextToken(‪Lexer::T_IF)) {
384  $this->‪match(‪Lexer::T_IF);
385  $this->‪match(‪Lexer::T_NOT);
387  }
388 
389  // Process schema object name (table name)
390  $tableName = $this->‪schemaObjectName();
391 
392  return new ‪CreateTableClause($tableName, $isTemporary);
393  }
394 
411  protected function ‪createDefinition(): ‪CreateDefinition
412  {
413  $createDefinitions = [];
414 
415  // Process opening parenthesis
417 
418  $createDefinitions[] = $this->‪createDefinitionItem();
419 
420  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
421  $this->‪match(‪Lexer::T_COMMA);
422 
423  // TYPO3 previously accepted invalid SQL files where a create definition
424  // item terminated with a comma before the final closing parenthesis.
425  // Silently swallow the extra comma and stop the create definition parsing.
426  if ($this->lexer->isNextToken(‪Lexer::T_CLOSE_PARENTHESIS)) {
427  break;
428  }
429 
430  $createDefinitions[] = $this->‪createDefinitionItem();
431  }
432 
433  // Process closing parenthesis
435 
436  return new ‪CreateDefinition($createDefinitions);
437  }
438 
447  {
448  $definitionItem = null;
449 
450  switch ($this->lexer->lookahead['type']) {
452  // Intentional fall-through
453  case ‪Lexer::T_SPATIAL:
454  // Intentional fall-through
455  case ‪Lexer::T_PRIMARY:
456  // Intentional fall-through
457  case ‪Lexer::T_UNIQUE:
458  // Intentional fall-through
459  case ‪Lexer::T_KEY:
460  // Intentional fall-through
461  case ‪Lexer::T_INDEX:
462  $definitionItem = $this->‪createIndexDefinitionItem();
463  break;
464  case ‪Lexer::T_FOREIGN:
465  $definitionItem = $this->‪createForeignKeyDefinitionItem();
466  break;
468  $this->‪semanticalError('CONSTRAINT [symbol] index definition part not supported');
469  break;
470  case ‪Lexer::T_CHECK:
471  $this->‪semanticalError('CHECK (expr) create definition not supported');
472  break;
473  default:
474  $definitionItem = $this->‪createColumnDefinitionItem();
475  }
476 
477  return $definitionItem;
478  }
479 
487  {
488  $indexName = null;
489  $isPrimary = false;
490  $isFulltext = false;
491  $isSpatial = false;
492  $isUnique = false;
493  $indexDefinition = new ‪CreateIndexDefinitionItem();
494 
495  switch ($this->lexer->lookahead['type']) {
496  case ‪Lexer::T_PRIMARY:
498  // KEY is a required keyword for PRIMARY index
499  $this->‪match(‪Lexer::T_KEY);
500  $isPrimary = true;
501  break;
502  case ‪Lexer::T_KEY:
503  // Plain index, no special configuration
504  $this->‪match(‪Lexer::T_KEY);
505  break;
506  case ‪Lexer::T_INDEX:
507  // Plain index, no special configuration
508  $this->‪match(‪Lexer::T_INDEX);
509  break;
510  case ‪Lexer::T_UNIQUE:
512  // INDEX|KEY are optional keywords for UNIQUE index
513  if ($this->lexer->isNextTokenAny([‪Lexer::T_INDEX, ‪Lexer::T_KEY])) {
514  $this->lexer->moveNext();
515  }
516  $isUnique = true;
517  break;
520  // INDEX|KEY are optional keywords for FULLTEXT index
521  if ($this->lexer->isNextTokenAny([‪Lexer::T_INDEX, ‪Lexer::T_KEY])) {
522  $this->lexer->moveNext();
523  }
524  $isFulltext = true;
525  break;
526  case ‪Lexer::T_SPATIAL:
528  // INDEX|KEY are optional keywords for SPATIAL index
529  if ($this->lexer->isNextTokenAny([‪Lexer::T_INDEX, ‪Lexer::T_KEY])) {
530  $this->lexer->moveNext();
531  }
532  $isSpatial = true;
533  break;
534  default:
535  $this->‪syntaxError('PRIMARY, KEY, INDEX, UNIQUE, FULLTEXT or SPATIAL');
536  }
537 
538  // PRIMARY KEY has no name in MySQL
539  if (!$indexDefinition->isPrimary) {
540  $indexName = $this->‪indexName();
541  }
542 
543  $indexDefinition = new ‪CreateIndexDefinitionItem(
544  $indexName,
545  $isPrimary,
546  $isUnique,
547  $isSpatial,
548  $isFulltext
549  );
550 
551  // FULLTEXT and SPATIAL indexes can not have a type definition
552  if (!$isFulltext && !$isSpatial) {
553  $indexDefinition->indexType = $this->‪indexType();
554  }
555 
557 
558  $indexDefinition->columnNames[] = $this->‪indexColumnName();
559 
560  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
561  $this->‪match(‪Lexer::T_COMMA);
562  $indexDefinition->columnNames[] = $this->‪indexColumnName();
563  }
564 
566 
567  $indexDefinition->options = $this->‪indexOptions();
568 
569  return $indexDefinition;
570  }
571 
579  {
581  $this->‪match(‪Lexer::T_KEY);
582 
583  $indexName = $this->‪indexName();
584 
586 
587  $indexColumns = [];
588  $indexColumns[] = $this->‪indexColumnName();
589 
590  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
591  $this->‪match(‪Lexer::T_COMMA);
592  $indexColumns[] = $this->‪indexColumnName();
593  }
594 
596 
597  $foreignKeyDefinition = new ‪CreateForeignKeyDefinitionItem(
598  $indexName,
599  $indexColumns,
600  $this->‪referenceDefinition()
601  );
602 
603  return $foreignKeyDefinition;
604  }
605 
613  public function ‪indexName(): ‪Identifier
614  {
615  $indexName = new ‪Identifier(null);
616  if (!$this->lexer->isNextTokenAny([‪Lexer::T_USING, ‪Lexer::T_OPEN_PARENTHESIS])) {
617  $indexName = $this->‪schemaObjectName();
618  }
619 
620  return $indexName;
621  }
622 
629  public function ‪indexType(): string
630  {
631  $indexType = '';
632  if (!$this->lexer->isNextToken(‪Lexer::T_USING)) {
633  return $indexType;
634  }
635 
636  $this->‪match(‪Lexer::T_USING);
637 
638  switch ($this->lexer->lookahead['type']) {
639  case ‪Lexer::T_BTREE:
640  $this->‪match(‪Lexer::T_BTREE);
641  $indexType = 'BTREE';
642  break;
643  case ‪Lexer::T_HASH:
644  $this->‪match(‪Lexer::T_HASH);
645  $indexType = 'HASH';
646  break;
647  default:
648  $this->‪syntaxError('BTREE or HASH');
649  }
650 
651  return $indexType;
652  }
653 
663  public function ‪indexOptions(): array
664  {
665  $options = [];
666 
667  while ($this->lexer->lookahead && !$this->lexer->isNextTokenAny([‪Lexer::T_COMMA, ‪Lexer::T_CLOSE_PARENTHESIS])) {
668  switch ($this->lexer->lookahead['type']) {
671  if ($this->lexer->isNextToken(‪Lexer::T_EQUALS)) {
673  }
674  $this->lexer->moveNext();
675  $options['key_block_size'] = (int)$this->lexer->token['value'];
676  break;
677  case ‪Lexer::T_USING:
678  $options['index_type'] = $this->indexType();
679  break;
680  case ‪Lexer::T_WITH:
681  $this->‪match(‪Lexer::T_WITH);
683  $options['parser'] = $this->‪schemaObjectName();
684  break;
685  case ‪Lexer::T_COMMENT:
688  $options['comment'] = $this->lexer->token['value'];
689  break;
690  default:
691  $this->‪syntaxError('KEY_BLOCK_SIZE, USING, WITH PARSER or COMMENT');
692  }
693  }
694 
695  return $options;
696  }
697 
713  {
714  $columnName = $this->‪schemaObjectName();
715  $dataType = $this->‪columnDataType();
716 
717  $columnDefinitionItem = new ‪CreateColumnDefinitionItem($columnName, $dataType);
718 
719  while ($this->lexer->lookahead && !$this->lexer->isNextTokenAny([‪Lexer::T_COMMA, ‪Lexer::T_CLOSE_PARENTHESIS])) {
720  switch ($this->lexer->lookahead['type']) {
721  case ‪Lexer::T_NOT:
722  $columnDefinitionItem->allowNull = false;
723  $this->‪match(‪Lexer::T_NOT);
724  $this->‪match(‪Lexer::T_NULL);
725  break;
726  case ‪Lexer::T_NULL:
727  $columnDefinitionItem->null = true;
728  $this->‪match(‪Lexer::T_NULL);
729  break;
730  case ‪Lexer::T_DEFAULT:
731  $columnDefinitionItem->hasDefaultValue = true;
732  $columnDefinitionItem->defaultValue = $this->‪columnDefaultValue();
733  break;
735  $columnDefinitionItem->autoIncrement = true;
737  break;
738  case ‪Lexer::T_UNIQUE:
739  $columnDefinitionItem->unique = true;
741  if ($this->lexer->isNextToken(‪Lexer::T_KEY)) {
742  $this->‪match(‪Lexer::T_KEY);
743  }
744  break;
745  case ‪Lexer::T_PRIMARY:
746  $columnDefinitionItem->primary = true;
748  if ($this->lexer->isNextToken(‪Lexer::T_KEY)) {
749  $this->‪match(‪Lexer::T_KEY);
750  }
751  break;
752  case ‪Lexer::T_KEY:
753  $columnDefinitionItem->index = true;
754  $this->‪match(‪Lexer::T_KEY);
755  break;
756  case ‪Lexer::T_COMMENT:
758  if ($this->lexer->isNextToken(‪Lexer::T_STRING)) {
759  $columnDefinitionItem->comment = $this->lexer->lookahead['value'];
761  }
762  break;
765  if ($this->lexer->isNextToken(‪Lexer::T_FIXED)) {
766  $columnDefinitionItem->columnFormat = 'fixed';
767  $this->‪match(‪Lexer::T_FIXED);
768  } elseif ($this->lexer->isNextToken(‪Lexer::T_DYNAMIC)) {
769  $columnDefinitionItem->columnFormat = 'dynamic';
771  } else {
773  }
774  break;
775  case ‪Lexer::T_STORAGE:
777  if ($this->lexer->isNextToken(‪Lexer::T_MEMORY)) {
778  $columnDefinitionItem->storage = 'memory';
780  } elseif ($this->lexer->isNextToken(‪Lexer::T_DISK)) {
781  $columnDefinitionItem->storage = 'disk';
782  $this->‪match(‪Lexer::T_DISK);
783  } else {
785  }
786  break;
788  $columnDefinitionItem->reference = $this->‪referenceDefinition();
789  break;
790  default:
791  $this->‪syntaxError(
792  'NOT, NULL, DEFAULT, AUTO_INCREMENT, UNIQUE, ' .
793  'PRIMARY, COMMENT, COLUMN_FORMAT, STORAGE or REFERENCES'
794  );
795  }
796  }
797 
798  return $columnDefinitionItem;
799  }
800 
838  protected function ‪columnDataType(): ‪AbstractDataType
839  {
840  $dataType = null;
841 
842  switch ($this->lexer->lookahead['type']) {
843  case ‪Lexer::T_BIT:
844  $this->‪match(‪Lexer::T_BIT);
845  $dataType = new ‪BitDataType(
846  $this->‪dataTypeLength()
847  );
848  break;
849  case ‪Lexer::T_TINYINT:
851  $dataType = new ‪TinyIntDataType(
852  $this->‪dataTypeLength(),
854  );
855  break;
858  $dataType = new ‪SmallIntDataType(
859  $this->‪dataTypeLength(),
861  );
862  break;
865  $dataType = new ‪MediumIntDataType(
866  $this->‪dataTypeLength(),
868  );
869  break;
870  case ‪Lexer::T_INT:
871  $this->‪match(‪Lexer::T_INT);
872  $dataType = new ‪IntegerDataType(
873  $this->‪dataTypeLength(),
875  );
876  break;
877  case ‪Lexer::T_INTEGER:
879  $dataType = new ‪IntegerDataType(
880  $this->‪dataTypeLength(),
882  );
883  break;
884  case ‪Lexer::T_BIGINT:
886  $dataType = new ‪BigIntDataType(
887  $this->‪dataTypeLength(),
889  );
890  break;
891  case ‪Lexer::T_REAL:
892  $this->‪match(‪Lexer::T_REAL);
893  $dataType = new ‪RealDataType(
894  $this->‪dataTypeDecimals(),
896  );
897  break;
898  case ‪Lexer::T_DOUBLE:
900  if ($this->lexer->isNextToken(‪Lexer::T_PRECISION)) {
902  }
903  $dataType = new ‪DoubleDataType(
904  $this->‪dataTypeDecimals(),
906  );
907  break;
908  case ‪Lexer::T_FLOAT:
909  $this->‪match(‪Lexer::T_FLOAT);
910  $dataType = new ‪FloatDataType(
911  $this->‪dataTypeDecimals(),
913  );
914 
915  break;
916  case ‪Lexer::T_DECIMAL:
918  $dataType = new ‪DecimalDataType(
919  $this->‪dataTypeDecimals(),
921  );
922  break;
923  case ‪Lexer::T_NUMERIC:
925  $dataType = new ‪NumericDataType(
926  $this->‪dataTypeDecimals(),
928  );
929  break;
930  case ‪Lexer::T_DATE:
931  $this->‪match(‪Lexer::T_DATE);
932  $dataType = new ‪DateDataType();
933  break;
934  case ‪Lexer::T_TIME:
935  $this->‪match(‪Lexer::T_TIME);
936  $dataType = new ‪TimeDataType($this->‪fractionalSecondsPart());
937  break;
940  $dataType = new ‪TimestampDataType($this->‪fractionalSecondsPart());
941  break;
944  $dataType = new ‪DateTimeDataType($this->‪fractionalSecondsPart());
945  break;
946  case ‪Lexer::T_YEAR:
947  $this->‪match(‪Lexer::T_YEAR);
948  $dataType = new ‪YearDataType();
949  break;
950  case ‪Lexer::T_CHAR:
951  $this->‪match(‪Lexer::T_CHAR);
952  $dataType = new ‪CharDataType(
953  $this->‪dataTypeLength(),
955  );
956  break;
957  case ‪Lexer::T_VARCHAR:
959  $dataType = new ‪VarCharDataType(
960  $this->‪dataTypeLength(true),
962  );
963  break;
964  case ‪Lexer::T_BINARY:
966  $dataType = new ‪BinaryDataType($this->‪dataTypeLength());
967  break;
970  $dataType = new ‪VarBinaryDataType($this->‪dataTypeLength(true));
971  break;
974  $dataType = new ‪TinyBlobDataType();
975  break;
976  case ‪Lexer::T_BLOB:
977  $this->‪match(‪Lexer::T_BLOB);
978  $dataType = new ‪BlobDataType();
979  break;
982  $dataType = new ‪MediumBlobDataType();
983  break;
986  $dataType = new ‪LongBlobDataType();
987  break;
990  $dataType = new ‪TinyTextDataType($this->‪characterDataTypeOptions());
991  break;
992  case ‪Lexer::T_TEXT:
993  $this->‪match(‪Lexer::T_TEXT);
994  $dataType = new ‪TextDataType($this->‪characterDataTypeOptions());
995  break;
998  $dataType = new ‪MediumTextDataType($this->‪characterDataTypeOptions());
999  break;
1000  case ‪Lexer::T_LONGTEXT:
1002  $dataType = new ‪LongTextDataType($this->‪characterDataTypeOptions());
1003  break;
1004  case ‪Lexer::T_ENUM:
1005  $this->‪match(‪Lexer::T_ENUM);
1006  $dataType = new ‪EnumDataType($this->‪valueList(), $this->‪enumerationDataTypeOptions());
1007  break;
1008  case ‪Lexer::T_SET:
1009  $this->‪match(‪Lexer::T_SET);
1010  $dataType = new ‪SetDataType($this->‪valueList(), $this->‪enumerationDataTypeOptions());
1011  break;
1012  case ‪Lexer::T_JSON:
1013  $this->‪match(‪Lexer::T_JSON);
1014  $dataType = new ‪JsonDataType();
1015  break;
1016  default:
1017  $this->‪syntaxError(
1018  'BIT, TINYINT, SMALLINT, MEDIUMINT, INT, INTEGER, BIGINT, REAL, DOUBLE, FLOAT, DECIMAL, NUMERIC, ' .
1019  'DATE, TIME, TIMESTAMP, DATETIME, YEAR, CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, BLOB, ' .
1020  'MEDIUMBLOB, LONGBLOB, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT, ENUM, SET, or JSON'
1021  );
1022  }
1023 
1024  return $dataType;
1025  }
1026 
1033  protected function ‪columnDefaultValue()
1034  {
1035  $this->‪match(‪Lexer::T_DEFAULT);
1036  $value = null;
1037 
1038  switch ($this->lexer->lookahead['type']) {
1039  case ‪Lexer::T_INTEGER:
1040  $value = (int)$this->lexer->lookahead['value'];
1041  break;
1042  case ‪Lexer::T_FLOAT:
1043  $value = (float)$this->lexer->lookahead['value'];
1044  break;
1045  case ‪Lexer::T_STRING:
1046  $value = (string)$this->lexer->lookahead['value'];
1047  break;
1049  $value = 'CURRENT_TIMESTAMP';
1050  break;
1051  case ‪Lexer::T_NULL:
1052  $value = null;
1053  break;
1054  default:
1055  $this->syntaxError('String, Integer, Float, NULL or CURRENT_TIMESTAMP');
1056  }
1057 
1058  $this->lexer->moveNext();
1059 
1060  return $value;
1061  }
1062 
1070  protected function ‪dataTypeLength(bool $required = false): int
1071  {
1072  $length = 0;
1073  if (!$this->lexer->isNextToken(‪Lexer::T_OPEN_PARENTHESIS)) {
1074  if ($required) {
1075  $this->‪semanticalError('The current data type requires a field length definition.');
1076  }
1077  return $length;
1078  }
1079 
1081  $length = (int)$this->lexer->lookahead['value'];
1082  $this->match(‪Lexer::T_INTEGER);
1084 
1085  return $length;
1086  }
1087 
1094  private function ‪dataTypeDecimals(): array
1095  {
1096  $options = [];
1097  if (!$this->lexer->isNextToken(‪Lexer::T_OPEN_PARENTHESIS)) {
1098  return $options;
1099  }
1100 
1102  $options['length'] = (int)$this->lexer->lookahead['value'];
1103  $this->match(‪Lexer::T_INTEGER);
1104 
1105  if ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
1106  $this->‪match(‪Lexer::T_COMMA);
1107  $options['decimals'] = (int)$this->lexer->lookahead['value'];
1108  $this->match(‪Lexer::T_INTEGER);
1109  }
1110 
1112 
1113  return $options;
1114  }
1115 
1122  protected function ‪numericDataTypeOptions(): array
1123  {
1124  $options = ['unsigned' => false, 'zerofill' => false];
1125 
1126  if (!$this->lexer->isNextTokenAny([‪Lexer::T_UNSIGNED, ‪Lexer::T_ZEROFILL])) {
1127  return $options;
1128  }
1129 
1130  while ($this->lexer->isNextTokenAny([‪Lexer::T_UNSIGNED, ‪Lexer::T_ZEROFILL])) {
1131  switch ($this->lexer->lookahead['type']) {
1132  case ‪Lexer::T_UNSIGNED:
1134  $options['unsigned'] = true;
1135  break;
1136  case ‪Lexer::T_ZEROFILL:
1138  $options['zerofill'] = true;
1139  break;
1140  default:
1141  $this->‪syntaxError('USIGNED or ZEROFILL');
1142  }
1143  }
1144 
1145  return $options;
1146  }
1147 
1154  protected function ‪fractionalSecondsPart(): int
1155  {
1156  $fractionalSecondsPart = $this->‪dataTypeLength();
1157  if ($fractionalSecondsPart < 0) {
1158  $this->‪semanticalError('the fractional seconds part for TIME, DATETIME or TIMESTAMP columns must >= 0');
1159  }
1160  if ($fractionalSecondsPart > 6) {
1161  $this->‪semanticalError('the fractional seconds part for TIME, DATETIME or TIMESTAMP columns must <= 6');
1162  }
1163 
1164  return $fractionalSecondsPart;
1165  }
1166 
1173  protected function ‪characterDataTypeOptions(): array
1174  {
1175  $options = ['binary' => false, 'charset' => null, 'collation' => null];
1176 
1177  if (!$this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE, ‪Lexer::T_BINARY])) {
1178  return $options;
1179  }
1180 
1181  while ($this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE, ‪Lexer::T_BINARY])) {
1182  switch ($this->lexer->lookahead['type']) {
1183  case ‪Lexer::T_BINARY:
1184  $this->‪match(‪Lexer::T_BINARY);
1185  $options['binary'] = true;
1186  break;
1187  case ‪Lexer::T_CHARACTER:
1189  $this->‪match(‪Lexer::T_SET);
1190  $this->‪match(‪Lexer::T_STRING);
1191  $options['charset'] = $this->lexer->token['value'];
1192  break;
1193  case ‪Lexer::T_COLLATE:
1194  $this->‪match(‪Lexer::T_COLLATE);
1195  $this->‪match(‪Lexer::T_STRING);
1196  $options['collation'] = $this->lexer->token['value'];
1197  break;
1198  default:
1199  $this->‪syntaxError('BINARY, CHARACTER SET or COLLATE');
1200  }
1201  }
1202 
1203  return $options;
1204  }
1205 
1212  protected function ‪enumerationDataTypeOptions(): array
1213  {
1214  $options = ['charset' => null, 'collation' => null];
1215 
1216  if (!$this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE])) {
1217  return $options;
1218  }
1219 
1220  while ($this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE])) {
1221  switch ($this->lexer->lookahead['type']) {
1222  case ‪Lexer::T_CHARACTER:
1224  $this->‪match(‪Lexer::T_SET);
1225  $this->‪match(‪Lexer::T_STRING);
1226  $options['charset'] = $this->lexer->token['value'];
1227  break;
1228  case ‪Lexer::T_COLLATE:
1229  $this->‪match(‪Lexer::T_COLLATE);
1230  $this->‪match(‪Lexer::T_STRING);
1231  $options['collation'] = $this->lexer->token['value'];
1232  break;
1233  default:
1234  $this->‪syntaxError('CHARACTER SET or COLLATE');
1235  }
1236  }
1237 
1238  return $options;
1239  }
1240 
1247  protected function ‪valueList(): array
1248  {
1250 
1251  $values = [];
1252  $values[] = $this->‪valueListItem();
1253 
1254  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
1255  $this->‪match(‪Lexer::T_COMMA);
1256  $values[] = $this->‪valueListItem();
1257  }
1258 
1260 
1261  return $values;
1262  }
1263 
1270  protected function ‪valueListItem(): string
1271  {
1272  $this->‪match(‪Lexer::T_STRING);
1273 
1274  return (string)$this->lexer->token['value'];
1275  }
1276 
1286  protected function ‪referenceDefinition(): ‪ReferenceDefinition
1287  {
1289  $tableName = $this->‪schemaObjectName();
1291 
1292  $referenceColumns = [];
1293  $referenceColumns[] = $this->‪indexColumnName();
1294 
1295  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
1296  $this->‪match(‪Lexer::T_COMMA);
1297  $referenceColumns[] = $this->‪indexColumnName();
1298  }
1299 
1301 
1302  $referenceDefinition = new ‪ReferenceDefinition($tableName, $referenceColumns);
1303 
1304  while (!$this->lexer->isNextTokenAny([‪Lexer::T_COMMA, ‪Lexer::T_CLOSE_PARENTHESIS])) {
1305  switch ($this->lexer->lookahead['type']) {
1306  case ‪Lexer::T_MATCH:
1307  $this->‪match(‪Lexer::T_MATCH);
1308  $referenceDefinition->match = $this->lexer->lookahead['value'];
1309  $this->lexer->moveNext();
1310  break;
1311  case ‪Lexer::T_ON:
1312  $this->‪match(‪Lexer::T_ON);
1313  if ($this->lexer->isNextToken(‪Lexer::T_DELETE)) {
1314  $this->‪match(‪Lexer::T_DELETE);
1315  $referenceDefinition->onDelete = $this->‪referenceOption();
1316  } else {
1317  $this->‪match(‪Lexer::T_UPDATE);
1318  $referenceDefinition->onUpdate = $this->‪referenceOption();
1319  }
1320  break;
1321  default:
1322  $this->‪syntaxError('MATCH, ON DELETE or ON UPDATE');
1323  }
1324  }
1325 
1326  return $referenceDefinition;
1327  }
1328 
1335  protected function ‪indexColumnName(): ‪IndexColumnName
1336  {
1337  $columnName = $this->‪schemaObjectName();
1338  $length = $this->‪dataTypeLength();
1339  $direction = null;
1340 
1341  if ($this->lexer->isNextToken(‪Lexer::T_ASC)) {
1342  $this->‪match(‪Lexer::T_ASC);
1343  $direction = 'ASC';
1344  } elseif ($this->lexer->isNextToken(‪Lexer::T_DESC)) {
1345  $this->‪match(‪Lexer::T_DESC);
1346  $direction = 'DESC';
1347  }
1348 
1349  return new ‪IndexColumnName($columnName, $length, $direction);
1350  }
1351 
1358  protected function ‪referenceOption(): string
1359  {
1360  $action = null;
1361 
1362  switch ($this->lexer->lookahead['type']) {
1363  case ‪Lexer::T_RESTRICT:
1365  $action = 'RESTRICT';
1366  break;
1367  case ‪Lexer::T_CASCADE:
1368  $this->‪match(‪Lexer::T_CASCADE);
1369  $action = 'CASCADE';
1370  break;
1371  case ‪Lexer::T_SET:
1372  $this->‪match(‪Lexer::T_SET);
1373  $this->‪match(‪Lexer::T_NULL);
1374  $action = 'SET NULL';
1375  break;
1376  case ‪Lexer::T_NO:
1377  $this->‪match(‪Lexer::T_NO);
1378  $this->‪match(‪Lexer::T_ACTION);
1379  $action = 'NO ACTION';
1380  break;
1381  default:
1382  $this->‪syntaxError('RESTRICT, CASCADE, SET NULL or NO ACTION');
1383  }
1384 
1385  return $action;
1386  }
1387 
1420  protected function ‪tableOptions(): array
1421  {
1422  $options = [];
1423 
1424  while ($this->lexer->lookahead && !$this->lexer->isNextToken(‪Lexer::T_SEMICOLON)) {
1425  switch ($this->lexer->lookahead['type']) {
1426  case ‪Lexer::T_DEFAULT:
1427  // DEFAULT prefix is optional for COLLATE/CHARACTER SET, do nothing
1428  $this->‪match(‪Lexer::T_DEFAULT);
1429  break;
1430  case ‪Lexer::T_ENGINE:
1431  $this->‪match(‪Lexer::T_ENGINE);
1432  $options['engine'] = (string)$this->‪tableOptionValue();
1433  break;
1436  $options['auto_increment'] = (int)$this->‪tableOptionValue();
1437  break;
1440  $options['average_row_length'] = (int)$this->‪tableOptionValue();
1441  break;
1442  case ‪Lexer::T_CHARACTER:
1444  $this->‪match(‪Lexer::T_SET);
1445  $options['character_set'] = (string)$this->‪tableOptionValue();
1446  break;
1447  case ‪Lexer::T_CHECKSUM:
1449  $options['checksum'] = (int)$this->‪tableOptionValue();
1450  break;
1451  case ‪Lexer::T_COLLATE:
1452  $this->‪match(‪Lexer::T_COLLATE);
1453  $options['collation'] = (string)$this->‪tableOptionValue();
1454  break;
1455  case ‪Lexer::T_COMMENT:
1456  $this->‪match(‪Lexer::T_COMMENT);
1457  $options['comment'] = (string)$this->‪tableOptionValue();
1458  break;
1461  $options['compression'] = strtoupper((string)$this->‪tableOptionValue());
1462  if (!in_array($options['compression'], ['ZLIB', 'LZ4', 'NONE'], true)) {
1463  $this->‪syntaxError('ZLIB, LZ4 or NONE', $this->lexer->token);
1464  }
1465  break;
1468  $options['connection'] = (string)$this->‪tableOptionValue();
1469  break;
1470  case ‪Lexer::T_DATA:
1471  $this->‪match(‪Lexer::T_DATA);
1473  $options['data_directory'] = (string)$this->‪tableOptionValue();
1474  break;
1477  $options['delay_key_write'] = (int)$this->‪tableOptionValue();
1478  break;
1481  $options['encryption'] = strtoupper((string)$this->‪tableOptionValue());
1482  if (!in_array($options['encryption'], ['Y', 'N'], true)) {
1483  $this->‪syntaxError('Y or N', $this->lexer->token);
1484  }
1485  break;
1486  case ‪Lexer::T_INDEX:
1487  $this->‪match(‪Lexer::T_INDEX);
1489  $options['index_directory'] = (string)$this->‪tableOptionValue();
1490  break;
1493  $options['insert_method'] = strtoupper((string)$this->‪tableOptionValue());
1494  if (!in_array($options['insert_method'], ['NO', 'FIRST', 'LAST'], true)) {
1495  $this->‪syntaxError('NO, FIRST or LAST', $this->lexer->token);
1496  }
1497  break;
1500  $options['key_block_size'] = (int)$this->‪tableOptionValue();
1501  break;
1502  case ‪Lexer::T_MAX_ROWS:
1504  $options['max_rows'] = (int)$this->‪tableOptionValue();
1505  break;
1506  case ‪Lexer::T_MIN_ROWS:
1508  $options['min_rows'] = (int)$this->‪tableOptionValue();
1509  break;
1510  case ‪Lexer::T_PACK_KEYS:
1512  $options['pack_keys'] = strtoupper((string)$this->‪tableOptionValue());
1513  if (!in_array($options['pack_keys'], ['0', '1', 'DEFAULT'], true)) {
1514  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1515  }
1516  break;
1517  case ‪Lexer::T_PASSWORD:
1519  $options['password'] = (string)$this->‪tableOptionValue();
1520  break;
1523  $options['row_format'] = (string)$this->‪tableOptionValue();
1524  $validRowFormats = ['DEFAULT', 'DYNAMIC', 'FIXED', 'COMPRESSED', 'REDUNDANT', 'COMPACT'];
1525  if (!in_array($options['row_format'], $validRowFormats, true)) {
1526  $this->‪syntaxError(
1527  'DEFAULT, DYNAMIC, FIXED, COMPRESSED, REDUNDANT, COMPACT',
1528  $this->lexer->token
1529  );
1530  }
1531  break;
1534  $options['stats_auto_recalc'] = strtoupper((string)$this->‪tableOptionValue());
1535  if (!in_array($options['stats_auto_recalc'], ['0', '1', 'DEFAULT'], true)) {
1536  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1537  }
1538  break;
1541  $options['stats_persistent'] = strtoupper((string)$this->‪tableOptionValue());
1542  if (!in_array($options['stats_persistent'], ['0', '1', 'DEFAULT'], true)) {
1543  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1544  }
1545  break;
1548  $options['stats_sample_pages'] = strtoupper((string)$this->‪tableOptionValue());
1549  if (!in_array($options['stats_sample_pages'], ['0', '1', 'DEFAULT'], true)) {
1550  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1551  }
1552  break;
1555  $options['tablespace'] = (string)$this->‪tableOptionValue();
1556  break;
1557  default:
1558  $this->‪syntaxError(
1559  'DEFAULT, ENGINE, AUTO_INCREMENT, AVG_ROW_LENGTH, CHARACTER SET, ' .
1560  'CHECKSUM, COLLATE, COMMENT, COMPRESSION, CONNECTION, DATA DIRECTORY, ' .
1561  'DELAY_KEY_WRITE, ENCRYPTION, INDEX DIRECTORY, INSERT_METHOD, KEY_BLOCK_SIZE, ' .
1562  'MAX_ROWS, MIN_ROWS, PACK_KEYS, PASSWORD, ROW_FORMAT, STATS_AUTO_RECALC, ' .
1563  'STATS_PERSISTENT, STATS_SAMPLE_PAGES or TABLESPACE'
1564  );
1565  }
1566  }
1567 
1568  return $options;
1569  }
1570 
1577  protected function ‪tableOptionValue()
1578  {
1579  // Skip the optional equals sign
1580  if ($this->lexer->isNextToken(‪Lexer::T_EQUALS)) {
1581  $this->‪match(‪Lexer::T_EQUALS);
1582  }
1583  $this->lexer->moveNext();
1584 
1585  return $this->lexer->token['value'];
1586  }
1587 
1595  protected function ‪schemaObjectName()
1596  {
1597  $schemaObjectName = $this->lexer->lookahead['value'];
1598  $this->lexer->moveNext();
1599 
1600  return new ‪Identifier((string)$schemaObjectName);
1601  }
1602 }
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\__construct
‪__construct(string $statement)
Definition: Parser.php:89
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateTableClause
Definition: CreateTableClause.php:26
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException\semanticalError
‪static StatementException semanticalError(string $message, \Exception $previous=null)
Definition: StatementException.php:52
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BigIntDataType
Definition: BigIntDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TimeDataType
Definition: TimeDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\Identifier
Definition: Identifier.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\VarCharDataType
Definition: VarCharDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NO
‪const T_NO
Definition: Lexer.php:126
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CREATE
‪const T_CREATE
Definition: Lexer.php:85
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_KEY
‪const T_KEY
Definition: Lexer.php:93
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SPATIAL
‪const T_SPATIAL
Definition: Lexer.php:95
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DateTimeDataType
Definition: DateTimeDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PASSWORD
‪const T_PASSWORD
Definition: Lexer.php:148
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FOREIGN
‪const T_FOREIGN
Definition: Lexer.php:134
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BTREE
‪const T_BTREE
Definition: Lexer.php:129
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException
Definition: StatementException.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_USING
‪const T_USING
Definition: Lexer.php:128
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\match
‪match($token)
Definition: Parser.php:128
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ENUM
‪const T_ENUM
Definition: Lexer.php:80
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BitDataType
Definition: BitDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\characterDataTypeOptions
‪array characterDataTypeOptions()
Definition: Parser.php:1171
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\JsonDataType
Definition: JsonDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_HASH
‪const T_HASH
Definition: Lexer.php:130
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DYNAMIC
‪const T_DYNAMIC
Definition: Lexer.php:107
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SIMPLE
‪const T_SIMPLE
Definition: Lexer.php:120
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\fractionalSecondsPart
‪int fractionalSecondsPart()
Definition: Parser.php:1152
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NULL
‪const T_NULL
Definition: Lexer.php:105
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CONNECTION
‪const T_CONNECTION
Definition: Lexer.php:139
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INT
‪const T_INT
Definition: Lexer.php:55
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TEMPORARY
‪const T_TEMPORARY
Definition: Lexer.php:86
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STRING
‪const T_STRING
Definition: Lexer.php:29
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateTableStatement
Definition: CreateTableStatement.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createColumnDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST CreateColumnDefinitionItem createColumnDefinitionItem()
Definition: Parser.php:710
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ON
‪const T_ON
Definition: Lexer.php:121
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INTEGER
‪const T_INTEGER
Definition: Lexer.php:56
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TIME
‪const T_TIME
Definition: Lexer.php:64
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateColumnDefinitionItem
Definition: CreateColumnDefinitionItem.php:27
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TIMESTAMP
‪const T_TIMESTAMP
Definition: Lexer.php:65
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateIndexDefinitionItem
Definition: CreateIndexDefinitionItem.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\VarBinaryDataType
Definition: VarBinaryDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\parse
‪Table[] parse()
Definition: Parser.php:190
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TABLE
‪const T_TABLE
Definition: Lexer.php:87
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_REAL
‪const T_REAL
Definition: Lexer.php:58
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createTableClause
‪TYPO3 CMS Core Database Schema Parser AST CreateTableClause createTableClause()
Definition: Parser.php:369
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\RealDataType
Definition: RealDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BINARY
‪const T_BINARY
Definition: Lexer.php:70
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEMORY
‪const T_MEMORY
Definition: Lexer.php:108
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MIN_ROWS
‪const T_MIN_ROWS
Definition: Lexer.php:146
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateDefinition
Definition: CreateDefinition.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHARACTER
‪const T_CHARACTER
Definition: Lexer.php:113
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyTextDataType
Definition: TinyTextDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_VARCHAR
‪const T_VARCHAR
Definition: Lexer.php:69
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_REFERENCES
‪const T_REFERENCES
Definition: Lexer.php:104
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\valueListItem
‪string valueListItem()
Definition: Parser.php:1268
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PRECISION
‪const T_PRECISION
Definition: Lexer.php:155
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TINYTEXT
‪const T_TINYTEXT
Definition: Lexer.php:76
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STATS_SAMPLE_PAGES
‪const T_STATS_SAMPLE_PAGES
Definition: Lexer.php:152
‪TYPO3\CMS\Core\Database\Schema\Parser\TableBuilder
Definition: TableBuilder.php:74
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FLOAT
‪const T_FLOAT
Definition: Lexer.php:60
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SMALLINT
‪const T_SMALLINT
Definition: Lexer.php:53
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateForeignKeyDefinitionItem
Definition: CreateForeignKeyDefinitionItem.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ENGINE
‪const T_ENGINE
Definition: Lexer.php:135
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SEMICOLON
‪const T_SEMICOLON
Definition: Lexer.php:45
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_UNIQUE
‪const T_UNIQUE
Definition: Lexer.php:97
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHAR
‪const T_CHAR
Definition: Lexer.php:68
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FIXED
‪const T_FIXED
Definition: Lexer.php:106
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PACK_KEYS
‪const T_PACK_KEYS
Definition: Lexer.php:147
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COMMENT
‪const T_COMMENT
Definition: Lexer.php:101
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_JSON
‪const T_JSON
Definition: Lexer.php:82
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\referenceOption
‪string referenceOption()
Definition: Parser.php:1356
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COMMA
‪const T_COMMA
Definition: Lexer.php:33
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser
Definition: Parser.php:71
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\dataTypeLength
‪int dataTypeLength(bool $required=false)
Definition: Parser.php:1068
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TINYINT
‪const T_TINYINT
Definition: Lexer.php:52
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexColumnName
‪TYPO3 CMS Core Database Schema Parser AST IndexColumnName indexColumnName()
Definition: Parser.php:1333
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\referenceDefinition
‪TYPO3 CMS Core Database Schema Parser AST ReferenceDefinition referenceDefinition()
Definition: Parser.php:1284
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\getAST
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateStatement getAST()
Definition: Parser.php:111
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHECKSUM
‪const T_CHECKSUM
Definition: Lexer.php:137
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TextDataType
Definition: TextDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BIT
‪const T_BIT
Definition: Lexer.php:51
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumTextDataType
Definition: MediumTextDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FULL
‪const T_FULL
Definition: Lexer.php:118
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ZEROFILL
‪const T_ZEROFILL
Definition: Lexer.php:111
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_RESTRICT
‪const T_RESTRICT
Definition: Lexer.php:124
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TINYBLOB
‪const T_TINYBLOB
Definition: Lexer.php:72
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyBlobDataType
Definition: TinyBlobDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_KEY_BLOCK_SIZE
‪const T_KEY_BLOCK_SIZE
Definition: Lexer.php:131
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DOUBLE
‪const T_DOUBLE
Definition: Lexer.php:59
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TEXT
‪const T_TEXT
Definition: Lexer.php:77
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_OPEN_PARENTHESIS
‪const T_OPEN_PARENTHESIS
Definition: Lexer.php:32
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException\sqlError
‪static StatementException sqlError(string $sql)
Definition: StatementException.php:30
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\tableOptionValue
‪mixed tableOptionValue()
Definition: Parser.php:1575
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\CharDataType
Definition: CharDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CLOSE_PARENTHESIS
‪const T_CLOSE_PARENTHESIS
Definition: Lexer.php:31
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createIndexDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST CreateIndexDefinitionItem createIndexDefinitionItem()
Definition: Parser.php:484
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DATA
‪const T_DATA
Definition: Lexer.php:140
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\semanticalError
‪semanticalError($message='', $token=null)
Definition: Parser.php:237
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\SetDataType
Definition: SetDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_IF
‪const T_IF
Definition: Lexer.php:88
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexOptions
‪array indexOptions()
Definition: Parser.php:661
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_WITH
‪const T_WITH
Definition: Lexer.php:132
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createDefinition
‪TYPO3 CMS Core Database Schema Parser AST CreateDefinition createDefinition()
Definition: Parser.php:409
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\getLexer
‪Lexer getLexer()
Definition: Parser.php:100
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\IntegerDataType
Definition: IntegerDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DIRECTORY
‪const T_DIRECTORY
Definition: Lexer.php:141
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DECIMAL
‪const T_DECIMAL
Definition: Lexer.php:61
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateDefinitionItem createDefinitionItem()
Definition: Parser.php:444
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException\syntaxError
‪static StatementException syntaxError(string $message, \Exception $previous=null)
Definition: StatementException.php:41
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\valueList
‪array valueList()
Definition: Parser.php:1245
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COLUMN_FORMAT
‪const T_COLUMN_FORMAT
Definition: Lexer.php:102
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INDEX
‪const T_INDEX
Definition: Lexer.php:92
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\columnDefaultValue
‪mixed columnDefaultValue()
Definition: Parser.php:1031
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\AbstractDataType
Definition: AbstractDataType.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COMPRESSION
‪const T_COMPRESSION
Definition: Lexer.php:138
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DESC
‪const T_DESC
Definition: Lexer.php:116
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\syntaxError
‪syntaxError($expected='', $token=null)
Definition: Parser.php:213
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\LongTextDataType
Definition: LongTextDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DATE
‪const T_DATE
Definition: Lexer.php:63
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\$statement
‪string $statement
Definition: Parser.php:82
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumIntDataType
Definition: MediumIntDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\FloatDataType
Definition: FloatDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\AbstractCreateStatement
Definition: AbstractCreateStatement.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\free
‪free($deep=false, $position=0)
Definition: Parser.php:167
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DELETE
‪const T_DELETE
Definition: Lexer.php:123
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DoubleDataType
Definition: DoubleDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumBlobDataType
Definition: MediumBlobDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyIntDataType
Definition: TinyIntDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PRIMARY
‪const T_PRIMARY
Definition: Lexer.php:96
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MATCH
‪const T_MATCH
Definition: Lexer.php:117
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BLOB
‪const T_BLOB
Definition: Lexer.php:73
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BinaryDataType
Definition: BinaryDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DecimalDataType
Definition: DecimalDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\peekBeyondClosingParenthesis
‪array peekBeyondClosingParenthesis($resetPeek=true)
Definition: Parser.php:269
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_LONGTEXT
‪const T_LONGTEXT
Definition: Lexer.php:79
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEDIUMBLOB
‪const T_MEDIUMBLOB
Definition: Lexer.php:74
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\IndexColumnName
Definition: IndexColumnName.php:26
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PARTIAL
‪const T_PARTIAL
Definition: Lexer.php:119
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\queryLanguage
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateStatement queryLanguage()
Definition: Parser.php:302
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ASC
‪const T_ASC
Definition: Lexer.php:115
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NOT
‪const T_NOT
Definition: Lexer.php:89
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\AbstractCreateDefinitionItem
Definition: AbstractCreateDefinitionItem.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BlobDataType
Definition: BlobDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\$lexer
‪Lexer $lexer
Definition: Parser.php:76
‪TYPO3\CMS\Core\Database\Schema\Parser
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DATETIME
‪const T_DATETIME
Definition: Lexer.php:66
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SET
‪const T_SET
Definition: Lexer.php:81
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_IDENTIFIER
‪const T_IDENTIFIER
Definition: Lexer.php:48
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ROW_FORMAT
‪const T_ROW_FORMAT
Definition: Lexer.php:149
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COLLATE
‪const T_COLLATE
Definition: Lexer.php:114
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHECK
‪const T_CHECK
Definition: Lexer.php:98
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\LongBlobDataType
Definition: LongBlobDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DEFAULT
‪const T_DEFAULT
Definition: Lexer.php:99
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_YEAR
‪const T_YEAR
Definition: Lexer.php:67
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\columnDataType
‪TYPO3 CMS Core Database Schema Parser AST DataType AbstractDataType columnDataType()
Definition: Parser.php:836
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\numericDataTypeOptions
‪array numericDataTypeOptions()
Definition: Parser.php:1120
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DateDataType
Definition: DateDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\tableOptions
‪array tableOptions()
Definition: Parser.php:1418
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\enumerationDataTypeOptions
‪array enumerationDataTypeOptions()
Definition: Parser.php:1210
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DISK
‪const T_DISK
Definition: Lexer.php:109
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\dataTypeDecimals
‪array dataTypeDecimals()
Definition: Parser.php:1092
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEDIUMTEXT
‪const T_MEDIUMTEXT
Definition: Lexer.php:78
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STATS_PERSISTENT
‪const T_STATS_PERSISTENT
Definition: Lexer.php:151
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEDIUMINT
‪const T_MEDIUMINT
Definition: Lexer.php:54
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_UPDATE
‪const T_UPDATE
Definition: Lexer.php:122
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\NumericDataType
Definition: NumericDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createForeignKeyDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST CreateForeignKeyDefinitionItem createForeignKeyDefinitionItem()
Definition: Parser.php:576
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\SmallIntDataType
Definition: SmallIntDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STATS_AUTO_RECALC
‪const T_STATS_AUTO_RECALC
Definition: Lexer.php:150
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STORAGE
‪const T_STORAGE
Definition: Lexer.php:103
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ENCRYPTION
‪const T_ENCRYPTION
Definition: Lexer.php:143
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\schemaObjectName
‪TYPO3 CMS Core Database Schema Parser AST Identifier schemaObjectName()
Definition: Parser.php:1593
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_VARBINARY
‪const T_VARBINARY
Definition: Lexer.php:71
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CASCADE
‪const T_CASCADE
Definition: Lexer.php:125
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\EnumDataType
Definition: EnumDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createStatement
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateStatement createStatement()
Definition: Parser.php:327
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\ReferenceDefinition
Definition: ReferenceDefinition.php:26
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DELAY_KEY_WRITE
‪const T_DELAY_KEY_WRITE
Definition: Lexer.php:142
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TABLESPACE
‪const T_TABLESPACE
Definition: Lexer.php:153
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexName
‪AST Identifier indexName()
Definition: Parser.php:611
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NUMERIC
‪const T_NUMERIC
Definition: Lexer.php:62
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_AVG_ROW_LENGTH
‪const T_AVG_ROW_LENGTH
Definition: Lexer.php:136
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexType
‪string indexType()
Definition: Parser.php:627
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\YearDataType
Definition: YearDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ACTION
‪const T_ACTION
Definition: Lexer.php:127
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_UNSIGNED
‪const T_UNSIGNED
Definition: Lexer.php:110
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_EQUALS
‪const T_EQUALS
Definition: Lexer.php:36
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INSERT_METHOD
‪const T_INSERT_METHOD
Definition: Lexer.php:144
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FULLTEXT
‪const T_FULLTEXT
Definition: Lexer.php:94
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TimestampDataType
Definition: TimestampDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_AUTO_INCREMENT
‪const T_AUTO_INCREMENT
Definition: Lexer.php:100
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BIGINT
‪const T_BIGINT
Definition: Lexer.php:57
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MAX_ROWS
‪const T_MAX_ROWS
Definition: Lexer.php:145
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_EXISTS
‪const T_EXISTS
Definition: Lexer.php:90
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CURRENT_TIMESTAMP
‪const T_CURRENT_TIMESTAMP
Definition: Lexer.php:112
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer
Definition: Lexer.php:26
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createTableStatement
‪createTableStatement()
Definition: Parser.php:353
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PARSER
‪const T_PARSER
Definition: Lexer.php:133
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_LONGBLOB
‪const T_LONGBLOB
Definition: Lexer.php:75
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CONSTRAINT
‪const T_CONSTRAINT
Definition: Lexer.php:91