Example #1
0
 public function getLastParameter()
 {
     if (is_null($this->lastParameter)) {
         $this->setLastParameter(SqlToken::T_TRUE());
     }
     return $this->lastParameter;
 }
Example #2
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_USE());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_USE()) {
         throw new MalformedSqlException("Tried to parse USE statement when token-iterator does not point to T_USE!", $tokens);
     }
     if ($tokens->seekTokenNum(T_VARIABLE)) {
         $databaseName = Variable::factory($tokens->getCurrentTokenString());
     } elseif ($tokens->seekTokenNum(T_STRING)) {
         $databaseName = $tokens->getCurrentTokenString();
     } elseif ($tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING)) {
         $databaseName = $tokens->getCurrentTokenString();
         if (($databaseName[0] === '"' || $databaseName[0] === "'") && $databaseName[0] === $databaseName[strlen($databaseName) - 1]) {
             // remove quotes if needed
             $databaseName = substr($databaseName, 1, strlen($databaseName) - 2);
         }
     } else {
         throw new MalformedSqlException("Missing database-specifier for USE statement!", $tokens);
     }
     $databaseNameValue = new ValuePart();
     $databaseNameValue->addChainValue($databaseName);
     $useJob = new UseStatement();
     $useJob->setDatabase($databaseNameValue);
     return $useJob;
 }
Example #3
0
 public function getOrderDirection()
 {
     if (is_null($this->orderDirection)) {
         $this->orderDirection = SqlToken::T_ASC();
     }
     return $this->orderDirection;
 }
Example #4
0
 public function convertSqlToJob(SQLTokenIterator $tokens, &$skipChecks = 0)
 {
     $likeCondition = new LikeConditionJob();
     $likeCondition->setIsNegated($tokens->seekTokenNum(SqlToken::T_NOT()));
     if (!$tokens->seekTokenNum(SqlToken::T_LIKE())) {
         throw new ErrorException("Missing [NOT] LIKE after value when parsing LIKE condition! (not used 'canParseTokens'?)");
     }
     return $likeCondition;
 }
Example #5
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $statement = null;
     if ($tokens->seekTokenNum(SqlToken::T_COMMIT())) {
         $statement = new CommitStatement();
     } else {
         throw new MalformedSqlException("Tried to parse COMMIT statement when token-iterator does not point to T_COMMIT!", $tokens);
     }
     return $statement;
 }
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $statement = null;
     if ($tokens->seekTokenNum(SqlToken::T_TRANSACTION(), SQLTokenIterator::NEXT, [SqlToken::T_START()])) {
         $statement = new StartTransactionStatement();
     } else {
         throw new MalformedSqlException("Tried to parse START TRANSACTION statement when token-iterator does not point to T_START!", $tokens);
     }
     return $statement;
 }
Example #7
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $statement = null;
     $tokens->seekTokenNum(SqlToken::T_ROLLBACK());
     if ($tokens->getCurrentTokenNumber() === SqlToken::T_ROLLBACK()) {
         $statement = new RollbackStatement();
     } else {
         throw new MalformedSqlException("Tried to parse ROLLBACK statement when token-iterator does not point to T_ROLLBACK!", $tokens);
     }
     return $statement;
 }
Example #8
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_DROP());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_DROP()) {
         throw new ErrorException("Tried to parse sql-drop when token-iterator does not point to T_DROP!");
     }
     $dropJob = new DropStatement();
     if ($tokens->seekTokenNum(SqlToken::T_TEMPORARY())) {
         $dropJob->setIsTemporary(true);
     }
     switch (true) {
         case $tokens->seekTokenNum(SqlToken::T_SCHEMA(), TokenIterator::NEXT):
         case $tokens->seekTokenNum(SqlToken::T_DATABASE()):
             $dropJob->setType(DropStatement::TYPE_DATABASE);
             break;
         case $tokens->seekTokenNum(SqlToken::T_TABLE()):
             $dropJob->setType(DropStatement::TYPE_TABLE);
             break;
         case $tokens->seekTokenNum(SqlToken::T_VIEW()):
             $dropJob->setType(DropStatement::TYPE_VIEW);
             break;
     }
     if ($tokens->seekTokenNum(SqlToken::T_IF())) {
         if (!$tokens->seekTokenNum(SqlToken::T_EXISTS())) {
             throw new MalformedSqlException("Malformed drop-statement (missing T_EXISTS after T_IF)!");
         }
         $dropJob->setOnlyIfExist(true);
     } else {
         $dropJob->setOnlyIfExist(false);
     }
     do {
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing a subject to drop for T_DROP statement!", $tokens);
         }
         $subject = $this->valueParser->convertSqlToJob($tokens);
         $dropJob->addSubject($subject);
     } while ($tokens->seekTokenText(','));
     if ($tokens->seekTokenNum(SqlToken::T_RESTRICT())) {
         $dropJob->setReferenceOption(ReferenceOption::RESTRICT());
         if ($tokens->seekTokenNum(SqlToken::T_CASCADE())) {
             throw new MalformedSqlException("Conflicting T_RESTRICT with T_CASCADE!", $tokens);
         }
     }
     if ($tokens->seekTokenNum(SqlToken::T_CASCADE())) {
         $dropJob->setReferenceOption(ReferenceOption::CASCADE());
         if ($tokens->seekTokenNum(SqlToken::T_RESTRICT())) {
             throw new MalformedSqlException("Conflicting T_RESTRICT with T_CASCADE!", $tokens);
         }
     }
     return $dropJob;
 }
Example #9
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_CASE());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_CASE()) {
         throw new ErrorException("Tried to parse CASE statement when token-iterator is not at CASE!");
     }
     $caseJob = new CaseJob();
     if (!$tokens->isTokenNum(SqlToken::T_WHEN()) && $this->valueParser->canParseTokens($tokens)) {
         $caseJob->setCaseValue($this->valueParser->convertSqlToJob($tokens));
     }
     do {
         if (!$tokens->seekTokenNum(SqlToken::T_WHEN())) {
             throw new MalformedSqlException("Missing WHEN in CASE statement!", $tokens);
         }
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing valid when-value in CASE statement!", $tokens);
         }
         $whenValue = $this->valueParser->convertSqlToJob($tokens);
         if (!$tokens->seekTokenNum(SqlToken::T_THEN())) {
             throw new MalformedSqlException("Missing THEN in CASE statement!", $tokens);
         }
         switch (true) {
             case $this->valueParser->canParseTokens($tokens):
                 $thenExpression = $this->valueParser->convertSqlToJob($tokens);
                 break;
             default:
                 throw new MalformedSqlException("Missing valid THEN statement for CASE statement!", $tokens);
         }
         $caseJob->addWhenThenStatement($whenValue, $thenExpression);
     } while ($tokens->isTokenNum(SqlToken::T_WHEN()));
     if ($tokens->seekTokenNum(SqlToken::T_ELSE())) {
         switch (true) {
             case $this->valueParser->canParseTokens($tokens):
                 $caseJob->setElseStatement($this->valueParser->convertSqlToJob($tokens));
                 break;
             default:
                 throw new MalformedSqlException("Missing valid THEN statement for CASE statement!", $tokens);
         }
     }
     if (!$tokens->seekTokenNum(SqlToken::T_END())) {
         throw new MalformedSqlException("Missing END at the end of for CASE statement!", $tokens);
     }
     $tokens->seekTokenNum(SqlToken::T_CASE());
     return $caseJob;
 }
