Example #1
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 #2
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 #3
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 #4
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;
 }