コード例 #1
0
 /**
  * Extracts the name of affected column.
  *
  * @param Parser     $parser The instance that requests parsing.
  * @param TokensList $list   The list of tokens to be parsed.
  * @param Token      $token  The token that is being parsed.
  *
  * @return void
  */
 public function after(Parser $parser, TokensList $list, Token $token)
 {
     // Parsing operation.
     ++$list->idx;
     $this->options->merge(OptionsFragment::parse($parser, $list, static::$OPTIONS));
     // Parsing affected field.
     ++$list->idx;
     $this->altered = FieldFragment::parse($parser, $list);
     //
     parent::after($parser, $list, $token);
 }
コード例 #2
0
 /**
  * Parses the additional options fragment at the end.
  *
  * @param Parser     $parser The instance that requests parsing.
  * @param TokensList $list   The list of tokens to be parsed.
  * @param Token      $token  The token that is being parsed.
  *
  * @return void
  */
 public function after(Parser $parser, TokensList $list, Token $token)
 {
     // [some options] is going to be parsed first.
     //
     // There is a parser specified in `Parser::$KEYWORD_PARSERS`
     // which parses the name of the tables.
     //
     // Finally, we parse here [some more options] and that's all.
     ++$list->idx;
     $this->options->merge(OptionsFragment::parse($parser, $list, static::$OPTIONS));
 }
コード例 #3
0
 /**
  * @param Parser     $parser  The parser that serves as context.
  * @param TokensList $list    The list of tokens that are being parsed.
  * @param array      $options Parameters for parsing.
  *
  * @return ReferencesKeyword
  */
 public static function parse(Parser $parser, TokensList $list, array $options = array())
 {
     $ret = new ReferencesKeyword();
     /**
      * The state of the parser.
      *
      * Below are the states of the parser.
      *
      *      0 ----------------------[ table ]---------------------> 1
      *
      *      1 ---------------------[ columns ]--------------------> 2
      *
      *      2 ---------------------[ options ]--------------------> -1
      *
      * @var int
      */
     $state = 0;
     for (; $list->idx < $list->count; ++$list->idx) {
         /**
          * Token parsed at this moment.
          * @var Token
          */
         $token = $list->tokens[$list->idx];
         // End of statement.
         if ($token->type === Token::TYPE_DELIMITER) {
             break;
         }
         // Skipping whitespaces and comments.
         if ($token->type === Token::TYPE_WHITESPACE || $token->type === Token::TYPE_COMMENT) {
             continue;
         }
         if ($state === 0) {
             $ret->table = $token->value;
             $state = 1;
         } else {
             if ($state === 1) {
                 $ret->columns = ArrayFragment::parse($parser, $list)->values;
                 $state = 2;
             } else {
                 if ($state === 2) {
                     $ret->options = OptionsFragment::parse($parser, $list, static::$REFERENCES_OPTIONS);
                     ++$list->idx;
                     break;
                 }
             }
         }
     }
     --$list->idx;
     return $ret;
 }
コード例 #4
0
 /**
  * @param Parser     $parser  The parser that serves as context.
  * @param TokensList $list    The list of tokens that are being parsed.
  * @param array      $options Parameters for parsing.
  *
  * @return DataTypeFragment[]
  */
 public static function parse(Parser $parser, TokensList $list, array $options = array())
 {
     $ret = new DataTypeFragment();
     /**
      * The state of the parser.
      *
      * Below are the states of the parser.
      *
      *      0 -------------------[ data type ]--------------------> 1
      *
      *      1 ----------------[ size and options ]----------------> 2
      *
      * @var int
      */
     $state = 0;
     for (; $list->idx < $list->count; ++$list->idx) {
         /**
          * Token parsed at this moment.
          * @var Token
          */
         $token = $list->tokens[$list->idx];
         // Skipping whitespaces and comments.
         if ($token->type === Token::TYPE_WHITESPACE || $token->type === Token::TYPE_COMMENT) {
             continue;
         }
         if ($state === 0) {
             $ret->name = strtoupper($token->value);
             if ($token->type !== Token::TYPE_KEYWORD || !($token->flags & Token::FLAG_KEYWORD_DATA_TYPE)) {
                 $parser->error('Unrecognized data type.', $token);
             }
             $state = 1;
         } elseif ($state === 1) {
             if ($token->type === Token::TYPE_OPERATOR && $token->value === '(') {
                 $size = ArrayFragment::parse($parser, $list);
                 ++$list->idx;
                 $ret->parameters = $ret->name === 'ENUM' || $ret->name === 'SET' ? $size->raw : $size->values;
             }
             $ret->options = OptionsFragment::parse($parser, $list, static::$DATA_TYPE_OPTIONS);
             ++$list->idx;
             break;
         }
     }
     if (empty($ret->name)) {
         return null;
     }
     --$list->idx;
     return $ret;
 }
