基于Druid的HiveSQL血缘解析

这篇具有很好参考价值的文章主要介绍了基于Druid的HiveSQL血缘解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、Druid简介

二、Druid SQL Parser

Parser

AST

Visitor

三、血缘功能实现

1.建表语句

1.直接Create+字段定义

2. Create table... as select..

 2.插入

1.标准语法

2.高级语法(Multiple Inserts)

3.高级语法(Dynamic Partition Inserts)

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢



前言

之前开发的基于Python语言的sqlparse库开发的SQL语言通用解析工具目前已经开源至github,大家如果有需要可以去看:https://github.com/Fanstuck/SQLblood-relationship。我说过做Python的SQL解析算是一个对AST解析树的深入理解。没想到的是基于sqlparse的工具做出sql解析是可行的,这涉及到较多的递归和判断,但是我写的程序应对的SQL语句应该是不多的1,很多条SQL语句都没有测试完还是有一定的风险的。如果大家有想要解析的SQL可以私信发我,将免费提供SQL解析,如果程序功能和兼容性足够完善的话,将再出一篇文章把所有的解析过程详解。

本篇文章主要讲述的是直接利用Druid的功能直接实现血缘解析,就不再过多的去解析其底层AST树的解析了,大致的做法都是相同的。Druid用于解析sql的工具是本身自带,其主要是数据库连接池实现。


一、Druid简介

Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。也正是因为有监控SQL注入因此必须要对上交的SQL任务进行解析,获取关键字段。

首先SQL本质上是一种数据处理的描述语言,是一种描述语言的规范。 如果我们用简单字符串处理,使用字符串查找或者正则表达式来提取SQL中的字段,对于简单的SQL可以这样实现,但SQL规范还有复杂的开闭括号以及嵌套查询,复杂SQL几乎不可能通过字符串匹配来实现。因此我们需要将SQL解析。Druid内置的SQL Parser, SQL Parser是Druid的一个重要组成部分,Druid内置使用SQL Parser来实现防御SQL注入(WallFilter)、合并统计没有参数化的SQL(StatFilter的mergeSql)、SQL格式化、分库分表。 而且官方强调:和Antlr生成的SQL有很大不同的是,Druid SQL Parser性能非常好,可以用于生产环境直接对SQL进行分析处理。

通过阅览源码会发现基本主流数据库的SQL语句都支持解析:

数据库 DML DDL
odps 完全支持 完全支持
mysql 完全支持 完全支持
postgresql 完全支持 完全支持
oracle 支持大部分 支持大部分
sql server 支持常用的 支持常用的ddl
db2 支持常用的 支持常用的ddl
hive 支持常用的 支持常用的ddl

druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

每个数据库都有自己对应的AST树解析、parser语法解析和visitor模式。个别几个数据库的解析较为特殊,比如Hive、mysql等带额外带有其他的功能。

二、Druid SQL Parser

Druid SQL Parser源码中主要的构成框架包括:Parser、AST和Visitor。

Parser

根据之前的研究我们清楚语法分析器(Parser):将上一步得到的Token流转换为语法定义的树结构。对于HiveSQL的解析来讲,对于其定义的grammar语法文件来看,其各个不同的语法解析文件就是其SQL执行过程的支撑,自然需要先解析获取其对应的语法结构:

druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

 From的解析文件可以说是通用的,因此在parser并没有看到关于Hive的From文件,都统一由全局SQLParser获取。

 druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

这些特定数据库的类都全部由通用parser继承而来,添加新方法。

AST

AST是abstract syntax tree的缩写,也就是抽象语法树。和所有的Parser一样,Druid Parser会生成一个抽象语法树。

之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。比如,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现;而类似于if-condition-then这样的条件跳转语句,可以使用带有两个分支的节点来表示。

和抽象语法树相对的是具体语法树。一般的,在源代码的翻译和编译过程中,语法分析器创建出分析树。一旦AST被创建出来,在后续的处理过程中,比如语义分析阶段,会添加一些信息。

druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

String sql_format=formatMysql(sql_4);
final DbType dbType = JdbcConstants.HIVE;
// SQLStatement就是AST
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql_4, dbType);
System.out.println(stmtList);

druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql​ 

在Druid中,AST节点类型主要包括SQLObject、SQLExpr、SQLStatement三种抽象类型。

官方文档解释的更加清楚:Druid_SQL_AST

package com.alibaba.druid.sql.ast.expr;

