public function convertSqlToJob(SQLTokenIterator $tokens) { $columnDefinition = new ColumnDefinitionJob(); $tokens->seekTokens([T_STRING, T_CONSTANT_ENCAPSED_STRING]); if (!$tokens->isTokens([T_STRING, T_CONSTANT_ENCAPSED_STRING], TokenIterator::CURRENT)) { throw new MalformedSqlException("Missing name for column!", $tokens); } $name = $tokens->getCurrentTokenString(); if ($name[0] === '`' && $name[strlen($name) - 1] === '`') { $name = substr($name, 1, strlen($name) - 2); } if ($name[0] === '"' && $name[strlen($name) - 1] === '"') { $name = substr($name, 1, strlen($name) - 2); } if ($name[0] === "'" && $name[strlen($name) - 1] === "'") { $name = substr($name, 1, strlen($name) - 2); } $columnDefinition->setName($name); # this makes sure that the next token is valid data-type $dataTypeString = strtoupper($tokens->getExclusiveTokenString()); $dataType = DataType::factory($dataTypeString); $columnDefinition->setDataType($dataType); $tokens->seekIndex($tokens->getExclusiveTokenIndex()); # data-type-length if ($tokens->seekTokenText('(')) { if ($dataType === DataType::ENUM() || $dataType === DataType::SET()) { do { if (!$this->valueParser->canParseTokens($tokens)) { throw new MalformedSqlException("Invalid value in ENUM!", $tokens); } $columnDefinition->addEnumValue($this->valueParser->convertSqlToJob($tokens)); } while ($tokens->seekTokenText(',')); } else { if (!$tokens->seekTokenNum(T_NUM_STRING)) { throw new MalformedSqlException("Missing number for length of data-type!", $tokens); } $columnDefinition->setDataTypeLength((int) $tokens->getCurrentTokenString()); if ($tokens->seekTokenText(',')) { if (!$tokens->seekTokenNum(T_NUM_STRING)) { throw new MalformedSqlException("Missing second number for length of data-type!", $tokens); } $columnDefinition->setDataTypeSecondLength((int) $tokens->getCurrentTokenString()); } } if (!$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing end-parenthesis for length of data-type!", $tokens); } } while (true) { switch (true) { case $tokens->seekTokenNum(SqlToken::T_NOT()): if (!$tokens->seekTokenNum(SqlToken::T_NULL())) { throw new MalformedSqlException("Missing T_NULL after T_NOT in column-definition!", $tokens); } $columnDefinition->setIsNullable(false); break; case $tokens->seekTokenNum(SqlToken::T_NULL()): $columnDefinition->setIsNullable(true); break; case $tokens->seekTokenNum(SqlToken::T_DEFAULT()): if (!$this->valueParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid default value for column definition!", $tokens); } $beforeIndex = $tokens->getIndex(); $defaultValue = $this->valueParser->convertSqlToJob($tokens); $afterIndex = $tokens->getIndex(); $defaultSqlRepresentation = ""; for ($index = $beforeIndex + 1; $index <= $afterIndex; $index++) { $defaultSqlRepresentation .= $tokens->getTokenArray()[$index][1]; } $columnDefinition->setDefaultValue($defaultValue); break; case $tokens->seekTokenNum(SqlToken::T_UNIQUE()): $tokens->seekTokenNum(SqlToken::T_KEY()); $columnDefinition->setIsUnique(true); break; case $tokens->seekTokenNum(SqlToken::T_PRIMARY()): $tokens->seekTokenNum(SqlToken::T_KEY()); $columnDefinition->setIsPrimaryKey(true); break; case $tokens->seekTokenNum(SqlToken::T_UNSIGNED()): $columnDefinition->setIsUnsigned(true); break; case $tokens->seekTokenNum(SqlToken::T_COMMENT()): if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING)) { throw new MalformedSqlException("Missing encapsed string for comment-declaration column-definition!", $tokens); } $columnDefinition->setComment($tokens->getCurrentTokenString()); break; case $tokens->seekTokenNum(SqlToken::T_AUTO_INCREMENT()): $columnDefinition->setAutoIncrement(true); break; case $tokens->seekTokenNum(SqlToken::T_CHARACTER(), TokenIterator::NEXT, [SqlToken::T_DEFAULT()]): if (!$tokens->seekTokenNum(SqlToken::T_SET())) { throw new MalformedSqlException("MIssing SET after CHARACTER keyword!", $tokens); } case $tokens->seekTokenNum(SqlToken::T_CHARSET(), TokenIterator::NEXT, [SqlToken::T_DEFAULT()]): $tokens->seekTokenText('='); if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING) && !$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing string for CHARACTER SET!", $tokens); } $columnDefinition->setCharacterSet($tokens->getCurrentTokenString()); break; case $tokens->seekTokenNum(SqlToken::T_COLLATE()): $tokens->seekTokenText('='); if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING) && !$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing string for COLLATE!", $tokens); } $columnDefinition->setCollate($tokens->getCurrentTokenString()); break; case $tokens->seekTokenNum(SqlToken::T_ON()): switch (true) { case $tokens->seekTokenNum(SqlToken::T_UPDATE()): switch (true) { case $this->valueParser->canParseTokens($tokens): $columnDefinition->setOnUpdate($this->valueParser->convertSqlToJob($tokens)); break; default: throw new MalformedSqlException("Invalid value for ON UPDATE!", $tokens); } break; case $tokens->seekTokenNum(SqlToken::T_DELETE()): switch (true) { case $this->valueParser->canParseTokens($tokens): $columnDefinition->setOnDelete($this->valueParser->convertSqlToJob($tokens)); break; default: throw new MalformedSqlException("Invalid value for ON UPDATE!", $tokens); } break; default: throw new MalformedSqlException("Only UPDATE and DELETE allowed for ON trigger!", $tokens); } break; case is_int($tokens->isTokenText(')')): case is_int($tokens->isTokenText(',')): break 2; default: break 2; } } return $columnDefinition; }
public function convertSqlToJob(SQLTokenIterator $tokens) { $alterJob = new AlterStatement(); $tokens->seekTokenNum(SqlToken::T_ALTER()); if ($tokens->getCurrentTokenNumber() !== SqlToken::T_ALTER()) { throw new ErrorException("Tried to parse an ALTER statement when token-iterator does not point to T_ALTER!"); } $alterJob->setDoIgnoreErrors($tokens->seekTokenNum(SqlToken::T_IGNORE())); if (!$tokens->seekTokenNum(SqlToken::T_TABLE())) { throw new MalformedSqlException("Missing TABLE for ALTER statement!", $tokens); } if (!$this->tableParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing Table-Specifier for ALTER TABLE statement!"); } $alterJob->setTable($this->tableParser->convertSqlToJob($tokens)); $dataChange = new AlterTableDataChange(); do { switch (true) { case $tokens->seekTokenNum(SqlToken::T_ADD()): $isInParenthesises = $tokens->seekTokenText('('); do { switch (true) { case $tokens->seekTokenNum(SqlToken::T_COLUMN()): if ($tokens->seekTokenText('(')) { do { if (!$this->columnDefinitionParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column definition after ALTER TABLE ADD COLUMN!", $tokens); } $dataChange->setAttribute(AlterAttributeType::ADD()); $dataChange->setSubjectColumnDefinition($this->columnDefinitionParser->convertSqlToJob($tokens)); $alterJob->addDataChange(clone $dataChange); } while ($tokens->seekTokenText(',')); if (!$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing ending parenthesis after column list", $tokens); } } else { if (!$this->columnDefinitionParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column definition after ALTER TABLE ADD COLUMN!", $tokens); } $dataChange->setAttribute(AlterAttributeType::ADD()); $dataChange->setSubjectColumnDefinition($this->columnDefinitionParser->convertSqlToJob($tokens)); $alterJob->addDataChange(clone $dataChange); } break; case $this->columnDefinitionParser->canParseTokens($tokens): $dataChange->setAttribute(AlterAttributeType::ADD()); $dataChange->setSubjectColumnDefinition($this->columnDefinitionParser->convertSqlToJob($tokens)); $alterJob->addDataChange(clone $dataChange); break; case $tokens->seekTokenNum(SqlToken::T_PRIMARY(), TokenIterator::NEXT, [SqlToken::T_CONSTRAINT(), T_STRING]): case $tokens->seekTokenNum(SqlToken::T_UNIQUE(), TokenIterator::NEXT, [SqlToken::T_CONSTRAINT(), T_STRING]): case $tokens->seekTokenNum(SqlToken::T_FOREIGN(), TokenIterator::NEXT, [SqlToken::T_CONSTRAINT(), T_STRING]): case $tokens->seekTokenNum(SqlToken::T_FULLTEXT()): case $tokens->seekTokenNum(SqlToken::T_SPATIAL()): case $tokens->seekTokenNum(SqlToken::T_INDEX()): $indexJob = new IndexJob(); if ($tokens->isTokenNum(SqlToken::T_CONSTRAINT(), TokenIterator::PREVIOUS)) { $beforeIndex = $tokens->getIndex(); if (!$tokens->seekTokenNum(T_STRING, TokenIterator::PREVIOUS)) { throw new MalformedSqlException("Missing constraing-symbol T_STRING after T_CONSTRAINT!", $tokens); } $indexJob->setContraintSymbol($tokens->getCurrentTokenString()); $tokens->seekIndex($beforeIndex); } $needsReferenceDefinition = false; switch ($tokens->getCurrentTokenNumber()) { case SqlToken::T_PRIMARY(): $indexJob->setIsPrimary(true); $indexJob->setName("PRIMARY"); if (!$tokens->seekTokenNum(SqlToken::T_KEY())) { throw new MalformedSqlException("Missing T_KEY after T_FOREIGN!", $tokens); } break; case SqlToken::T_UNIQUE(): $indexJob->setIsUnique(true); $tokens->seekTokenNum(SqlToken::T_INDEX()); break; case SqlToken::T_FOREIGN(): if (!$tokens->seekTokenNum(SqlToken::T_KEY())) { throw new MalformedSqlException("Missing T_KEY after T_FOREIGN!", $tokens); } $needsReferenceDefinition = true; break; case SqlToken::T_FULLTEXT(): $indexJob->setIsFullText(true); break; case SqlToken::T_SPATIAL(): $indexJob->setIsSpatial(true); break; } if (!$indexJob->getIsPrimary() && $tokens->seekTokenNum(T_STRING)) { $indexJob->setName($tokens->getCurrentTokenString()); } if ($tokens->seekTokenNum(T_STRING)) { $indexJob->setType(IndexType::factory(strtoupper($tokens->getCurrentTokenString()))); } if (!$tokens->seekTokenText('(')) { throw new MalformedSqlException("Missing beginning parenthesis for defining columns for PRIMARY KEY index!", $tokens); } do { if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Invalid column-specifier in defining columns for PRIMARY KEY index!", $tokens); } $indexJob->addColumn($this->columnParser->convertSqlToJob($tokens)); } while ($tokens->seekTokenText(',')); if (!$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing ending parenthesis for defining columns for PRIMARY KEY index!", $tokens); } if ($needsReferenceDefinition) { if (!$tokens->seekTokenNum(SqlToken::T_REFERENCES())) { throw new MalformedSqlException("Missing reference-definition in foreign-constraint-definition!", $tokens); } if (!$this->tableParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing table-definition in foreign-constraint-definition!", $tokens); } $fkTable = $this->tableParser->convertSqlToJob($tokens); # columns in index if ($tokens->seekTokenText('(')) { do { if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Invalid column in column-list for defining index!", $tokens); } $fkColumn = $this->columnParser->convertSqlToJob($tokens); $indexJob->addForeignKey(Column::factory("{$fkTable}.{$fkColumn->getColumn()}")); } while ($tokens->seekTokenText(',')); if (!$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing closing parenthesis at column-list for index!", $tokens); } } if ($tokens->seekTokenNum(SqlToken::T_MATCH())) { switch (true) { case $tokens->seekTokenNum(SqlToken::T_FULL()): $indexJob->setForeignKeyMatchType(MatchType::FULL()); break; case $tokens->seekTokenNum(SqlToken::T_PARTIAL()): $indexJob->setForeignKeyMatchType(MatchType::PARTIAL()); break; case $tokens->seekTokenNum(SqlToken::T_SIMPLE()): $indexJob->setForeignKeyMatchType(MatchType::SIMPLE()); break; default: throw new MalformedSqlException("Invalid match parameter for foreign key!", $tokens); } } while ($tokens->seekTokenNum(SqlToken::T_ON())) { switch (true) { case $tokens->seekTokenNum(SqlToken::T_DELETE()): switch (true) { case $tokens->seekTokenNum(SqlToken::T_RESTRICT()): $indexJob->setForeignKeyOnDeleteReferenceOption(ReferenceOption::RESTRICT()); break; case $tokens->seekTokenNum(SqlToken::T_CASCADE()): $indexJob->setForeignKeyOnDeleteReferenceOption(ReferenceOption::CASCADE()); break; case $tokens->seekTokenNum(SqlToken::T_SET()) && $tokens->seekTokenNum(SqlToken::T_NULL()): $indexJob->setForeignKeyOnDeleteReferenceOption(ReferenceOption::SET_NULL()); break; case $tokens->seekTokenNum(SqlToken::T_NO()) && $tokens->seekTokenText('ACTION'): $indexJob->setForeignKeyOnDeleteReferenceOption(ReferenceOption::NO_ACTION()); break; default: throw new MalformedSqlException("Invalid reference-option for foreign key ON DELETE option!", $tokens); } break; case $tokens->seekTokenNum(SqlToken::T_UPDATE()): switch (true) { case $tokens->seekTokenNum(SqlToken::T_RESTRICT()): $indexJob->setForeignKeyOnUpdateReferenceOption(ReferenceOption::RESTRICT()); break; case $tokens->seekTokenNum(SqlToken::T_CASCADE()): $indexJob->setForeignKeyOnUpdateReferenceOption(ReferenceOption::CASCADE()); break; case $tokens->seekTokenNum(SqlToken::T_SET()) && $tokens->seekTokenNum(SqlToken::T_NULL()): $indexJob->setForeignKeyOnUpdateReferenceOption(ReferenceOption::SET_NULL()); break; case $tokens->seekTokenNum(SqlToken::T_NO()) && $tokens->seekTokenText('ACTION'): $indexJob->setForeignKeyOnUpdateReferenceOption(ReferenceOption::NO_ACTION()); break; default: throw new MalformedSqlException("Invalid reference-option for foreign key ON UPDATE option!", $tokens); } break; default: throw new MalformedSqlException("Invalid ON event for foreign key (allowed are UPDATE and DELETE)!", $tokens); } } } $dataChange->setAttribute(AlterAttributeType::ADD()); $dataChange->setSubjectIndex($indexJob); $alterJob->addDataChange(clone $dataChange); break; } } while ($isInParenthesises && $tokens->seekTokenText(',')); if ($isInParenthesises && !$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing closing parenthesis after ALTER ADD statement!", $tokens); } break; case $tokens->seekTokenNum(SqlToken::T_ALTER()): $tokens->seekTokenNum(SqlToken::T_COLUMN()); if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column-specification for ALTER COLUMN statement!", $tokens); } $dataChange->setAttribute(AlterAttributeType::DEFAULT_VALUE()); $dataChange->setSubject($this->columnParser->convertSqlToJob($tokens)); switch (true) { case $tokens->seekTokenNum(SqlToken::T_SET()): if (!$tokens->seekTokenNum(SqlToken::T_DEFAULT())) { throw new MalformedSqlException("Missing T_DEFAULT for ALTER TABLE ALTER COLUMN SET DEFAULT statement", $tokens); } if (!$this->valueParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing new valid value for DEFAULT value!"); } $dataChange->setValue($this->valueParser->convertSqlToJob($tokens)); break; case $tokens->seekTokenNum(SqlToken::T_DROP()): if (!$tokens->seekTokenNum(SqlToken::T_DEFAULT())) { throw new MalformedSqlException("Missing T_DEFAULT for ALTER TABLE ALTER COLUMN SET DEFAULT statement", $tokens); } $dataChange->setValue(null); break; default: throw new MalformedSqlException("Invalid action (SET or DROP) for ALTER TABLE ALTER COLUMN statement!", $tokens); } $alterJob->addDataChange(clone $dataChange); break; case $tokens->seekTokenNum(SqlToken::T_CHANGE()): $dataChange->setAttribute(AlterAttributeType::MODIFY()); $tokens->seekTokenNum(SqlToken::T_COLUMN()); if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column-specification for ALTER TABLE CHANGE COLUMN statement!", $tokens); } $dataChange->setSubject($this->columnParser->convertSqlToJob($tokens)); if (!$this->columnDefinitionParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid column-definiton for ALTER TABLE CHANGE COLUMN statement!", $tokens); } $dataChange->setValue($this->columnDefinitionParser->convertSqlToJob($tokens)); switch (true) { case $tokens->seekTokenNum(SqlToken::T_FIRST()): $dataChange->setAttribute(AlterAttributeType::SET_FIRST()); break; case $tokens->seekTokenNum(SqlToken::T_AFTER()): $dataChange->setAttribute(AlterAttributeType::SET_AFTER()); if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column specifier for ALTER TABLE CHANGE COLUMN AFTER statement!", $tokens); } $dataChange->setValue($this->columnParser->convertSqlToJob($tokens)); break; } $alterJob->addDataChange(clone $dataChange); break; case $tokens->seekTokenNum(SqlToken::T_MODIFY()): $dataChange->setAttribute(AlterAttributeType::MODIFY()); $tokens->seekTokenNum(SqlToken::T_COLUMN()); if (!$this->columnDefinitionParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid column definition for ALTER TABLE MODIFY COLUMN statement!", $tokens); } $dataChange->setSubjectColumnDefinition($this->columnDefinitionParser->convertSqlToJob($tokens)); switch (true) { case $tokens->seekTokenNum(SqlToken::T_FIRST()): $dataChange->setAttribute(AlterAttributeType::SET_FIRST()); break; case $tokens->seekTokenNum(SqlToken::T_AFTER()): $dataChange->setAttribute(AlterAttributeType::SET_AFTER()); if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column specifier for ALTER TABLE MODIFY COLUMN AFTER statement!", $tokens); } $dataChange->setValue($this->columnParser->convertSqlToJob($tokens)); break; } $alterJob->addDataChange(clone $dataChange); break; case $tokens->seekTokenNum(SqlToken::T_DROP()): $dataChange->setAttribute(AlterAttributeType::DROP()); switch (true) { case $tokens->seekTokenNum(SqlToken::T_COLUMN()): if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid column specificator for ALTER TABLE DROP COLUMN statement!", $tokens); } $dataChange->setSubject($this->columnParser->convertSqlToJob($tokens)); break; case $this->columnParser->canParseTokens($tokens): $dataChange->setSubject($this->columnParser->convertSqlToJob($tokens)); break; case $tokens->seekTokenNum(SqlToken::T_PRIMARY()): if (!$tokens->seekTokenNum(SqlToken::T_KEY())) { throw new MalformedSqlException("Missing T_KEY after T_PRIMARY for ALTER TABLE DROP PRIMARY KEY statement!"); } $dataChange->setSubject(Index::factory("PRIMARY")); break; case $tokens->seekTokenNum(SqlToken::T_FOREIGN()): if (!$tokens->seekTokenNum(SqlToken::T_KEY())) { throw new MalformedSqlException("Missing T_KEY after T_FOREIGN for ALTER TABLE DROP FOREIGN KEY statement!", $tokens); } case $tokens->seekTokenNum(SqlToken::T_INDEX()): if (!$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing index name for ALTER TABLE DROP INDEX statement!", $tokens); } $dataChange->setSubject(Index::factory($tokens->getCurrentTokenString())); break; } $alterJob->addDataChange(clone $dataChange); break; case $tokens->seekTokenNum(SqlToken::T_DISABLE()): $alterJob->setAction(Action::DISABLE()); if (!$tokens->seekTokenText(SqlToken::T_KEYS())) { throw new MalformedSqlException("Missing T_KEYS after T_DISABLE!", $tokens); } break; case $tokens->seekTokenNum(SqlToken::T_ENABLE()): $alterJob->setAction(Action::ENABLE()); if (!$tokens->seekTokenText(SqlToken::T_KEYS())) { throw new MalformedSqlException("Missing T_KEYS after T_DISABLE!", $tokens); } break; case $tokens->seekTokenNum(SqlToken::T_RENAME()): if (!$tokens->seekTokenNum(SqlToken::T_TO())) { throw new MalformedSqlException("Missing T_TO after T_RENAME for ALTER TABLE RENAME TO statement!", $tokens); } if (!$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing new table-name for ALTER TABLE RENAME TO statement!", $tokens); } $dataChange->setAttribute(AlterAttributeType::RENAME()); $dataChange->setValue($tokens->getCurrentTokenString()); $alterJob->addDataChange(clone $dataChange); break; case $tokens->seekTokenNum(SqlToken::T_ORDER()): if (!$tokens->seekTokenNum(SqlToken::T_BY())) { throw new MalformedSqlException("Missing BY after ORDER in ALTER TABLE ORDER BY statement!", $tokens); } if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing column specifier for ALTER TABLE ORDER BY statement!", $tokens); } $dataChange->setSubject($this->columnParser->convertSqlToJob($tokens)); switch (true) { case $tokens->seekTokenNum(SqlToken::T_DESC()): $dataChange->setAttribute(AlterAttributeType::ORDER_BY_DESC()); break; default: case $tokens->seekTokenNum(SqlToken::T_ASC()): $dataChange->setAttribute(AlterAttributeType::ORDER_BY_ASC()); break; } break; case $tokens->seekTokenNum(SqlToken::T_CHARACTER(), TokenIterator::NEXT, [SqlToken::T_DEFAULT()]): case $tokens->seekTokenNum(SqlToken::T_CHARACTER(), TokenIterator::NEXT, [SqlToken::T_CONVERT(), SqlToken::T_TO()]): if (!$tokens->seekTokenNum(SqlToken::T_SET())) { throw new MalformedSqlException("Missing T_SET after T_CHARACTER for ALTER TABLE CONVERT TO CHARACTER SET statement!", $tokens); } if (!$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing character-set specifier for ALTER TABLE CONVERT TO CHARACTER SET statement!", $tokens); } $dataChange->setAttribute(AlterAttributeType::CHARACTER_SET()); $dataChange->setValue($tokens->getCurrentTokenString()); $alterJob->addDataChange(clone $dataChange); if ($tokens->seekTokenNum(SqlToken::T_COLLATE())) { if (!$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing collation-specifier for ALTER TABLE CONVERT TO CHARACTER SET COLLATE statement!", $tokens); } $dataChange->setAttribute(AlterAttributeType::COLLATE()); $dataChange->setValue($tokens->getCurrentTokenString()); $alterJob->addDataChange(clone $dataChange); } break; case $tokens->seekTokenNum(SqlToken::T_DISCARD()): case $tokens->seekTokenNum(SqlToken::T_IMPORT()): if (!$tokens->seekTokenNum(SqlToken::T_TABLESPACE())) { throw new MalformedSqlException("Missing T_TABLESPACE after T_DISCARD or T_IMPORT!", $tokens); } break; } } while ($tokens->seekTokenText(',')); return $alterJob; }
/** * This parses a CREATE INDEX statement. */ protected function parseCreateIndex(SQLTokenIterator $tokens) { /* @var $entity CreateIndexStatement */ $entity = new CreateIndexStatement(); ### FLAGS if ($tokens->isToken(SqlToken::T_UNIQUE(), TokenIterator::PREVIOUS, [SqlToken::T_PRIMARY()])) { $entity->setIsUnique(true); } if ($tokens->isToken(SqlToken::T_PRIMARY(), TokenIterator::PREVIOUS, [SqlToken::T_UNIQUE()])) { $entity->setIsPrimary(true); } ### NAME if (!$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing valid index-name!", $tokens); } $entity->setName($tokens->getCurrentTokenString()); ### USING if ($tokens->seekTokenNum(SqlToken::T_USING())) { switch (true) { // TODO: R-TREE index not implemented yet! case $tokens->seekTokenNum(SqlToken::T_RTREE()): case $tokens->seekTokenNum(SqlToken::T_BTREE()): $entity->setIndexType(IndexType::BTREE()); break; case $tokens->seekTokenNum(SqlToken::T_HASH()): $entity->setIndexType(IndexType::HASH()); break; default: throw new MalformedSqlException("Invalid index-type specified!", $tokens); } } ### TABLE if (!$tokens->seekTokenNum(SqlToken::T_ON())) { throw new MalformedSqlException("Missing T_ON for CREATE INDEX statement!", $tokens); } if (!$this->tableParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid table-specifier for CREATE INDEX statement!", $tokens); } $entity->setTable($this->tableParser->convertSqlToJob($tokens)); ### COLUMNS if (!$tokens->seekTokenText('(')) { throw new MalformedSqlException("Missing beginning parenthesis holding columns in CREATE INDEX statement!", $tokens); } do { if (!$this->columnParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid column-specifier in CREATE INDEX statement!", $tokens); } $column = $this->columnParser->convertSqlToJob($tokens); $length = null; if ($tokens->seekTokenText('(')) { if (!$this->valueParser->canParseTokens($tokens)) { throw new MalformedSqlException("Missing valid column-length in CREATE INDEX statement!", $tokens); } $length = $this->valueParser->convertSqlToJob($tokens); if (!$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing closing parenthesis holding column-length in CREATE INDEX statement!", $tokens); } } $direction = null; if ($tokens->seekTokenNum(SqlToken::T_ASC())) { $direction = SqlToken::T_ASC(); } elseif ($tokens->seekTokenNum(SqlToken::T_DESC())) { $direction = SqlToken::T_DESC(); } $entity->addColumn($column, $length, $direction); } while ($tokens->seekTokenText(',')); if (!$tokens->seekTokenText(')')) { throw new MalformedSqlException("Missing closing parenthesis holding columns in CREATE INDEX statement!", $tokens); } ### WITH PARSER if ($tokens->seekTokenNum(SqlToken::T_WITH())) { if (!$tokens->seekTokenNum(SqlToken::T_PARSER())) { throw new MalformedSqlException("Missing T_PARSER after T_WITH in CREATE INDEX statement!", $tokens); } if (!$tokens->seekTokenNum(T_STRING)) { throw new MalformedSqlException("Missing valid parser name after WITH PARSER in CREATE INDEX statement!", $tokens); } $entity->setParser($tokens->getCurrentTokenString()); } return $entity; }