SQL 解析在 CloudQuery 中的应用

hi 好久不见!今天将为大家带来一期干货满满的技术分享。

作为一款数据库管控平台,大家通常认为 CloudQuery 的核心能力是对平台的管控,包括统一入口管理、权限体系、审计分析等,但实际上 CloudQuery 的核心技术点之一在于其独特的 SQL 解析能力。

01

SQL 解析功能界定

SQL 解析是指将结构化查询语言( SQL 语句)转换成可以被数据库系统理解和执行的内部表示形式的过程。在执行 SQL 查询之前,数据库系统需要对查询语句进行解析,以确定查询语句的语法是否正确,是否存在语义错误,并生成执行计划。

目前 SQL 解析工具有 Druid、JSqlParser、Apache Calcite、Presto 等,它们都提供了一些 API 用于分析 SQL 语句中的信息,比如获取表名、列名等字段。但是上述工具提供的 SQL 解析功能通常封装性比较强,扩展性不足,支持的数据源有限,在许多特殊场景下它们无法准确的给出 SQL 解析结果。

因此, CloudQuery 技术团队选择使用 ANTLR 作为 SQL 解析的引擎。ANTLR 作为 SQL 解析引擎具有很多优势,它帮助我们构建高效、可扩展和易于维护的 SQL 解析器。

02

SQL 解析原理介绍

SQL 解析是将用户输入的 SQL 语句转换为数据库能够理解的结构化查询语言的过程,与普通编程语言的解析无本质区别。主要分为词法分析、语法分析、语义分析、优化、代码生成这些步骤。SQL 解析的原理可以分为两个主要阶段:词法分析和语法分析。

词法分析

词法分析是将 SQL 语句分解为一个个单独的 Token,标识每一个关键字、符号或者其他语法元素的过程。词法分析器会逐个读取 SQL 语句中的字符,根据预定义好的规则组成不同的 Token,并将 Token 序列传递给下一个步骤。

比如,下面是一个简单的 SELECT 语句:

SELECT FirstName FROM Employee WHERE Department = ‘Sales’

在进行词法分析后,将生成的 Token 序列如下:

图片

语法分析

语法分析是将 Token 序列转换成语法分析树,并进行语义分析、类型检查等处理的过程。语法分析器会根据事先定义好的 SQL 语法规则,将 Token 序列转换为语法分析树,并对其进行分析,以确定 SQL 语句是否符合语法规范。

比如,针对上述 SELECT 语句,语法分析器会将其转换为以下语法分析树:

SELECT_STATEMENT
/ |
SELECT COLUMN_LIST FROM WHERE
| | |
FirstName Employee Department = ‘Sales’

SQL 语句数据收集

在经过词法分析和语法分析的步骤后,我们就得到了一棵语法分析树。我们要收集 SQL 语句中的表名、列名、表达式等信息,其实就是遍历这个语法树的各个节点,将想要获取的信息保存下来。

在上面的语法树中,我们通过访问 COLUMN_LIST 节点可以获取到语句中查询的列名,通过 FROM 节点可以获取到语句中查询的表名,通过WHERE 节点可以获取到语句中的查询条件。

有了这些信息,我们就可以基于这些信息做许多数据库方面的功能,比如 SQL 语句权限管控、SQL 合法性检查、SQL 高危操作检查等。

03

SQL 解析在 CloudQuery 中的应用

CloudQuery 很多功能的实现都离不开强大的 SQL 解析能力,SQL 解析是 CQ 稳步前行的一大基石。

SQL 高亮

在编辑框中输入一条 SQL 语句,可以看到语句中的关键字部分 SELECT、FROM、WHERE 会被渲染成蓝色,这其实就是上面讲到的词法分析的应用。

图片

在语句经过词法分析后,语句会变成一系列 Token,Token 代表了语句中不同类型的字符。Token 大致上可以分为关键字、标识符、数字、字符串、注释这几种,然后编辑器就可以根据这几种类别,将用户输入的 SQL 语句进行着色。

语法提示

我们在输入 SQL 的过程中,比如输入下面的文本:

SELECT * FROM SYS.