Example #10
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_SET());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_SET()) {
         throw new ErrorException("Tried to parse SET statement when token-iterator is not at T_SET!");
     }
     $setJob = new SetStatement();
     if (!$tokens->seekTokenNum(T_STRING)) {
         throw new MalformedSqlException("Missing configuration name for SET statement!", $tokens);
     }
     $setJob->setKey($tokens->getCurrentTokenString());
     $tokens->seekTokenText('=');
     if (!$this->valueParser->canParseTokens($tokens)) {
         throw new MalformedSqlException("Missing valid value definition for SET statement!", $tokens);
     }
     $setJob->setValue($this->valueParser->convertSqlToJob($tokens));
     return $setJob;
 }
Example #11
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_DESCRIBE());
     $tokens->seekTokenNum(SqlToken::T_DESC());
     if (!in_array($tokens->getCurrentTokenNumber(), [SqlToken::T_DESCRIBE(), SqlToken::T_DESC()])) {
         throw new ErrorException("Tried to parse DESCRIBE statement when token-iterator does not point to DESC or DESCRIBE!");
     }
     if (!$this->tableParser->canParseTokens($tokens)) {
         throw new MalformedSqlException("Missing table-specifier for DESCRIBE statement!", $tokens);
     }
     $describeJob = new DescribeStatement();
     $describeJob->setTable($this->tableParser->convertSqlToJob($tokens));
     if ($tokens->seekTokenText('wild')) {
         $describeJob->setIsWild(true);
     } elseif ($tokens->seekTokenNum(T_STRING)) {
         $describeJob->setColumnName($tokens->getCurrentTokenString());
     }
     return $describeJob;
 }
Example #12
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     /* @var $valueParser ValueParser */
     $valueParser = $this->valueParser;
     $tokens->seekTokenNum(SqlToken::T_SHOW());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_SHOW()) {
         throw new ErrorException("Tried to convert sql-show to job-entity when tokeniterator does not point to T_SHOW!");
     }
     $showJob = new ShowStatement();
     if ($tokens->seekTokenNum(SqlToken::T_FULL())) {
         $showJob->setIsFull(true);
     }
     switch (true) {
         case $tokens->seekTokenNum(SqlToken::T_DATABASES()):
             $showJob->setType(ShowType::DATABASES());
             break;
         case $tokens->seekTokenNum(SqlToken::T_TABLES()):
             $showJob->setType(ShowType::TABLES());
             break;
         case $tokens->seekTokenNum(SqlToken::T_VIEWS()):
             $showJob->setType(ShowType::VIEWS());
             break;
         default:
             throw new MalformedSqlException("Invalid parameter for show-statement!", $tokens);
     }
     if ($tokens->seekTokenNum(SqlToken::T_FROM())) {
         if (!$tokens->seekTokenNum(T_STRING)) {
             throw new MalformedSqlException("Missing database name after FROM in SHOW statement!");
         }
         $showJob->setDatabase($tokens->getCurrentTokenString());
     }
     if ($tokens->seekTokenNum(SqlToken::T_WHERE())) {
         if (!$valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing valid condition-value after WHERE in SHOW statement!");
         }
         /* @var $conditionValue ValuePart */
         $conditionValue = $valueParser->convertSqlToJob($tokens);
         $showJob->setConditionValue($conditionValue);
     }
     return $showJob;
 }
Example #13
0
 public function convertSqlToJob(SQLTokenIterator $tokens, &$checkFlags = 0)
 {
     if (!$tokens->seekTokenNum(SqlToken::T_IN(), TokenIterator::NEXT, [SqlToken::T_NOT()])) {
         throw new ErrorException("Missing IN after string when tried to parse IN-condition! (was 'canParseTokens' not used?)");
     }
     $enumConditionJob = new EnumConditionJob();
     $enumConditionJob->setIsNegated($tokens->isTokenNum(SqlToken::T_NOT(), TokenIterator::PREVIOUS));
     if (!$tokens->seekTokenText('(')) {
         throw new MalformedSqlException("Missing beginning parenthesis for IN condition!", $tokens);
     }
     do {
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing valid value in value-listing for IN condition!", $tokens);
         }
         $enumConditionJob->addValue($this->valueParser->convertSqlToJob($tokens));
     } while ($tokens->seekTokenText(','));
     if (!$tokens->seekTokenText(')')) {
         throw new MalformedSqlException("Missing ending parenthesis for IN condition!", $tokens);
     }
     return $enumConditionJob;
 }
Example #14
0
 public function getSortIndexByColumns(array $orderColumns)
 {
     $insertionSortFile = new FileResourceProxy(fopen("php://memory", "w"));
     $columnPage = new ColumnSchema();
     $columnPages = array();
     foreach ($orderColumns as $columnIndex => $columnDataset) {
         if ($columnDataset instanceof Column) {
             $direction = 'ASC';
             $columnPage = $columnDataset;
         } else {
             $direction = $columnDataset['direction'] === SqlToken::T_ASC() ? 'ASC' : 'DESC';
             /* @var $value Value */
             $value = $columnDataset['value'];
             $columnPage->setDataType(DataType::VARCHAR());
             # TODO: get actual column-page if possible
             $columnPage->setLength(64);
             $columnPage->setName("INDEXVALUE_{$columnIndex}");
         }
         $columnPages[] = [clone $columnPage, $direction];
     }
     $sortIndex = new QuickSort($insertionSortFile, $columnPages);
     return $sortIndex;
 }
