当前位置: 首页 > news >正文

SQL字段来源表的解析

测试例子:

SELECT e.NAME, d.DEPT_NAME,d.DEPT_ID,EMP_ID,100+EMP_ID+100 FROM EMP e JOIN DEPT d ON e.DEPT_ID = d.DEPT_ID WHERE e.EMP_ID IN (SELECT EMP_ID FROM EMP WHERE DEPT_ID = 10)

代码示例:

package com.test;
import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.metadata.RelColumnOrigin;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.schema.impl.AbstractTable;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.tools.FrameworkConfig;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.tools.Planner;
import org.apache.calcite.tools.RelConversionException;
import org.apache.calcite.tools.ValidationException;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.metadata.RelMetadataQuery;import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Set;public class SqlLineageExample {public static void main(String[] args) throws SQLException, ValidationException, RelConversionException, SqlParseException {// 创建 Calcite 连接Properties info = new Properties();info.setProperty("lex", "JAVA");CalciteConnection connection = (CalciteConnection) DriverManager.getConnection("jdbc:calcite:", info);SchemaPlus rootSchema = connection.getRootSchema();// 定义并添加自定义表到 schemarootSchema.add("EMP", new AbstractTable() {@Overridepublic RelDataType getRowType(RelDataTypeFactory typeFactory) {return typeFactory.builder().add("EMP_ID", SqlTypeName.INTEGER).add("NAME", SqlTypeName.VARCHAR, 20).add("DEPT_ID", SqlTypeName.INTEGER).build();}});rootSchema.add("DEPT", new AbstractTable() {@Overridepublic RelDataType getRowType(RelDataTypeFactory typeFactory) {return typeFactory.builder().add("DEPT_ID", SqlTypeName.INTEGER).add("DEPT_NAME", SqlTypeName.VARCHAR, 20).build();}});// 创建 FrameworkConfigFrameworkConfig config = Frameworks.newConfigBuilder().defaultSchema(rootSchema).build();// 创建 PlannerPlanner planner = Frameworks.getPlanner(config);// 复杂 SQL 查询String sql = "SELECT e.NAME, d.DEPT_NAME,d.DEPT_ID,EMP_ID,100+EMP_ID+100 FROM EMP e JOIN DEPT d ON e.DEPT_ID = d.DEPT_ID " +"WHERE e.EMP_ID IN (SELECT EMP_ID FROM EMP WHERE DEPT_ID = 10)";// 解析 SQLSqlNode parsedNode = planner.parse(sql);// 校验 SQLSqlNode validatedNode = planner.validate(parsedNode);// 转换为关系代数树RelRoot relRoot = planner.rel(validatedNode);RelNode relNode = relRoot.project();// 打印字段来源printFieldLineage(relNode);}private static void printFieldLineage(RelNode relNode) {RelMetadataQuery mq = relNode.getCluster().getMetadataQuery();for (RelDataTypeField field : relNode.getRowType().getFieldList()) {Set<RelColumnOrigin> origins = mq.getColumnOrigins(relNode, field.getIndex());if (origins != null) {for (RelColumnOrigin origin : origins) {String fieldName = field.getName();String tableName = origin.getOriginTable().getQualifiedName().get(0);System.out.println("Field: " + fieldName + " comes from Table: " + tableName);}} else {System.out.println("Field: " + field.getName() + " origin unknown");}}}
}

结果输出:

打印结果如下:

Field: NAME comes from Table: EMP
Field: DEPT_NAME comes from Table: DEPT
Field: DEPT_ID comes from Table: DEPT
Field: EMP_ID comes from Table: EMP
Field: EXPR$4 comes from Table: EMP
 

依赖 JAR包

<dependencies><dependency><groupId>org.apache.calcite</groupId><artifactId>calcite-core</artifactId><version>1.34.0</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.36</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.36</version></dependency>
</dependencies>
http://www.lryc.cn/news/486947.html

相关文章:

  • 理解 Python 解释器:CPython 与 IPython 的比较及选择指南
  • Java NIO 深度解析:构建高效的 I/O 操作
  • 总结拓展十六:特殊采购业务——VMI采购模式
  • vue2 + iview(view-design) 中封装使用 vxe-table 处理表格渲染大量数据卡顿现象
  • 初学者指南:知识库问答(KBQA)多跳路径的核心与应用
  • 创建springboot+vue项目相关配置问题
  • 基于AOA算术优化的KNN数据聚类算法matlab仿真
  • 【机器学习】在泊松分布中,当λ值较大时,其近似正态分布的误差如何评估?
  • ABAP开发-面向对象开发_2
  • 微信小程序-prettier 格式化
  • 241118学习日志——[CSDIY] [ByteDance] 后端训练营 [06]
  • Android WMS概览
  • 新一代API开发工具,让API调试更快 更简单
  • 友元类和友元函数
  • Sulfo-Cy5-Iodoacetamide能够发出明亮的荧光信号,使得生物样本的精细结构得以清晰呈现
  • Python中的TCP
  • CSS(8)高级技巧:精灵图,css三角,用户界面,vertical-align属性应用
  • Flink新版Source接口源码解析
  • SLM561A系列60V10-50mA单通道线性恒流LED驱动芯片,为汽车照明、景观照明助力
  • 一次失败的wxpython安装macOS M1
  • 【大数据技术基础 | 实验十一】Hive实验:新建Hive表
  • 【yarn】yarn rest api每日job数量分析
  • 蓝桥杯单片机第十一届省赛(第一场)
  • hive复杂数据类型Array Map Struct 炸裂函数explode
  • FIFO架构专题-FIFO是什么
  • Pythony——多线程简单爬虫实现
  • 如何修改 a 链接的样式
  • 第6章 详细设计-6.5 软硬件接口文档设计
  • 【pyspark学习从入门到精通14】MLlib_1
  • C++全局构造和初始化