Пример #1
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;
 }
Пример #2
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $parts = array();
     do {
         $tokens->seekIndex($tokens->getExclusiveTokenIndex());
         $part = $tokens->getCurrentTokenString();
         if ($part[0] === '`' && $part[strlen($part) - 1] === '`') {
             $part = substr($part, 1, strlen($part) - 2);
         }
         $parts[] = $part;
     } while ($tokens->seekTokenText(".") && !$tokens->isTokenText('*'));
     return TableSpecifier::factory(implode(".", $parts));
 }
Пример #3
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;
 }
Пример #4
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $parts = array();
     do {
         if (!$tokens->seekTokenNum(T_STRING)) {
             throw new ErrorException("Tried to convert sql-database-specifier when token-iterator does not point to T_STRING!");
         }
         $part = $tokens->getCurrentTokenString();
         if ($part[0] === '`' && $part[strlen($part) - 1] === '`') {
             $part = substr($part, 1, strlen($part) - 2);
         }
         $parts[] = $part;
     } while ($tokens->seekTokenText("."));
     $specifier = DatabaseSpecifier::factory(implode(".", $parts));
     return $specifier;
 }
Пример #5
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;
 }
Пример #6
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     if (get_class($this) !== __CLASS__) {
         throw new ErrorException("Class '" . get_class($this) . "' needs to declare an own method '" . __FUNCTION__ . "'!");
     }
     if (!$this->wasInitialized) {
         $this->initSqlSubParsers();
     }
     /* @var $jobEntity Job */
     $jobEntities = array();
     #   $tokens->seekIndex(-1);
     do {
         while ($tokens->seekTokenText(';')) {
         }
         $parserFound = false;
         foreach ($this->sqlParser as $sqlParser) {
             /* @var $sqlParser SqlParser */
             if ($sqlParser->canParseTokens($tokens)) {
                 $parserFound = true;
                 $jobEntity = $sqlParser->convertSqlToJob($tokens);
                 while ($jobEntity instanceof ParenthesisPart) {
                     $jobEntity = $jobEntity->getContain();
                 }
                 $jobEntities[] = $jobEntity;
                 break;
             }
         }
         if (!$parserFound) {
             if (is_null($tokens->getExclusiveTokenNumber()) || $tokens->isAtEnd()) {
                 break;
             } else {
                 $relevantToken = $tokens->getExclusiveTokenString();
                 throw new MalformedSqlException("Invalid SQL-statement! (Cannot extract command: '{$relevantToken}')", $tokens);
             }
         }
     } while ($tokens->isTokenText(';'));
     if (!$tokens->isAtEnd() && $tokens->getExclusiveTokenIndex() !== $tokens->getIndex()) {
         throw new MalformedSqlException("Overlapping unparsed SQL at the end of statement!", $tokens);
     }
     foreach ($jobEntities as $job) {
         $job->checkPlausibility();
     }
     return $jobEntities;
 }
Пример #7
0
 public function convertSqlToJob(SQLTokenIterator $tokens)
 {
     $parts = array();
     do {
         if ($tokens->seekTokenNum(T_VARIABLE)) {
             $part = Variable::factory($tokens->getCurrentTokenString());
         } elseif ($tokens->seekTokens([T_STRING, T_CONSTANT_ENCAPSED_STRING])) {
             $part = $tokens->getCurrentTokenString();
             if ($part[0] === '`' && $part[strlen($part) - 1] === '`') {
                 $part = substr($part, 1, strlen($part) - 2);
             } elseif ($part[0] === '"' && $part[strlen($part) - 1] === '"') {
                 $part = substr($part, 1, strlen($part) - 2);
             } elseif ($part[0] === "'" && $part[strlen($part) - 1] === "'") {
                 $part = substr($part, 1, strlen($part) - 2);
             }
         } else {
             throw new ErrorException("Tried to convert sql-column-specifier when token-iterator does not point to T_STRING!");
         }
         $parts[] = $part;
     } while ($tokens->seekTokenText("."));
     $specifier = ColumnSpecifier::factory(implode(".", $parts));
     return $specifier;
 }
Пример #8
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;
 }
Пример #9
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;
 }
Пример #10
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;
     }
 }
Пример #11
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;
 }
Пример #12
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;
 }
Пример #13
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;
 }
Пример #14
0
 protected function parseJoinOperator(SQLTokenIterator $tokens)
 {
     $joinData = array('isInner' => false, 'isRight' => false);
     if ($tokens->seekTokenText(',')) {
         return $joinData;
     }
     if (!$tokens->isTokenNum(SqlToken::T_JOIN(), TokenIterator::NEXT, [SqlToken::T_LEFT(), SqlToken::T_RIGHT(), SqlToken::T_INNER(), SqlToken::T_OUTER(), SqlToken::T_CROSS()])) {
         return null;
     }
     while (true) {
         switch (true) {
             case $tokens->seekTokenNum(SqlToken::T_RIGHT()):
                 $joinData['isRight'] = true;
                 break;
             case $tokens->seekTokenNum(SqlToken::T_LEFT()):
                 $joinData['isRight'] = false;
                 break;
             case $tokens->seekTokenNum(SqlToken::T_INNER()):
                 $joinData['isInner'] = true;
                 break;
             case $tokens->seekTokenNum(SqlToken::T_CROSS()):
             case $tokens->seekTokenNum(SqlToken::T_OUTER()):
                 $joinData['isInner'] = false;
                 break;
             case $tokens->seekTokenNum(SqlToken::T_JOIN()):
                 return $joinData;
             default:
                 throw new MalformedSqlException("Invalid JOIN definition!");
         }
     }
 }