Example #15
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_INSERT());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_INSERT()) {
         throw new ErrorException("Tried to parse INSERT statement when token-iterator is not at INSERT!");
     }
     $dataChange = new InsertDataChange();
     $insertJob = new InsertStatement();
     switch (true) {
         case $tokens->seekTokenNum(SqlToken::T_LOW_PRIORITY()):
             $insertJob->setPriority(Priority::LOW_PRIORITY());
             break;
         case $tokens->seekTokenNum(SqlToken::T_DELAYED()):
             $insertJob->setPriority(Priority::DELAYED());
             break;
         case $tokens->seekTokenNum(SqlToken::T_HIGH_PRIORITY()):
             $insertJob->setPriority(Priority::HIGH_PRIORITY());
             break;
     }
     if ($tokens->seekTokenNum(SqlToken::T_IGNORE())) {
         $insertJob->setDoIgnoreErrors(true);
     }
     if (!$tokens->seekTokenNum(SqlToken::T_INTO())) {
         throw new MalformedSqlException("Missing INTO after INSERT for INSERT INTO statement!", $tokens);
     }
     if (!$this->tableParser->canParseTokens($tokens)) {
         throw new MalformedSqlException("Missing table-specifier for INSERT INTO statement!", $tokens);
     }
     $insertJob->setTable($this->tableParser->convertSqlToJob($tokens));
     if ($tokens->seekTokenText('(')) {
         do {
             if (!$this->columnParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing valid column name in column selection for INSERT INTO statement!", $tokens);
             }
             $insertJob->addColumnSelection($this->columnParser->convertSqlToJob($tokens));
         } while ($tokens->seekTokenText(','));
         if (!$tokens->seekTokenText(')')) {
             throw new MalformedSqlException("Missing closing parenthesis after column-selection for INSERT INTO statement!");
         }
         if ($tokens->seekTokenNum(SqlToken::T_VALUES())) {
             do {
                 if (!$tokens->seekTokenText('(')) {
                     throw new MalformedSqlException("Missing begin parenthesis in value definiton for INSERT INTO statement!", $tokens);
                 }
                 $dataRow = array();
                 do {
                     switch (true) {
                         case $this->valueParser->canParseTokens($tokens):
                             $dataRow[] = $this->valueParser->convertSqlToJob($tokens);
                             break;
                         default:
                             throw new MalformedSqlException("Invalid value in value-defintion for INSERT INTO statement!", $tokens);
                     }
                 } while ($tokens->seekTokenText(','));
                 if (!$tokens->seekTokenText(')')) {
                     throw new MalformedSqlException("Missing ending parenthesis in value definiton for INSERT INTO statement!", $tokens);
                 }
                 $insertJob->addDataSourceValuesRow($dataRow);
             } while ($tokens->seekTokenText(','));
         } elseif ($this->selectParser->canParseTokens($tokens)) {
             $insertJob->setDataSourceSelect($this->selectParser->convertSqlToJob($tokens));
         } else {
             throw new MalformedSqlException("Invalid data-source-definiton (VALUES or SELECT) in INSERT INTO statement!", $tokens);
         }
     } elseif ($tokens->seekTokenNum(SqlToken::T_SET())) {
         do {
             if (!$this->columnParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing column specifier for INSERT INTO SET statement!", $tokens);
             }
             $dataChange->setColumn($this->columnParser->convertSqlToJob($tokens));
             if (!$tokens->seekTokenText('=')) {
                 throw new MalformedSqlException("Missing '=' in INSERT INTO SET statement!", $tokens);
             }
             switch (true) {
                 case $this->valueParser->canParseTokens($tokens):
                     $dataChange->setValue($this->valueParser->convertSqlToJob($tokens));
                     break;
                 default:
                     throw new MalformedSqlException("Invalid value for INSERT INTO SET statement!", $tokens);
             }
             $insertJob->addColumnSetValue(clone $dataChange);
         } while ($tokens->seekTokenText(','));
     } elseif ($this->selectParser->canParseTokens($tokens)) {
         $insertJob->setDataSourceSelect($this->selectParser->convertSqlToJob($tokens));
     } else {
         throw new MalformedSqlException("Invalid column-selection for INSERT INTO statement!", $tokens);
     }
     if ($tokens->seekTokenNum(SqlToken::T_ON())) {
         if (!$tokens->seekTokenNum(SqlToken::T_DUPLICATE())) {
             throw new MalformedSqlException("Missing DUPLICATE in INSERT INTO ON DUPLICATE KEY UPDATE statement!", $tokens);
         }
         if (!$tokens->seekTokenNum(SqlToken::T_KEY())) {
             throw new MalformedSqlException("Missing KEY in INSERT INTO ON DUPLICATE KEY UPDATE statement!", $tokens);
         }
         if (!$tokens->seekTokenNum(SqlToken::T_UPDATE())) {
             throw new MalformedSqlException("Missing UPDATE in INSERT INTO ON DUPLICATE KEY UPDATE statement!", $tokens);
         }
         do {
             if (!$this->columnParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing column specifier for INSERT INTO ON DUPLICATE KEY UPDATE statement!", $tokens);
             }
             $dataChange->setColumn($this->columnParser->convertSqlToJob($tokens));
             if (!$tokens->seekTokenText('=')) {
                 throw new MalformedSqlException("Missing '=' in INSERT INTO ON DUPLICATE KEY UPDATE statement!", $tokens);
             }
             switch (true) {
                 case $valueParser->canParseTokens($tokens):
                     $dataChange->setValue($valueParser->convertSqlToJob($tokens));
                     break;
                 default:
                     throw new MalformedSqlException("Invalid value for INSERT INTO ON DUPLICATE KEY UPDATE statement!", $tokens);
             }
             $insertJob->addOnDuplicateDataChange(clone $dataChange);
         } while ($tokens->seekTokenText(','));
     }
     return $insertJob;
 }
