Hive Select * 替换回列字段

Hive中会把TOK_ALLCOLREF替换成各个列名称,来看看代码中是如何做到的。
我以TOK_ALLCOLREF入手看代码,执行顺序不是这样的,这算是倒叙?=。= 来看SemanticAnalyzer.class这个类,这是查询中用得最多了。
首先看到genSelectPlan()方法

private Operator<?> genSelectPlan(ASTNode selExprList, QB qb,
      Operator<?> input) throws SemanticException {
...
      if (expr.getType() == HiveParser.TOK_ALLCOLREF) {
        pos = genColListRegex(".*", expr.getChildCount() == 0 ? null
            : getUnescapedName((ASTNode)expr.getChild(0)).toLowerCase(),
            expr, col_list, inputRR, pos, out_rwsch, qb.getAliases());
        selectStar = true;
      }
...
}

咱们的列名称就在col_list存着,继续看genColListRegex()方法。可以发现它是由传入的inputRR字段获取的。
这inputRR是从调用这个方法就传过来了。。继续往上看。
genBodyPlan(QB qb, Operator input)
还是传过来的。。

Operator bodyOpInfo = genBodyPlan(qb, srcOpInfo);

srcOpInfo就是从这里来的,看一下genTablePlan

// Recurse over all the source tables
    for (String alias : qb.getTabAliases()) {
      Operator op = genTablePlan(alias, qb);
      aliasToOpInfo.put(alias, op);
    }
private Operator genTablePlan(String alias, QB qb) throws SemanticException {

    String alias_id = (qb.getId() == null ? alias : qb.getId() + ":" + alias);
    Table tab = qb.getMetaData().getSrcForAlias(alias);
    RowResolver rwsch;

    ........................
      rwsch = new RowResolver();
      try {
// 先从Table中取到所有字段,加入RowResolver中
        StructObjectInspector rowObjectInspector = (StructObjectInspector) tab
            .getDeserializer().getObjectInspector();
        List<? extends StructField> fields = rowObjectInspector
            .getAllStructFieldRefs();
        for (int i = 0; i < fields.size(); i++) {
          rwsch.put(alias, fields.get(i).getFieldName(), new ColumnInfo(fields
              .get(i).getFieldName(), TypeInfoUtils
              .getTypeInfoFromObjectInspector(fields.get(i)
              .getFieldObjectInspector()), alias, false));
        }
      } catch (SerDeException e) {
        throw new RuntimeException(e);
      }
// 这里再把Partition的字段给补上
      // Hack!! - refactor once the metadata APIs with types are ready
      // Finally add the partitioning columns
      for (FieldSchema part_col : tab.getPartCols()) {
        LOG.trace("Adding partition col: " + part_col);
        // TODO: use the right type by calling part_col.getType() instead of
        // String.class
        rwsch.put(alias, part_col.getName(), new ColumnInfo(part_col.getName(),
            TypeInfoFactory.stringTypeInfo, alias, true));
      }

可以看到RowResolver存的值是列字段+分区字段。
最终select * 会得到这些值。。

updatedupdated2024-11-302024-11-30