// SQLName是一种的SQLExpr的Expr,包括SQLIdentifierExpr、SQLPropertyExpr等
public interface SQLName extends SQLExpr {}

// 例如 ID = 3 这里的ID是一个SQLIdentifierExpr
class SQLIdentifierExpr implements SQLExpr, SQLName {
    String name;
} 

// 例如 A.ID = 3 这里的A.ID是一个SQLPropertyExpr
class SQLPropertyExpr implements SQLExpr, SQLName {
    SQLExpr owner;
    String name;
} 

// 例如 ID = 3 这是一个SQLBinaryOpExpr
// left是ID (SQLIdentifierExpr)
// right是3 (SQLIntegerExpr)
class SQLBinaryOpExpr implements SQLExpr {
    SQLExpr left;
    SQLExpr right;
    SQLBinaryOperator operator;
}

// 例如 select * from where id = ?,这里的?是一个SQLVariantRefExpr,name是'?'
class SQLVariantRefExpr extends SQLExprImpl { 
    String name;
}

// 例如 ID = 3 这里的3是一个SQLIntegerExpr
public class SQLIntegerExpr extends SQLNumericLiteralExpr implements SQLValuableExpr { 
    Number number;

    // 所有实现了SQLValuableExpr接口的SQLExpr都可以直接调用这个方法求值
    @Override
    public Object getValue() {
        return this.number;
    }
}

// 例如 NAME = 'jobs' 这里的'jobs'是一个SQLCharExpr
public class SQLCharExpr extends SQLTextLiteralExpr implements SQLValuableExpr{
    String text;
}

最常用的Statement当然是SELECT/UPDATE/DELETE/INSERT,他们分别是

package com.alibaba.druid.sql.ast.statement;

class SQLSelectStatement implements SQLStatement {
    SQLSelect select;
}
class SQLUpdateStatement implements SQLStatement {
    SQLExprTableSource tableSource;
     List<SQLUpdateSetItem> items;
     SQLExpr where;
}
class SQLDeleteStatement implements SQLStatement {
    SQLTableSource tableSource; 
    SQLExpr where;
}
class SQLInsertStatement implements SQLStatement {
    SQLExprTableSource tableSource;
    List<SQLExpr> columns;
    SQLSelect query;
}

Visitor

Visitor是遍历AST的手段,是处理AST最方便的模式,Visitor是一个接口。Druid内置提供了如下Visitor:

  • OutputVisitor用来把AST输出为字符串
  • WallVisitor 来分析SQL语意来防御SQL注入攻击
  • ParameterizedOutputVisitor用来合并未参数化的SQL进行统计
  • EvalVisitor 用来对SQL表达式求值
  • ExportParameterVisitor用来提取SQL中的变量参数
  • SchemaStatVisitor 用来统计SQL中使用的表、字段、过滤条件、排序表达式、分组表达式
  • SQL格式化 Druid内置了基于语义的SQL格式化功能
     

Druid提供了多种默认实现的Visitor,可以满足基本需求,如果默认提供的不满足需求,可自行实现自定义Visitor。也就是利用该功能我们能够快速获取表与字段。

更多详细功能参阅官方对于Visitor的文档:SQL_Parser_Demo_visitor

三、血缘功能实现

1.建表语句

关于建表SQL语句一般包括一下两种常见方式,以Hive建表语句为例:

1.直接Create+字段定义

CREATE EXTERNAL TABLE dwd_database.table_name( 
id                BIGINT,
user_id           STRING,
gmt_modified      TIMESTAMP,
gmt_create        TIMESTAMP,
pending_reward    INT,
description       STRING
)
PARTITIONED BY ( 
pt STRING 
)
row format delimited fields terminated by '\t'
STORED AS TEXTFILE
location 'hdfs://nameservice1/user/hive/warehouse/dwd_database.db/table_name';

 解析结果为:

druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

2. Create table... as select..

这个存在多重嵌套select,涉及到表和字段。如:

create table table_name
        as   
       select *  from t_table_name where pt='20210829';

 解析结果为:druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

 2.插入

1.标准语法

INSERT OVERWRITE TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)](z, y) select_statement1 FROM from_statement;

2.高级语法(Multiple Inserts)

FROM from_statement
INSERT OVERWRITE TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2]
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2];

3.高级语法(Dynamic Partition Inserts)

INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;
INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;

解析和Create差不多直接代入功能就好了:

druid血缘关系,sqlparse血缘解析,数据库,数据中台,血缘分析,数据治理,sql

 这里我没有写那么多可以自行添加。好了先写这么多,内容已经足够多了,下篇文章将继续完善基础功能。

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢

以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见文章来源地址https://www.toymoban.com/news/detail-832549.html

到了这里,关于基于Druid的HiveSQL血缘解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java】数据库连接池--Druid

    数据库连接池是一个容器,负责分配、管理数据库连接(Connection) 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏 好处: 资源重用 提升系统的响应

    2024年01月22日
    浏览(40)
  • springboot引入druid解析sql

    一、前言 在开发中,有时我们可能会需要获取SQL中的表名,那么因为不同的数据源类型SQL会存在部分差异,那么我们就可以使用alibaba 的druid包实现不同的数据源类型的sql解析。 二、引入相关maven依赖 三、通过工具类SqlUtils实现对SQL的解析。 三、测试结果 运行结果如下: 大

    2024年02月12日
    浏览(36)
  • 数据库连接池(Druid(德鲁伊))

    在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤 在主程序(如servlet、beans)中建立数据库连接 进行sql操作 断开数据库连接   这种模式开发,存在的问题: 普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection加载到内存

    2024年03月14日
    浏览(55)
  • 【八】spring boot集成数据库连接池druid

            最近在进行程序优化的过程中发现程序瓶颈在数据库连接这块,于是开始研究怎么对数据库连接池参数进行调优,在这个过程中发现很多人使用druid很不规范,经常会出现导入的包和配置参数不对应的情况,这些都是因为对集成druid一知半解导致的,因此决心写一

    2024年02月09日
    浏览(54)
  • Spring Boot 数据库操作Druid和HikariDataSource

    目录 Spring Boot  数据库操作 应用实例-需求 创建测试数据库和表 进行数据库开发, 在pom.xml 引入data-jdbc starter 参考官方文档 需要在pom.xml 指定导入数据库驱动 在application.yml 配置操作数据源的信息 创建beanFurn.java 测试结果 整合Druid 到Spring-Boot  官方文档 Durid 基本使用 修改

    2024年02月06日
    浏览(102)
  • Springboot+dynamic-datasource+Druid数据库配置加密

    Springboot+mybatis-plus+dynamic-datasource+Druid数据库配置加密 背景 生产环境中, 为了保密,我们希望将数据库密码加密, 甚至用户名和jdbc连接串加密。本章我们使用由苞米豆(baomidou)团队开发的 dynamic-datasource 多数据源组件自带的加密工具实现数据库配置加密 从 dynamic-datasource-star

    2024年02月04日
    浏览(41)
  • 使用Druid解析SQL,获取SQL中所有使用的表

      Druid SQL Parser分三个模块: - Parser - AST - Visitor 1.1 Parser parser是将输入文本转换为ast(抽象语法树),parser有包括两个部分,Parser和Lexer,其中Lexer实现词法分析,Parser实现语法分析。 1.2 AST AST是Abstract Syntax Tree的缩写,也就是抽象语法树。AST是parser输出的结果。这也是语法树

    2024年02月12日
    浏览(42)
  • SpringBoot整合Druid数据库连接池&多数据源&注解切换&动态添加

    配置好之后 Druid 会通过 DruidDataSourceAutoConfigure 自动装配 属性配置 数据源枚举 动态数据源 继承 AbstractRoutingDataSource 就可以实现动态数据源了 实现了一个动态数据源类的构造方法,主要是为了设置默认数据源,以及以Map保存的各种目标数据源。其中Map的key是设置的数据源名称

    2024年03月22日
    浏览(65)
  • SpringBoot整合(五)HikariCP、Druid数据库连接池—多数据源配置

    在项目中,数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中,主要是 Druid ,为 监控 而生的数据库连接池。 HikariCP ,号称 性能 最好的数据库连接池。 在Spring Boot 2.X 版本,默认采用 HikariCP 连接池。而阿里大规模采用 Druid 。下面介绍在SpringBoot中使用Hika

    2024年02月17日
    浏览(77)
  • elastic-job-ui在使用druid作为数据库连接池时作业维度报错

    我们项目中使用到了elastic-job,然后自己封装了个sdk,方便使用,里面的数据源配置是常用的druid+mysql的组合,在操作中,发现elastic-job-ui可视化控制台会报错无法使用。 深究其原因是因为,各个服务把定时任务注册到了zk中,包括数据库配置类的一些信息,但是elastic-job-ui源

    2024年02月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包