Example #16
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     // catch both cases when select is current AND when its next token.
     $tokens->seekTokenNum(SqlToken::T_SELECT());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_SELECT()) {
         throw new ErrorException("Tried to convert select-sql to job when sql-token-iterator does not point to T_SELECT!");
     }
     $entitySelect = new SelectStatement();
     ### SPECIAL FLAGS
     foreach ([[SpecialFlags::FLAG_ALL(), SqlToken::T_ALL()], [SpecialFlags::FLAG_DISTINCT(), SqlToken::T_DISTINCT()], [SpecialFlags::FLAG_DISTINCTROW(), SqlToken::T_DISTINCTROW()], [SpecialFlags::FLAG_HIGH_PRIORITY(), SqlToken::T_HIGH_PRIORITY()], [SpecialFlags::FLAG_STRAIGHT_JOIN(), SqlToken::T_STRAIGHT_JOIN()], [SpecialFlags::FLAG_SQL_SMALL_RESULT(), SqlToken::T_SQL_SMALL_RESULT()], [SpecialFlags::FLAG_SQL_BIG_RESULT(), SqlToken::T_SQL_BIG_RESULT()], [SpecialFlags::FLAG_SQL_BUFFER_RESULT(), SqlToken::T_SQL_BUFFER_RESULT()], [SpecialFlags::FLAG_SQL_CACHE(), SqlToken::T_SQL_CACHE()], [SpecialFlags::FLAG_SQL_NO_CACHE(), SqlToken::T_SQL_NO_CACHE()], [SpecialFlags::FLAG_SQL_CALC_FOUND_ROWS(), SqlToken::T_SQL_CALC_FOUND_ROWS()]] as $pair) {
         list($flagValue, $tokenNum) = $pair;
         if ($tokens->seekTokenNum($tokenNum)) {
             $entitySelect->addFlag($flagValue);
         }
     }
     ### COLLECT COLUMNS
     do {
         try {
             switch (true) {
                 # parse jokers like: fooTable.*
                 case is_int($tokens->isTokenText('*', TokenIterator::NEXT, [T_STRING, '.'])):
                     if ($this->tableParser->canParseTokens($tokens)) {
                         $tableFilter = $this->tableParser->convertSqlToJob($tokens);
                     } else {
                         $tableFilter = null;
                     }
                     $tokens->seekTokenText('*', TokenIterator::NEXT, [T_STRING, '.']);
                     $entitySelect->addColumnAllTable($tableFilter);
                     break;
                 case $this->valueParser->canParseTokens($tokens):
                     $value = $this->valueParser->convertSqlToJob($tokens);
                     if ($tokens->seekTokenNum(T_STRING, TokenIterator::NEXT, [SqlToken::T_AS()])) {
                         $entitySelect->addColumnValue($value, $tokens->getCurrentTokenString());
                     } else {
                         $entitySelect->addColumnValue($value);
                     }
                     break;
                 default:
                     throw new MalformedSqlException("Non-column-sql found in column-part of select!", $tokens);
             }
         } catch (MalformedSqlException $exception) {
             throw new MalformedSqlException($exception->getMessage(), $tokens);
         }
     } while ($tokens->seekTokenText(','));
     ### COLLECT TABLES
     if ($tokens->seekTokenNum(SqlToken::T_FROM())) {
         if (!$this->joinParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing valid join definition after FROM in SELECT statement!", $tokens);
         }
         $entitySelect->setJoinDefinition($this->joinParser->convertSqlToJob($tokens));
     }
     ### PREPENDED CONDITION (WHERE)
     if ($tokens->seekTokenNum(SqlToken::T_WHERE())) {
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing condition for WHERE clause in SELECT statement!", $tokens);
         }
         $entitySelect->setCondition($this->valueParser->convertSqlToJob($tokens));
     }
     ### GROUP
     if ($tokens->seekTokenNum(SqlToken::T_GROUP())) {
         if (!$tokens->seekTokenNum(SqlToken::T_BY())) {
             throw new MalformedSqlException("Missing BY after GROUP in SELECT statement!", $tokens);
         }
         do {
             $groupingDefinition = new GroupingDefinition();
             if (!$this->columnParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Invalid grouping value in SELECT statement!!", $tokens);
             }
             $groupingDefinition->setValue($this->columnParser->convertSqlToJob($tokens));
             if ($tokens->seekTokenNum(SqlToken::T_DESC())) {
                 $groupingDefinition->setDirection(SqlToken::T_DESC());
             } elseif ($tokens->seekTokenNum(SqlToken::T_ASC())) {
                 $groupingDefinition->setDirection(SqlToken::T_ASC());
             }
             $entitySelect->addGrouping($groupingDefinition);
         } while ($tokens->seekTokenText(','));
     }
     ### APPENDED CONDITION (HAVING)
     if ($tokens->seekTokenNum(SqlToken::T_HAVING())) {
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing condition for WHERE clause in SELECT statement!", $tokens);
         }
         $condition = new ConditionJob();
         $condition->setFirstParameter($this->valueParser->convertSqlToJob($tokens));
         $entitySelect->setResultFilter($condition);
     }
     ### ORDER
     if ($tokens->seekTokenNum(SqlToken::T_ORDER())) {
         if (!$tokens->seekTokenNum(SqlToken::T_BY())) {
             throw new MalformedSqlException("Missing BY after ORDER on SELECT statement!", $tokens);
         }
         do {
             if (!$this->valueParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing value for ORDER BY part on SELECT statement!", $tokens);
             }
             $orderValue = $this->valueParser->convertSqlToJob($tokens);
             if ($tokens->seekTokenNum(SqlToken::T_DESC())) {
                 $entitySelect->addOrderColumn($orderValue, SqlToken::T_DESC());
             } else {
                 $tokens->seekTokenNum(SqlToken::T_ASC());
                 $entitySelect->addOrderColumn($orderValue, SqlToken::T_ASC());
             }
         } while ($tokens->seekTokenText(','));
     }
     ### LIMIT
     if ($tokens->seekTokenNum(SqlToken::T_LIMIT())) {
         if (!$tokens->seekTokenNum(T_NUM_STRING)) {
             throw new MalformedSqlException("Missing offset number for LIMIT part in SELECT statement!", $tokens);
         }
         $entitySelect->setLimitOffset((int) $tokens->getCurrentTokenString());
         if ($tokens->seekTokenText(',')) {
             if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                 throw new MalformedSqlException("Missing length number for LIMIT part in SELECT statement!", $tokens);
             }
             $entitySelect->setLimitRowCount((int) $tokens->getCurrentTokenString());
         }
     }
     ### PROCEDURE
     if ($tokens->seekTokenNum(SqlToken::T_PROCEDURE())) {
         if (!$functionParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing valid procedure specifier after PROCEDURE!", $tokens);
         }
         $entitySelect->setProcedure($functionParser->convertSqlToJob($tokens));
     }
     ### INTO OUTFILE|DUMPFILE
     if ($tokens->seekTokenNum(SqlToken::T_INTO())) {
         if (!$tokens->seekTokenNum(SqlToken::T_OUTFILE()) && !$tokens->seekTokenNum(SqlToken::T_DUMPFILE())) {
             throw new MalformedSqlException("Missing OUTFILE or DUMPFILE after INTO!", $tokens);
         }
         if (!$tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING)) {
             throw new MalformedSqlException("Missing escaped string after INTO OUTFILE!");
         }
         $entitySelect->setIntoOutFile($tokens->seekTokenText($searchToken));
     }
     ### FOR UPDATE
     if ($tokens->seekTokenNum(SqlToken::T_FOR())) {
         if (!$tokens->seekTokenNum(SqlToken::T_UPDATE())) {
             throw new MalformedSqlException("Missing UPDATE after FOR on FOR UPDATE parameter in SELECT statement!", $tokens);
         }
         $entitySelect->setIsForUpdate(true);
     }
     ### LOCK IN SHARE MODE
     if ($tokens->seekTokenNum(SqlToken::T_LOCK())) {
         if (!$tokens->seekTokenNum(SqlToken::T_IN())) {
             throw new MalformedSqlException("Missing UPDATE after FOR on FOR UPDATE parameter in SELECT statement!", $tokens);
         }
         if (!$tokens->seekTokenNum(SqlToken::T_SHARE())) {
             throw new MalformedSqlException("Missing UPDATE after FOR on FOR UPDATE parameter in SELECT statement!", $tokens);
         }
         if (!$tokens->seekTokenNum(SqlToken::T_MODE())) {
             throw new MalformedSqlException("Missing UPDATE after FOR on FOR UPDATE parameter in SELECT statement!", $tokens);
         }
         $entitySelect->setIsLockInShareMode(true);
     }
     ### UNION
     if ($tokens->seekTokenNum(SqlToken::T_UNION())) {
         $isUnionAll = $tokens->seekTokenNum(SqlToken::T_ALL());
         $isUnionDistinct = $tokens->seekTokenNum(SqlToken::T_DISTINCT());
         $isUnionAll = $isUnionAll || $tokens->seekTokenNum(SqlToken::T_ALL());
         if ($isUnionAll && $isUnionDistinct) {
             throw new MalformedSqlException("UNION cannot be ALL and DISTINCT at the same time!", $tokens);
         }
         $isUnionInParenthesis = $tokens->seekTokenText('(');
         if (!$this->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing following SELECT statement after UNION in SELECT statement!", $tokens);
         }
         $entitySelect->setUnionSelect($this->convertSqlToJob($tokens), $isUnionDistinct);
         if ($isUnionInParenthesis && !$tokens->seekTokenText(')')) {
             throw new MalformedSqlException("Missing ending parenthesis after UNION in SELECT statement!", $tokens);
         }
     }
     return $entitySelect;
 }
