diff options
author | Dan Ungureanu <udan1107@gmail.com> | 2015-06-23 19:06:11 +0300 |
---|---|---|
committer | Dan Ungureanu <udan1107@gmail.com> | 2015-06-23 19:06:11 +0300 |
commit | 22f167b6fe82809c33e49a3a23dd500178282985 (patch) | |
tree | 1437b3de48840ab77a895dfafcbdbf27bde966fd | |
parent | e316e267117a38e59040002154f2f980b1a6501d (diff) | |
download | sql-parser-22f167b6fe82809c33e49a3a23dd500178282985.zip sql-parser-22f167b6fe82809c33e49a3a23dd500178282985.tar.gz sql-parser-22f167b6fe82809c33e49a3a23dd500178282985.tar.bz2 |
Added table utilities.
Implemented better support for keys in FieldDefFragment.
Improved contexts' documentation and definition.
-rw-r--r-- | src/Context.php | 19 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50000.php | 19 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50100.php | 19 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50500.php | 19 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50600.php | 19 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50700.php | 19 | ||||
-rw-r--r-- | src/Fragments/FieldDefFragment.php | 76 | ||||
-rw-r--r-- | src/Fragments/KeyFragment.php | 132 | ||||
-rw-r--r-- | src/Fragments/ReferencesKeyword.php | 115 | ||||
-rw-r--r-- | src/Utils/Table.php | 45 | ||||
-rw-r--r-- | tests/data/parseCreateTable.out | 2 |
11 files changed, 420 insertions, 64 deletions
diff --git a/src/Context.php b/src/Context.php index eed10d3..cbe666d 100644 --- a/src/Context.php +++ b/src/Context.php @@ -53,30 +53,22 @@ abstract class Context */ public static $contextPrefix = '\\SqlParser\\Contexts\\Context'; - // ------------------------------------------------------------------------- - // Keywords. - /** * List of keywords. * * Because, PHP's associative arrays are basically hash tables, it is more * efficient to store keywords as keys instead of values. * - * There are multiple types of keyword, depending on the value associated: - * 1 - reserved keywords - * 2 - keyword - * 3 - composite keyword (unofficial); used to make the job of the lexer - * much easier by grouping keywords that may appear together + * The value associated to each keyword represents its flags. * - * Keywords below are sorted by type, length and keyword. + * @see Token::FLAG_KEYWORD_* + * + * Elements are sorted by flags, length and keyword. * * @var array */ public static $KEYWORDS = array(); - // ------------------------------------------------------------------------- - // Operators. - /** * List of operators and their flags. * @@ -110,9 +102,6 @@ abstract class Context '(' => 16, ')' => 16, '.' => 16, ',' => 16, ); - // ------------------------------------------------------------------------- - // SQL Modes. - /* * Server SQL Modes * https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html diff --git a/src/Contexts/ContextMySql50000.php b/src/Contexts/ContextMySql50000.php index b81d687..f2357f2 100644 --- a/src/Contexts/ContextMySql50000.php +++ b/src/Contexts/ContextMySql50000.php @@ -1,5 +1,11 @@ <?php +/** + * Context for MySQL 5. + * + * @link https://dev.mysql.com/doc/refman/5.0/en/keywords.html + */ + namespace SqlParser\Contexts; use SqlParser\Context; @@ -16,6 +22,15 @@ use SqlParser\Context; class ContextMySql50000 extends Context { + /** + * List of keywords. + * + * The value associated to each keyword represents its flags. + * + * @see Token::FLAG_KEYWORD_* + * + * @var array + */ public static $KEYWORDS = array( 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -137,8 +152,8 @@ class ContextMySql50000 extends Context 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/src/Contexts/ContextMySql50100.php b/src/Contexts/ContextMySql50100.php index 260925e..dcdce84 100644 --- a/src/Contexts/ContextMySql50100.php +++ b/src/Contexts/ContextMySql50100.php @@ -1,5 +1,11 @@ <?php +/** + * Context for MySQL 5.1. + * + * @link https://dev.mysql.com/doc/refman/5.1/en/keywords.html + */ + namespace SqlParser\Contexts; use SqlParser\Context; @@ -16,6 +22,15 @@ use SqlParser\Context; class ContextMySql50100 extends Context { + /** + * List of keywords. + * + * The value associated to each keyword represents its flags. + * + * @see Token::FLAG_KEYWORD_* + * + * @var array + */ public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -151,8 +166,8 @@ class ContextMySql50100 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/src/Contexts/ContextMySql50500.php b/src/Contexts/ContextMySql50500.php index e70b931..15e079e 100644 --- a/src/Contexts/ContextMySql50500.php +++ b/src/Contexts/ContextMySql50500.php @@ -1,5 +1,11 @@ <?php +/** + * Context for MySQL 5.5. + * + * @link https://dev.mysql.com/doc/refman/5.5/en/keywords.html + */ + namespace SqlParser\Contexts; use SqlParser\Context; @@ -16,6 +22,15 @@ use SqlParser\Context; class ContextMySql50500 extends Context { + /** + * List of keywords. + * + * The value associated to each keyword represents its flags. + * + * @see Token::FLAG_KEYWORD_* + * + * @var array + */ public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -154,8 +169,8 @@ class ContextMySql50500 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/src/Contexts/ContextMySql50600.php b/src/Contexts/ContextMySql50600.php index 819ec1c..1135e52 100644 --- a/src/Contexts/ContextMySql50600.php +++ b/src/Contexts/ContextMySql50600.php @@ -1,5 +1,11 @@ <?php +/** + * Context for MySQL 5.6. + * + * @link https://dev.mysql.com/doc/refman/5.6/en/keywords.html + */ + namespace SqlParser\Contexts; use SqlParser\Context; @@ -16,6 +22,15 @@ use SqlParser\Context; class ContextMySql50600 extends Context { + /** + * List of keywords. + * + * The value associated to each keyword represents its flags. + * + * @see Token::FLAG_KEYWORD_* + * + * @var array + */ public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -165,8 +180,8 @@ class ContextMySql50600 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/src/Contexts/ContextMySql50700.php b/src/Contexts/ContextMySql50700.php index db047b1..799ae1b 100644 --- a/src/Contexts/ContextMySql50700.php +++ b/src/Contexts/ContextMySql50700.php @@ -1,5 +1,11 @@ <?php +/** + * Context for MySQL 5.7. + * + * @link https://dev.mysql.com/doc/refman/5.7/en/keywords.html + */ + namespace SqlParser\Contexts; use SqlParser\Context; @@ -16,6 +22,15 @@ use SqlParser\Context; class ContextMySql50700 extends Context { + /** + * List of keywords. + * + * The value associated to each keyword represents its flags. + * + * @see Token::FLAG_KEYWORD_* + * + * @var array + */ public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -170,8 +185,8 @@ class ContextMySql50700 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/src/Fragments/FieldDefFragment.php b/src/Fragments/FieldDefFragment.php index f4a08bd..20983e9 100644 --- a/src/Fragments/FieldDefFragment.php +++ b/src/Fragments/FieldDefFragment.php @@ -49,6 +49,13 @@ class FieldDefFragment extends Fragment public $name; /** + * Whether this field is a constraint or not. + * + * @var bool + */ + public $isConstraint; + + /** * The data type of thew new column. * * @var DataTypeFragment @@ -56,11 +63,18 @@ class FieldDefFragment extends Fragment public $type; /** - * The array of indexes. + * The key. * - * @var ArrayFragment + * @var KeyFragment */ - public $indexes; + public $key; + + /** + * The table that is referenced. + * + * @var ReferencesKeyword + */ + public $references; /** * The options of the new field fragment. @@ -89,22 +103,18 @@ class FieldDefFragment extends Fragment * * 0 -----------------------[ ( ]------------------------> 1 * - * 1 -------------------[ CONSTRAINT ]-------------------> 4 - * 1 --------------------[ key type ]--------------------> 5 - * 1 -------------------[ column name ]------------------> 2 + * 1 --------------------[ CONSTRAINT ]------------------> 1 + * 1 -----------------------[ key ]----------------------> 2 + * 1 -------------[ constraint / column name ]-----------> 2 * - * 2 -------------------[ data type ]--------------------> 3 + * 2 --------------------[ data type ]-------------------> 3 * - * 3 ---------------------[ size ]---------------------> 3 * 3 ---------------------[ options ]--------------------> 4 * - * 4 -----------------[ CONSTRAINT name ]----------------> 4 - * 4 -----------------[ CONSTRAINT type ]----------------> 5 - * - * 5 -------------------[ index names ]------------------> 6 + * 4 --------------------[ REFERENCES ]------------------> 4 * - * 6 ------------------------[ , ]-----------------------> 1 - * 6 ------------------------[ ) ]-----------------------> -1 + * 5 ------------------------[ , ]-----------------------> 1 + * 5 ------------------------[ ) ]-----------------------> -1 * * @var int */ @@ -132,42 +142,34 @@ class FieldDefFragment extends Fragment if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $state = 1; } - continue; } elseif ($state === 1) { if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'CONSTRAINT')) { - $state = 4; + $expr->isConstraint = true; } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_KEY)) { - $expr->type = $token->value; - $state = 5; - } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { - $parser->error('Unexpected keyword.', $token); - break; // TODO: Skip to the end of the query. + $expr->key = KeyFragment::parse($parser, $list); + $state = 4; } else { $expr->name = $token->value; - $state = 2; + 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 = 6; + $state = 4; } elseif ($state === 4) { - if (($token->type !== Token::TYPE_KEYWORD) || (!($token->flags & Token::FLAG_KEYWORD_KEY))) { - $expr->name = $token->value; + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'REFERENCES')) { + ++$list->idx; // Skipping keyword 'REFERENCES'. + $expr->references = ReferencesKeyword::parse($parser, $list); } else { - $expr->type = $token->value; - $state = 5; - } - } elseif ($state === 5) { - if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { - $expr->indexes = ArrayFragment::parse($parser, $list); - $state = 6; - } else { - $expr->name = $token->value; + --$list->idx; } - } elseif ($state === 6) { - if (!empty($expr->type)) { + $state = 5; + } else if ($state === 5) { + if ((!empty($expr->type)) || (!empty($expr->key))) { $ret[] = $expr; } $expr = new FieldDefFragment(); @@ -183,7 +185,7 @@ class FieldDefFragment extends Fragment } // Last iteration was not saved. - if (!empty($expr->type)) { + if ((!empty($expr->type)) || (!empty($expr->key))) { $ret[] = $expr; } diff --git a/src/Fragments/KeyFragment.php b/src/Fragments/KeyFragment.php new file mode 100644 index 0000000..9685f9e --- /dev/null +++ b/src/Fragments/KeyFragment.php @@ -0,0 +1,132 @@ +<?php + +namespace SqlParser\Fragments; + +use SqlParser\Context; +use SqlParser\Fragment; +use SqlParser\Parser; +use SqlParser\Token; +use SqlParser\TokensList; + +/** + * Parses the definition of a key. + * + * Used for parsing `CREATE TABLE` statement. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu <udan1107@gmail.com> + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class KeyFragment extends Fragment +{ + + /** + * All key options. + * + * @var array + */ + public static $KEY_OPTIONS = array( + 'KEY_BLOCK_SIZE' => array(1, 'var'), + 'USING' => array(2, 'var'), + 'WITH PARSER' => array(3, 'var'), + ); + + /** + * The name of this key. + * + * @var string + */ + public $name; + + /** + * Columns. + * + * @var array + */ + public $columns; + + /** + * The type of this key. + * + * @var string + */ + public $type; + + /** + * @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 KeyFragment[] + */ + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + $ret = new KeyFragment(); + + /** + * 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) { + $ret->type = $token->value; + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $ret->columns = ArrayFragment::parse($parser, $list)->array; + $state = 2; + } else { + $ret->name = $token->value; + } + } elseif ($state === 2) { + $ret->options = OptionsFragment::parse($parser, $list, static::$KEY_OPTIONS); + ++$list->idx; + break; + } + + } + + --$list->idx; + return $ret; + + } +} diff --git a/src/Fragments/ReferencesKeyword.php b/src/Fragments/ReferencesKeyword.php new file mode 100644 index 0000000..fbd69ba --- /dev/null +++ b/src/Fragments/ReferencesKeyword.php @@ -0,0 +1,115 @@ +<?php + +namespace SqlParser\Fragments; + +use SqlParser\Fragment; +use SqlParser\Parser; +use SqlParser\Token; +use SqlParser\TokensList; + +/** + * `REFERENCES` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu <udan1107@gmail.com> + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ReferencesKeyword extends Fragment +{ + + /** + * All references options. + * + * @var array + */ + public static $REFERENCES_OPTIONS = array( + 'MATCH' => array(1, 'var'), + 'ON DELETE' => array(2, 'var'), + 'ON UPDATE' => array(3, 'var'), + ); + + /** + * The referenced table. + * + * @var string + */ + public $table; + + /** + * The referenced columns. + * + * @var array + */ + public $columns; + + /** + * The options of the referencing. + * + * @var OptionsFragment + */ + public $options; + + /** + * @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)->array; + $state = 2; + } else if ($state === 2) { + $ret->options = OptionsFragment::parse($parser, $list, static::$REFERENCES_OPTIONS); + ++$list->idx; + break; + } + + } + + --$list->idx; + return $ret; + } +} diff --git a/src/Utils/Table.php b/src/Utils/Table.php index 7560f9d..1e88297 100644 --- a/src/Utils/Table.php +++ b/src/Utils/Table.php @@ -20,6 +20,49 @@ use SqlParser\Statements\CreateStatement; class Table { + public static function getForeignKeys(CreateStatement $tree) + { + if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { + return array(); + } + + $ret = array(); + + foreach ($tree->fields as $field) { + + if ((empty($field->key)) || ($field->key->type !== 'FOREIGN KEY')) { + continue; + } + + $tmp = array( + 'constraint' => $field->name, + 'index_list' => $field->key->columns, + ); + + if (!empty($field->references)) { + $tmp['ref_table_name'] = $field->references->table; + $tmp['ref_index_list'] = $field->references->columns; + + if (($opt = $field->references->options->has('ON UPDATE'))) { + $tmp['on_update'] = str_replace(' ', '_', $opt); + } + + if (($opt = $field->references->options->has('ON DELETE'))) { + $tmp['on_delete'] = str_replace(' ', '_', $opt); + } + + if (($opt = $field->references->options->has('MATCH'))) { + $tmp['match'] = str_replace(' ', '_', $opt); + } + } + + $ret[] = $tmp; + + } + + return $ret; + } + public static function getFields(CreateStatement $tree) { if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { @@ -31,7 +74,7 @@ class Table foreach ($tree->fields as $field) { // Skipping keys. - if (is_string($field->type)) { + if (empty($field->type)) { continue; } diff --git a/tests/data/parseCreateTable.out b/tests/data/parseCreateTable.out index 500bfb3..a607f9e 100644 --- a/tests/data/parseCreateTable.out +++ b/tests/data/parseCreateTable.out @@ -4,4 +4,4 @@ a:2:{s:6:"parser";O:16:"SqlParser\Parser":4:{s:4:"list";O:20:"SqlParser\TokensLi ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:103;}i:29;O:15:"SqlParser\Token":5:{s:5:"token";s:10:"`password`";s:5:"value";s:8:"password";s:4:"type";i:8;s:5:"flags";i:2;s:8:"position";i:108;}i:30;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:118;}i:31;O:15:"SqlParser\Token":5:{s:5:"token";s:7:"VARCHAR";s:5:"value";s:7:"VARCHAR";s:4:"type";i:1;s:5:"flags";i:11;s:8:"position";i:119;}i:32;O:15:"SqlParser\Token":5:{s:5:"token";s:1:"(";s:5:"value";s:1:"(";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:126;}i:33;O:15:"SqlParser\Token":5:{s:5:"token";s:3:"256";s:5:"value";i:256;s:4:"type";i:6;s:5:"flags";i:0;s:8:"position";i:127;}i:34;O:15:"SqlParser\Token":5:{s:5:"token";s:1:")";s:5:"value";s:1:")";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:130;}i:35;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:131;}i:36;O:15:"SqlParser\Token":5:{s:5:"token";s:7:"DEFAULT";s:5:"value";s:7:"DEFAULT";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:132;}i:37;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:139;}i:38;O:15:"SqlParser\Token":5:{s:5:"token";s:8:"'123456'";s:5:"value";s:6:"123456";s:4:"type";i:7;s:5:"flags";i:1;s:8:"position";i:140;}i:39;O:15:"SqlParser\Token":5:{s:5:"token";s:1:",";s:5:"value";s:1:",";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:148;}i:40;O:15:"SqlParser\Token":5:{s:5:"token";s:5:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:149;}i:41;O:15:"SqlParser\Token":5:{s:5:"token";s:10:"CONSTRAINT";s:5:"value";s:10:"CONSTRAINT";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:154;}i:42;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:164;}i:43;O:15:"SqlParser\Token":5:{s:5:"token";s:5:"pk_id";s:5:"value";s:5:"pk_id";s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:165;}i:44;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:170;}i:45;O:15:"SqlParser\Token":5:{s:5:"token";s:11:"PRIMARY KEY";s:5:"value";s:11:"PRIMARY KEY";s:4:"type";i:1;s:5:"flags";i:21;s:8:"position";i:171;}i:46;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:182;}i:47;O:15:"SqlParser\Token":5:{s:5:"token";s:1:"(";s:5:"value";s:1:"(";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:183;}i:48;O:15:"SqlParser\Token":5:{s:5:"token";s:4:"`id`";s:5:"value";s:2:"id";s:4:"type";i:8;s:5:"flags";i:2;s:8:"position";i:184;}i:49;O:15:"SqlParser\Token":5:{s:5:"token";s:1:")";s:5:"value";s:1:")";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:188;}i:50;O:15:"SqlParser\Token":5:{s:5:"token";s:1:",";s:5:"value";s:1:",";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:189;}i:51;O:15:"SqlParser\Token":5:{s:5:"token";s:5:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:190;}i:52;O:15:"SqlParser\Token":5:{s:5:"token";s:6:"UNIQUE";s:5:"value";s:6:"UNIQUE";s:4:"type";i:1;s:5:"flags";i:19;s:8:"position";i:195;}i:53;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:201;}i:54;O:15:"SqlParser\Token":5:{s:5:"token";s:1:"(";s:5:"value";s:1:"(";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:202;}i:55;O:15:"SqlParser\Token":5:{s:5:"token";s:8:"username";s:5:"value";s:8:"username";s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:203;}i:56;O:15:"SqlParser\Token":5:{s:5:"token";s:1:")";s:5:"value";s:1:")";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:211;}i:57;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" -";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:212;}i:58;O:15:"SqlParser\Token":5:{s:5:"token";s:1:")";s:5:"value";s:1:")";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:213;}i:59;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:214;}i:60;O:15:"SqlParser\Token":5:{s:5:"token";s:6:"ENGINE";s:5:"value";s:6:"ENGINE";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:215;}i:61;O:15:"SqlParser\Token":5:{s:5:"token";s:1:"=";s:5:"value";s:1:"=";s:4:"type";i:2;s:5:"flags";i:2;s:8:"position";i:221;}i:62;O:15:"SqlParser\Token":5:{s:5:"token";s:6:"InnoDB";s:5:"value";s:6:"InnoDB";s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:222;}i:63;O:15:"SqlParser\Token":5:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:228;}i:64;O:15:"SqlParser\Token":5:{s:5:"token";N;s:5:"value";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:65;s:3:"idx";i:65;}s:6:"strict";b:0;s:6:"errors";a:0:{}s:10:"statements";a:1:{i:0;O:36:"SqlParser\Statements\CreateStatement":8:{s:4:"name";O:37:"SqlParser\Fragments\CreateDefFragment":1:{s:4:"name";s:5:"users";}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:2:{i:1;s:5:"TABLE";i:3;s:13:"IF NOT EXISTS";}}s:10:"parameters";N;s:12:"tableOptions";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:1:{i:1;a:2:{s:4:"name";s:6:"ENGINE";s:5:"value";s:6:"InnoDB";}}}s:6:"fields";a:5:{i:0;O:36:"SqlParser\Fragments\FieldDefFragment":4:{s:4:"name";s:2:"id";s:4:"type";O:36:"SqlParser\Fragments\DataTypeFragment":3:{s:4:"name";s:3:"INT";s:4:"size";a:0:{}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:7:"indexes";N;s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:2:{i:1;s:8:"NOT NULL";i:3;s:14:"AUTO_INCREMENT";}}}i:1;O:36:"SqlParser\Fragments\FieldDefFragment":4:{s:4:"name";s:8:"username";s:4:"type";O:36:"SqlParser\Fragments\DataTypeFragment":3:{s:4:"name";s:7:"VARCHAR";s:4:"size";a:1:{i:0;i:64;}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:7:"indexes";N;s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:1:{i:1;s:4:"NULL";}}}i:2;O:36:"SqlParser\Fragments\FieldDefFragment":4:{s:4:"name";s:8:"password";s:4:"type";O:36:"SqlParser\Fragments\DataTypeFragment":3:{s:4:"name";s:7:"VARCHAR";s:4:"size";a:1:{i:0;i:256;}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:7:"indexes";N;s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:1:{i:2;a:2:{s:4:"name";s:7:"DEFAULT";s:5:"value";s:6:"123456";}}}}i:3;O:36:"SqlParser\Fragments\FieldDefFragment":4:{s:4:"name";s:5:"pk_id";s:4:"type";s:11:"PRIMARY KEY";s:7:"indexes";O:33:"SqlParser\Fragments\ArrayFragment":2:{s:5:"array";a:1:{i:0;s:2:"id";}s:3:"raw";a:1:{i:0;s:4:"`id`";}}s:7:"options";N;}i:4;O:36:"SqlParser\Fragments\FieldDefFragment":4:{s:4:"name";N;s:4:"type";s:6:"UNIQUE";s:7:"indexes";O:33:"SqlParser\Fragments\ArrayFragment":2:{s:5:"array";a:1:{i:0;s:8:"username";}s:3:"raw";a:1:{i:0;s:8:"username";}}s:7:"options";N;}}s:4:"body";N;s:5:"first";N;s:4:"last";i:62;}}}s:6:"errors";a:0:{}}
\ No newline at end of file +";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:212;}i:58;O:15:"SqlParser\Token":5:{s:5:"token";s:1:")";s:5:"value";s:1:")";s:4:"type";i:2;s:5:"flags";i:16;s:8:"position";i:213;}i:59;O:15:"SqlParser\Token":5:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:214;}i:60;O:15:"SqlParser\Token":5:{s:5:"token";s:6:"ENGINE";s:5:"value";s:6:"ENGINE";s:4:"type";i:1;s:5:"flags";i:1;s:8:"position";i:215;}i:61;O:15:"SqlParser\Token":5:{s:5:"token";s:1:"=";s:5:"value";s:1:"=";s:4:"type";i:2;s:5:"flags";i:2;s:8:"position";i:221;}i:62;O:15:"SqlParser\Token":5:{s:5:"token";s:6:"InnoDB";s:5:"value";s:6:"InnoDB";s:4:"type";i:0;s:5:"flags";i:0;s:8:"position";i:222;}i:63;O:15:"SqlParser\Token":5:{s:5:"token";s:1:";";s:5:"value";s:1:";";s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";i:228;}i:64;O:15:"SqlParser\Token":5:{s:5:"token";N;s:5:"value";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:65;s:3:"idx";i:65;}s:6:"strict";b:0;s:6:"errors";a:0:{}s:10:"statements";a:1:{i:0;O:36:"SqlParser\Statements\CreateStatement":8:{s:4:"name";O:37:"SqlParser\Fragments\CreateDefFragment":1:{s:4:"name";s:5:"users";}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:2:{i:1;s:5:"TABLE";i:3;s:13:"IF NOT EXISTS";}}s:10:"parameters";N;s:12:"tableOptions";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:1:{i:1;a:2:{s:4:"name";s:6:"ENGINE";s:5:"value";s:6:"InnoDB";}}}s:6:"fields";a:5:{i:0;O:36:"SqlParser\Fragments\FieldDefFragment":6:{s:4:"name";s:2:"id";s:12:"isConstraint";N;s:4:"type";O:36:"SqlParser\Fragments\DataTypeFragment":3:{s:4:"name";s:3:"INT";s:4:"size";a:0:{}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:3:"key";N;s:10:"references";N;s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:2:{i:1;s:8:"NOT NULL";i:3;s:14:"AUTO_INCREMENT";}}}i:1;O:36:"SqlParser\Fragments\FieldDefFragment":6:{s:4:"name";s:8:"username";s:12:"isConstraint";N;s:4:"type";O:36:"SqlParser\Fragments\DataTypeFragment":3:{s:4:"name";s:7:"VARCHAR";s:4:"size";a:1:{i:0;i:64;}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:3:"key";N;s:10:"references";N;s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:1:{i:1;s:4:"NULL";}}}i:2;O:36:"SqlParser\Fragments\FieldDefFragment":6:{s:4:"name";s:8:"password";s:12:"isConstraint";N;s:4:"type";O:36:"SqlParser\Fragments\DataTypeFragment":3:{s:4:"name";s:7:"VARCHAR";s:4:"size";a:1:{i:0;i:256;}s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:3:"key";N;s:10:"references";N;s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:1:{i:2;a:2:{s:4:"name";s:7:"DEFAULT";s:5:"value";s:6:"123456";}}}}i:3;O:36:"SqlParser\Fragments\FieldDefFragment":6:{s:4:"name";s:5:"pk_id";s:12:"isConstraint";b:1;s:4:"type";N;s:3:"key";O:31:"SqlParser\Fragments\KeyFragment":4:{s:4:"name";N;s:7:"columns";a:1:{i:0;s:2:"id";}s:4:"type";s:11:"PRIMARY KEY";s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:10:"references";N;s:7:"options";N;}i:4;O:36:"SqlParser\Fragments\FieldDefFragment":6:{s:4:"name";N;s:12:"isConstraint";N;s:4:"type";N;s:3:"key";O:31:"SqlParser\Fragments\KeyFragment":4:{s:4:"name";N;s:7:"columns";a:1:{i:0;s:8:"username";}s:4:"type";s:6:"UNIQUE";s:7:"options";O:35:"SqlParser\Fragments\OptionsFragment":1:{s:7:"options";a:0:{}}}s:10:"references";N;s:7:"options";N;}}s:4:"body";N;s:5:"first";N;s:4:"last";i:62;}}}s:6:"errors";a:0:{}}
\ No newline at end of file |