public Column resolveColumn()

in tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java [256:379]


  public Column resolveColumn(QueryBlock block, ColumnReferenceExpr columnRef) throws PlanningException {

    if (columnRef.hasQualifier()) { // if a column reference is qualified

      RelationNode relationOp = block.getRelation(columnRef.getQualifier());

      // if a column name is outside of this query block
      if (relationOp == null) {
        // TODO - nested query can only refer outer query block? or not?
        for (QueryBlock eachBlock : queryBlocks.values()) {
          if (eachBlock.existsRelation(columnRef.getQualifier())) {
            relationOp = eachBlock.getRelation(columnRef.getQualifier());
          }
        }
      }

      // If we cannot find any relation against a qualified column name
      if (relationOp == null) {
        throw new NoSuchColumnException(columnRef.getCanonicalName());
      }

      Schema schema = relationOp.getTableSchema();
      Column column = schema.getColumn(columnRef.getCanonicalName());
      if (column == null) {
        throw new NoSuchColumnException(columnRef.getCanonicalName());
      }

      // If code reach here, a column is found.
      // But, it may be aliased from bottom logical node.
      // If the column is aliased, the found name may not be used in upper node.

      // Here, we try to check if column reference is already aliased.
      // If so, it replaces the name with aliased name.
      LogicalNode currentNode = block.getCurrentNode();

      // The condition (currentNode.getInSchema().contains(column)) means
      // the column can be used at the current node. So, we don't need to find aliase name.
      if (currentNode != null && !currentNode.getInSchema().contains(column)) {
        List<Column> candidates = TUtil.newList();
        if (block.namedExprsMgr.isAliased(column.getQualifiedName())) {
          String alias = block.namedExprsMgr.getAlias(columnRef.getCanonicalName());
          Column found = resolveColumn(block, new ColumnReferenceExpr(alias));
          if (found != null) {
            candidates.add(found);
          }
        }
        if (!candidates.isEmpty()) {
          return ensureUniqueColumn(candidates);
        }
      }

      return column;
    } else { // if a column reference is not qualified

      // Trying to find the column within the current block

      if (block.currentNode != null && block.currentNode.getInSchema() != null) {
        Column found = block.currentNode.getInSchema().getColumn(columnRef.getCanonicalName());
        if (found != null) {
          return found;
        }
      }

      if (block.getLatestNode() != null) {
        Column found = block.getLatestNode().getOutSchema().getColumn(columnRef.getName());
        if (found != null) {
          return found;
        }
      }

      List<Column> candidates = TUtil.newList();
      // Trying to find columns from aliased references.
      if (block.namedExprsMgr.isAliased(columnRef.getCanonicalName())) {
        String originalName = block.namedExprsMgr.getAlias(columnRef.getCanonicalName());
        Column found = resolveColumn(block, new ColumnReferenceExpr(originalName));
        if (found != null) {
          candidates.add(found);
        }
      }
      if (!candidates.isEmpty()) {
        return ensureUniqueColumn(candidates);
      }

      // Trying to find columns from other relations in the current block
      for (RelationNode rel : block.getRelations()) {
        Column found = rel.getTableSchema().getColumn(columnRef.getName());
        if (found != null) {
          candidates.add(found);
        }
      }

      if (!candidates.isEmpty()) {
        return ensureUniqueColumn(candidates);
      }

      // Trying to find columns from other relations in other blocks
      for (QueryBlock eachBlock : queryBlocks.values()) {
        for (RelationNode rel : eachBlock.getRelations()) {
          Column found = rel.getTableSchema().getColumn(columnRef.getName());
          if (found != null) {
            candidates.add(found);
          }
        }
      }

      if (!candidates.isEmpty()) {
        return ensureUniqueColumn(candidates);
      }

      // Trying to find columns from schema in current block.
      if (block.getSchema() != null) {
        Column found = block.getSchema().getColumn(columnRef.getName());
        if (found != null) {
          candidates.add(found);
        }
      }

      if (!candidates.isEmpty()) {
        return ensureUniqueColumn(candidates);
      }

      throw new VerifyException("ERROR: no such a column name "+ columnRef.getCanonicalName());
    }
  }