Example #17
0
 public function executeJob(StatementJob $statement, array $parameters = array())
 {
     /* @var $statement SelectStatement */
     $defaultSchema = $this->schemaManager->getSchema();
     $executionContext = new ExecutionContext($this->schemaManager, $statement, $parameters);
     ### COLLECT SOURCE TABLES
     if (!is_null($statement->getJoinDefinition())) {
         foreach ($statement->getJoinDefinition()->getTables() as $joinTable) {
             /* @var $joinTable TableJoin */
             /* @var $dataSource ParenthesisPart */
             $dataSource = $joinTable->getDataSource();
             $tableResource = null;
             $alias = $dataSource->getAlias();
             $dataSource = $dataSource->getContain();
             if ($dataSource instanceof TableInterface) {
                 $tableResource = $dataSource;
                 if (is_null($alias)) {
                     $alias = $tableResource->getName();
                 }
             }
             if ($dataSource instanceof SelectStatement) {
                 /* @var $subQueryResult TemporaryResult */
                 $tableResource = $this->executeJob($dataSource, $parameters);
             }
             if ($dataSource instanceof TableSpecifier) {
                 if (!is_null($dataSource->getDatabase())) {
                     if (!$this->schemaManager->schemaExists($dataSource->getDatabase())) {
                         throw new InvalidArgumentException("Database '{$dataSource->getDatabase()}' does not exist!");
                     }
                     $schema = $this->schemaManager->getSchema($dataSource->getDatabase());
                 } else {
                     $schema = $defaultSchema;
                 }
                 if (!$schema->tableExists($dataSource->getTable())) {
                     throw new InvalidArgumentException("Table '{$dataSource}' does not exist!");
                 }
                 if (is_null($alias)) {
                     $alias = $dataSource->getTable();
                 }
                 $tableResource = $this->tableManager->getTable($dataSource->getTable(), $dataSource->getDatabase());
             }
             $executionContext->setTable($tableResource, (string) $alias);
         }
     }
     ### INIT RESULTSET
     $resultColumns = array();
     foreach ($statement->getColumns() as $column) {
         if ($column === '*') {
             foreach ($executionContext->getTables() as $alias => $table) {
                 /* @var $table Table */
                 /* @var $tableSchema TableSchema */
                 $tableSchema = $table->getTableSchema();
                 foreach ($tableSchema->getColumnIterator() as $columnPage) {
                     /* @var $columnPage ColumnSchema */
                     $columnName = $columnPage->getName();
                     if (count($executionContext->getTables()) > 1) {
                         $columnName = "{$alias}.{$columnName}";
                     }
                     $resultColumns[] = $columnName;
                 }
             }
         } elseif ($column instanceof ValuePart) {
             $resultColumns[] = $column->getAlias();
         }
     }
     $result = new TemporaryResult($resultColumns);
     $executionContext->setCurrentResultSet(new TemporaryResult($resultColumns));
     $executionContext->setCurrentSourceSet(new TemporaryResult());
     ### PRE-FILTER SOURCE COLUMNS (currently not implemented)
     if (!is_null($statement->getCondition())) {
         /* @var $condition ValuePart */
         $condition = $statement->getCondition();
         $tableConditions = $this->findFixedConditions($condition);
         foreach ($executionContext->getTables() as $alias => $table) {
             /* @var $table TableInterface */
             /* @var $tableSchema TableSchema */
             $tableSchema = $table->getTableSchema();
             $tableIterator = $table;
             $indexes = $this->findIndexesForTableConditions($tableConditions, $table, $alias);
             if (!empty($indexes)) {
                 # TODO: actually choose the best index instead of using the first usable index
                 #       (We probably need table-statistics to do that.)
                 $index = $indexes[0];
                 /* @var $indexSchema IndexSchema */
                 $indexSchema = $index->getIndexSchema();
                 $indexecColumns = array();
                 foreach ($indexSchema->getColumns() as $columnId) {
                     $columnName = $tableSchema->getColumn($columnId)->getName();
                     $indexecColumns[$columnId] = $columnName;
                 }
                 $tableIterator = new FilteredResourceIterator($tableIterator, $condition, $this->valueResolver, $executionContext, $index, $indexecColumns);
             }
             if ($tableIterator !== $table) {
                 $executionContext->setTable($tableIterator, $alias);
             }
         }
     }
     /* @var $joinDefinition Join */
     $joinDefinition = $statement->getJoinDefinition();
     if (!is_null($joinDefinition)) {
         ### BUILD JOIN
         if (count($joinDefinition->getTables()) > 1) {
             $iterator = new JoinIterator($joinDefinition, $executionContext, $this, $this->valueResolver, $statement, null);
         } else {
             /* @var $tableJoin TableJoin */
             $tableJoin = $joinDefinition->getTables()[0];
             $tableSource = $tableJoin->getDataSource();
             $alias = null;
             while ($tableSource instanceof ParenthesisPart) {
                 if (is_null($alias)) {
                     $alias = $tableSource->getAlias();
                 }
                 $tableSource = $tableSource->getContain();
             }
             if ($tableSource instanceof TableSpecifier) {
                 if (is_null($alias)) {
                     $alias = $tableSource->getTable();
                 }
                 $iterator = $executionContext->getTable($alias);
             } elseif ($tableSource instanceof SelectStatement) {
                 $iterator = $this->executeJob($tableSource);
             } else {
                 throw new ErrorException("Unexpected object given as source for join!");
             }
             $iterator = new AliasedResourceIterator($iterator, $alias);
         }
         ### FILTER RESULT
         // WHERE condition
         $condition = $statement->getCondition();
         if (!is_null($condition)) {
             if ($iterator instanceof IteratorAggreagte) {
                 $iterator = $iterator->getIterator();
             }
             $iterator = new FilteredResourceIterator($iterator, $condition, $this->valueResolver, $executionContext);
         }
         // ON/USING conditions from joins
         foreach ($joinDefinition->getTables() as $joinTable) {
             /* @var $joinTable TableJoin */
             $joinCondition = $joinTable->getCondition();
             if (!is_null($joinCondition)) {
                 if ($iterator instanceof IteratorAggreagte) {
                     $iterator = $iterator->getIterator();
                 }
                 $iterator = new FilteredResourceIterator($iterator, $joinCondition, $this->valueResolver, $executionContext);
             }
         }
         ### SET UP SORTING
         $orderColumns = $statement->getOrderColumns();
         if (count($orderColumns) > 0) {
             $innerIterator = $iterator;
             $iterator = new SortedResourceIterator($iterator, $this->valueResolver);
             $iterator->setTemporaryBuildChildIteratorByValue($orderColumns, $innerIterator, $executionContext);
         }
         ### WRITE RESULTSET
         foreach ($iterator as $dataRow) {
             if ($iterator instanceof UsesBinaryDataInterface && $iterator->usesBinaryData()) {
                 $dataRow = $iterator->convertDataRowToStringRow($dataRow);
             }
             $executionContext->getCurrentSourceSet()->addRow($dataRow);
             $executionContext->setCurrentSourceRow($dataRow);
             $resolvedRow = $this->valueResolver->resolveSourceRow($statement->getColumns(), $executionContext);
             $executionContext->getCurrentResultSet()->addRow($resolvedRow);
         }
     } else {
         // no joining (something like "SELECT 5+5 as foo")
         $resolvedRow = $this->valueResolver->resolveSourceRow($statement->getColumns(), $executionContext);
         $executionContext->getCurrentResultSet()->addRow($resolvedRow);
     }
     ### UNLOCK TABLES
     foreach ($executionContext->getTables() as $table) {
         # TODO: unlock tables
     }
     ### APPLY GROUPING
     $groupings = $statement->getGroupings();
     if (count($groupings) > 0) {
         foreach ($groupings as $groupingDefinition) {
             /* @var $groupingDefinition GroupingDefinition */
             /* @var $groupingValue ValuePart */
             $groupingValue = $groupingDefinition->getValue();
             $beforeSourceRow = $executionContext->getCurrentSourceRow();
             $groupedRows = array();
             foreach ($executionContext->getCurrentSourceSet() as $row) {
                 $executionContext->setCurrentSourceRow($row);
                 $groupId = $this->valueResolver->resolveValue($groupingValue, $executionContext);
                 if (!isset($groupedRows[$groupId])) {
                     $groupedRows[$groupId] = array();
                 }
                 $groupedRows[$groupId][] = $row;
             }
             $groupedResultSet = new TemporaryResult($resultColumns);
             foreach ($groupedRows as $groupId => $rows) {
                 if ($groupingDefinition->getDirection() === SqlToken::T_ASC()) {
                     $groupingMainRow = reset($rows);
                 } else {
                     $groupingMainRow = end($rows);
                 }
                 $currentGroupResultSet = new TemporaryResult();
                 foreach ($rows as $row) {
                     $currentGroupResultSet->addRow($row);
                 }
                 $executionContext->setCurrentSourceRow($groupingMainRow);
                 $executionContext->setCurrentSourceSet($currentGroupResultSet);
                 $resolvedRow = $this->valueResolver->resolveSourceRow($statement->getColumns(), $executionContext);
                 $groupedResultSet->addRow($resolvedRow);
             }
             $executionContext->setCurrentSourceRow($beforeSourceRow);
             $executionContext->setCurrentResultSet($groupedResultSet);
         }
     }
     ### APPLY RESULT-FILTER (HAVING)
     /* @var $resultFilter ConditionJob */
     $resultFilter = $statement->getResultFilter();
     if (!is_null($resultFilter)) {
         $filteredResult = new TemporaryResult($resultColumns);
         foreach ($executionContext->getCurrentResultSet() as $row) {
             $executionContext->setCurrentSourceRow($row);
             $passesFilter = (bool) $this->valueResolver->resolveValue($resultFilter, $executionContext);
             if ($passesFilter) {
                 $filteredResult->addRow($row);
             }
         }
         $executionContext->setCurrentResultSet($filteredResult);
     }
     ### APPEND UNIONED SELECT
     $unionSelect = $statement->getUnionSelect();
     if (!is_null($unionSelect)) {
         $unionResult = $this->executeJob($unionSelect, $parameters);
         foreach ($unionResult as $unionRow) {
             $executionContext->getCurrentResultSet()->addRow($unionRow);
         }
     }
     return $executionContext->getCurrentResultSet();
 }
