diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Component.php | 11 | ||||
-rw-r--r-- | src/Components/Expression.php | 15 | ||||
-rw-r--r-- | src/Components/FieldDefinition.php | 6 | ||||
-rw-r--r-- | src/Components/OptionsArray.php | 146 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50000.php | 7 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50100.php | 10 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50500.php | 10 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50600.php | 9 | ||||
-rw-r--r-- | src/Contexts/ContextMySql50700.php | 7 | ||||
-rw-r--r-- | src/Statement.php | 13 |
10 files changed, 179 insertions, 55 deletions
diff --git a/src/Component.php b/src/Component.php index 3505f3d..599784a 100644 --- a/src/Component.php +++ b/src/Component.php @@ -57,4 +57,15 @@ abstract class Component // abstract. return null; } + + /** + * Builds the string representation of a component of this type. + * + * @see static::build + * + * @return string + */ + public function __toString() { + return static::build($this); + } } diff --git a/src/Components/Expression.php b/src/Components/Expression.php index 29b5635..065810c 100644 --- a/src/Components/Expression.php +++ b/src/Components/Expression.php @@ -205,7 +205,7 @@ class Expression extends Component // We don't check to see if `$prev` is `true` (open bracket // was found before) because the brackets count is one (the // only bracket we found is this one). - if (($brackets === 1) && (empty($ret->function)) && ($prev !== null) && ($prev !== true)) { + if ((empty($ret->function)) && ($prev !== null) && ($prev !== true)) { // A function name was previously found and now an open // bracket, so this is a function call. $ret->function = $prev; @@ -213,7 +213,15 @@ class Expression extends Component $isExpr = true; } elseif ($token->value === ')') { --$brackets; - if ($brackets < 0) { + if ($brackets === 0) { + if (!empty($options['bracketsDelimited'])) { + // The current token is the last brackets, the next + // one will be outside. + $ret->expr .= $token->token; + ++$list->idx; + break; + } + } elseif ($brackets < 0) { $parser->error('Unexpected bracket.', $token); $brackets = 0; } @@ -268,11 +276,12 @@ class Expression extends Component } else { // Parsing aliases without `AS` keyword. // Example: SELECT 'foo' `bar` - if ($brackets === 0) { + if (($brackets === 0) && (empty($options['noAlias']))) { if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING) || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK)) ) { $ret->alias = $token->value; + continue; } } } diff --git a/src/Components/FieldDefinition.php b/src/Components/FieldDefinition.php index 0c3ea4f..22719eb 100644 --- a/src/Components/FieldDefinition.php +++ b/src/Components/FieldDefinition.php @@ -47,6 +47,12 @@ class FieldDefinition extends Component 'COMMENT' => array(5, 'var'), 'COLUMN_FORMAT' => array(6, 'var'), 'ON UPDATE' => array(7, 'var'), + + // MariaDB options. + 'GENERATED ALWAYS' => 1, + 'AS' => array(2, 'expr', array('bracketsDelimited' => true)), + 'VIRTUAL' => 3, + 'PERSISTENT' => 3, ); /** diff --git a/src/Components/OptionsArray.php b/src/Components/OptionsArray.php index d691e86..1bd68c5 100644 --- a/src/Components/OptionsArray.php +++ b/src/Components/OptionsArray.php @@ -72,8 +72,27 @@ class OptionsArray extends Component */ $lastOptionId = 0; + /** + * Counts brackets. + * @var int $brackets + */ $brackets = 0; + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 ---------------------[ option ]----------------------> 1 + * + * 1 -------------------[ = (optional) ]------------------> 2 + * + * 2 ----------------------[ value ]----------------------> 0 + * + * @var int + */ + $state = 0; + for (; $list->idx < $list->count; ++$list->idx) { /** * Token parsed at this moment. @@ -86,23 +105,36 @@ class OptionsArray extends Component break; } - // Skipping whitespaces and comments. - if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + // Skipping comments. + if ($token->type === Token::TYPE_COMMENT) { + continue; + } + + // Skipping whitespaces if not parsing value. + if (($token->type === Token::TYPE_WHITESPACE) && ($brackets === 0)) { continue; } if ($lastOption === null) { - if (isset($options[strtoupper($token->token)])) { - $lastOption = $options[strtoupper($token->token)]; - $lastOptionId = is_array($lastOption) ? $lastOption[0] : $lastOption; + $upper = strtoupper($token->token); + if (isset($options[$upper])) { + $lastOption = $options[$upper]; + $lastOptionId = is_array($lastOption) ? + $lastOption[0] : $lastOption; + $state = 0; // Checking for option conflicts. - // For example, in `SELECT` statements the keywords `ALL` and `DISTINCT` - // conflict and if used together, they produce an invalid query. - // Usually, tokens can be identified in the array by the option ID, - // but if conflicts occur, a generated option ID is used. - // The first pseudo duplicate ID is the maximum value of the real - // options (e.g. if there are 5 options, the first fake ID is 6). + // For example, in `SELECT` statements the keywords `ALL` + // and `DISTINCT` conflict and if used together, they + // produce an invalid query. + // + // Usually, tokens can be identified in the array by the + // option ID, but if conflicts occur, a generated option ID + // is used. + // + // The first pseudo duplicate ID is the maximum value of the + // real options (e.g. if there are 5 options, the first + // fake ID is 6). if (isset($ret->options[$lastOptionId])) { $parser->error('This option conflicts with \'' . $ret->options[$lastOptionId] . '\'.', $token); $lastOptionId = $lastAssignedId++; @@ -113,33 +145,79 @@ class OptionsArray extends Component } } - if (is_array($lastOption)) { - if (empty($ret->options[$lastOptionId])) { + if ($state === 0) { + if (!is_array($lastOption)) { + // This is a just keyword option without any value. + // This is the beginning and the end of it. + $ret->options[$lastOptionId] = $token->value; + $lastOption = null; + $state = 0; + } elseif (($lastOption[1] === 'var') || ($lastOption[1] === 'var=')) { + // This is a keyword that is followewd by a value. + // This is only the beginning. The value is parsed in state + // 1 and 2. State 1 is used to skip the first equals sign + // and state 2 to parse the actual value. $ret->options[$lastOptionId] = array( + // @var The name of the option. 'name' => $token->value, + // @var Whether it contains an equal sign. + // This is used by the builder to rebuild it. 'equal' => $lastOption[1] === 'var=', + // @var Raw value. 'value' => '', + // @var Processed value. 'value_' => '', ); + $state = 1; + } elseif ($lastOption[1] === 'expr') { + // This is a keyword that is followed by an expression. + // The expression is used by the specialized parser. + + // Skipping this option in order to parse the expression. + ++$list->idx; + $ret->options[$lastOptionId] = array( + 'name' => $token->value, + 'value' => null, + ); + $state = 1; + } + } elseif ($state === 1) { + $state = 2; + if ($token->value === '=') { + $ret->options[$lastOptionId]['equal'] = true; + continue; + } + } + + // This is outside the `elseif` group above because the change might + // change this iteration. + if ($state === 2) { + if ($lastOption[1] === 'expr') { + $ret->options[$lastOptionId]['value'] = Expression::parse( + $parser, + $list, + empty($lastOption[2]) ? array() : $lastOption[2] + ); + $lastOption = null; + $state = 0; } else { - if ($token->value !== '=') { - if ($token->value === '(') { - ++$brackets; - } elseif ($token->value === ')') { - --$brackets; - } else { - // Raw and processed value. - $ret->options[$lastOptionId]['value'] .= $token->token; - $ret->options[$lastOptionId]['value_'] .= $token->value; - } - if ($brackets === 0) { - $lastOption = null; - } + if ($token->token === '(') { + ++$brackets; + } elseif ($token->token === ')') { + --$brackets; + } + + // Raw value. + $ret->options[$lastOptionId]['value'] .= $token->token; + + // Processed value. + $ret->options[$lastOptionId]['value_'] .= $token->value; + + // Checking if we finished parsing. + if ($brackets === 0) { + $lastOption = null; } } - } else { - $ret->options[$lastOptionId] = $token->value; - $lastOption = null; } } @@ -161,12 +239,14 @@ class OptionsArray extends Component } $options = array(); foreach ($component->options as $option) { - if (is_array($option)) { + if (!is_array($option)) { + $options[] = $option; + } else { $options[] = $option['name'] . (!empty($option['equal']) ? '=' : ' ') - . $option['value']; - } else { - $options[] = $option; + . ((string) $option['value']); + // If `$option['value']` happens to be a component, the magic + // method will build it automatically. } } return implode(' ', $options); diff --git a/src/Contexts/ContextMySql50000.php b/src/Contexts/ContextMySql50000.php index 48a928c..5069b91 100644 --- a/src/Contexts/ContextMySql50000.php +++ b/src/Contexts/ContextMySql50000.php @@ -63,7 +63,7 @@ class ContextMySql50000 extends Context 'MIGRATE' => 1, 'PARTIAL' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, - 'UPGRADE' => 1, 'USE_FRM' => 1, + 'UPGRADE' => 1, 'USE_FRM' => 1, 'VIRTUAL' => 1, 'CASCADED' => 1, 'CHECKSUM' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, @@ -77,8 +77,8 @@ class ContextMySql50000 extends Context 'VARIABLES' => 1, 'BERKELEYDB' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, - 'NDBCLUSTER' => 1, 'PRIVILEGES' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, - 'SQL_THREAD' => 1, 'TABLESPACE' => 1, + 'NDBCLUSTER' => 1, 'PERSISTENT' => 1, 'PRIVILEGES' => 1, 'REPEATABLE' => 1, + 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, @@ -151,6 +151,7 @@ class ContextMySql50000 extends Context 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, + 'GENERATED ALWAYS' => 7, 'DEFAULT CHARACTER SET' => 7, 'XML' => 9, diff --git a/src/Contexts/ContextMySql50100.php b/src/Contexts/ContextMySql50100.php index fa43a6f..ad39eb7 100644 --- a/src/Contexts/ContextMySql50100.php +++ b/src/Contexts/ContextMySql50100.php @@ -67,7 +67,8 @@ class ContextMySql50100 extends Context 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, - 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, + 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'VIRTUAL' => 1, + 'WRAPPER' => 1, 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAXVALUE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, @@ -83,9 +84,9 @@ class ContextMySql50100 extends Context 'UNINSTALL' => 1, 'VARIABLES' => 1, 'BERKELEYDB' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, - 'MASTER_SSL' => 1, 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PRIVILEGES' => 1, - 'REORGANISE' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, - 'SQL_THREAD' => 1, 'TABLESPACE' => 1, + 'MASTER_SSL' => 1, 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, + 'PRIVILEGES' => 1, 'REORGANISE' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, + 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, @@ -162,6 +163,7 @@ class ContextMySql50100 extends Context 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, + 'GENERATED ALWAYS' => 7, 'DEFAULT CHARACTER SET' => 7, 'XML' => 9, diff --git a/src/Contexts/ContextMySql50500.php b/src/Contexts/ContextMySql50500.php index 49afca3..c0074c7 100644 --- a/src/Contexts/ContextMySql50500.php +++ b/src/Contexts/ContextMySql50500.php @@ -67,7 +67,8 @@ class ContextMySql50500 extends Context 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, - 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, + 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'VIRTUAL' => 1, + 'WRAPPER' => 1, 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, @@ -82,9 +83,9 @@ class ContextMySql50500 extends Context 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, - 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, - 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, - 'TABLE_NAME' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PRIVILEGES' => 1, + 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, + 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, @@ -167,6 +168,7 @@ class ContextMySql50500 extends Context 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, + 'GENERATED ALWAYS' => 7, 'DEFAULT CHARACTER SET' => 7, 'XML' => 9, diff --git a/src/Contexts/ContextMySql50600.php b/src/Contexts/ContextMySql50600.php index 8c91bdb..453d9e2 100644 --- a/src/Contexts/ContextMySql50600.php +++ b/src/Contexts/ContextMySql50600.php @@ -68,7 +68,7 @@ class ContextMySql50600 extends Context 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, - 'USE_FRM' => 1, 'WRAPPER' => 1, + 'USE_FRM' => 1, 'VIRTUAL' => 1, 'WRAPPER' => 1, 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXCHANGE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, @@ -83,9 +83,9 @@ class ContextMySql50600 extends Context 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, - 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, - 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, - 'TABLESPACE' => 1, 'TABLE_NAME' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PLUGIN_DIR' => 1, + 'PRIVILEGES' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, + 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, 'EXTENT_SIZE' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, @@ -173,6 +173,7 @@ class ContextMySql50600 extends Context 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, + 'GENERATED ALWAYS' => 7, 'DEFAULT CHARACTER SET' => 7, 'XML' => 9, diff --git a/src/Contexts/ContextMySql50700.php b/src/Contexts/ContextMySql50700.php index b522e82..9946a26 100644 --- a/src/Contexts/ContextMySql50700.php +++ b/src/Contexts/ContextMySql50700.php @@ -85,9 +85,9 @@ class ContextMySql50700 extends Context 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, - 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, - 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, - 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'VALIDATION' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PLUGIN_DIR' => 1, + 'PRIVILEGES' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, + 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'VALIDATION' => 1, 'COLUMN_NAME' => 1, 'COMPRESSION' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, 'EXTENT_SIZE' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1, 'NONBLOCKING' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, @@ -181,6 +181,7 @@ class ContextMySql50700 extends Context 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7, 'DATA DIRECTORY' => 7, 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7, + 'GENERATED ALWAYS' => 7, 'DEFAULT CHARACTER SET' => 7, 'XML' => 9, diff --git a/src/Statement.php b/src/Statement.php index a9ee3d3..f2d72b3 100644 --- a/src/Statement.php +++ b/src/Statement.php @@ -95,7 +95,7 @@ abstract class Statement } /** - * Builds the statement. + * Builds the string representation of this statement. * * @return string */ @@ -292,4 +292,15 @@ abstract class Statement { } + + /** + * Builds the string representation of this statement. + * + * @see static::build + * + * @return string + */ + public function __toString() { + return static::build($this); + } } |