PMA\libraries\Tracker::parseQuery PHP 메소드

parseQuery() 공개 정적인 메소드

..) - type of statement, is it part of DDL or DML ? - tablename
public static parseQuery ( string $query ) : mixed
$query string query
리턴 mixed Array containing identifier, type and tablename.
    public static function parseQuery($query)
    {
        // Usage of PMA_SQP does not work here
        //
        // require_once("libraries/sqlparser.lib.php");
        // $parsed_sql = PMA_SQP_parse($query);
        // $sql_info = PMA_SQP_analyze($parsed_sql);
        $parser = new \SqlParser\Parser($query);
        $tokens = $parser->list->tokens;
        // Parse USE statement, need it for SQL dump imports
        if ($tokens[0]->value == 'USE') {
            $GLOBALS['db'] = $tokens[2]->value;
        }
        $result = array();
        if (!empty($parser->statements)) {
            $statement = $parser->statements[0];
            $options = isset($statement->options) ? $statement->options->options : null;
            /*
             * DDL statements
             */
            $result['type'] = 'DDL';
            // Parse CREATE statement
            if ($statement instanceof \SqlParser\Statements\CreateStatement) {
                if (empty($options) || !isset($options[6])) {
                    return $result;
                }
                if ($options[6] == 'VIEW' || $options[6] == 'TABLE') {
                    $result['identifier'] = 'CREATE ' . $options[6];
                    $result['tablename'] = $statement->name->table;
                } elseif ($options[6] == 'DATABASE') {
                    $result['identifier'] = 'CREATE DATABASE';
                    $result['tablename'] = '';
                    // In case of CREATE DATABASE, table field of the CreateStatement is actually name of the database
                    $GLOBALS['db'] = $statement->name->table;
                } elseif ($options[6] == 'INDEX' || $options[6] == 'UNIQUE INDEX' || $options[6] == 'FULLTEXT INDEX' || $options[6] == 'SPATIAL INDEX') {
                    $result['identifier'] = 'CREATE INDEX';
                    // In case of CREATE INDEX, we have to get the table name from body of the statement
                    $result['tablename'] = $statement->body[3]->value == '.' ? $statement->body[4]->value : $statement->body[2]->value;
                }
            } elseif ($statement instanceof \SqlParser\Statements\AlterStatement) {
                if (empty($options) || !isset($options[3])) {
                    return $result;
                }
                if ($options[3] == 'VIEW' || $options[3] == 'TABLE') {
                    $result['identifier'] = 'ALTER ' . $options[3];
                    $result['tablename'] = $statement->table->table;
                } elseif ($options[3] == 'DATABASE') {
                    $result['identifier'] = 'ALTER DATABASE';
                    $result['tablename'] = '';
                    $GLOBALS['db'] = $statement->table->table;
                }
            } elseif ($statement instanceof \SqlParser\Statements\DropStatement) {
                if (empty($options) || !isset($options[1])) {
                    return $result;
                }
                if ($options[1] == 'VIEW' || $options[1] == 'TABLE') {
                    $result['identifier'] = 'DROP ' . $options[1];
                    $result['tablename'] = $statement->fields[0]->table;
                } elseif ($options[1] == 'DATABASE') {
                    $result['identifier'] = 'DROP DATABASE';
                    $result['tablename'] = '';
                    $GLOBALS['db'] = $statement->fields[0]->table;
                } elseif ($options[1] == 'INDEX') {
                    $result['identifier'] = 'DROP INDEX';
                    $result['tablename'] = $statement->table->table;
                }
            } elseif ($statement instanceof \SqlParser\Statements\RenameStatement) {
                $result['identifier'] = 'RENAME TABLE';
                $result['tablename'] = $statement->renames[0]->old->table;
                $result['tablename_after_rename'] = $statement->renames[0]->new->table;
            }
            if (isset($result['identifier'])) {
                return $result;
            }
            /*
             * DML statements
             */
            $result['type'] = 'DML';
            // Parse UPDATE statement
            if ($statement instanceof \SqlParser\Statements\UpdateStatement) {
                $result['identifier'] = 'UPDATE';
                $result['tablename'] = $statement->tables[0]->table;
            }
            // Parse INSERT INTO statement
            if ($statement instanceof \SqlParser\Statements\InsertStatement) {
                $result['identifier'] = 'INSERT';
                $result['tablename'] = $statement->into->dest->table;
            }
            // Parse DELETE statement
            if ($statement instanceof \SqlParser\Statements\DeleteStatement) {
                $result['identifier'] = 'DELETE';
                $result['tablename'] = $statement->from[0]->table;
            }
            // Parse TRUNCATE statement
            if ($statement instanceof \SqlParser\Statements\TruncateStatement) {
                $result['identifier'] = 'TRUNCATE';
                $result['tablename'] = $statement->table->table;
            }
        }
        return $result;
    }

Usage Example

 /**
  * Test for Tracker::parseQuery
  *
  * @param string $query                  Query to parse
  * @param string $type                   Expected type
  * @param string $identifier             Expected identifier
  * @param string $tablename              Expected tablename
  * @param string $db                     Expected dbname
  * @param string $tablename_after_rename Expected name after rename
  *
  * @return void
  *
  * @test
  * @dataProvider parseQueryData
  */
 public function testParseQuery($query, $type, $identifier, $tablename, $db = null, $tablename_after_rename = null)
 {
     $result = Tracker::parseQuery($query);
     $this->assertEquals($type, $result['type']);
     $this->assertEquals($identifier, $result['identifier']);
     $this->assertEquals($tablename, $result['tablename']);
     if ($db) {
         $this->assertEquals($db, $GLOBALS['db']);
     }
     if ($tablename_after_rename) {
         $this->assertEquals($result['tablename_after_rename'], $tablename_after_rename);
     }
 }