Example #18
0
 public function parsePlainValue(SQLTokenIterator $tokens, ValueJob $valueJob)
 {
     switch (true) {
         case $tokens->seekTokenNum(T_NUM_STRING):
             $valueJob->addChainValue((double) $tokens->getCurrentTokenString());
             break;
         case $tokens->seekTokenNum(T_CONSTANT_ENCAPSED_STRING):
             $string = $tokens->getCurrentTokenString();
             if (($string[0] === '"' || $string[0] === "'") && $string[0] === $string[strlen($string) - 1]) {
                 // remove quotes if needed
                 $string = substr($string, 1, strlen($string) - 2);
             }
             $valueJob->addChainValue($string);
             break;
         case $tokens->seekTokenNum(T_VARIABLE):
             $variableString = $tokens->getCurrentTokenString();
             $variable = Variable::factory($variableString);
             if ($variableString === '?') {
                 $variable->setIndex($tokens->countTokenOccourences(T_VARIABLE, 0, $tokens->getIndex() - 1));
             }
             $valueJob->addChainValue($variable);
             break;
         case $this->parenthesisParser->canParseTokens($tokens):
             $valueJob->addChainValue($this->parenthesisParser->convertSqlToJob($tokens));
             break;
         case $this->functionParser->canParseTokens($tokens):
             $valueJob->addChainValue($this->functionParser->convertSqlToJob($tokens));
             break;
         case $this->columnParser->canParseTokens($tokens):
             $valueJob->addChainValue($this->columnParser->convertSqlToJob($tokens));
             break;
         case $this->caseParser->canParseTokens($tokens):
             $valueJob->addChainValue($this->caseParser->convertSqlToJob($tokens));
             break;
         case $tokens->seekTokenNum(SqlToken::T_DEFAULT()):
         case $tokens->seekTokenNum(SqlToken::T_NULL()):
         case $tokens->seekTokenNum(SqlToken::T_FALSE()):
         case $tokens->seekTokenNum(SqlToken::T_TRUE()):
         case $tokens->seekTokenNum(SqlToken::T_CURRENT_TIMESTAMP()):
         case $tokens->seekTokenNum(SqlToken::T_CURRENT_DATE()):
         case $tokens->seekTokenNum(SqlToken::T_CURRENT_TIME()):
         case $tokens->seekTokenNum(SqlToken::T_CURRENT_USER()):
             $valueJob->addChainValue($tokens->getCurrentTokenNumber());
             break;
         default:
             return false;
     }
     return true;
 }
Example #19
0
 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;
 }
Example #20
0
 public function convertSqlToJob(SQLTokenIterator $tokens, $from = TokenIterator::NEXT)
 {
     if (!$tokens->seekTokenText('(', $from)) {
         throw new ErrorException("Tried to parse sql-parenthesis when token-iterator does not point to paranthesis ('(' sign)!");
     }
     /* @var $parenthesis ParenthesisPart */
     $parenthesis = new ParenthesisPart();
     switch (true) {
         case $this->selectParser->canParseTokens($tokens):
             $parenthesis->setContain($this->selectParser->convertSqlToJob($tokens));
             break;
         case $this->valueParser->canParseTokens($tokens):
             $parenthesis->setContain($this->valueParser->convertSqlToJob($tokens));
             break;
     }
     if (!$tokens->seekTokenText(')')) {
         throw new MalformedSqlException("Missing ')' at the end of a parenthesis!", $tokens);
     }
     if ($tokens->seekTokenNum(T_STRING, TokenIterator::NEXT, [SqlToken::T_AS()])) {
         $parenthesis->setAlias($tokens->getCurrentTokenString());
     }
     if ($parenthesis->getContain() instanceof Select && $tokens->isTokenNum(SqlToken::T_UNION())) {
         $unionSelect = new Select();
         while ($tokens->seekTokenNum(SqlToken::T_UNION())) {
             /* @var $lastUnionedSelect Select */
             $lastUnionedSelect = $parenthesis->getContain();
             while (!is_null($lastUnionedSelect->getUnionSelect())) {
                 $lastUnionedSelect = $lastUnionedSelect->getUnionSelect();
             }
             $isUnionAll = $tokens->seekTokenNum(SqlToken::T_ALL());
             $isUnionDistinct = $tokens->seekTokenNum(SqlToken::T_DISTINCT());
             $isUnionAll = $isUnionAll || $tokens->seekTokenNum(SqlToken::T_ALL());
             if ($isUnionAll && $isUnionDistinct) {
                 throw new MalformedSqlException("UNION cannot be ALL and DISTINCT at the same time!", $tokens);
             }
             $isUnionInParenthesis = $tokens->seekTokenText('(');
             if (!$this->selectParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing following SELECT statement after UNION in SELECT statement!", $tokens);
             }
             $lastUnionedSelect->setUnionSelect($this->selectParser->convertSqlToJob($tokens), $isUnionDistinct);
             if ($isUnionInParenthesis && !$tokens->seekTokenText(')')) {
                 throw new MalformedSqlException("Missing ending parenthesis after UNION in SELECT statement!", $tokens);
             }
         }
         $unionSelect->setUnionSelect($parenthesis->getContain());
         ### APPENDED CONDITION (HAVING)
         if ($tokens->seekTokenNum(SqlToken::T_HAVING())) {
             if (!$this->valueParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing condition for WHERE clause in SELECT statement!", $tokens);
             }
             $condition = new Condition();
             $condition->setFirstParameter($this->valueParser->convertSqlToJob($tokens));
             $unionSelect->setResultFilter($condition);
         }
         ### ORDER
         if ($tokens->seekTokenNum(SqlToken::T_ORDER())) {
             if (!$tokens->seekTokenNum(SqlToken::T_BY())) {
                 throw new MalformedSqlException("Missing BY after ORDER on SELECT statement!", $tokens);
             }
             do {
                 if (!$this->valueParser->canParseTokens($tokens)) {
                     throw new MalformedSqlException("Missing value for ORDER BY part on SELECT statement!", $tokens);
                 }
                 $orderValue = $this->valueParser->convertSqlToJob($tokens);
                 if ($tokens->seekTokenNum(SqlToken::T_DESC())) {
                     $unionSelect->addOrderColumn($orderValue, SqlToken::T_DESC());
                 } else {
                     $tokens->seekTokenNum(SqlToken::T_ASC());
                     $unionSelect->addOrderColumn($orderValue, SqlToken::T_ASC());
                 }
             } while ($tokens->seekTokenText(','));
         }
         ### LIMIT
         if ($tokens->seekTokenNum(SqlToken::T_LIMIT())) {
             if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                 throw new MalformedSqlException("Missing offset number for LIMIT part in SELECT statement!", $tokens);
             }
             $unionSelect->setLimitOffset((int) $tokens->getCurrentTokenString());
             if ($tokens->seekTokenText(',')) {
                 if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                     throw new MalformedSqlException("Missing length number for LIMIT part in SELECT statement!", $tokens);
                 }
                 $unionSelect->setLimitRowCount((int) $tokens->getCurrentTokenString());
             }
         }
         $parenthesis->setContain($unionSelect);
     }
     return $parenthesis;
 }
