‪TYPO3CMS  9.5
Parser.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
3 
5 
6 /*
7  * This file is part of the TYPO3 CMS project.
8  *
9  * It is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License, either version 2
11  * of the License, or any later version.
12  *
13  * For the full copyright and license information, please read the
14  * LICENSE.txt file that was distributed with this source code.
15  *
16  * The TYPO3 project - inspiring people to share!
17  */
18 
19 use Doctrine\DBAL\Schema\Table;
22 
27 class ‪Parser
28 {
34  protected ‪$lexer;
35 
41  protected ‪$statement;
42 
48  public function ‪__construct(string ‪$statement)
49  {
50  $this->statement = ‪$statement;
51  $this->lexer = new ‪Lexer(‪$statement);
52  }
53 
59  public function ‪getLexer(): ‪Lexer
60  {
61  return ‪$this->lexer;
62  }
63 
70  public function ‪getAST(): ‪AST\AbstractCreateStatement
71  {
72  // Parse & build AST
73  return $this->‪queryLanguage();
74  }
75 
87  public function ‪match($token)
88  {
89  $lookaheadType = $this->lexer->lookahead['type'];
90 
91  // Short-circuit on first condition, usually types match
92  if ($lookaheadType !== $token) {
93  // If parameter is not identifier (1-99) must be exact match
94  if ($token < ‪Lexer::T_IDENTIFIER) {
95  $this->‪syntaxError($this->lexer->getLiteral($token));
96  }
97 
98  // If parameter is keyword (200+) must be exact match
99  if ($token > ‪Lexer::T_IDENTIFIER) {
100  $this->‪syntaxError($this->lexer->getLiteral($token));
101  }
102 
103  // If parameter is MATCH then FULL, PARTIAL or SIMPLE must follow
104  if ($token === ‪Lexer::T_MATCH
105  && $lookaheadType !== ‪Lexer::T_FULL
106  && $lookaheadType !== ‪Lexer::T_PARTIAL
107  && $lookaheadType !== ‪Lexer::T_SIMPLE
108  ) {
109  $this->‪syntaxError($this->lexer->getLiteral($token));
110  }
111 
112  if ($token === ‪Lexer::T_ON && $lookaheadType !== ‪Lexer::T_DELETE && $lookaheadType !== ‪Lexer::T_UPDATE) {
113  $this->‪syntaxError($this->lexer->getLiteral($token));
114  }
115  }
116 
117  $this->lexer->moveNext();
118  }
119 
126  public function ‪free($deep = false, $position = 0)
127  {
128  // WARNING! Use this method with care. It resets the scanner!
129  $this->lexer->resetPosition($position);
130 
131  // Deep = true cleans peek and also any previously defined errors
132  if ($deep) {
133  $this->lexer->resetPeek();
134  }
135 
136  $this->lexer->token = null;
137  $this->lexer->lookahead = null;
138  }
139 
149  public function ‪parse(): array
150  {
151  $ast = $this->‪getAST();
152 
153  if (!$ast instanceof ‪CreateTableStatement) {
154  return [];
155  }
156 
157  $tableBuilder = new ‪TableBuilder();
158  $table = $tableBuilder->create($ast);
159 
160  return [$table];
161  }
162 
172  public function ‪syntaxError($expected = '', $token = null)
173  {
174  if ($token === null) {
175  $token = $this->lexer->lookahead;
176  }
177 
178  $tokenPos = $token['position'] ?? '-1';
179 
180  $message = "line 0, col {$tokenPos}: Error: ";
181  $message .= ($expected !== '') ? "Expected {$expected}, got " : 'Unexpected ';
182  $message .= ($this->lexer->lookahead === null) ? 'end of string.' : "'{$token['value']}'";
183 
184  throw ‪StatementException::syntaxError($message, ‪StatementException::sqlError($this->statement));
185  }
186 
196  public function ‪semanticalError($message = '', $token = null)
197  {
198  if ($token === null) {
199  $token = $this->lexer->lookahead;
200  }
201 
202  // Minimum exposed chars ahead of token
203  $distance = 12;
204 
205  // Find a position of a final word to display in error string
206  $createTableStatement = ‪$this->statement;
207  $length = strlen($createTableStatement);
208  $pos = $token['position'] + $distance;
209  $pos = strpos($createTableStatement, ' ', ($length > $pos) ? $pos : $length);
210  $length = ($pos !== false) ? $pos - $token['position'] : $distance;
211 
212  $tokenPos = array_key_exists('position', $token) && $token['position'] > 0 ? $token['position'] : '-1';
213  $tokenStr = substr($createTableStatement, $token['position'], $length);
214 
215  // Building informative message
216  $message = 'line 0, col ' . $tokenPos . " near '" . $tokenStr . "': Error: " . $message;
217 
219  }
220 
228  protected function ‪peekBeyondClosingParenthesis($resetPeek = true)
229  {
230  $token = $this->lexer->peek();
231  $numUnmatched = 1;
232 
233  while ($numUnmatched > 0 && $token !== null) {
234  switch ($token['type']) {
236  ++$numUnmatched;
237  break;
239  --$numUnmatched;
240  break;
241  default:
242  // Do nothing
243  }
244 
245  $token = $this->lexer->peek();
246  }
247 
248  if ($resetPeek) {
249  $this->lexer->resetPeek();
250  }
251 
252  return $token;
253  }
254 
262  {
263  $this->lexer->moveNext();
264 
265  if ($this->lexer->lookahead['type'] !== ‪Lexer::T_CREATE) {
266  $this->‪syntaxError('CREATE');
267  }
268 
269  $statement = $this->‪createStatement();
270 
271  // Check for end of string
272  if ($this->lexer->lookahead !== null) {
273  $this->‪syntaxError('end of string');
274  }
275 
276  return ‪$statement;
277  }
278 
287  {
288  ‪$statement = null;
290 
291  switch ($this->lexer->lookahead['type']) {
293  // Intentional fall-through
294  case ‪Lexer::T_TABLE:
296  break;
297  default:
298  $this->‪syntaxError('TEMPORARY or TABLE');
299  break;
300  }
301 
303 
304  return ‪$statement;
305  }
306 
313  {
314  $createTableStatement = new ‪AST\CreateTableStatement($this->‪createTableClause(), $this->‪createDefinition());
315 
316  if (!$this->lexer->isNextToken(‪Lexer::T_SEMICOLON)) {
317  $createTableStatement->tableOptions = $this->‪tableOptions();
318  }
319  return $createTableStatement;
320  }
321 
328  protected function ‪createTableClause(): ‪AST\CreateTableClause
329  {
330  $isTemporary = false;
331  // Check for TEMPORARY
332  if ($this->lexer->isNextToken(‪Lexer::T_TEMPORARY)) {
334  $isTemporary = true;
335  }
336 
337  $this->‪match(‪Lexer::T_TABLE);
338 
339  // Check for IF NOT EXISTS
340  if ($this->lexer->isNextToken(‪Lexer::T_IF)) {
341  $this->‪match(‪Lexer::T_IF);
342  $this->‪match(‪Lexer::T_NOT);
344  }
345 
346  // Process schema object name (table name)
347  $tableName = $this->‪schemaObjectName();
348 
349  return new ‪AST\CreateTableClause($tableName, $isTemporary);
350  }
351 
368  protected function ‪createDefinition(): ‪AST\CreateDefinition
369  {
370  $createDefinitions = [];
371 
372  // Process opening parenthesis
374 
375  $createDefinitions[] = $this->‪createDefinitionItem();
376 
377  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
378  $this->‪match(‪Lexer::T_COMMA);
379 
380  // TYPO3 previously accepted invalid SQL files where a create definition
381  // item terminated with a comma before the final closing parenthesis.
382  // Silently swallow the extra comma and stop the create definition parsing.
383  if ($this->lexer->isNextToken(‪Lexer::T_CLOSE_PARENTHESIS)) {
384  break;
385  }
386 
387  $createDefinitions[] = $this->‪createDefinitionItem();
388  }
389 
390  // Process closing parenthesis
392 
393  return new ‪AST\CreateDefinition($createDefinitions);
394  }
395 
404  {
405  $definitionItem = null;
406 
407  switch ($this->lexer->lookahead['type']) {
409  // Intentional fall-through
410  case ‪Lexer::T_SPATIAL:
411  // Intentional fall-through
412  case ‪Lexer::T_PRIMARY:
413  // Intentional fall-through
414  case ‪Lexer::T_UNIQUE:
415  // Intentional fall-through
416  case ‪Lexer::T_KEY:
417  // Intentional fall-through
418  case ‪Lexer::T_INDEX:
419  $definitionItem = $this->‪createIndexDefinitionItem();
420  break;
421  case ‪Lexer::T_FOREIGN:
422  $definitionItem = $this->‪createForeignKeyDefinitionItem();
423  break;
425  $this->‪semanticalError('CONSTRAINT [symbol] index definition part not supported');
426  break;
427  case ‪Lexer::T_CHECK:
428  $this->‪semanticalError('CHECK (expr) create definition not supported');
429  break;
430  default:
431  $definitionItem = $this->‪createColumnDefinitionItem();
432  }
433 
434  return $definitionItem;
435  }
436 
444  {
445  $indexName = null;
446  $isPrimary = false;
447  $isFulltext = false;
448  $isSpatial = false;
449  $isUnique = false;
450  $indexDefinition = new ‪AST\CreateIndexDefinitionItem();
451 
452  switch ($this->lexer->lookahead['type']) {
453  case ‪Lexer::T_PRIMARY:
455  // KEY is a required keyword for PRIMARY index
456  $this->‪match(‪Lexer::T_KEY);
457  $isPrimary = true;
458  break;
459  case ‪Lexer::T_KEY:
460  // Plain index, no special configuration
461  $this->‪match(‪Lexer::T_KEY);
462  break;
463  case ‪Lexer::T_INDEX:
464  // Plain index, no special configuration
465  $this->‪match(‪Lexer::T_INDEX);
466  break;
467  case ‪Lexer::T_UNIQUE:
469  // INDEX|KEY are optional keywords for UNIQUE index
470  if ($this->lexer->isNextTokenAny([‪Lexer::T_INDEX, ‪Lexer::T_KEY])) {
471  $this->lexer->moveNext();
472  }
473  $isUnique = true;
474  break;
477  // INDEX|KEY are optional keywords for FULLTEXT index
478  if ($this->lexer->isNextTokenAny([‪Lexer::T_INDEX, ‪Lexer::T_KEY])) {
479  $this->lexer->moveNext();
480  }
481  $isFulltext = true;
482  break;
483  case ‪Lexer::T_SPATIAL:
485  // INDEX|KEY are optional keywords for SPATIAL index
486  if ($this->lexer->isNextTokenAny([‪Lexer::T_INDEX, ‪Lexer::T_KEY])) {
487  $this->lexer->moveNext();
488  }
489  $isSpatial = true;
490  break;
491  default:
492  $this->‪syntaxError('PRIMARY, KEY, INDEX, UNIQUE, FULLTEXT or SPATIAL');
493  }
494 
495  // PRIMARY KEY has no name in MySQL
496  if (!$indexDefinition->isPrimary) {
497  $indexName = $this->‪indexName();
498  }
499 
500  $indexDefinition = new ‪AST\CreateIndexDefinitionItem(
501  $indexName,
502  $isPrimary,
503  $isUnique,
504  $isSpatial,
505  $isFulltext
506  );
507 
508  // FULLTEXT and SPATIAL indexes can not have a type definition
509  if (!$isFulltext && !$isSpatial) {
510  $indexDefinition->indexType = $this->‪indexType();
511  }
512 
514 
515  $indexDefinition->columnNames[] = $this->‪indexColumnName();
516 
517  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
518  $this->‪match(‪Lexer::T_COMMA);
519  $indexDefinition->columnNames[] = $this->‪indexColumnName();
520  }
521 
523 
524  $indexDefinition->options = $this->‪indexOptions();
525 
526  return $indexDefinition;
527  }
528 
536  {
538  $this->‪match(‪Lexer::T_KEY);
539 
540  $indexName = $this->‪indexName();
541 
543 
544  $indexColumns = [];
545  $indexColumns[] = $this->‪indexColumnName();
546 
547  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
548  $this->‪match(‪Lexer::T_COMMA);
549  $indexColumns[] = $this->‪indexColumnName();
550  }
551 
553 
554  $foreignKeyDefinition = new ‪AST\CreateForeignKeyDefinitionItem(
555  $indexName,
556  $indexColumns,
557  $this->‪referenceDefinition()
558  );
559 
560  return $foreignKeyDefinition;
561  }
562 
570  public function ‪indexName(): ‪AST\Identifier
571  {
572  $indexName = new ‪AST\Identifier(null);
573  if (!$this->lexer->isNextTokenAny([‪Lexer::T_USING, ‪Lexer::T_OPEN_PARENTHESIS])) {
574  $indexName = $this->‪schemaObjectName();
575  }
576 
577  return $indexName;
578  }
579 
586  public function ‪indexType(): string
587  {
588  $indexType = '';
589  if (!$this->lexer->isNextToken(‪Lexer::T_USING)) {
590  return $indexType;
591  }
592 
593  $this->‪match(‪Lexer::T_USING);
594 
595  switch ($this->lexer->lookahead['type']) {
596  case ‪Lexer::T_BTREE:
597  $this->‪match(‪Lexer::T_BTREE);
598  $indexType = 'BTREE';
599  break;
600  case ‪Lexer::T_HASH:
601  $this->‪match(‪Lexer::T_HASH);
602  $indexType = 'HASH';
603  break;
604  default:
605  $this->‪syntaxError('BTREE or HASH');
606  }
607 
608  return $indexType;
609  }
610 
620  public function ‪indexOptions(): array
621  {
622  $options = [];
623 
624  while ($this->lexer->lookahead && !$this->lexer->isNextTokenAny([‪Lexer::T_COMMA, ‪Lexer::T_CLOSE_PARENTHESIS])) {
625  switch ($this->lexer->lookahead['type']) {
628  if ($this->lexer->isNextToken(‪Lexer::T_EQUALS)) {
630  }
631  $this->lexer->moveNext();
632  $options['key_block_size'] = (int)$this->lexer->token['value'];
633  break;
634  case ‪Lexer::T_USING:
635  $options['index_type'] = $this->indexType();
636  break;
637  case ‪Lexer::T_WITH:
638  $this->‪match(‪Lexer::T_WITH);
640  $options['parser'] = $this->‪schemaObjectName();
641  break;
642  case ‪Lexer::T_COMMENT:
645  $options['comment'] = $this->lexer->token['value'];
646  break;
647  default:
648  $this->‪syntaxError('KEY_BLOCK_SIZE, USING, WITH PARSER or COMMENT');
649  }
650  }
651 
652  return $options;
653  }
654 
670  {
671  $columnName = $this->‪schemaObjectName();
672  $dataType = $this->‪columnDataType();
673 
674  $columnDefinitionItem = new ‪AST\CreateColumnDefinitionItem($columnName, $dataType);
675 
676  while ($this->lexer->lookahead && !$this->lexer->isNextTokenAny([‪Lexer::T_COMMA, ‪Lexer::T_CLOSE_PARENTHESIS])) {
677  switch ($this->lexer->lookahead['type']) {
678  case ‪Lexer::T_NOT:
679  $columnDefinitionItem->allowNull = false;
680  $this->‪match(‪Lexer::T_NOT);
681  $this->‪match(‪Lexer::T_NULL);
682  break;
683  case ‪Lexer::T_NULL:
684  $columnDefinitionItem->null = true;
685  $this->‪match(‪Lexer::T_NULL);
686  break;
687  case ‪Lexer::T_DEFAULT:
688  $columnDefinitionItem->hasDefaultValue = true;
689  $columnDefinitionItem->defaultValue = $this->‪columnDefaultValue();
690  break;
692  $columnDefinitionItem->autoIncrement = true;
694  break;
695  case ‪Lexer::T_UNIQUE:
696  $columnDefinitionItem->unique = true;
698  if ($this->lexer->isNextToken(‪Lexer::T_KEY)) {
699  $this->‪match(‪Lexer::T_KEY);
700  }
701  break;
702  case ‪Lexer::T_PRIMARY:
703  $columnDefinitionItem->primary = true;
705  if ($this->lexer->isNextToken(‪Lexer::T_KEY)) {
706  $this->‪match(‪Lexer::T_KEY);
707  }
708  break;
709  case ‪Lexer::T_KEY:
710  $columnDefinitionItem->index = true;
711  $this->‪match(‪Lexer::T_KEY);
712  break;
713  case ‪Lexer::T_COMMENT:
715  if ($this->lexer->isNextToken(‪Lexer::T_STRING)) {
716  $columnDefinitionItem->comment = $this->lexer->lookahead['value'];
718  }
719  break;
722  if ($this->lexer->isNextToken(‪Lexer::T_FIXED)) {
723  $columnDefinitionItem->columnFormat = 'fixed';
724  $this->‪match(‪Lexer::T_FIXED);
725  } elseif ($this->lexer->isNextToken(‪Lexer::T_DYNAMIC)) {
726  $columnDefinitionItem->columnFormat = 'dynamic';
728  } else {
730  }
731  break;
732  case ‪Lexer::T_STORAGE:
734  if ($this->lexer->isNextToken(‪Lexer::T_MEMORY)) {
735  $columnDefinitionItem->storage = 'memory';
737  } elseif ($this->lexer->isNextToken(‪Lexer::T_DISK)) {
738  $columnDefinitionItem->storage = 'disk';
739  $this->‪match(‪Lexer::T_DISK);
740  } else {
742  }
743  break;
745  $columnDefinitionItem->reference = $this->‪referenceDefinition();
746  break;
747  default:
748  $this->‪syntaxError(
749  'NOT, NULL, DEFAULT, AUTO_INCREMENT, UNIQUE, ' .
750  'PRIMARY, COMMENT, COLUMN_FORMAT, STORAGE or REFERENCES'
751  );
752  }
753  }
754 
755  return $columnDefinitionItem;
756  }
757 
796  {
797  $dataType = null;
798 
799  switch ($this->lexer->lookahead['type']) {
800  case ‪Lexer::T_BIT:
801  $this->‪match(‪Lexer::T_BIT);
802  $dataType = new ‪AST\DataType\BitDataType(
803  $this->‪dataTypeLength()
804  );
805  break;
806  case ‪Lexer::T_TINYINT:
808  $dataType = new ‪AST\DataType\TinyIntDataType(
809  $this->‪dataTypeLength(),
811  );
812  break;
815  $dataType = new ‪AST\DataType\SmallIntDataType(
816  $this->‪dataTypeLength(),
818  );
819  break;
822  $dataType = new ‪AST\DataType\MediumIntDataType(
823  $this->‪dataTypeLength(),
825  );
826  break;
827  case ‪Lexer::T_INT:
828  $this->‪match(‪Lexer::T_INT);
829  $dataType = new ‪AST\DataType\IntegerDataType(
830  $this->‪dataTypeLength(),
832  );
833  break;
834  case ‪Lexer::T_INTEGER:
836  $dataType = new ‪AST\DataType\IntegerDataType(
837  $this->‪dataTypeLength(),
839  );
840  break;
841  case ‪Lexer::T_BIGINT:
843  $dataType = new ‪AST\DataType\BigIntDataType(
844  $this->‪dataTypeLength(),
846  );
847  break;
848  case ‪Lexer::T_REAL:
849  $this->‪match(‪Lexer::T_REAL);
850  $dataType = new ‪AST\DataType\RealDataType(
851  $this->‪dataTypeDecimals(),
853  );
854  break;
855  case ‪Lexer::T_DOUBLE:
857  if ($this->lexer->isNextToken(‪Lexer::T_PRECISION)) {
859  }
860  $dataType = new ‪AST\DataType\DoubleDataType(
861  $this->‪dataTypeDecimals(),
863  );
864  break;
865  case ‪Lexer::T_FLOAT:
866  $this->‪match(‪Lexer::T_FLOAT);
867  $dataType = new ‪AST\DataType\FloatDataType(
868  $this->‪dataTypeDecimals(),
870  );
871 
872  break;
873  case ‪Lexer::T_DECIMAL:
875  $dataType = new ‪AST\DataType\DecimalDataType(
876  $this->‪dataTypeDecimals(),
878  );
879  break;
880  case ‪Lexer::T_NUMERIC:
882  $dataType = new ‪AST\DataType\NumericDataType(
883  $this->‪dataTypeDecimals(),
885  );
886  break;
887  case ‪Lexer::T_DATE:
888  $this->‪match(‪Lexer::T_DATE);
889  $dataType = new ‪AST\DataType\DateDataType();
890  break;
891  case ‪Lexer::T_TIME:
892  $this->‪match(‪Lexer::T_TIME);
893  $dataType = new ‪AST\DataType\TimeDataType($this->‪fractionalSecondsPart());
894  break;
898  break;
902  break;
903  case ‪Lexer::T_YEAR:
904  $this->‪match(‪Lexer::T_YEAR);
905  $dataType = new ‪AST\DataType\YearDataType();
906  break;
907  case ‪Lexer::T_CHAR:
908  $this->‪match(‪Lexer::T_CHAR);
909  $dataType = new ‪AST\DataType\CharDataType(
910  $this->‪dataTypeLength(),
912  );
913  break;
914  case ‪Lexer::T_VARCHAR:
916  $dataType = new ‪AST\DataType\VarCharDataType(
917  $this->‪dataTypeLength(true),
919  );
920  break;
921  case ‪Lexer::T_BINARY:
923  $dataType = new ‪AST\DataType\BinaryDataType($this->‪dataTypeLength());
924  break;
927  $dataType = new ‪AST\DataType\VarBinaryDataType($this->‪dataTypeLength(true));
928  break;
931  $dataType = new ‪AST\DataType\TinyBlobDataType();
932  break;
933  case ‪Lexer::T_BLOB:
934  $this->‪match(‪Lexer::T_BLOB);
935  $dataType = new ‪AST\DataType\BlobDataType();
936  break;
939  $dataType = new ‪AST\DataType\MediumBlobDataType();
940  break;
943  $dataType = new ‪AST\DataType\LongBlobDataType();
944  break;
948  break;
949  case ‪Lexer::T_TEXT:
950  $this->‪match(‪Lexer::T_TEXT);
952  break;
956  break;
960  break;
961  case ‪Lexer::T_ENUM:
962  $this->‪match(‪Lexer::T_ENUM);
963  $dataType = new ‪AST\DataType\EnumDataType($this->‪valueList(), $this->‪enumerationDataTypeOptions());
964  break;
965  case ‪Lexer::T_SET:
966  $this->‪match(‪Lexer::T_SET);
967  $dataType = new ‪AST\DataType\SetDataType($this->‪valueList(), $this->‪enumerationDataTypeOptions());
968  break;
969  case ‪Lexer::T_JSON:
970  $this->‪match(‪Lexer::T_JSON);
971  $dataType = new ‪AST\DataType\JsonDataType();
972  break;
973  default:
974  $this->‪syntaxError(
975  'BIT, TINYINT, SMALLINT, MEDIUMINT, INT, INTEGER, BIGINT, REAL, DOUBLE, FLOAT, DECIMAL, NUMERIC, ' .
976  'DATE, TIME, TIMESTAMP, DATETIME, YEAR, CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, BLOB, ' .
977  'MEDIUMBLOB, LONGBLOB, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT, ENUM, SET, or JSON'
978  );
979  }
980 
981  return $dataType;
982  }
983 
990  protected function ‪columnDefaultValue()
991  {
993  $value = null;
994 
995  switch ($this->lexer->lookahead['type']) {
996  case ‪Lexer::T_INTEGER:
997  $value = (int)$this->lexer->lookahead['value'];
998  break;
999  case ‪Lexer::T_FLOAT:
1000  $value = (float)$this->lexer->lookahead['value'];
1001  break;
1002  case ‪Lexer::T_STRING:
1003  $value = (string)$this->lexer->lookahead['value'];
1004  break;
1006  $value = 'CURRENT_TIMESTAMP';
1007  break;
1008  case ‪Lexer::T_NULL:
1009  $value = null;
1010  break;
1011  default:
1012  $this->syntaxError('String, Integer, Float, NULL or CURRENT_TIMESTAMP');
1013  }
1014 
1015  $this->lexer->moveNext();
1016 
1017  return $value;
1018  }
1019 
1027  protected function ‪dataTypeLength(bool $required = false): int
1028  {
1029  $length = 0;
1030  if (!$this->lexer->isNextToken(‪Lexer::T_OPEN_PARENTHESIS)) {
1031  if ($required) {
1032  $this->‪semanticalError('The current data type requires a field length definition.');
1033  }
1034  return $length;
1035  }
1036 
1038  $length = (int)$this->lexer->lookahead['value'];
1039  $this->match(‪Lexer::T_INTEGER);
1041 
1042  return $length;
1043  }
1044 
1051  private function ‪dataTypeDecimals(): array
1052  {
1053  $options = [];
1054  if (!$this->lexer->isNextToken(‪Lexer::T_OPEN_PARENTHESIS)) {
1055  return $options;
1056  }
1057 
1059  $options['length'] = (int)$this->lexer->lookahead['value'];
1060  $this->match(‪Lexer::T_INTEGER);
1061 
1062  if ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
1063  $this->‪match(‪Lexer::T_COMMA);
1064  $options['decimals'] = (int)$this->lexer->lookahead['value'];
1065  $this->match(‪Lexer::T_INTEGER);
1066  }
1067 
1069 
1070  return $options;
1071  }
1072 
1079  protected function ‪numericDataTypeOptions(): array
1080  {
1081  $options = ['unsigned' => false, 'zerofill' => false];
1082 
1083  if (!$this->lexer->isNextTokenAny([‪Lexer::T_UNSIGNED, ‪Lexer::T_ZEROFILL])) {
1084  return $options;
1085  }
1086 
1087  while ($this->lexer->isNextTokenAny([‪Lexer::T_UNSIGNED, ‪Lexer::T_ZEROFILL])) {
1088  switch ($this->lexer->lookahead['type']) {
1089  case ‪Lexer::T_UNSIGNED:
1091  $options['unsigned'] = true;
1092  break;
1093  case ‪Lexer::T_ZEROFILL:
1095  $options['zerofill'] = true;
1096  break;
1097  default:
1098  $this->‪syntaxError('USIGNED or ZEROFILL');
1099  }
1100  }
1101 
1102  return $options;
1103  }
1104 
1111  protected function ‪fractionalSecondsPart(): int
1112  {
1113  $fractionalSecondsPart = $this->‪dataTypeLength();
1114  if ($fractionalSecondsPart < 0) {
1115  $this->‪semanticalError('the fractional seconds part for TIME, DATETIME or TIMESTAMP columns must >= 0');
1116  }
1117  if ($fractionalSecondsPart > 6) {
1118  $this->‪semanticalError('the fractional seconds part for TIME, DATETIME or TIMESTAMP columns must <= 6');
1119  }
1120 
1121  return $fractionalSecondsPart;
1122  }
1123 
1130  protected function ‪characterDataTypeOptions(): array
1131  {
1132  $options = ['binary' => false, 'charset' => null, 'collation' => null];
1133 
1134  if (!$this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE, ‪Lexer::T_BINARY])) {
1135  return $options;
1136  }
1137 
1138  while ($this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE, ‪Lexer::T_BINARY])) {
1139  switch ($this->lexer->lookahead['type']) {
1140  case ‪Lexer::T_BINARY:
1141  $this->‪match(‪Lexer::T_BINARY);
1142  $options['binary'] = true;
1143  break;
1144  case ‪Lexer::T_CHARACTER:
1146  $this->‪match(‪Lexer::T_SET);
1147  $this->‪match(‪Lexer::T_STRING);
1148  $options['charset'] = $this->lexer->token['value'];
1149  break;
1150  case ‪Lexer::T_COLLATE:
1151  $this->‪match(‪Lexer::T_COLLATE);
1152  $this->‪match(‪Lexer::T_STRING);
1153  $options['collation'] = $this->lexer->token['value'];
1154  break;
1155  default:
1156  $this->‪syntaxError('BINARY, CHARACTER SET or COLLATE');
1157  }
1158  }
1159 
1160  return $options;
1161  }
1162 
1169  protected function ‪enumerationDataTypeOptions(): array
1170  {
1171  $options = ['charset' => null, 'collation' => null];
1172 
1173  if (!$this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE])) {
1174  return $options;
1175  }
1176 
1177  while ($this->lexer->isNextTokenAny([‪Lexer::T_CHARACTER, ‪Lexer::T_COLLATE])) {
1178  switch ($this->lexer->lookahead['type']) {
1179  case ‪Lexer::T_CHARACTER:
1181  $this->‪match(‪Lexer::T_SET);
1182  $this->‪match(‪Lexer::T_STRING);
1183  $options['charset'] = $this->lexer->token['value'];
1184  break;
1185  case ‪Lexer::T_COLLATE:
1186  $this->‪match(‪Lexer::T_COLLATE);
1187  $this->‪match(‪Lexer::T_STRING);
1188  $options['collation'] = $this->lexer->token['value'];
1189  break;
1190  default:
1191  $this->‪syntaxError('CHARACTER SET or COLLATE');
1192  }
1193  }
1194 
1195  return $options;
1196  }
1197 
1204  protected function ‪valueList(): array
1205  {
1207 
1208  $values = [];
1209  $values[] = $this->‪valueListItem();
1210 
1211  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
1212  $this->‪match(‪Lexer::T_COMMA);
1213  $values[] = $this->‪valueListItem();
1214  }
1215 
1217 
1218  return $values;
1219  }
1220 
1227  protected function ‪valueListItem(): string
1228  {
1229  $this->‪match(‪Lexer::T_STRING);
1230 
1231  return (string)$this->lexer->token['value'];
1232  }
1233 
1244  {
1246  $tableName = $this->‪schemaObjectName();
1248 
1249  $referenceColumns = [];
1250  $referenceColumns[] = $this->‪indexColumnName();
1251 
1252  while ($this->lexer->isNextToken(‪Lexer::T_COMMA)) {
1253  $this->‪match(‪Lexer::T_COMMA);
1254  $referenceColumns[] = $this->‪indexColumnName();
1255  }
1256 
1258 
1259  $referenceDefinition = new ‪AST\ReferenceDefinition($tableName, $referenceColumns);
1260 
1261  while (!$this->lexer->isNextTokenAny([‪Lexer::T_COMMA, ‪Lexer::T_CLOSE_PARENTHESIS])) {
1262  switch ($this->lexer->lookahead['type']) {
1263  case ‪Lexer::T_MATCH:
1264  $this->‪match(‪Lexer::T_MATCH);
1265  $referenceDefinition->match = $this->lexer->lookahead['value'];
1266  $this->lexer->moveNext();
1267  break;
1268  case ‪Lexer::T_ON:
1269  $this->‪match(‪Lexer::T_ON);
1270  if ($this->lexer->isNextToken(‪Lexer::T_DELETE)) {
1271  $this->‪match(‪Lexer::T_DELETE);
1272  $referenceDefinition->onDelete = $this->‪referenceOption();
1273  } else {
1274  $this->‪match(‪Lexer::T_UPDATE);
1275  $referenceDefinition->onUpdate = $this->‪referenceOption();
1276  }
1277  break;
1278  default:
1279  $this->‪syntaxError('MATCH, ON DELETE or ON UPDATE');
1280  }
1281  }
1282 
1283  return $referenceDefinition;
1284  }
1285 
1292  protected function ‪indexColumnName(): ‪AST\IndexColumnName
1293  {
1294  $columnName = $this->‪schemaObjectName();
1295  $length = $this->‪dataTypeLength();
1296  $direction = null;
1297 
1298  if ($this->lexer->isNextToken(‪Lexer::T_ASC)) {
1299  $this->‪match(‪Lexer::T_ASC);
1300  $direction = 'ASC';
1301  } elseif ($this->lexer->isNextToken(‪Lexer::T_DESC)) {
1302  $this->‪match(‪Lexer::T_DESC);
1303  $direction = 'DESC';
1304  }
1305 
1306  return new ‪AST\IndexColumnName($columnName, $length, $direction);
1307  }
1308 
1315  protected function ‪referenceOption(): string
1316  {
1317  $action = null;
1318 
1319  switch ($this->lexer->lookahead['type']) {
1320  case ‪Lexer::T_RESTRICT:
1322  $action = 'RESTRICT';
1323  break;
1324  case ‪Lexer::T_CASCADE:
1325  $this->‪match(‪Lexer::T_CASCADE);
1326  $action = 'CASCADE';
1327  break;
1328  case ‪Lexer::T_SET:
1329  $this->‪match(‪Lexer::T_SET);
1330  $this->‪match(‪Lexer::T_NULL);
1331  $action = 'SET NULL';
1332  break;
1333  case ‪Lexer::T_NO:
1334  $this->‪match(‪Lexer::T_NO);
1335  $this->‪match(‪Lexer::T_ACTION);
1336  $action = 'NO ACTION';
1337  break;
1338  default:
1339  $this->‪syntaxError('RESTRICT, CASCADE, SET NULL or NO ACTION');
1340  }
1341 
1342  return $action;
1343  }
1344 
1377  protected function ‪tableOptions(): array
1378  {
1379  $options = [];
1380 
1381  while ($this->lexer->lookahead && !$this->lexer->isNextToken(‪Lexer::T_SEMICOLON)) {
1382  switch ($this->lexer->lookahead['type']) {
1383  case ‪Lexer::T_DEFAULT:
1384  // DEFAULT prefix is optional for COLLATE/CHARACTER SET, do nothing
1385  $this->‪match(‪Lexer::T_DEFAULT);
1386  break;
1387  case ‪Lexer::T_ENGINE:
1388  $this->‪match(‪Lexer::T_ENGINE);
1389  $options['engine'] = (string)$this->‪tableOptionValue();
1390  break;
1393  $options['auto_increment'] = (int)$this->‪tableOptionValue();
1394  break;
1397  $options['average_row_length'] = (int)$this->‪tableOptionValue();
1398  break;
1399  case ‪Lexer::T_CHARACTER:
1401  $this->‪match(‪Lexer::T_SET);
1402  $options['character_set'] = (string)$this->‪tableOptionValue();
1403  break;
1404  case ‪Lexer::T_CHECKSUM:
1406  $options['checksum'] = (int)$this->‪tableOptionValue();
1407  break;
1408  case ‪Lexer::T_COLLATE:
1409  $this->‪match(‪Lexer::T_COLLATE);
1410  $options['collation'] = (string)$this->‪tableOptionValue();
1411  break;
1412  case ‪Lexer::T_COMMENT:
1413  $this->‪match(‪Lexer::T_COMMENT);
1414  $options['comment'] = (string)$this->‪tableOptionValue();
1415  break;
1418  $options['compression'] = strtoupper((string)$this->‪tableOptionValue());
1419  if (!in_array($options['compression'], ['ZLIB', 'LZ4', 'NONE'], true)) {
1420  $this->‪syntaxError('ZLIB, LZ4 or NONE', $this->lexer->token);
1421  }
1422  break;
1425  $options['connection'] = (string)$this->‪tableOptionValue();
1426  break;
1427  case ‪Lexer::T_DATA:
1428  $this->‪match(‪Lexer::T_DATA);
1430  $options['data_directory'] = (string)$this->‪tableOptionValue();
1431  break;
1434  $options['delay_key_write'] = (int)$this->‪tableOptionValue();
1435  break;
1438  $options['encryption'] = strtoupper((string)$this->‪tableOptionValue());
1439  if (!in_array($options['encryption'], ['Y', 'N'], true)) {
1440  $this->‪syntaxError('Y or N', $this->lexer->token);
1441  }
1442  break;
1443  case ‪Lexer::T_INDEX:
1444  $this->‪match(‪Lexer::T_INDEX);
1446  $options['index_directory'] = (string)$this->‪tableOptionValue();
1447  break;
1450  $options['insert_method'] = strtoupper((string)$this->‪tableOptionValue());
1451  if (!in_array($options['insert_method'], ['NO', 'FIRST', 'LAST'], true)) {
1452  $this->‪syntaxError('NO, FIRST or LAST', $this->lexer->token);
1453  }
1454  break;
1457  $options['key_block_size'] = (int)$this->‪tableOptionValue();
1458  break;
1459  case ‪Lexer::T_MAX_ROWS:
1461  $options['max_rows'] = (int)$this->‪tableOptionValue();
1462  break;
1463  case ‪Lexer::T_MIN_ROWS:
1465  $options['min_rows'] = (int)$this->‪tableOptionValue();
1466  break;
1467  case ‪Lexer::T_PACK_KEYS:
1469  $options['pack_keys'] = strtoupper((string)$this->‪tableOptionValue());
1470  if (!in_array($options['pack_keys'], ['0', '1', 'DEFAULT'], true)) {
1471  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1472  }
1473  break;
1474  case ‪Lexer::T_PASSWORD:
1476  $options['password'] = (string)$this->‪tableOptionValue();
1477  break;
1480  $options['row_format'] = (string)$this->‪tableOptionValue();
1481  $validRowFormats = ['DEFAULT', 'DYNAMIC', 'FIXED', 'COMPRESSED', 'REDUNDANT', 'COMPACT'];
1482  if (!in_array($options['row_format'], $validRowFormats, true)) {
1483  $this->‪syntaxError(
1484  'DEFAULT, DYNAMIC, FIXED, COMPRESSED, REDUNDANT, COMPACT',
1485  $this->lexer->token
1486  );
1487  }
1488  break;
1491  $options['stats_auto_recalc'] = strtoupper((string)$this->‪tableOptionValue());
1492  if (!in_array($options['stats_auto_recalc'], ['0', '1', 'DEFAULT'], true)) {
1493  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1494  }
1495  break;
1498  $options['stats_persistent'] = strtoupper((string)$this->‪tableOptionValue());
1499  if (!in_array($options['stats_persistent'], ['0', '1', 'DEFAULT'], true)) {
1500  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1501  }
1502  break;
1505  $options['stats_sample_pages'] = strtoupper((string)$this->‪tableOptionValue());
1506  if (!in_array($options['stats_sample_pages'], ['0', '1', 'DEFAULT'], true)) {
1507  $this->‪syntaxError('0, 1 or DEFAULT', $this->lexer->token);
1508  }
1509  break;
1512  $options['tablespace'] = (string)$this->‪tableOptionValue();
1513  break;
1514  default:
1515  $this->‪syntaxError(
1516  'DEFAULT, ENGINE, AUTO_INCREMENT, AVG_ROW_LENGTH, CHARACTER SET, ' .
1517  'CHECKSUM, COLLATE, COMMENT, COMPRESSION, CONNECTION, DATA DIRECTORY, ' .
1518  'DELAY_KEY_WRITE, ENCRYPTION, INDEX DIRECTORY, INSERT_METHOD, KEY_BLOCK_SIZE, ' .
1519  'MAX_ROWS, MIN_ROWS, PACK_KEYS, PASSWORD, ROW_FORMAT, STATS_AUTO_RECALC, ' .
1520  'STATS_PERSISTENT, STATS_SAMPLE_PAGES or TABLESPACE'
1521  );
1522  }
1523  }
1524 
1525  return $options;
1526  }
1527 
1534  protected function ‪tableOptionValue()
1535  {
1536  // Skip the optional equals sign
1537  if ($this->lexer->isNextToken(‪Lexer::T_EQUALS)) {
1538  $this->‪match(‪Lexer::T_EQUALS);
1539  }
1540  $this->lexer->moveNext();
1541 
1542  return $this->lexer->token['value'];
1543  }
1544 
1552  protected function ‪schemaObjectName()
1553  {
1554  $schemaObjectName = $this->lexer->lookahead['value'];
1555  $this->lexer->moveNext();
1556 
1557  return new ‪AST\Identifier((string)$schemaObjectName);
1558  }
1559 }
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateTableClause
Definition: CreateTableClause.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\__construct
‪__construct(string $statement)
Definition: Parser.php:46
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException\semanticalError
‪static StatementException semanticalError(string $message, \Exception $previous=null)
Definition: StatementException.php:51
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BigIntDataType
Definition: BigIntDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TimeDataType
Definition: TimeDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\Identifier
Definition: Identifier.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\VarCharDataType
Definition: VarCharDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NO
‪const T_NO
Definition: Lexer.php:123
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CREATE
‪const T_CREATE
Definition: Lexer.php:82
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_KEY
‪const T_KEY
Definition: Lexer.php:90
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SPATIAL
‪const T_SPATIAL
Definition: Lexer.php:92
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DateTimeDataType
Definition: DateTimeDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PASSWORD
‪const T_PASSWORD
Definition: Lexer.php:145
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FOREIGN
‪const T_FOREIGN
Definition: Lexer.php:131
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BTREE
‪const T_BTREE
Definition: Lexer.php:126
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException
Definition: StatementException.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_USING
‪const T_USING
Definition: Lexer.php:125
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\match
‪match($token)
Definition: Parser.php:85
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ENUM
‪const T_ENUM
Definition: Lexer.php:77
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BitDataType
Definition: BitDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\characterDataTypeOptions
‪array characterDataTypeOptions()
Definition: Parser.php:1128
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\JsonDataType
Definition: JsonDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_HASH
‪const T_HASH
Definition: Lexer.php:127
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DYNAMIC
‪const T_DYNAMIC
Definition: Lexer.php:104
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SIMPLE
‪const T_SIMPLE
Definition: Lexer.php:117
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\fractionalSecondsPart
‪int fractionalSecondsPart()
Definition: Parser.php:1109
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NULL
‪const T_NULL
Definition: Lexer.php:102
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CONNECTION
‪const T_CONNECTION
Definition: Lexer.php:136
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INT
‪const T_INT
Definition: Lexer.php:52
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TEMPORARY
‪const T_TEMPORARY
Definition: Lexer.php:83
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STRING
‪const T_STRING
Definition: Lexer.php:26
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateTableStatement
Definition: CreateTableStatement.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createColumnDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST CreateColumnDefinitionItem createColumnDefinitionItem()
Definition: Parser.php:667
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ON
‪const T_ON
Definition: Lexer.php:118
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INTEGER
‪const T_INTEGER
Definition: Lexer.php:53
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TIME
‪const T_TIME
Definition: Lexer.php:61
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateColumnDefinitionItem
Definition: CreateColumnDefinitionItem.php:26
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TIMESTAMP
‪const T_TIMESTAMP
Definition: Lexer.php:62
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateIndexDefinitionItem
Definition: CreateIndexDefinitionItem.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\VarBinaryDataType
Definition: VarBinaryDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\parse
‪Table[] parse()
Definition: Parser.php:147
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TABLE
‪const T_TABLE
Definition: Lexer.php:84
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_REAL
‪const T_REAL
Definition: Lexer.php:55
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createTableClause
‪TYPO3 CMS Core Database Schema Parser AST CreateTableClause createTableClause()
Definition: Parser.php:326
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\RealDataType
Definition: RealDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BINARY
‪const T_BINARY
Definition: Lexer.php:67
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEMORY
‪const T_MEMORY
Definition: Lexer.php:105
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MIN_ROWS
‪const T_MIN_ROWS
Definition: Lexer.php:143
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateDefinition
Definition: CreateDefinition.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHARACTER
‪const T_CHARACTER
Definition: Lexer.php:110
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyTextDataType
Definition: TinyTextDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_VARCHAR
‪const T_VARCHAR
Definition: Lexer.php:66
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_REFERENCES
‪const T_REFERENCES
Definition: Lexer.php:101
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\valueListItem
‪string valueListItem()
Definition: Parser.php:1225
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PRECISION
‪const T_PRECISION
Definition: Lexer.php:152
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TINYTEXT
‪const T_TINYTEXT
Definition: Lexer.php:73
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STATS_SAMPLE_PAGES
‪const T_STATS_SAMPLE_PAGES
Definition: Lexer.php:149
‪TYPO3\CMS\Core\Database\Schema\Parser\TableBuilder
Definition: TableBuilder.php:43
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FLOAT
‪const T_FLOAT
Definition: Lexer.php:57
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SMALLINT
‪const T_SMALLINT
Definition: Lexer.php:50
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateForeignKeyDefinitionItem
Definition: CreateForeignKeyDefinitionItem.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ENGINE
‪const T_ENGINE
Definition: Lexer.php:132
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SEMICOLON
‪const T_SEMICOLON
Definition: Lexer.php:42
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_UNIQUE
‪const T_UNIQUE
Definition: Lexer.php:94
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHAR
‪const T_CHAR
Definition: Lexer.php:65
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FIXED
‪const T_FIXED
Definition: Lexer.php:103
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PACK_KEYS
‪const T_PACK_KEYS
Definition: Lexer.php:144
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COMMENT
‪const T_COMMENT
Definition: Lexer.php:98
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_JSON
‪const T_JSON
Definition: Lexer.php:79
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\referenceOption
‪string referenceOption()
Definition: Parser.php:1313
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COMMA
‪const T_COMMA
Definition: Lexer.php:30
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser
Definition: Parser.php:28
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\dataTypeLength
‪int dataTypeLength(bool $required=false)
Definition: Parser.php:1025
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TINYINT
‪const T_TINYINT
Definition: Lexer.php:49
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexColumnName
‪TYPO3 CMS Core Database Schema Parser AST IndexColumnName indexColumnName()
Definition: Parser.php:1290
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\referenceDefinition
‪TYPO3 CMS Core Database Schema Parser AST ReferenceDefinition referenceDefinition()
Definition: Parser.php:1241
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\getAST
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateStatement getAST()
Definition: Parser.php:68
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHECKSUM
‪const T_CHECKSUM
Definition: Lexer.php:134
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TextDataType
Definition: TextDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BIT
‪const T_BIT
Definition: Lexer.php:48
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumTextDataType
Definition: MediumTextDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FULL
‪const T_FULL
Definition: Lexer.php:115
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ZEROFILL
‪const T_ZEROFILL
Definition: Lexer.php:108
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_RESTRICT
‪const T_RESTRICT
Definition: Lexer.php:121
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TINYBLOB
‪const T_TINYBLOB
Definition: Lexer.php:69
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyBlobDataType
Definition: TinyBlobDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_KEY_BLOCK_SIZE
‪const T_KEY_BLOCK_SIZE
Definition: Lexer.php:128
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DOUBLE
‪const T_DOUBLE
Definition: Lexer.php:56
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TEXT
‪const T_TEXT
Definition: Lexer.php:74
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_OPEN_PARENTHESIS
‪const T_OPEN_PARENTHESIS
Definition: Lexer.php:29
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException\sqlError
‪static StatementException sqlError(string $sql)
Definition: StatementException.php:29
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\tableOptionValue
‪mixed tableOptionValue()
Definition: Parser.php:1532
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\CharDataType
Definition: CharDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CLOSE_PARENTHESIS
‪const T_CLOSE_PARENTHESIS
Definition: Lexer.php:28
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createIndexDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST CreateIndexDefinitionItem createIndexDefinitionItem()
Definition: Parser.php:441
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DATA
‪const T_DATA
Definition: Lexer.php:137
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\semanticalError
‪semanticalError($message='', $token=null)
Definition: Parser.php:194
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\SetDataType
Definition: SetDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_IF
‪const T_IF
Definition: Lexer.php:85
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexOptions
‪array indexOptions()
Definition: Parser.php:618
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_WITH
‪const T_WITH
Definition: Lexer.php:129
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createDefinition
‪TYPO3 CMS Core Database Schema Parser AST CreateDefinition createDefinition()
Definition: Parser.php:366
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\getLexer
‪Lexer getLexer()
Definition: Parser.php:57
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\IntegerDataType
Definition: IntegerDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DIRECTORY
‪const T_DIRECTORY
Definition: Lexer.php:138
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DECIMAL
‪const T_DECIMAL
Definition: Lexer.php:58
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateDefinitionItem createDefinitionItem()
Definition: Parser.php:401
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException\syntaxError
‪static StatementException syntaxError(string $message, \Exception $previous=null)
Definition: StatementException.php:40
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\valueList
‪array valueList()
Definition: Parser.php:1202
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COLUMN_FORMAT
‪const T_COLUMN_FORMAT
Definition: Lexer.php:99
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INDEX
‪const T_INDEX
Definition: Lexer.php:89
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\columnDefaultValue
‪mixed columnDefaultValue()
Definition: Parser.php:988
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\AbstractDataType
Definition: AbstractDataType.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COMPRESSION
‪const T_COMPRESSION
Definition: Lexer.php:135
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DESC
‪const T_DESC
Definition: Lexer.php:113
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\syntaxError
‪syntaxError($expected='', $token=null)
Definition: Parser.php:170
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\LongTextDataType
Definition: LongTextDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DATE
‪const T_DATE
Definition: Lexer.php:60
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\$statement
‪string $statement
Definition: Parser.php:39
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumIntDataType
Definition: MediumIntDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\FloatDataType
Definition: FloatDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\AbstractCreateStatement
Definition: AbstractCreateStatement.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\free
‪free($deep=false, $position=0)
Definition: Parser.php:124
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DoubleDataType
Definition: DoubleDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DELETE
‪const T_DELETE
Definition: Lexer.php:120
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumBlobDataType
Definition: MediumBlobDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyIntDataType
Definition: TinyIntDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PRIMARY
‪const T_PRIMARY
Definition: Lexer.php:93
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MATCH
‪const T_MATCH
Definition: Lexer.php:114
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BLOB
‪const T_BLOB
Definition: Lexer.php:70
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BinaryDataType
Definition: BinaryDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DecimalDataType
Definition: DecimalDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\peekBeyondClosingParenthesis
‪array peekBeyondClosingParenthesis($resetPeek=true)
Definition: Parser.php:226
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_LONGTEXT
‪const T_LONGTEXT
Definition: Lexer.php:76
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEDIUMBLOB
‪const T_MEDIUMBLOB
Definition: Lexer.php:71
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\IndexColumnName
Definition: IndexColumnName.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PARTIAL
‪const T_PARTIAL
Definition: Lexer.php:116
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\queryLanguage
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateStatement queryLanguage()
Definition: Parser.php:259
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ASC
‪const T_ASC
Definition: Lexer.php:112
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NOT
‪const T_NOT
Definition: Lexer.php:86
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\AbstractCreateDefinitionItem
Definition: AbstractCreateDefinitionItem.php:24
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BlobDataType
Definition: BlobDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\$lexer
‪Lexer $lexer
Definition: Parser.php:33
‪TYPO3\CMS\Core\Database\Schema\Parser
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DATETIME
‪const T_DATETIME
Definition: Lexer.php:63
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_SET
‪const T_SET
Definition: Lexer.php:78
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_IDENTIFIER
‪const T_IDENTIFIER
Definition: Lexer.php:45
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ROW_FORMAT
‪const T_ROW_FORMAT
Definition: Lexer.php:146
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_COLLATE
‪const T_COLLATE
Definition: Lexer.php:111
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CHECK
‪const T_CHECK
Definition: Lexer.php:95
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\LongBlobDataType
Definition: LongBlobDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DEFAULT
‪const T_DEFAULT
Definition: Lexer.php:96
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_YEAR
‪const T_YEAR
Definition: Lexer.php:64
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\columnDataType
‪TYPO3 CMS Core Database Schema Parser AST DataType AbstractDataType columnDataType()
Definition: Parser.php:793
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\numericDataTypeOptions
‪array numericDataTypeOptions()
Definition: Parser.php:1077
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DateDataType
Definition: DateDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\tableOptions
‪array tableOptions()
Definition: Parser.php:1375
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\enumerationDataTypeOptions
‪array enumerationDataTypeOptions()
Definition: Parser.php:1167
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DISK
‪const T_DISK
Definition: Lexer.php:106
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\dataTypeDecimals
‪array dataTypeDecimals()
Definition: Parser.php:1049
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEDIUMTEXT
‪const T_MEDIUMTEXT
Definition: Lexer.php:75
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STATS_PERSISTENT
‪const T_STATS_PERSISTENT
Definition: Lexer.php:148
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MEDIUMINT
‪const T_MEDIUMINT
Definition: Lexer.php:51
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_UPDATE
‪const T_UPDATE
Definition: Lexer.php:119
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\NumericDataType
Definition: NumericDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createForeignKeyDefinitionItem
‪TYPO3 CMS Core Database Schema Parser AST CreateForeignKeyDefinitionItem createForeignKeyDefinitionItem()
Definition: Parser.php:533
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\SmallIntDataType
Definition: SmallIntDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STATS_AUTO_RECALC
‪const T_STATS_AUTO_RECALC
Definition: Lexer.php:147
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_STORAGE
‪const T_STORAGE
Definition: Lexer.php:100
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ENCRYPTION
‪const T_ENCRYPTION
Definition: Lexer.php:140
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\schemaObjectName
‪TYPO3 CMS Core Database Schema Parser AST Identifier schemaObjectName()
Definition: Parser.php:1550
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_VARBINARY
‪const T_VARBINARY
Definition: Lexer.php:68
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CASCADE
‪const T_CASCADE
Definition: Lexer.php:122
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\EnumDataType
Definition: EnumDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createStatement
‪TYPO3 CMS Core Database Schema Parser AST AbstractCreateStatement createStatement()
Definition: Parser.php:284
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\ReferenceDefinition
Definition: ReferenceDefinition.php:25
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_DELAY_KEY_WRITE
‪const T_DELAY_KEY_WRITE
Definition: Lexer.php:139
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_TABLESPACE
‪const T_TABLESPACE
Definition: Lexer.php:150
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexName
‪AST Identifier indexName()
Definition: Parser.php:568
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_NUMERIC
‪const T_NUMERIC
Definition: Lexer.php:59
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_AVG_ROW_LENGTH
‪const T_AVG_ROW_LENGTH
Definition: Lexer.php:133
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\indexType
‪string indexType()
Definition: Parser.php:584
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\YearDataType
Definition: YearDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_ACTION
‪const T_ACTION
Definition: Lexer.php:124
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_UNSIGNED
‪const T_UNSIGNED
Definition: Lexer.php:107
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_EQUALS
‪const T_EQUALS
Definition: Lexer.php:33
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_INSERT_METHOD
‪const T_INSERT_METHOD
Definition: Lexer.php:141
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_FULLTEXT
‪const T_FULLTEXT
Definition: Lexer.php:91
‪TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TimestampDataType
Definition: TimestampDataType.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_AUTO_INCREMENT
‪const T_AUTO_INCREMENT
Definition: Lexer.php:97
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_BIGINT
‪const T_BIGINT
Definition: Lexer.php:54
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_MAX_ROWS
‪const T_MAX_ROWS
Definition: Lexer.php:142
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_EXISTS
‪const T_EXISTS
Definition: Lexer.php:87
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CURRENT_TIMESTAMP
‪const T_CURRENT_TIMESTAMP
Definition: Lexer.php:109
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer
Definition: Lexer.php:23
‪TYPO3\CMS\Core\Database\Schema\Parser\Parser\createTableStatement
‪createTableStatement()
Definition: Parser.php:310
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_PARSER
‪const T_PARSER
Definition: Lexer.php:130
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_LONGBLOB
‪const T_LONGBLOB
Definition: Lexer.php:72
‪TYPO3\CMS\Core\Database\Schema\Parser\Lexer\T_CONSTRAINT
‪const T_CONSTRAINT
Definition: Lexer.php:88