Used for parsing CREATE TABLE statement.
Author: Dan Ungureanu (udan1107@gmail.com)
Inheritance: extends SqlParser\Component
 /**
  * @param FieldDefinition|FieldDefinition[] $component The component to be built.
  *
  * @return string
  */
 public static function build($component)
 {
     if (is_array($component)) {
         $ret = array();
         foreach ($component as $c) {
             $ret[] = static::build($c);
         }
         return "(\n" . implode(",\n", $ret) . "\n)";
     } else {
         $tmp = '';
         if ($component->isConstraint) {
             $tmp .= 'CONSTRAINT ';
         }
         if (!empty($component->name)) {
             $tmp .= Context::escape($component->name) . ' ';
         }
         if (!empty($component->type)) {
             $tmp .= DataType::build($component->type) . ' ';
         }
         if (!empty($component->key)) {
             $tmp .= Key::build($component->key) . ' ';
         }
         if (!empty($component->references)) {
             $tmp .= 'REFERENCES ' . Reference::build($component->references) . ' ';
         }
         $tmp .= OptionsArray::build($component->options);
         return trim($tmp);
     }
 }
 /**
  * @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 CreateDefinition[]
  */
 public static function parse(Parser $parser, TokensList $list, array $options = array())
 {
     $ret = array();
     $expr = new CreateDefinition();
     /**
      * 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 ------------------------[ ) ]-----------------------> 6 (-1)
      *
      * @var int $state
      */
     $state = 0;
     for (; $list->idx < $list->count; ++$list->idx) {
         /**
          * Token parsed at this moment.
          *
          * @var Token $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;
             } else {
                 $parser->error(__('An opening bracket was expected.'), $token);
                 break;
             }
         } 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 = Key::parse($parser, $list);
                 $state = 4;
             } else {
                 $expr->name = $token->value;
                 if (!$expr->isConstraint) {
                     $state = 2;
                 }
             }
         } elseif ($state === 2) {
             $expr->type = DataType::parse($parser, $list);
             $state = 3;
         } elseif ($state === 3) {
             $expr->options = OptionsArray::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 = Reference::parse($parser, $list);
             } else {
                 --$list->idx;
             }
             $state = 5;
         } elseif ($state === 5) {
             if (!empty($expr->type) || !empty($expr->key)) {
                 $ret[] = $expr;
             }
             $expr = new CreateDefinition();
             if ($token->value === ',') {
                 $state = 1;
             } elseif ($token->value === ')') {
                 $state = 6;
                 ++$list->idx;
                 break;
             } else {
                 $parser->error(__('A comma or a closing bracket was expected.'), $token);
                 $state = 0;
                 break;
             }
         }
     }
     // Last iteration was not saved.
     if (!empty($expr->type) || !empty($expr->key)) {
         $ret[] = $expr;
     }
     if ($state !== 0 && $state !== 6) {
         $parser->error(__('A closing bracket was expected.'), $list->tokens[$list->idx - 1]);
     }
     --$list->idx;
     return $ret;
 }
Exemple #3
0
 public function testParse()
 {
     $component = Key::parse(new Parser(), $this->getTokensList(''));
     $this->assertEquals(null, $component->name);
 }