通常输入到这里的时候,我们希望提示出 SYS 下面的一些信息来帮助我们快速写完 SQL,比如提示出表名、视图名、函数名等。目前 CloudQuery 在用户书写 SQL 语句的过程中有完善的智能提示功能, 包括提示出关键字、表名、列名、函数名、子查询别名等。

这里 SQL 的智能提示技术就是上面讲到的语法分析的应用,当我们输入 SELECT FROM SYS. 的时候,其实已经经过语法分析构成了一棵语法树,只是这棵语法树不完整,CloudQuery 在用户输入 SQL 语句时会实时遍历语法树,找出当前语法树中缺失的节点,在例子中缺失的节点就是表名节点,由此可以得到我们当前提示信息应该是 SYS 下的表名或视图名。

图片

SQL 语句权限控制

CloudQuery 使用基于角色的权限访问控制体系,权限控制粒度可以详细到每一种 SQL 语句、每一个数据库对象。比如常用的 SELECT、UPDATE、DELETE、CREATE TABLE、CREATE FUNCTION、函数调用等语句。

这里语句权限的控制就是 SQL 解析的重要应用场景,CloudQuery 在接收到用户输入的 SQL 语句后,会经过上述的词法分析和语法分析步骤,再遍历语法树收集 SQL 语句中的信息。在信息收集过程中,会提取出 SQL 语句中涉及到的所有表名、列名、别名、函数、查询条件等信息,接下来会对这些信息做进一步加工处理,比如消除 TABLE 的别名、绑定列的来源表、对象的真实类型查询等。

无权限的用户输入下面的SQL语句,将会受到权限管控:

SELECT * FROM “SYS”.“ACCESS

"

L

E

F

T

J

O

I

N

"

S

Y

S

"

.

"

A

C

L

M

V

" LEFT JOIN "SYS"."ACLMV

"LEFTJOIN"SYS"."ACLMV”;
DELETE FROM “CQ”.“USER” WHERE ID = 1;
CREATE OR REPLACE FUNCTION GET_UUID RETURN VARCHAR2 IS
uuid VARCHAR2(32);
BEGIN
uuid := REPLACE(SYS_GUID(),‘-’,‘’);
RETURN uuid;
END;
BEGIN
“CQ”.“GET_UUID”();
END;

图片

动态过滤数据行

CloudQuery 支持数据行安全控制,行安全控制是 CloudQuery 的一项安全特性,它允许管理员定义基于行的安全规则,以限制用户在表中的访问权限。

使用行安全控制,可以根据用户的角色、组织、部门等信息来动态控制数据的可见性,从而增强数据库的安全性。CloudQuery 的行安全控制条件支持任意的 SQL 表达式、支持引用用户的任何参数值、支持引用系统级别的参数值、支持引用环境变量等。

下面用一个例子说明行安全控制的使用场景: 存在一张业务数据表,其中有一个部门字段( dept ),管理员希望普通用户在查询这张表里的数据时,只能查询到自己部门的数据。在 CloudQuery 可以通过给表配置行安全控制实现上面的需求,配置方式类似下面这样:

DEPT = ‘${USER.DEPT}’

上面配置中 DEPT 是表中的列名, ${USER.DEPT} 是引用用户的部门参数,在真正执行 SQL 时这里会被替换成用户的真实部门值。用户在执行下面的 SQL 语句时:

SELECT * FROM DEPT;

最终执行的 SQL 会被修改成:

SELECT * FROM DEPT WHERE DEPT = ‘dept1’;

行安全控制的实现方式也依赖于 SQL 解析,在经过前面所说的词法分析、语法分析、SQL 语句信息收集这几步后,我们可以收集到语句中的需要行过滤的表名,当然还要知道这个表名所在的 SELECT 语句的位置信息, 以及所在 SELECT 语句中 FROM 的位置和WHERE条件的位置。通过这些信息,我们就可以对原始语句进行改写。

以上就是 SQL 解析在 CloudQuery 中的基本应用,正是凭借强大的 SQL 解析能力,CloudQuery 持续不断地为用户提供稳定高效的操作体验。

图片

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>