コード例 #5
0
ファイル: Statement.php プロジェクト: dmitry-php/sql-parser
 /**
  * Parses the statements defined by the tokens list.
  *
  * @param Parser     $parser The instance that requests parsing.
  * @param TokensList $list   The list of tokens to be parsed.
  *
  * @return void
  */
 public function parse(Parser $parser, TokensList $list)
 {
     $this->first = $list->idx;
     /**
      * Whether options were parsed or not.
      * For statements that do not have any options this is set to `true` by
      * default.
      * @var bool
      */
     $parsedOptions = isset(static::$OPTIONS) ? false : true;
     for (; $list->idx < $list->count; ++$list->idx) {
         /**
          * Token parsed at this moment.
          * @var Token
          */
         $token = $list->tokens[$list->idx];
         // End of statement.
         if ($token->type === Token::TYPE_DELIMITER) {
             break;
         }
         // Only keywords are relevant here. Other parts of the query are
         // processed in the functions below.
         if ($token->type !== Token::TYPE_KEYWORD) {
             continue;
         }
         /**
          * The name of the class that is used for parsing.
          * @var string
          */
         $class = null;
         /**
          * The name of the field where the result of the parsing is stored.
          * @var string
          */
         $field = null;
         /**
          * Parser's options.
          * @var array
          */
         $options = array();
         if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) {
             $class = Parser::$KEYWORD_PARSERS[$token->value]['class'];
             $field = Parser::$KEYWORD_PARSERS[$token->value]['field'];
             if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) {
                 $options = Parser::$KEYWORD_PARSERS[$token->value]['options'];
             }
         }
         if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
             if (!$parsedOptions) {
                 ++$list->idx;
                 // Skipping keyword.
                 $this->options = OptionsFragment::parse($parser, $list, static::$OPTIONS);
                 $parsedOptions = true;
             }
         } else {
             if ($class === null) {
                 // There is no parser for this keyword and isn't the beggining
                 // of a statement (so no options) either.
                 $parser->error('Unrecognized keyword "' . $token->value . '".', $token);
                 continue;
             }
         }
         $this->before($parser, $list, $token);
         // Parsing this keyword.
         if ($class !== null) {
             ++$list->idx;
             // Skipping keyword.
             $this->{$field} = $class::parse($parser, $list, $options);
         }
         $this->after($parser, $list, $token);
     }
     $this->last = $list->idx--;
     // Go back to last used token.
 }
コード例 #6
0
 /**
  * Parsing the `CREATE` statement.
  *
  * @param Parser     $parser The instance that requests parsing.
  * @param TokensList $list   The list of tokens to be parsed.
  * @param Token      $token  The token that is being parsed.
  *
  * @return void
  */
 public function before(Parser $parser, TokensList $list, Token $token)
 {
     ++$list->idx;
     $this->name = CreateDefFragment::parse($parser, $list);
     if ($this->options->has('TABLE')) {
         ++$list->idx;
         $this->fields = FieldDefFragment::parse($parser, $list);
         ++$list->idx;
         $this->entityOptions = OptionsFragment::parse($parser, $list, CreateDefFragment::$TABLE_OPTIONS);
     } elseif ($this->options->has('PROCEDURE') || $this->options->has('FUNCTION')) {
         ++$list->idx;
         $this->parameters = ParamDefFragment::parse($parser, $list);
         if ($this->options->has('FUNCTION')) {
             $token = $list->getNextOfType(Token::TYPE_KEYWORD);
             if ($token->value !== 'RETURNS') {
                 $parser->error('\'RETURNS\' keyword was expected.', $token);
             } else {
                 ++$list->idx;
                 $this->return = DataTypeFragment::parse($parser, $list);
             }
         }
         ++$list->idx;
         $this->entityOptions = OptionsFragment::parse($parser, $list, CreateDefFragment::$FUNC_OPTIONS);
         ++$list->idx;
         $this->body = array();
         for (; $list->idx < $list->count; ++$list->idx) {
             $token = $list->tokens[$list->idx];
             $this->body[] = $token;
             if ($token->type === Token::TYPE_KEYWORD && $token->value === 'END') {
                 break;
             }
         }
     }
 }
