Home  >  Article  >  Backend Development  >  Using sql-parser for SQL syntax analysis in PHPMyAdmin

Using sql-parser for SQL syntax analysis in PHPMyAdmin

David Beckham
David BeckhamOriginal
2017-12-23 14:13:073567browse

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(
    &#39;db2&#39;, &#39;tb2&#39;, &#39;&#39;
);
var_dump($statement_0->build());
//处理第二条语句
$statement_1 = $parser->statements[1];
$statement_1->table  = new Expression(
    &#39;db3&#39;, &#39;tb3&#39;, &#39;&#39;
);
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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn