PHPMyAdmin で SQL 構文分析に SQL パーサーを使用する

*文
リリース: 2023-03-18 09:44:01
オリジナル
3704 人が閲覧しました

SQL を書くのは PHP にとって一般的なことですが、SQL ステートメントを分析して SQL を最適化するにはどうすればよいでしょうか? sql-parser はそのような機能を提供します。見てみましょう。

phpMyAdmin は、Web 上で実行され、MySQL および MariaDB データベースの管理をサポートするオープンソースのデータベース管理ツールです。 phpMyAdmin のプログラムは主に PHP と JavaScript を使用して開発されており、そのインストールと使用方法は比較的簡単です。ここでは、ソース コードのコア コンポーネントの 1 つである sql-parser を紹介します。

sql-parser の概要

sql-parser コンポーネントの主な目的は、SQL ステートメントの字句分析と構文分析を実行することです。これにより、SQL ステートメントの分解、処理、置換、および再アセンブリが実現されます。 SQL 分析のハイライトやその他の処理も実行できます。 sql-parser は純粋な PHP 言語で実装されており、phpMyAdmin ソース コード全体の中で比較的明確なコード構造を持ち、PHP 業界の現在の PSR 標準仕様に準拠している数少ないモジュールの 1 つでもあります。

sql-parserコンポーネントのインストール

事前にphp、git client、composer phpパッケージ管理ツールをインストールする必要があります

margin@margin-MB1:~/tmp$ sudo git clone https://github.com/phpmyadmin/sql-parser.git
margin@margin-MB1:~/tmp$ cd sql-parser && sudo composer install
ログイン後にコピー

コンポーネントがインストールされ、特定の呼び出しが以下に紹介されます

通常のステートメントを解析します

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);
ログイン後にコピー

$parser実行結果内 変数は、$query ステートメントの字句解析結果 $query->list、構文解析結果 $query-statements、およびエラー情報を格納するラージ オブジェクトです。
$query-statements の構造は次のとおりです:

{"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}
ログイン後にコピー


トランザクションの解析

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);
ログイン後にコピー

出力結果:

{"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}
ログイン後にコピー

上記の 2 つのステートメントに加えて、sql-parser はストアド プロシージャとほぼすべての MySQL 構文の解析もサポートしていますいくつかの例を一つずつ挙げてください。以下は SQL コンストラクターの使用例です。

SQL ステートメントを組み立てる

選択ステートメントを組み立てる:

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());
ログイン後にコピー

出力結果:

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 "
ログイン後にコピー

トリガーステートメントを組み立てる:

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());
ログイン後にコピー


出力結果:

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 再処理

複数のステートメントを一緒に処理:

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>
ログイン後にコピー

出力結果:

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"
ログイン後にコピー

上記は、sql-parser コンポーネントの基本的な使用例です。phpMyAdmin の sql-parser コンポーネントには、スペースの制限があるため、すべてを網羅することはできません。興味のある方は、以下の記事を読んでください。非常に高度な使用法。

関連する推奨事項:

MySQL の最適化に関するいくつかの操作

mysql の最適化 (3) クラスター化インデックスと非クラスター化インデックス

MySq l SQL最適化スキルの写真とテキストの詳細な紹介コードに

以上がPHPMyAdmin で SQL 構文分析に SQL パーサーを使用するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート