【问题标题】:Generating relational algebra for unnested repeated records为未嵌套的重复记录生成关系代数
【发布时间】:2021-12-21 13:15:09
【问题描述】:

如何为看起来像这样的 SQL stmt 生成关系代数?

SELECT
  id,
  (
  SELECT
    h.is_active
  FROM
    UNNEST(history.all_of_history) h
  WHERE
    start_date <= "2021-06-01" AND (end_date >= "2021-06-01" OR end_date IS NULL))
FROM
  `table`

table 有两列:idhistoryhistory 是一条记录,history.all_of_history 是一条重复记录,包含三个字段(is_activestart_dateend_date

【问题讨论】:

    标签: apache-calcite


    【解决方案1】:

    假设您只对逻辑计划感兴趣,您提到的查询的关系代数如下:

        LogicalProject(id=[$0], $f1=[$SCALAR_QUERY({
        LogicalProject(is_active=[$0])
          LogicalFilter(condition=[AND(<=($1, 2021-06-01), >=($2, 2021-06-01))])
            LogicalTableFunctionScan(invocation=[UNNEST($1)], rowType=[RecordType(BOOLEAN is_active, DATE start_date, DATE end_date)])
        })])
          LogicalTableScan(table=[[scott, my_table]])
    
    

    这里是关于如何创建 RelNode 的高级概述:

    1. 您需要先定义表格的行类型,即my_table:

      1.1 你的行应该是这样的:

      RecordType(INTEGER id, RecordType:peek(BOOLEAN is_active, DATE start_date, DATE end_date) MULTISET history)

      1.2 需要观察history的数据类型。它需要遵守UNNEST sql 函数的定义。为了解释这篇文章,我考虑了MULTISET 数据类型。

      1.3 假设您只对逻辑计划感兴趣,因此您可以创建一个简单的表,如下所示:

        Table tableImpl = new AbstractTable() {
          @Override
          public RelDataType getRowType(RelDataTypeFactory typeFactory) {
            RelDataType id = typeFactory.createSqlType(SqlTypeName.INTEGER);
            List<RelDataType> historyRecordDataTypes = Arrays.asList(
                typeFactory.createSqlType(SqlTypeName.BOOLEAN),
                typeFactory.createSqlType(SqlTypeName.DATE),
                typeFactory.createSqlType(SqlTypeName.DATE)
                );
            List<String> historyRecordFieldNames = Arrays.asList("is_active", "start_date", "end_date");
            RelDataType history = typeFactory.createStructType(StructKind.PEEK_FIELDS, historyRecordDataTypes, historyRecordFieldNames);
            return typeFactory.createStructType(Arrays.asList(id, typeFactory.createMultisetType(history, -1L)), Arrays.asList("id", "history"));
          }
        };
    
    1. 创建表并定义其rowType 后,您需要将其填充到 schemPlus。让我们在 calcite 测试套件中的模式 scott 中添加上面创建的表。
      rootSchema.getParentSchema().getSubSchema("scott")).add("my_table", tableImpl)
      
      
    2. 创建自定义表并填充到schemaPlus后,首先需要创建my_table的表扫描
      builder.scan("my_table");
      
      
    3. 然后你需要创建未嵌套子查询的rel。您需要为此使用RelBuilder#functionScan(...) API。根据帖子中提到的查询,unnestRelNode 将如下:
            builder.functionScan(SqlStdOperatorTable.UNNEST, 0, builder.field("history"));
            List<RexNode> innerQueryFilterPredicates = Arrays.asList(
                // start_date <= "2021-06-01"
                builder.call(
                    SqlStdOperatorTable.LESS_THAN_OR_EQUAL,
                    builder.field("start_date"), builder.getRexBuilder().makeDateLiteral(new DateString("2021-06-01"))),
                // end_date >= "2021-06-01" OR end_date IS NULL
                builder.call(
                    SqlStdOperatorTable.OR,
                    // end_date >= "2021-06-01"
                    builder.call(
                        SqlStdOperatorTable.GREATER_THAN_OR_EQUAL,
                        builder.field("end_date"), builder.getRexBuilder().makeDateLiteral(new DateString("2021-06-01"))
                    ),
                    // end_date IS NULL
                    builder.call(
                        SqlStdOperatorTable.IS_NULL, builder.field("end_date")
                    )
                )
        
            );
            RelNode unnestRel = builder.filter(builder.call(SqlStdOperatorTable.AND, innerQueryFilterPredicates))
                   .project(builder.field("is_active"))
                   .build();
    
    1. 最后,为了创建最终的 RelNode,您需要将 unnestRel 变成一个标量子查询:
        RelNode finalRel = builder.project(builder.field("id"), builder.scalarQuery(b -> unnestRel))
               .build();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      相关资源
      最近更新 更多