• 基于SqlNode的血缘解析


    案例分析

    基于社区当前最新版本calcite-1.32.0进行分析

    当前的SqlValidatorTest$testFieldOrigin中有一个单测可以直接用来调试
    在这里插入图片描述

    调试后,很快就能在测试专用方法assertFieldOrigin找到SqlValidatorTest$getFieldOrigins这个血缘入口方法

    public SqlValidatorFixture assertFieldOrigin(Matcher matcher) {
      tester.validateAndThen(factory, toSql(false), (sap, validator, n) -> {
        final List> list = validator.getFieldOrigins(n);
        final StringBuilder buf = new StringBuilder("{");
        int i = 0;
        for (List strings : list) {
          if (i++ > 0) {
            buf.append(", ");
          }
          if (strings == null) {
            buf.append("null");
          } else {
            int j = 0;
            for (String s : strings) {
              if (j++ > 0) {
                buf.append('.');
              }
              buf.append(s);
            }
          }
        }
        buf.append("}");
        assertThat(buf.toString(), matcher);
      });
      return this;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    getFieldOrigins具体实现如下

    @Override public List<@Nullable List> getFieldOrigins(SqlNode sqlQuery) {
      if (sqlQuery instanceof SqlExplain) {
        return Collections.emptyList();
      }
      // validate获得query的rowType,
      final RelDataType rowType = getValidatedNodeType(sqlQuery);
      final int fieldCount = rowType.getFieldCount();
      if (!sqlQuery.isA(SqlKind.QUERY)) {
        return Collections.nCopies(fieldCount, null);
      }
      // 再遍历rowType获得每个filed的origin列
      final List<@Nullable List> list = new ArrayList<>();
      for (int i = 0; i < fieldCount; i++) {
        list.add(getFieldOrigin(sqlQuery, i));
      }
      return ImmutableNullableList.copyOf(list);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    getFieldOrigin是处理每个Field的方法,但是看代码只支持select语句,不支持insert语句

    注意这里的selectItem是擦除了别名的,上面代码有个stripAs方法;同时也只处理了别名,而没有处理其他情况

    在这里插入图片描述
    具体的实现如下:通过sqlSelect获得scope,每个scope再取出对应selectItem的SqlQualified

    注意namespace可以获得table path

    selectItem$1
    selectItem$2
    selectItem$n
    sqlSelect
    SelectScope
    SqlQualified$1
    SqlQualified$2
    SqlQualified$n

    SqlQualified封装了namespace+identifier(table+column)
    在这里插入图片描述
    至此,可以获得列对应的表信息

  • 相关阅读:
    OpenCV-Python学习(10)—— OpenCV 图像二值化处理(cv.threshold)
    Clickhouse数据库部署、Python3压测实践
    Windows_COM编程
    python爬取电影
    分布式搜索引擎Elasticsearch
    Shell基础— Bash的基本功能(二)
    Harris图像角点检测
    面试中的批判性思维:如何展示你的分析能力
    【数据结构】 七大排序详解(贰)——冒泡排序、快速排序、归并排序
    Vue 正计时器组件
  • 原文地址:https://blog.csdn.net/weixin_44112790/article/details/126930491