血缘解析<二>:如何解析带CTE语句的Sql

blood

    • 一、思路
    • 二、代码

一、思路

之前文章血缘解析介绍了血缘解析的思路,但是对于带CTE语句的sql解析不到
eg:

with tmp as (select id,name,agefrom personinfo
),tmp1 as (select a.id,a.name,a.age,b.classnofrom tmp ajoin classinfo bon a.id = b.id
)select id,name,age,classno from tmp1

上述sql在解析的时候会获取到源表是tmp1,而不是cte中的personinfo和classinfo,原因是:com.alibaba.druid.sql获取getSelect().getQuery()只能获取到不包含cte的select语句,如下所示

        try{statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);}catch (Exception e){System.out.println("can't parser by druid oracle"+e);}// 只考虑一条语句SQLStatement statement = statements.get(0);// 只考虑查询语句SQLSelectStatement sqlSelectStatement = (SQLSelectStatement) statement;SQLSelectQuery sqlSelectQuery = sqlSelectStatement.getSelect().getQuery();

后面我想到了一种思路:带with的cte语句实际上也是临时表,tmp是临时表的表名,包含的select语句是临时表名的加工语句,可以把所有cte中的select语句都拿出来解析,最后通过递归获取最原始的血缘关系,对应关系如下所示:

  • 假设上述加工语句是写入test表
  • 第一层:
target_tabtarget_colsource_tabsource_col
testidtmp1id
testnametmp1name
testagetmp1age
testclassnotmp1classno
  • 第二层:
target_tabtarget_colsource_tabsource_col
tmp1idtmpid
tmp1nametmpname
tmp1agetmpage
tmp1classnoclassinfoclassno
  • 第三层:
target_tabtarget_colsource_tabsource_col
tmpidpersoninfoid
tmpnamepersoninfoname
tmpagepersoninfoage

会把上述所有层的对应关系都写到Mysql的表中,最后会利用Mysql的递归获取最原始的对应关系,递归代码如下所示:

with recursive cte (target_tab,target_col,source_tab,source_col,level) as 
(select target_tab,target_col,source_tab,source_col,1 as levelfrom blood_tabunion allselect t1.target_tab,t1.target_col,t.source_tab,t.source_col,t1.level + 1from blood_tab tjoin cte1 t1on t.target_tab = t1.source_taband t.target_col = t1.source_col
),cte1 as (select target_tab,target_col,source_tab,source_col,rank()over(partition by target_tab,target_col order by level desc) as rnfrom cte
)select target_tab,target_col,source_tab,source_colfrom cte1 twhere t.rn <= 1

二、代码

  • 如何获取所有cte的别名和包含的select语句?,可以用正则表达式匹配或者其它方式,我这里还是利用com.alibaba.druid.sql包进行解析获取
