image.png

    planFrom

    1. private PlanBuilder planFrom(QuerySpecification node)
    2. {
    3. RelationPlan relationPlan;
    4. // 如果From语句存在
    5. if (node.getFrom().isPresent()) {
    6. relationPlan = new RelationPlanner(analysis, planSymbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, metadata, session, namedSubPlan, uniqueIdAllocator)
    7. .process(node.getFrom().get(), null); // 继续获取From子句进行
    8. }
    9. else {
    10. relationPlan = planImplicitTable();
    11. }
    12. return planBuilderFor(relationPlan);
    13. }

    process继续处理到Join类
    from 子句为Join类型
    image.png

    visitJoin 子句先对join左边子句进行处理,然后对右边子句进行处理
    image.png
    左边子句处理
    image.png
    visitAliasedRelation子句对表继续处理
    image.png

    RelationPlanner::visitTable

    1. @Override
    2. protected RelationPlan visitTable(Table node, Void context)
    3. {
    4. // 获取表
    5. // 根据节点Table获取对应的字段信息
    6. Scope scope = analysis.getScope(node);
    7. // 查询from子句是否是with子句
    8. Query namedQuery = analysis.getNamedQuery(node);
    9. // 如果包含with子句需要进一步处理
    10. if (namedQuery != null) {
    11. RelationPlan subPlan = process(namedQuery, null);
    12. // Add implicit coercions if view query produces types that don't match the declared output types
    13. // of the view (e.g., if the underlying tables referenced by the view changed)
    14. // 如果视图查询生成的类型与视图的声明输出类型不匹配(例如,如果视图引用的基础表发生了变化),则添加隐式强制转换
    15. Type[] types = scope.getRelationType().getAllFields().stream().map(Field::getType).toArray(Type[]::new);
    16. RelationPlan withCoercions = addCoercions(subPlan, types);
    17. if ((!isCTEReuseEnabled(session) || getExecutionPolicy(session).equals("phased"))
    18. || (getCteMaxQueueSize(session) < getTaskConcurrency(session) * 2) || !(analysis.getStatement() instanceof Query) || !((Query) analysis.getStatement()).getWith().isPresent()) {
    19. if (getCteMaxQueueSize(session) < getTaskConcurrency(session) * 2) {
    20. LOG.info("Main queue size " + getCteMaxQueueSize(session) + "should be more than 2 times of concurrent task " + getTaskConcurrency(session));
    21. }
    22. return new RelationPlan(withCoercions.getRoot(), scope, withCoercions.getFieldMappings());
    23. }
    24. Integer commonCTERefNum;
    25. if (namedSubPlan.containsKey(node.getName())) {
    26. commonCTERefNum = namedSubPlan.get(node.getName());
    27. }
    28. else {
    29. commonCTERefNum = uniqueIdAllocator.getNextId();
    30. namedSubPlan.put(node.getName(), commonCTERefNum);
    31. }
    32. PlanNode cteNode = new CTEScanNode(idAllocator.getNextId(),
    33. withCoercions.getRoot(),
    34. withCoercions.getFieldMappings(),
    35. Optional.empty(),
    36. node.getName().toString(),
    37. new HashSet<>(),
    38. commonCTERefNum);
    39. subPlan = new RelationPlan(cteNode, scope, withCoercions.getFieldMappings());
    40. return subPlan;
    41. }
    42. // 获取表句柄
    43. TableHandle handle = analysis.getTableHandle(node);
    44. ImmutableList.Builder<Symbol> outputSymbolsBuilder = ImmutableList.builder();
    45. ImmutableMap.Builder<Symbol, ColumnHandle> columns = ImmutableMap.builder();
    46. // 遍历字段类型
    47. for (Field field : scope.getRelationType().getAllFields()) {
    48. // 字段的名称 字段的类型
    49. Symbol symbol = planSymbolAllocator.newSymbol(field.getName().get(), field.getType());
    50. // 缓存到输出列中
    51. outputSymbolsBuilder.add(symbol);
    52. columns.put(symbol, analysis.getColumn(field));
    53. }
    54. // 输出字段信息
    55. List<Symbol> outputSymbols = outputSymbolsBuilder.build();
    56. /// 判断是否是删除语句(DELETE)
    57. boolean isDeleteTarget = analysis.isDeleteTarget(createQualifiedObjectName(session, node, node.getName()));
    58. // 创建TableScanNode
    59. PlanNode root = TableScanNode.newInstance(idAllocator.getNextId(), handle, outputSymbols, columns.build(), ReuseExchangeOperator.STRATEGY.REUSE_STRATEGY_DEFAULT, new UUID(0, 0), 0, isDeleteTarget);
    60. // 从from递归到表名后,生成对应的
    61. RelationPlan tableScan = new RelationPlan(root, scope, outputSymbols);
    62. tableScan = addRowFilters(node, tableScan);
    63. tableScan = addColumnMasks(node, tableScan);
    64. return tableScan;
    65. }

    addRowFilters的方法

    1. private RelationPlan addRowFilters(Table node, RelationPlan plan)
    2. {
    3. // 添加行过滤器 初始化计划构造器
    4. PlanBuilder planBuilder = initializePlanBuilder(plan);
    5. for (Expression filter : analysis.getRowFilters(node)) {
    6. planBuilder = subqueryPlanner.handleSubqueries(planBuilder, filter, filter);
    7. planBuilder = planBuilder.withNewRoot(new FilterNode(
    8. idAllocator.getNextId(),
    9. planBuilder.getRoot(),
    10. castToRowExpression(planBuilder.rewrite(filter))));
    11. }
    12. // 跟节点 表与根节点
    13. return new RelationPlan(planBuilder.getRoot(), plan.getScope(), plan.getFieldMappings());
    14. }

    addColumnMasks

    1. // 添加字段掩码
    2. private RelationPlan addColumnMasks(Table table, RelationPlan plan)
    3. {
    4. Map<String, List<Expression>> columnMasks = analysis.getColumnMasks(table);
    5. PlanNode root = plan.getRoot();
    6. List<Symbol> mappings = plan.getFieldMappings();
    7. // 保存字段映射关系
    8. TranslationMap translations = new TranslationMap(plan, analysis, lambdaDeclarationToSymbolMap);
    9. translations.setFieldMappings(mappings);
    10. PlanBuilder planBuilder = new PlanBuilder(translations, root, analysis.getParameters());
    11. for (int i = 0; i < plan.getDescriptor().getAllFieldCount(); i++) {
    12. Field field = plan.getDescriptor().getFieldByIndex(i);
    13. for (Expression mask : columnMasks.getOrDefault(field.getName().get(), ImmutableList.of())) {
    14. planBuilder = subqueryPlanner.handleSubqueries(planBuilder, mask, mask);
    15. Map<Symbol, RowExpression> assignments = new LinkedHashMap<>();
    16. for (Symbol symbol : root.getOutputSymbols()) {
    17. assignments.put(symbol, castToRowExpression(toSymbolReference(symbol)));
    18. }
    19. assignments.put(mappings.get(i), castToRowExpression(translations.rewrite(mask)));
    20. planBuilder = planBuilder.withNewRoot(new ProjectNode(
    21. idAllocator.getNextId(),
    22. planBuilder.getRoot(),
    23. Assignments.copyOf(assignments)));
    24. }
    25. }
    26. return new RelationPlan(planBuilder.getRoot(), plan.getScope(), mappings);
    27. }

    Group分组语句

    1.预处理所有标量输入
    1).过滤器表达式需要先投影 (group by

    1. 分组
      1. 重写聚合参数
      2. 重写分组列
        1. 这会在考虑复杂表达式之前跟踪分组集(请参阅下面的评论)
        2. 它还用于计算实现 grouping() 所需的描述符
        3. 为了“distinct”的目的,我们需要规范化可能具有不同的列引用,句法形式(例如,“t.a”与“a”)。因此我们需要枚举基于底层的分组集,fieldId 与每个列引用表达式相关联。
        4. 问题在于简单的 group-by 表达式可以是任意表达式(这与 SQL 规范背道而驰)。但是,它们不会影响分组集的数量或“distinct”的行为。我们可以根据 fieldId 计算所有候选分组集,适当地进行重复数据删除,然后将它们与复杂的表达式交叉连接。
        5. 添加复杂的表达式,然后根据计划列具体化分组集
      3. 生成 GroupIdNode(多个分组集)或 ProjectNode(单个分组集)
      4. 重写聚合
    2. 处理之后
      1. 重新添加我们在 2.a 中删除的隐式转换
    3. 处理并重写所有分组函数