/**
   * This constructor is used during from AndNode during where clause evaluation to create QueryInfo
   * Object
   *
   * @param cr ColumnReference object
   * @throws StandardException
   * @see AndNode#computeQueryInfo()
   */
  public ColumnQueryInfo(final ColumnReference cr, QueryInfoContext qic) throws StandardException {
    final ResultColumn rc = cr.getSource();
    this.tableNum = cr.getTableNumber();
    this.columnDescriptor = searchColumnDescriptor(rc);

    if (this.columnDescriptor != null) {
      this.actualColumnName = this.columnDescriptor.getColumnName();
      this.actualColumnNumber = this.columnDescriptor.getPosition();
      this.columnType = this.columnDescriptor.getType();
      this.td = this.columnDescriptor.getTableDescriptor();
    } else {
      String columnName = rc.getSourceColumnName();
      if (columnName == null) {
        columnName = rc.getActualName();
      }
      this.actualColumnName = columnName;
      this.actualColumnNumber = rc.getColumnPosition();
      this.columnType = rc.getType();
      this.td = null;
    }
    this.exposedColumnName = this.actualColumnName;
    this.virtualColumnNumber = this.actualColumnNumber;
    if (tableNum > -1) {
      DMLQueryInfo current = qic.getCurrentScopeQueryInfo();
      this.tqi = current.getTableQueryInfo(tableNum);
      if (tqi != null) {
        this.initResolverForColumnIfApplicable();
      } else {
        DMLQueryInfo root = qic.getRootQueryInfo();
        if (root.isSelect() && qic.getNestingLevelOfScope() > 0) {
          // It is possible that this column refers to an outer scope table.
          // We need to find the Scope to which it belongs
          Scope owningScope = qic.findOwningScope(tableNum);
          if (owningScope != null) {
            this.initResolverForOuterScopeColumn(cr, qic, owningScope);
            this.isOuterScope = true;
          } else {
            // the subquery flag remains set as UNSUPPORTED_CORRELATED_SUBQUERY
          }
        }
      }
    }

    // !!!:ezoerner:20090622 a null columnDescriptor is problem if we need the
    // type for byte array formatting. Allow it for now, but may cause an NPE
    // later
    /*
    assert this.columnDescriptor != null;
    */
  }
  private void initResolverForOuterScopeColumn(
      ColumnReference cr, QueryInfoContext qic, Scope owningScope) throws StandardException {
    // we want to find the following:
    // The owning table's Resolver so that we can find the column number as per
    // colocation criteria.
    // That column number will be the same as the root table's colocation column
    // number.

    final int tableNumber = cr.getTableNumber();
    DMLQueryInfo owningDML = owningScope.getDMLQueryInfo();
    this.tqi = owningDML.getTableQueryInfo(tableNumber);
    this.initResolverForColumnIfApplicable();
    SubQueryInfo sqi = (SubQueryInfo) qic.getCurrentScopeQueryInfo();
    // Now the partitioning column position is correctly set based on the owning region's resolver
    // of outer scope,
    // in case it is a  partitioned table
    // Now we need the resolver of the independent PR based table ( i.e   if this column is part of
    // resolver.)
    // the partitioning column position will remain unchanged.
    if (this.resolver != null) {
      // Check if the owning scope's level is less than independent PR scope level. If yes throw
      // exception

      int independentPRScopeLevel = sqi.getLastPushedPRBasedIndependentScopeLevel();
      if (owningScope.getScopeLevel() < independentPRScopeLevel) {
        throw StandardException.newException(SQLState.COLOCATION_CRITERIA_UNSATISFIED);
      }
      // reset the resolver to the immediate independent query. Note that from this point onwards
      // the resolver will not point to that
      // of owning region but that of immediate independent PR query's resolver. Though rest of the
      // data will point correctly
      // to owning table
      // This will be the master table of the independent query on which we will base our colocation
      // criteria
      AbstractRegion master = qic.getScopeAt(independentPRScopeLevel).getDMLQueryInfo().getRegion();
      assert master.getDataPolicy().withPartitioning();
      this.resolver = GemFireXDUtils.getResolver(master);
    }
  }
  /**
   * This constructor is invoked while analyzing the projection attributes
   *
   * @param rc ResultColumn
   * @throws StandardException
   * @see SelectQueryInfo#visit(com.pivotal.gemfirexd.internal.iapi.sql.compile.Visitable)
   */
  ColumnQueryInfo(final ResultColumn rc, QueryInfoContext qic) throws StandardException {
    final ColumnDescriptor cd = searchColumnDescriptor(rc);

    if (cd != null) {
      this.actualColumnName = cd.getColumnName();
      this.actualColumnNumber = cd.getPosition();
      this.columnDescriptor = cd;
      this.columnType = cd.getType();
      this.td = cd.getTableDescriptor();
    } else {
      String columnName = rc.getSourceColumnName();
      if (columnName == null) {
        columnName = rc.getActualName();
      }
      this.actualColumnName = columnName;
      this.actualColumnNumber = rc.getColumnPosition();
      this.columnType = rc.getType();
      this.td = null;
      this.columnDescriptor =
          new ColumnDescriptor(
              this.actualColumnName,
              this.actualColumnNumber,
              this.columnType,
              null, // default
              null, // defaultInfo
              (UUID) null, // table uuid
              (UUID) null, // default uuid
              0L, // autoincStart
              0L, // autoincInc
              0L,
              false); // autoincValue
    }

    if (tableNum > -1) {
      DMLQueryInfo currentTop = qic.getCurrentScopeQueryInfo();
      this.tqi = currentTop.getTableQueryInfo(tableNum);
      // TODO:Asif Should we do correlation check here?
    }
    this.exposedColumnName = rc.getName();
    this.virtualColumnNumber = rc.getVirtualColumnId();
    assert this.columnDescriptor != null;
  }