SQL字段来源表的解析

打印 上一主题 下一主题

主题 784|帖子 784|积分 2352

测试例子:

  1. 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)
复制代码
代码示例:

  1. package com.test;
  2. import org.apache.calcite.jdbc.CalciteConnection;
  3. import org.apache.calcite.rel.RelNode;
  4. import org.apache.calcite.rel.metadata.RelColumnOrigin;
  5. import org.apache.calcite.rel.type.RelDataType;
  6. import org.apache.calcite.rel.type.RelDataTypeField;
  7. import org.apache.calcite.schema.impl.AbstractTable;
  8. import org.apache.calcite.sql.SqlNode;
  9. import org.apache.calcite.sql.parser.SqlParseException;
  10. import org.apache.calcite.sql.type.SqlTypeName;
  11. import org.apache.calcite.tools.FrameworkConfig;
  12. import org.apache.calcite.tools.Frameworks;
  13. import org.apache.calcite.tools.Planner;
  14. import org.apache.calcite.tools.RelConversionException;
  15. import org.apache.calcite.tools.ValidationException;
  16. import org.apache.calcite.rel.RelRoot;
  17. import org.apache.calcite.schema.SchemaPlus;
  18. import org.apache.calcite.rel.type.RelDataTypeFactory;
  19. import org.apache.calcite.rel.metadata.RelMetadataQuery;
  20. import java.sql.DriverManager;
  21. import java.sql.SQLException;
  22. import java.util.Properties;
  23. import java.util.Set;
  24. public class SqlLineageExample {
  25.     public static void main(String[] args) throws SQLException, ValidationException, RelConversionException, SqlParseException {
  26.         // 创建 Calcite 连接
  27.         Properties info = new Properties();
  28.         info.setProperty("lex", "JAVA");
  29.         CalciteConnection connection = (CalciteConnection) DriverManager.getConnection("jdbc:calcite:", info);
  30.         SchemaPlus rootSchema = connection.getRootSchema();
  31.         // 定义并添加自定义表到 schema
  32.         rootSchema.add("EMP", new AbstractTable() {
  33.             @Override
  34.             public RelDataType getRowType(RelDataTypeFactory typeFactory) {
  35.                 return typeFactory.builder()
  36.                         .add("EMP_ID", SqlTypeName.INTEGER)
  37.                         .add("NAME", SqlTypeName.VARCHAR, 20)
  38.                         .add("DEPT_ID", SqlTypeName.INTEGER)
  39.                         .build();
  40.             }
  41.         });
  42.         rootSchema.add("DEPT", new AbstractTable() {
  43.             @Override
  44.             public RelDataType getRowType(RelDataTypeFactory typeFactory) {
  45.                 return typeFactory.builder()
  46.                         .add("DEPT_ID", SqlTypeName.INTEGER)
  47.                         .add("DEPT_NAME", SqlTypeName.VARCHAR, 20)
  48.                         .build();
  49.             }
  50.         });
  51.         // 创建 FrameworkConfig
  52.         FrameworkConfig config = Frameworks.newConfigBuilder()
  53.                 .defaultSchema(rootSchema)
  54.                 .build();
  55.         // 创建 Planner
  56.         Planner planner = Frameworks.getPlanner(config);
  57.         // 复杂 SQL 查询
  58.         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 " +
  59.                 "WHERE e.EMP_ID IN (SELECT EMP_ID FROM EMP WHERE DEPT_ID = 10)";
  60.         // 解析 SQL
  61.         SqlNode parsedNode = planner.parse(sql);
  62.         // 校验 SQL
  63.         SqlNode validatedNode = planner.validate(parsedNode);
  64.         // 转换为关系代数树
  65.         RelRoot relRoot = planner.rel(validatedNode);
  66.         RelNode relNode = relRoot.project();
  67.         // 打印字段来源
  68.         printFieldLineage(relNode);
  69.     }
  70.     private static void printFieldLineage(RelNode relNode) {
  71.         RelMetadataQuery mq = relNode.getCluster().getMetadataQuery();
  72.         for (RelDataTypeField field : relNode.getRowType().getFieldList()) {
  73.             Set<RelColumnOrigin> origins = mq.getColumnOrigins(relNode, field.getIndex());
  74.             if (origins != null) {
  75.                 for (RelColumnOrigin origin : origins) {
  76.                     String fieldName = field.getName();
  77.                     String tableName = origin.getOriginTable().getQualifiedName().get(0);
  78.                     System.out.println("Field: " + fieldName + " comes from Table: " + tableName);
  79.                 }
  80.             } else {
  81.                 System.out.println("Field: " + field.getName() + " origin unknown");
  82.             }
  83.         }
  84.     }
  85. }
复制代码
结果输出:

打印结果如下:
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包

  1. <dependencies>
  2.     <dependency>
  3.         <groupId>org.apache.calcite</groupId>
  4.         <artifactId>calcite-core</artifactId>
  5.         <version>1.34.0</version>
  6.     </dependency>
  7.     <dependency>
  8.         <groupId>org.slf4j</groupId>
  9.         <artifactId>slf4j-api</artifactId>
  10.         <version>1.7.36</version>
  11.     </dependency>
  12.     <dependency>
  13.         <groupId>org.slf4j</groupId>
  14.         <artifactId>slf4j-log4j12</artifactId>
  15.         <version>1.7.36</version>
  16.     </dependency>
  17. </dependencies>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表