phpMyAdmin是一款基于Web端运行的开源数据库管理工具,支持管理MySQL和MariaDB两种数据库。 phpMyAdmin的程序主要使用php和javascript开发,它的安装使用都比较简单而且已有很多相关介绍不再重复,今天要介绍的是源码中的一个核心组件sql-parser。

sql-parser简介

sql-parser组件的主要用途是对SQL语句进行词法分析、语法分析,继而可以实现对SQL语句的解构、加工、替换、再组装等需求,另外也可以对SQL进行highlight等处理。sql-parser由纯PHP语言实现,同时也是整个phpMyAdmin源码中为数不多的代码架构比较清晰且符合当前PHP界PSR标准规范的模块。

sql-parser组件安装

需事先安装好php,git客户端,以及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

组件安装完毕,下面介绍具体的调用

解析普通语句

<?php
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}

除以上两种语句之外,sql-parser还支持解析存储过程等几乎所有MySQL语法,不再一一举例。下面是其SQL构造器的用法举例。

组装SQL语句

组装select语句:

<?php

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 "

组装触发器语句:

<?php
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再加工

多条语句一起加工处理:

<?php
require_once '../sql-parser/vendor/autoload.php'; use SqlParser\Parser;
use SqlParser\Components\Expression; $query = <<&lt;STR
ALTER TABLE `tbl` CHANGE `uid` `uid` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl` CHANGE `field_1` `field_2` INT( 10 ) UNSIGNED NOT NULL;
select * from tbl3 where id = 3
STR; $parser = new Parser($query); //处理第一条语句
$statement_0 = $parser-&gt;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());

输出结果:

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?
存储总量达20T的MySQL实例,如何完成迁移?
CDB for MySQL相关文档


此文已由作者授权腾讯云技术社区发布,转载请注明文章出处,获取更多云计算技术干货,可请前往腾讯云技术社区

欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~

腾讯云数据库团队:phpMyAdmin中sql-parser组件的使用的更多相关文章

  1. 腾讯云数据库团队:浅谈如何对MySQL内核进行深度优化

    作者介绍:简怀兵,腾讯云数据库团队高级工程师,负责腾讯云CDB内核及基础设施建设:先后供职于Thomson Reuters和YY等公司,PTimeDB作者,曾获一项发明专利:从事MySQL内核开发工作 ...

  2. 腾讯云数据库团队:MySQL AHI 实现解析

    MySQL 定位用户记录的过程可以描述为:打开索引 -> 根据索引键值逐层查找 B+ 树 branch 结点 -> 定位到叶子结点,将 cursor 定位到满足条件的 rec 上:如果树高 ...

  3. 腾讯云数据库团队:MySQL数据库的高可用性分析

    作者介绍:易固武,腾讯高级工程师,参与腾讯账号安全建设,腾讯数据仓库(TDW)优化改造,腾讯云数据库等项目,对大规模分布式存储和计算系统有浓厚的兴趣和经历 MySQL数据库是目前开源应用最大的关系型数 ...

  4. 腾讯云数据库团队:SQL Server 数据加密功能解析

    数据加密是数据库被破解.物理介质被盗.备份被窃取的最后一道防线:数据加密,一方面解决数据被窃取安全问题,另一方面有关法律要求强制加密数据:SQL Server 的数据加密相较于其他数据库,功能相对完善 ...

  5. 腾讯云数据库团队:MySQL语句复制(SBR)的缺陷列举

    作者介绍: 赵伟 腾讯云TDSQL数据库开发者 MySQL (这里的MySQL是指广义的mysql,包括oracle,mysql,percona,mariadb等)的Statement Based R ...

  6. 腾讯云数据库团队:MySQL5.7 JSON实现简单介绍

    作者介绍:吴双桥 腾讯云project师 阅读原文.很多其它技术干货.请訪问fromSource=gwzcw.57435.57435.57435">腾云阁. 本文主要介绍在MySQL ...

  7. 腾讯云数据库团队:PostgreSQL TOAST技术理解

    作者介绍:胡彬 腾讯云高级工程师 TOAST是"The Oversized-Attribute Storage Technique"的缩写,主要用于存储一个大字段的值.要理解TOA ...

  8. MySQL之父造访腾讯云 为腾讯云数据库开源点赞

    近日,技术大牛 MariaDB 公司创始人兼CTO Michael Widenius(又名Monty).MariaDB 基金会主席 Kaj 来到中国,针对MariaDB与腾讯云的技术合作进行回访.去年 ...

  9. TDSQL|三篇论文入选国际顶会SIGMOD,厉害了腾讯云数据库

    好消息!6月13日,腾讯云数据库三篇论文再次入选数据库行业顶会SIGMOD,被SIGMOD 2022 Research Full Paper(研究类长文)收录. 本次被收录的研究成果中,新型数据结构设 ...

随机推荐

  1. 《Linux多线程服务端编程》笔记——线程同步精要

    并发编程基本模型 message passing和shared memory. 线程同步的四项原则 尽量最低限度地共享对象,减少需要同步的场合.如果确实需要,优先考虑共享 immutable 对象. ...

  2. Bootstrap入门(二十八)JS插件5:工具提醒

    Bootstrap入门(二十八)JS插件5:工具提醒 工具提示在使用过程中比较常见,但是实现起来有些麻烦,而bootstrap则很好地解决了这个问题. 我们来写一个简单的实例 先引入CSS文件和JS文 ...

  3. springmvc java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.requiresPropertyOrdering()Z

    在hibernate spring springMVC整合的时候出现下面的情况: WARNING: Exception encountered during context initializatio ...

  4. SoapUI:使用Excel进行参数化

    本章中学习如下内容: 1)         使用DataSource调用Excel中的数据给接口参数化: 2)         使用DataSource Loop使得测试用例根据Excel中的取值循环 ...

  5. 【蒙地卡罗法求PI】

    /* 蒙地卡罗法求PI 说明 蒙地卡罗为摩洛哥王国之首都,该国位于法国与义大利国境,以赌博闻名.蒙地卡罗的基本原理为以乱数配合面积公式来进行解题,这种以机 率来解题的方式带有赌博的意味,虽然在精确度上 ...

  6. java cooki的使用

    session: 当新客户端发现一个HTTP请求时服务端会创建一个session.并分配一个sessionID作为服务端来客户端的识别,session对象会 保存在服务端.此时session对象处天N ...

  7. C# Webform中读取Windows AD/LDAP域用户清单

    直接上干货,核心代码如下,读取出来相应的用户清单到DataTable中.需要其它字段可以自己增加,别忘了引用using System.DirectoryServices. #region privat ...

  8. RESTful_简介

    一.概括总结一下什么是RESTful架构: (1)每一个URI代表一种资源: (2)客户端和服务器之间,传递这种资源的某种表现层(Representation): (3)客户端通过四个HTTP动词,对 ...

  9. Linux(Ubuntu)下载安装破解Matlab2016

    跳过废话, 直接看教程 前言 笔者平常不是很喜欢用Matlab, 因为所需要的功能都能被Python替代, 而Matlab的肥和慢实在令人难以忍受. 在Linux系统下安装Matlab也比Window ...

  10. linux目录下各文件夹作用

      作为一个程序员,我们难免会接触到linux系统,特别是后台程序员,因为现在项目的部署环境基本都是在linux系统上进行的,所以了解linux系统是十分重要的,虽然我接触了linux系统已经有一段时 ...