Example #21
0
 public function setDirection()
 {
     $this->direction = SqlToken::T_ASC() ? $direction : SqlToken::T_DESC();
 }
Example #22
0
 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;
 }
Example #23
0
 public function setOrderDirection(SqlToken $direction)
 {
     $this->orderDirection = $direction === SqlToken::T_ASC() ? $direction : SqlToken::T_DESC();
 }
Example #24
0
 public function addColumn(ColumnSpecifier $column, $length = null, $direction = null)
 {
     $direction = $direction === SqlToken::T_DESC() ? SqlToken::T_DESC() : SqlToken::T_ASC();
     $this->columns[] = ['column' => $column, 'length' => $length, 'direction' => $direction];
 }
Example #25
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_DELETE());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_DELETE()) {
         throw new ErrorException("Tried to parse DELETE statement when token iterator is not at T_DELETE!");
     }
     $deleteJob = new DeleteStatement();
     if ($tokens->seekTokenNum(SqlToken::T_LOW_PRIORITY())) {
         $deleteJob->setIsLowPriority(true);
     }
     if ($tokens->seekTokenNum(SqlToken::T_QUICK())) {
         $deleteJob->setIsQuick(true);
     }
     if ($tokens->seekTokenNum(SqlToken::T_IGNORE())) {
         $deleteJob->setIsIgnore(true);
     }
     if ($tokens->seekTokenNum(SqlToken::T_FROM())) {
         do {
             if (!$this->tableParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing valid table specifier in DELETE statement!", $tokens);
             }
             $deleteJob->addDeleteTable($this->tableParser->convertSqlToJob($tokens));
             if ($tokens->seekTokenText('.')) {
                 if (!$tokens->seekTokenText('*')) {
                     throw new MalformedSqlException("Only '*' allowed for column specification in DELETE statement!", $tokens);
                 }
             }
         } while ($tokens->seekTokenText(','));
         if ($tokens->seekTokenNum(SqlToken::T_USING())) {
             if (!$this->joinParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing valid JOIN definition after USING in DELETE statement!", $tokens);
             }
             $deleteJob->setJoinDefinition($this->joinParser->convertSqlToJob($tokens));
         }
     } else {
         do {
             if (!$this->tableParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing valid table specifier in DELETE statement!", $tokens);
             }
             $deleteJob->addDeleteTable($this->tableParser->convertSqlToJob($tokens));
             if ($tokens->seekTokenText('.')) {
                 if (!$tokens->seekTokenText('*')) {
                     throw new MalformedSqlException("Only '*' allowed for column specification in DELETE statement!", $tokens);
                 }
             }
         } while ($tokens->seekTokenText(','));
         if ($tokens->seekTokenNum(SqlToken::T_FROM())) {
             if (!$this->joinParser->canParseTokens($tokens)) {
                 throw new MalformedSqlException("Missing valid JOIN definition after FROM in DELETE statement!", $tokens);
             }
             $deleteJob->setJoinDefinition($this->joinParser->convertSqlToJob($tokens));
         }
     }
     if ($tokens->seekTokenNum(SqlToken::T_WHERE())) {
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing condition for WHERE clause in UPDATE statement!", $tokens);
         }
         $deleteJob->setCondition($this->valueParser->convertSqlToJob($tokens));
     }
     if ($tokens->seekTokenNum(SqlToken::T_ORDER())) {
         if (!$tokens->seekTokenNum(SqlToken::T_BY())) {
             throw new MalformedSqlException("Missing BY after ORDER on DELETE statement!", $tokens);
         }
         if (!$columnParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing column specifier for ORDER BY part on DELETE statement!", $tokens);
         }
         $deleteJob->setOrderColumn($columnParser->convertSqlToJob($tokens));
         if ($tokens->seekTokenNum(SqlToken::T_DESC())) {
             $deleteJob->setOrderDirection(SqlToken::T_DESC());
         } elseif ($tokens->seekTokenNum(SqlToken::T_ASC())) {
             $deleteJob->setOrderDirection(SqlToken::T_ASC());
         }
     }
     if ($tokens->seekTokenNum(SqlToken::T_LIMIT())) {
         if (!$tokens->seekTokenNum(T_NUM_STRING)) {
             throw new MalformedSqlException("Missing offset number for LIMIT part in DELETE statement!", $tokens);
         }
         $deleteJob->setLimitOffset((int) $tokens->getCurrentTokenString());
         if ($tokens->seekTokenText(',')) {
             if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                 throw new MalformedSqlException("Missing length number for LIMIT part in DELETE statement!", $tokens);
             }
             $deleteJob->setLimitRowCount((int) $tokens->getCurrentTokenString());
         }
     }
     return $deleteJob;
 }
Example #26
0
 protected function parseTableSource(SQLTokenIterator $tokens)
 {
     $parenthesis = new ParenthesisPart();
     switch (true) {
         case $this->tableParser->canParseTokens($tokens):
             $parenthesis->setContain($this->tableParser->convertSqlToJob($tokens));
             if ($tokens->seekTokenNum(T_STRING, TokenIterator::NEXT, [SqlToken::T_AS()])) {
                 $parenthesis->setAlias($tokens->getCurrentTokenString());
             }
             break;
         case $this->parenthesisParser->canParseTokens($tokens):
             $parenthesisJob = $this->parenthesisParser->convertSqlToJob($tokens);
             if ($tokens->seekTokenNum(T_STRING, TokenIterator::NEXT, [SqlToken::T_AS()])) {
                 $parenthesis->setAlias($tokens->getCurrentTokenString());
             }
             // resolve cascaded parenthesis
             $extractParenthesis = $parenthesisJob;
             while ($extractParenthesis->getContain() instanceof Parenthesis) {
                 $extractParenthesis = $extractParenthesis->getContain();
             }
             if ($extractParenthesis->getContain() instanceof SelectStatement) {
                 $parenthesis = $parenthesisJob;
                 // return original parenthesis for correct alias
             } else {
                 throw new MalformedSqlException("Parenthesis in JOIN condition has to contain SELECT statement!", $tokens);
             }
             break;
         default:
             throw new MalformedSqlException("Missing valid table-source in JOIN defintion!", $tokens);
     }
     return $parenthesis;
 }
Example #27
0
 /**
  * @param SQLTokenIterator $tokens
  * @return Operator
  */
 protected function parseCondition(SQLTokenIterator $tokens)
 {
     switch (true) {
         case $tokens->seekTokenText('='):
             return Operator::OP_EQUAL();
         case $tokens->seekTokenText('<=>'):
             return Operator::OP_EQUAL_NULLSAFE();
         case $tokens->seekTokenText('!='):
             return Operator::OP_NOT_EQUAL();
         case $tokens->seekTokenText('<>'):
             return Operator::OP_LESSERGREATER();
         case $tokens->seekTokenText('<='):
             return Operator::OP_LESSEREQUAL();
         case $tokens->seekTokenText('<'):
             return Operator::OP_LESSER();
         case $tokens->seekTokenText('>='):
             return Operator::OP_GREATEREQUAL();
         case $tokens->seekTokenText('>'):
             return Operator::OP_GREATER();
         case $tokens->seekTokenText('+'):
             return Operator::OP_ADDITION();
         case $tokens->seekTokenText('-'):
             return Operator::OP_SUBTRACTION();
         case $tokens->seekTokenText('*'):
             return Operator::OP_MULTIPLICATION();
         case $tokens->seekTokenText('/'):
             return Operator::OP_DIVISION();
         case $tokens->seekTokenNum(SqlToken::T_IS()):
             if ($tokens->seekTokenNum(SqlToken::T_NOT())) {
                 return Operator::OP_IS_NOT();
             } else {
                 return Operator::OP_IS();
             }
             break;
         case $tokens->seekTokenNum(SqlToken::T_AND()):
             return Operator::OP_AND();
         case $tokens->seekTokenNum(SqlToken::T_OR()):
             return Operator::OP_OR();
         case $tokens->seekTokenNum(SqlToken::T_BETWEEN(), TokenIterator::NEXT, SqlToken::T_NOT()):
             if ($tokens->isTokenNum(SqlToken::T_NOT(), TokenIterator::PREVIOUS)) {
                 return Operator::OP_NOT_BETWEEN();
             } else {
                 return Operator::OP_BETWEEN();
             }
         default:
             return null;
     }
 }
Example #28
0
 public function resolveSqlToken(SqlToken $token)
 {
     switch ($token) {
         case SqlToken::T_DEFAULT():
             return $this->getCurrentColumnSchema()->getDefaultValue();
         case SqlToken::T_FALSE():
             return 0;
         case SqlToken::T_TRUE():
             return 1;
         case SqlToken::T_NULL():
             return null;
         case SqlToken::T_CURRENT_TIMESTAMP():
             return date("Y-m-d H:i:s", time());
         case SqlToken::T_CURRENT_DATE():
             return date("Y-m-d", time());
         case SqlToken::T_CURRENT_TIME():
             return time();
         case SqlToken::T_CURRENT_USER():
             // There is simply no user management, so what to do here?
             return "NoUserManagementImplemented";
         default:
             throw new ErrorException("Unknown or unimplemented SqlToken '{$token->getName()}' to resolve to scalar value!");
     }
 }
Example #29
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $tokens->seekTokenNum(SqlToken::T_UPDATE());
     if ($tokens->getCurrentTokenNumber() !== SqlToken::T_UPDATE()) {
         throw new ErrorException("Tried to parse update statement when token-iterator does not point to T_UPDATE!");
     }
     $dataChange = new UpdateDataChange();
     $updateJob = new UpdateStatement();
     if ($tokens->seekTokenNum(SqlToken::T_LOW_PRIORITY())) {
         $updateJob->setIsLowPriority(true);
     }
     if ($tokens->seekTokenNum(SqlToken::T_IGNORE())) {
         $updateJob->setDoIgnoreErrors(true);
     }
     do {
         if (!$this->tableParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing table specifier in UPDATE statement!", $tokens);
         }
         $updateJob->addTable($this->tableParser->convertSqlToJob($tokens));
     } while ($tokens->seekTokenText(','));
     if (!$tokens->seekTokenNum(SqlToken::T_SET())) {
         throw new MalformedSqlException("Missing SET after table specifier in UPDATE statement!", $tokens);
     }
     do {
         if (!$this->columnParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing column specifier for SET part in UPDATE statement!", $tokens);
         }
         $dataChange->setColumn($this->columnParser->convertSqlToJob($tokens));
         if (!$tokens->seekTokenText('=')) {
             throw new MalformedSqlException("Missing '=' on SET part in UPDATE statement!", $tokens);
         }
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("MIssing valid value on SET part in UPDATE statement!", $tokens);
         }
         $dataChange->setValue($this->valueParser->convertSqlToJob($tokens));
         $updateJob->addDataChange(clone $dataChange);
     } while ($tokens->seekTokenText(','));
     if ($tokens->seekTokenNum(SqlToken::T_WHERE())) {
         if (!$this->valueParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing condition for WHERE clause in UPDATE statement!", $tokens);
         }
         $updateJob->setCondition($this->valueParser->convertSqlToJob($tokens));
     }
     if ($tokens->seekTokenNum(SqlToken::T_ORDER())) {
         if (!$tokens->seekTokenNum(SqlToken::T_BY())) {
             throw new MalformedSqlException("Missing BY after ORDER on UPDATE statement!", $tokens);
         }
         if (!$this->columnParser->canParseTokens($tokens)) {
             throw new MalformedSqlException("Missing column specifier for ORDER BY part on UPDATE statement!", $tokens);
         }
         $updateJob->setOrderColumn($this->columnParser->convertSqlToJob($tokens));
         if ($tokens->seekTokenNum(SqlToken::T_DESC())) {
             $updateJob->setOrderDirection(SqlToken::T_DESC());
         } elseif ($tokens->seekTokenNum(SqlToken::T_ASC())) {
             $updateJob->setOrderDirection(SqlToken::T_ASC());
         }
     }
     if ($tokens->seekTokenNum(SqlToken::T_LIMIT())) {
         if (!$tokens->seekTokenNum(T_NUM_STRING)) {
             throw new MalformedSqlException("Missing offset number for LIMIT part in UPDATE statement!", $tokens);
         }
         $updateJob->setLimitOffset((int) $tokens->getCurrentTokenString());
         if ($tokens->seekTokenText(',')) {
             if (!$tokens->seekTokenNum(T_NUM_STRING)) {
                 throw new MalformedSqlException("Missing length number for LIMIT part in UPDATE statement!", $tokens);
             }
             $updateJob->setLimitRowCount((int) $tokens->getCurrentTokenString());
         }
     }
     return $updateJob;
 }
Example #30
0
 public function addOrderColumn($value, $direction)
 {
     $this->orderColumns[] = ['value' => $value, 'direction' => SqlToken::T_ASC() ? $direction : SqlToken::T_DESC()];
 }