package com.lan.lineage.operate;import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;
import com.alibaba.druid.util.JdbcConstants;
import com.lan.lineage.common.EmptyUtils;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;public class CteSpilt {public static void splitcte(String sql, String target_tab, String target_schema) {String target_tab_with;String target_sql;String text;if ( EmptyUtils.isEmpty(sql)){return;}AtomicReference<Boolean> isContinue = new AtomicReference<>(false);List<SQLStatement> statements = new ArrayList<>();// 解析try{statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);}catch (Exception mysqlerr) {System.out.println("can't parser by druid mysql" + mysqlerr);try {statements = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);} catch (Exception oracleerr){System.out.println("can't parser by druid ORACLE" + oracleerr);}}try {SQLStatement statement = statements.get(0);SQLSelectStatement sqlSelectStatement = (SQLSelectStatement) statement;SQLWithSubqueryClause withSub = sqlSelectStatement.getSelect().getWithSubQuery();if (withSub != null) {List<SQLWithSubqueryClause.Entry> withSubEntry = withSub.getEntries();for (int i = 0; i < withSubEntry.size(); i++) {target_tab_with = withSubEntry.get(i).getAlias();target_sql = String.valueOf(withSubEntry.get(i).getSubQuery());}}} catch (Exception e){e.printStackTrace();}}
}
  • 上述代码的target_tab_with就是cte名,target_sql就是cte中包含的select语句

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搜索功能技术方案

1. 背景与需求分析 门户平台需要实现对服务信息的高效查询&#xff0c;包括通过关键字搜索服务以及基于地理位置进行服务搜索。面对未来可能的数据增长和性能需求&#xff0c;选择使用 Elasticsearch 来替代 MySQL 的全文检索功能。这一选择的背景与需求可以总结为以下几点&am…

Rust程序结构与代码注释

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust编程与项目实战_夏天又到了的博客-CSDN博客 3.1 Rust程序结构 我们从一个最简单的程序入手&#xff0c;来观察一个Rust的程序结…

宏任务微任务题目

常见宏任务&#xff1a;setTimeout、setInterval、requestAnimationFrame、I/O 操作、script&#xff08;整体代码&#xff09; 微任务&#xff1a;Promise.then()、MutationObserver、process.nextTick&#xff08;在 Node.js 中&#xff09; 在执行完一个宏任务后&#xff…

关于前端知识中框架概念部分的详细介绍

1、为什么要学习流行框架&#xff1f; 企业&#xff1a;为了提高效率&#xff0c;因为时间就是金钱。开发人员&#xff1a;提高了开发效率发展进程&#xff1a; JS>JQuery>模板引擎>框架时代&#xff08;Angular(2)、React、Vue&#xff09;好处&#xff1a;不用直接…

揭秘蛇形机器人的主动SLAM算法和障碍物避让策略

更多优质内容&#xff0c;请关注公众号&#xff1a;智驾机器人技术前线 1.论文信息 论文标题&#xff1a;An active SLAM with multi-sensor fusion for snake robots based on deep reinforcement learning 作者&#xff1a;Xin Liu, Shuhuan Wen, Yaohua Hu, Fei Han, Hong…

文件IO编程

文章目录 文件描述符相关系统调用文件有关的系统调用文件操作函数--creat函数文件操作函数--open函数文件操作函数--read函数文件操作函数--write函数文件操作函数--close函数文件操作函数--lseek函数缓冲区的大小对性能的影响 实验&#xff1a;调用系统函数&#xff0c;实现文…

STM32 WDG看门狗

在大型项目中&#xff0c;BUG根本无法避免&#xff0c;因为可能的状态太多了&#xff0c;总有那么意想不到的情况发生&#xff0c; 所以&#xff0c;对于程序员&#xff0c;第一要要丰富的经验&#xff0c;避免一些常见的bug&#xff0c; 第二&#xff0c;程序要经常迭代&#…

集成学习(Ensembling Learning)

0. 来源 概念比较全&#xff0c;可以作为目录&#xff0c;前置知识讲得好&#xff0c;其他一般。 01.内容简介_哔哩哔哩_bilibili01.内容简介是集成学习&#xff1a;XGBoost, lightGBM的第1集视频&#xff0c;该合集共计19集&#xff0c;视频收藏或关注UP主&#xff0c;及时了…

【数据结构】排序算法系列——序言(附源码+图解)

作为基础算法的中流砥柱部分&#xff0c;排序算法一直都是计算机学习者们不可忽略的一部分。而其中的算法思想也蕴含着许多在今后的算法学习甚至是整个计算机技术的学习之中仍然熠熠生辉的算法思想&#xff0c;它们引领着我们不断探索算法的奥秘之处。所以&#xff0c;学习排序…

简单聊聊bait文件

场景&#xff1a;业务同事发现某云主机部署了企业主机安全&#xff0c;在该主机上发现了一个诱饵文件&#xff0c;显示注意&#xff1a;此文件是诱饵文件&#xff0c;用于防止重要文件被病毒加密。请勿修改或删除此文件。 解决方法&#xff1a;联系企业主机安全运维同事发现&am…

信号保存和处理

把上一篇回顾一下吧&#xff1a;共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;进程不再通过执行进入内核的系统调用来传递彼此的数据 共享内存的数据结构&#xff1a; struct shmid_ds {…

QT实现TCP/UDP通信

服务器端&#xff1a; 客户端&#xff1a; 服务器&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QList> #include <QMessageBox> #include <QDebug&…

point transformer v3复现及核心代码详解

point transformer v3复现及核心代码详解 1. 复现1.1 复现1.2 数据预处理1.3 跑通 2. 核心代码详解2.1 读取数据2.2 dataloder2.3 模型读取数据的逻辑2.4 forward2.4.1 Point2.4.2 backbone2.4.2.1 point.serialization2.4.2.2 稀疏化2.4.2.3 embedding2.4.2.4 encoder 1. 复现…

Emlog程序屏蔽用户IP拉黑名单插件

插件介绍 在很多时候我们需要得到用户的真实IP地址&#xff0c;例如&#xff0c;日志记录&#xff0c;地理定位&#xff0c;将用户信息&#xff0c;网站数据分析等,其实获取IP地址很简单&#xff0c;感兴趣的可以参考一下。 今天给大家带来舍力写的emlog插件&#xff1a;屏蔽…

wakenet尾迹

1、数据集介绍SWIM_Dataset_1.0.0 1.1标注文件介绍 标注文件介绍&#xff0c; 第一种&#xff1a;角度和框的坐标 <annotation><folder>Positive</folder><filename>00001</filename>文件名字<format>jpg</format>图片后缀<s…

自掘坟墓?开源正在卷爆程序员!

前端训练营&#xff1a;1v1私教&#xff0c;终身辅导计划&#xff0c;帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer Hello&#xff0c;大家好&#xff0c;我是 Sunday。 今天这篇文章其实我想了好久&#xff0c;因为这并不是一个 和光同尘 的话题&#xff0c;它…

golang学习笔记10——golang 的 Gin 框架,快速构建高效 Web 应用

推荐学习文档 golang应用级os框架&#xff0c;欢迎star基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学…

第143天:内网安全-权限维持自启动映像劫持粘滞键辅助屏保后门WinLogon

案例一&#xff1a; 权限维持-域环境&单机版-自启动 自启动路径加载 路径地址 C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\ ##英文C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\开始菜单\程序\启动\ ##中文…

OpenHarmony鸿蒙( Beta5.0)智能窗户通风设备开发详解

鸿蒙开发往期必看&#xff1a; 一分钟了解”纯血版&#xff01;鸿蒙HarmonyOS Next应用开发&#xff01; “非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; “一杯冰美式的时间” 了解鸿蒙HarmonyOS Next应用开发路…

如何逆转Instagram账号流量减少?实用技巧分享

Instagram作为全球十大社媒之一&#xff0c;不仅是个人分享生活的平台&#xff0c;还是跨境卖家进行宣传推广和客户开发的关键工具。在运营Instagram的过程中&#xff0c;稍有不慎就容易出现账号被限流的情况&#xff0c;对于账号状态和运营工作的进行都十分不利。 一、如何判断…