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; }
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; }
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; }