Home > Article > Backend Development > Using sql-parser for SQL syntax analysis in PHPMyAdmin
Writing SQL is a common thing for PHP, so how to analyze SQL statements to optimize SQL? sql-parser provides such a function, let us take a look.
phpMyAdmin is an open source database management tool that runs on the Web and supports the management of MySQL and MariaDB databases. The program of phpMyAdmin is mainly developed using PHP and JavaScript. Its installation and use are relatively simple and there are many related introductions. I will not repeat them. Today I will introduce one of the core components in the source code, sql-parser.
Introduction to sql-parser
The main purpose of the sql-parser component is to perform lexical analysis and syntax analysis of SQL statements, and then to deconstruct, process, replace, and reassemble SQL statements, etc. requirements, and you can also perform highlight processing on SQL. sql-parser is implemented in pure PHP language. It is also one of the few modules in the entire phpMyAdmin source code that has a relatively clear code structure and complies with the current PSR standard specifications in the PHP industry.
sql-parser component installation
You need to install php, git client, and composer php package management tool in advance
margin@margin-MB1:~/tmp$ sudo git clone https://github.com/phpmyadmin/sql-parser.git margin@margin-MB1:~/tmp$ cd sql-parser && sudo composer install
After the component is installed, the specific calls are introduced below
Parsing ordinary statements
require_once '../sql-parser/vendor/autoload.php'; use SqlParser\Parser; $query = 'SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ' . 'ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)'; $parser = new Parser($query); $stmt = $parser->statements[0]; echo json_encode($stmt);
The $parser variable in the running result is a large object, which stores the lexical analysis results of the $query statement $query->list, and the syntax analysis results $query- statements, and error messages, etc.
The structure of $query-statements is as follows:
{"expr": [{"database":null,"table":null,"column":null,"expr":"*","alias":null,"function":n ull,"subquery":null}],"from": [{"database":null,"table":"t1","column":null,"expr":"t1","alias":null,"function": null,"subquery":null}],"partition":null,"where":null,"group":null,"having":null," order":null,"limit":null,"procedure":null,"into":null,"join": [{"type":"LEFT","expr":{"database":null,"table":null,"column":null,"expr":"(t2, t3, t4)","alias":null,"function":null,"subquery":null},"on":[{"identifiers": ["t2","a","t1"],"isOperator":false,"expr":"(t2.a=t1.a"},{"identifiers": [],"isOperator":true,"expr":"AND"},{"identifiers": ["t3","b","t1"],"isOperator":false,"expr":"t3.b=t1.b"},{"identifiers": [],"isOperator":true,"expr":"AND"},{"identifiers": ["t4","c","t1"],"isOperator":false,"expr":"t4.c=t1.c)"}],"using":null}],"union": [],"options":{"options":[]},"first":0,"last":50}
Parse transaction
require_once '../sql-parser/vendor/autoload.php'; use SqlParser\Parser; $query = 'START TRANSACTION;' . 'SELECT @A:=SUM(salary) FROM table1 WHERE type=1;' . 'UPDATE table2 SET summary=@A WHERE type=1;' . 'COMMIT;'; $parser = new Parser($query); $stmt = $parser->statements[0]; echo json_encode($stmt);
Output result:
{"type":1,"statements":[{"expr": [{"database":null,"table":null,"column":null,"expr":"@A:=SUM(salary)","alias":nul l,"function":"SUM","subquery":null}],"from": [{"database":null,"table":"table1","column":null,"expr":"table1","alias":null,"fu nction":null,"subquery":null}],"partition":null,"where":[{"identifiers": ["type"],"isOperator":false,"expr":"type=1"}],"group":null,"having":null,"order": null,"limit":null,"procedure":null,"into":null,"join":null,"union":[],"options": {"options":[]},"first":1,"last":19},{"tables": [{"database":null,"table":"table2","column":null,"expr":"table2","alias":null,"fu nction":null,"subquery":null}],"set":[{"column":"summary","value":"@A"}],"where": [{"identifiers": ["type"],"isOperator":false,"expr":"type=1"}],"order":null,"limit":null,"options" :{"options":[]},"first":20,"last":35}],"end": {"type":2,"statements":null,"end":null,"options":{"options": {"1":"COMMIT"}},"first":36,"last":37},"options":{"options":{"1":"START TRANSACTION"}},"first":0,"last":0}
Divide the above two In addition to these statements, sql-parser also supports parsing stored procedures and almost all MySQL syntax. I will not give examples one by one. The following is an example of usage of its SQL constructor.
Assemble SQL statement
Assemble select statement:
require_once '../sql-parser/vendor/autoload.php'; use SqlParser\Components\OptionsArray; use SqlParser\Components\Expression; use SqlParser\Components\Condition; use SqlParser\Components\Limit; use SqlParser\Statements\SelectStatement; $stmt = new SelectStatement(); $stmt->options = new OptionsArray(array('DISTINCT')); $stmt->expr[] = new Expression('sakila', 'film', 'film_id', 'fid'); $stmt->expr[] = new Expression('COUNT(film_id)'); $stmt->from[] = new Expression('', 'film', ''); $stmt->from[] = new Expression('', 'actor', ''); $stmt->where[] = new Condition('film_id > 10'); $stmt->where[] = new Condition('OR'); $stmt->where[] = new Condition('actor.age > 25'); $stmt->limit = new Limit(1, 10); var_dump($stmt->build());
Output result:
margin@margin-MB1:~/code/parserTest$ php build.php string(137) "SELECT DISTINCT `sakila`.`film`.`film_id` AS `fid`, COUNT(film_id) FROM `film`, `actor` WHERE film_id > 10 OR actor.age > 25 LIMIT 10, 1 "
Assemble trigger statement:
require_once '../sql-parser/vendor/autoload.php'; use SqlParser\Components\Expression; use SqlParser\Components\OptionsArray; use SqlParser\Statements\CreateStatement; $stmt = new CreateStatement(); $stmt->options = new OptionsArray(array('TRIGGER')); $stmt->name = new Expression('ins_sum'); $stmt->entityOptions = new OptionsArray(array('BEFORE', 'INSERT')); $stmt->table = new Expression('account'); $stmt->body = 'SET @sum = @sum + NEW.amount'; var_dump($stmt->build());
Output result:
margin@margin-MB1:~/code/parserTest$ php build.php string(89) "CREATE TRIGGER ins_sum BEFORE INSERT ON account FOR EACH ROW SET @sum = @sum + NEW.amount"
SQL reprocessing
Multiple statements processed together:
require_once '../sql-parser/vendor/autoload.php'; use SqlParser\Parser; use SqlParser\Components\Expression; $query = <<<str id="3" from="" change="" $statement_0="$parser-" 处理第一条语句="" parser($query);="" $parser="new" str;="" where="" tbl3="" *="" select="" null;="" not="" unsigned="" )="" 10="" int(="" `field_2`="" `field_1`="" `tbl`="" table="" alter="" auto_increment;="" null="" `uid`="">statements[0]; $statement_0->table = new Expression( 'db2', 'tb2', '' ); var_dump($statement_0->build()); //处理第二条语句 $statement_1 = $parser->statements[1]; $statement_1->table = new Expression( 'db3', 'tb3', '' ); var_dump($statement_1->build());</str>
Output result:
margin@margin-MB1:~/code/parserTest$ php build.php string(85) "ALTER TABLE `db2`.`tb2` CHANGE `uid` `uid` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT" string(78) "ALTER TABLE `db3`.`tb3` CHANGE `field_1` `field_2` INT( 10 ) UNSIGNED NOT NULL"
The above are some basic usage examples of the sql-parser component. The sql-parser component of phpMyAdmin has relatively rich and complete functions. This article cannot be exhaustive due to space limitations. Interested readers can learn more advanced usage by reading the source code.
Related recommendations:
Some operations about MySQL optimization
mysql optimization (3) clustered index and non-clustered index
##MySql Sql optimization techniques detailed graphic code introduction
The above is the detailed content of Using sql-parser for SQL syntax analysis in PHPMyAdmin. For more information, please follow other related articles on the PHP Chinese website!