SqlValidatorScope 主要用于声明校验过程中名称解析的范围,Calcite 对 SqlValidatorScope 的具体描述为 A SqlValidatorScope describes the tables and columns accessible at a particular point in the query,即:SqlValidatorScope 描述了查询中的某个具体位置可以访问的表和列。
// It is assumed that unknown type is nullable by default unknownType = typeFactory.createTypeWithNullability(typeFactory.createUnknownType(), true); booleanType = typeFactory.createSqlType(SqlTypeName.BOOLEAN);
SqlCall call; List<SqlNode> operands; switch (node.getKind()) { case SELECT: ... // Start by registering the WHERE clause // clauseScopes 用于记录 Select 中的子句,用于后续子句的注册 clauseScopes.put(IdPair.of(select, Clause.WHERE), selectScope); // 注册 WHERE 运算符中的子查询 registerOperandSubQueries(selectScope, select, SqlSelect.WHERE_OPERAND); // 注册 QUALIFY 子句中的子查询,QUALIFY 子句通常用于 WINDOW 函数结果的过滤 registerOperandSubQueries( selectScope, select, SqlSelect.QUALIFY_OPERAND); // Register FROM with the inherited scope 'parentScope', not // 'selectScope', otherwise tables in the FROM clause would be // able to see each other. finalSqlNodefrom= select.getFrom(); if (from != null) { // 注册 FROM,本示例中包含了 FROM 子查询,因此子查询会再次调用 registerQuery finalSqlNodenewFrom= registerFrom(parentScope, selectScope, true, from, from, null, null, false, false); if (newFrom != from) { select.setFrom(newFrom); } } // If this is an aggregating query, the SELECT list and HAVING // clause use a different scope, where you can only reference // columns which are in the GROUP BY clause. SqlValidatorScopeaggScope= selectScope; if (isAggregate(select)) { aggScope = newAggregatingSelectScope(selectScope, select, false); clauseScopes.put(IdPair.of(select, Clause.SELECT), aggScope); } else { clauseScopes.put(IdPair.of(select, Clause.SELECT), selectScope); } if (select.getGroup() != null) { GroupByScopegroupByScope=newGroupByScope(selectScope, select.getGroup(), select); clauseScopes.put(IdPair.of(select, Clause.GROUP_BY), groupByScope); // 注册 GROUP BY 中的子句 registerSubQueries(groupByScope, select.getGroup()); } // 注册 HAVING 运算符中的子查询 registerOperandSubQueries(aggScope, select, SqlSelect.HAVING_OPERAND); // 注册投影列中的子查询,并会将子查询转换为标量子查询 registerSubQueries(aggScope, SqlNonNullableAccessors.getSelectList(select)); finalSqlNodeListorderList= select.getOrderList(); if (orderList != null) { // If the query is 'SELECT DISTINCT', restrict the columns // available to the ORDER BY clause. if (select.isDistinct()) { aggScope = newAggregatingSelectScope(selectScope, select, true); } OrderByScopeorderScope=newOrderByScope(aggScope, orderList, select); clauseScopes.put(IdPair.of(select, Clause.ORDER), orderScope); // 注册 ORDER BY 中的子句 registerSubQueries(orderScope, orderList); // ... } break; }
@Override publicfinalvoidvalidate(RelDataType targetRowType) { switch (status) { case UNVALIDATED: try { status = SqlValidatorImpl.Status.IN_PROGRESS; Preconditions.checkArgument(rowType == null, "Namespace.rowType must be null before validate has been called"); RelDataTypetype= validateImpl(targetRowType); Preconditions.checkArgument(type != null, "validateImpl() returned null"); setType(type); } finally { status = SqlValidatorImpl.Status.VALID; } break; case IN_PROGRESS: thrownewAssertionError("Cycle detected during type-checking"); case VALID: break; default: throw Util.unexpected(status); } }
protectedvoidvalidateSelect(SqlSelect select, RelDataType targetRowType) { // Namespace is either a select namespace or a wrapper around one. finalSelectNamespacens= getNamespaceOrThrow(select).unwrap(SelectNamespace.class); // 获取 Select 语句中的投影列表 finalSqlNodeListselectItems= SqlNonNullableAccessors.getSelectList(select); RelDataTypefromType= unknownType; ... // Make sure that items in FROM clause have distinct aliases. finalSelectScopefromScope= (SelectScope) getFromScope(select); ... if (select.getFrom() == null) { if (this.config.conformance().isFromRequired()) { throw newValidationError(select, RESOURCE.selectMissingFrom()); } } else { // 校验 From 子句 validateFrom(select.getFrom(), fromType, fromScope); } // 校验 Where 子句 validateWhereClause(select); // 校验 Group 子句 validateGroupClause(select); // 校验 Having 子句 validateHavingClause(select); // 校验 Window 子句 validateWindowClause(select); // 校验 Qualify 子句 validateQualifyClause(select); handleOffsetFetch(select.getOffset(), select.getFetch()); // Validate the SELECT clause late, because a select item might // depend on the GROUP BY list, or the window function might reference // window name in the WINDOW clause etc. // 校验 Select 投影列 finalRelDataTyperowType= validateSelectList(selectItems, select, targetRowType); ns.setType(rowType); // Validate ORDER BY after we have set ns.rowType because in some // dialects you can refer to columns of the select list, e.g. // "SELECT empno AS x FROM emp ORDER BY x" // 校验 Order 子句 validateOrderList(select); ... }
protected RelDataType validateSelectList(final SqlNodeList selectItems, SqlSelect select, RelDataType targetRowType) { // Validate SELECT list. Expand terms of the form "*" or "TABLE.*". finalSqlValidatorScopeselectScope= getSelectScope(select); final List<SqlNode> expandedSelectItems = newArrayList<>(); final Set<String> aliases = newHashSet<>(); final PairList<String, RelDataType> fieldList = PairList.of(); // 遍历 selectItems 投影列,如果是 SqlSelect 则处理标量子查询 for (SqlNode selectItem : selectItems) { if (selectItem instanceof SqlSelect) { handleScalarSubQuery(select, (SqlSelect) selectItem, expandedSelectItems, aliases, fieldList); } else { // Use the field list size to record the field index // because the select item may be a STAR(*), which could have been expanded. finalintfieldIdx= fieldList.size(); finalRelDataTypefieldType= targetRowType.isStruct() && targetRowType.getFieldCount() > fieldIdx ? targetRowType.getFieldList().get(fieldIdx).getType() : unknownType; // 展开投影列,将 NAME 展开为 EMPS.NAME expandSelectItem(selectItem, select, fieldType, expandedSelectItems, aliases, fieldList, false); } } // Create the new select list with expanded items. Pass through // the original parser position so that any overall failures can // still reference the original input text. SqlNodeListnewSelectList=newSqlNodeList(expandedSelectItems, selectItems.getParserPosition()); if (config.identifierExpansion()) { // 将展开后的 newSelectList 设置到 select 中 select.setSelectList(newSelectList); } // 将展开后的 newSelectList 设置到 selectScope 中 getRawSelectScopeNonNull(select).setExpandedSelectList(expandedSelectItems); // TODO: when SELECT appears as a value sub-query, should be using // something other than unknownType for targetRowType inferUnknownTypes(targetRowType, selectScope, newSelectList); for (SqlNode selectItem : expandedSelectItems) { validateNoAggs(groupFinder, selectItem, "SELECT"); validateExpr(selectItem, selectScope); } return typeFactory.createStructType(fieldList); }