コード例 #7
0
 /**
  * @param Parser     $parser  The parser that serves as context.
  * @param TokensList $list    The list of tokens that are being parsed.
  * @param array      $options Parameters for parsing.
  *
  * @return FieldDefFragment[]
  */
 public static function parse(Parser $parser, TokensList $list, array $options = array())
 {
     $ret = array();
     $expr = new FieldDefFragment();
     /**
      * The state of the parser.
      *
      * Below are the states of the parser.
      *
      *      0 -----------------------[ ( ]------------------------> 1
      *
      *      1 --------------------[ CONSTRAINT ]------------------> 1
      *      1 -----------------------[ key ]----------------------> 2
      *      1 -------------[ constraint / column name ]-----------> 2
      *
      *      2 --------------------[ data type ]-------------------> 3
      *
      *      3 ---------------------[ options ]--------------------> 4
      *
      *      4 --------------------[ REFERENCES ]------------------> 4
      *
      *      5 ------------------------[ , ]-----------------------> 1
      *      5 ------------------------[ ) ]-----------------------> -1
      *
      * @var int
      */
     $state = 0;
     for (; $list->idx < $list->count; ++$list->idx) {
         /**
          * Token parsed at this moment.
          * @var Token
          */
         $token = $list->tokens[$list->idx];
         // End of statement.
         if ($token->type === Token::TYPE_DELIMITER) {
             break;
         }
         // Skipping whitespaces and comments.
         if ($token->type === Token::TYPE_WHITESPACE || $token->type === Token::TYPE_COMMENT) {
             continue;
         }
         if ($state === 0) {
             if ($token->type === Token::TYPE_OPERATOR && $token->value === '(') {
                 $state = 1;
             }
         } elseif ($state === 1) {
             if ($token->type === Token::TYPE_KEYWORD && $token->value === 'CONSTRAINT') {
                 $expr->isConstraint = true;
             } elseif ($token->type === Token::TYPE_KEYWORD && $token->flags & Token::FLAG_KEYWORD_KEY) {
                 $expr->key = KeyFragment::parse($parser, $list);
                 $state = 4;
             } else {
                 $expr->name = $token->value;
                 if (!$expr->isConstraint) {
                     $state = 2;
                 }
             }
         } elseif ($state === 2) {
             $expr->type = DataTypeFragment::parse($parser, $list);
             $state = 3;
         } elseif ($state === 3) {
             $expr->options = OptionsFragment::parse($parser, $list, static::$FIELD_OPTIONS);
             $state = 4;
         } elseif ($state === 4) {
             if ($token->type === Token::TYPE_KEYWORD && $token->value === 'REFERENCES') {
                 ++$list->idx;
                 // Skipping keyword 'REFERENCES'.
                 $expr->references = ReferencesKeyword::parse($parser, $list);
             } else {
                 --$list->idx;
             }
             $state = 5;
         } else {
             if ($state === 5) {
                 if (!empty($expr->type) || !empty($expr->key)) {
                     $ret[] = $expr;
                 }
                 $expr = new FieldDefFragment();
                 if ($token->value === ',') {
                     $state = 1;
                     continue;
                 } elseif ($token->value === ')') {
                     ++$list->idx;
                     break;
                 }
             }
         }
     }
     // Last iteration was not saved.
     if (!empty($expr->type) || !empty($expr->key)) {
         $ret[] = $expr;
     }
     --$list->idx;
     return $ret;
 }