/**
  * Prints the sub-nodes of this object. See QueryTreeNode.java for how tree printing is supposed
  * to work.
  *
  * @param depth The depth of this node in the tree
  */
 public void printSubNodes(int depth) {
   super.printSubNodes(depth);
   if (receiver != null) {
     printLabel(depth, "receiver :");
     receiver.treePrint(depth + 1);
   }
 }
  /**
   * Accept the visitor for all visitable children of this node.
   *
   * @param v the visitor
   * @exception StandardException on error
   */
  void acceptChildren(Visitor v) throws StandardException {
    super.acceptChildren(v);

    if (receiver != null) {
      receiver = (JavaValueNode) receiver.accept(v);
    }
  }
 /**
  * Prints the sub-nodes of this object. See QueryTreeNode.java for how tree printing is supposed
  * to work.
  *
  * @param depth The depth of this node in the tree
  */
 public void printSubNodes(int depth) {
   super.printSubNodes(depth);
   if (value != null) {
     printLabel(depth, "value: ");
     value.treePrint(depth + 1);
   }
 }
  /**
   * Accept the visitor for all visitable children of this node.
   *
   * @param v the visitor
   * @exception StandardException on error
   */
  void acceptChildren(Visitor v) throws StandardException {
    super.acceptChildren(v);

    if (javaNode != null) {
      javaNode = (JavaValueNode) javaNode.accept(v);
    }
  }
  /**
   * Accept the visitor for all visitable children of this node.
   *
   * @param v the visitor
   * @exception StandardException on error
   */
  void acceptChildren(Visitor v) throws StandardException {
    super.acceptChildren(v);

    if (value != null) {
      value = (ValueNode) value.accept(v);
    }
  }
  /**
   * Prints the sub-nodes of this object. See QueryTreeNode for how tree printing is supposed to
   * work.
   *
   * @param depth The depth of this node in the tree
   */
  public void printSubNodes(int depth) {
    if (SanityManager.DEBUG) {
      super.printSubNodes(depth);

      printLabel(depth, "javaNode: ");
      javaNode.treePrint(depth + 1);
    }
  }
  /**
   * Preprocess an expression tree. We do a number of transformations here (including subqueries, IN
   * lists, LIKE and BETWEEN) plus subquery flattening. NOTE: This is done before the outer
   * ResultSetNode is preprocessed.
   *
   * @param numTables Number of tables in the DML Statement
   * @param outerFromList FromList from outer query block
   * @param outerSubqueryList SubqueryList from outer query block
   * @param outerPredicateList PredicateList from outer query block
   * @return The modified expression
   * @exception StandardException Thrown on error
   */
  public ValueNode preprocess(
      int numTables,
      FromList outerFromList,
      SubqueryList outerSubqueryList,
      PredicateList outerPredicateList)
      throws StandardException {
    javaNode.preprocess(numTables, outerFromList, outerSubqueryList, outerPredicateList);

    return this;
  }
  /**
   * Bind this expression. This means binding the sub-expressions, as well as figuring out what the
   * return type is for this expression.
   *
   * @param fromList The FROM list for the query this expression is in, for binding columns.
   * @param subqueryList The subquery list being built as we find SubqueryNodes
   * @param aggregateVector The aggregate vector being built as we find AggregateNodes
   * @return The new top of the expression tree.
   * @exception StandardException Thrown on error
   */
  public ValueNode bindExpression(
      FromList fromList, SubqueryList subqueryList, List aggregateVector) throws StandardException {
    // method invocations are not allowed in ADD TABLE clauses.
    // And neither are field references.
    javaNode.checkReliability(this);

    /* Bind the expression under us */
    javaNode = javaNode.bindExpression(fromList, subqueryList, aggregateVector);

    if (javaNode instanceof StaticMethodCallNode) {
      AggregateNode agg = ((StaticMethodCallNode) javaNode).getResolvedAggregate();

      if (agg != null) {
        return agg.bindExpression(fromList, subqueryList, aggregateVector);
      }
    }

    DataTypeDescriptor dts = javaNode.getDataType();
    if (dts == null) {
      throw StandardException.newException(
          SQLState.LANG_NO_CORRESPONDING_S_Q_L_TYPE, javaNode.getJavaTypeName());
    }

    TypeDescriptor catalogType = dts.getCatalogType();

    if (catalogType.isRowMultiSet() || (catalogType.getTypeName().equals("java.sql.ResultSet"))) {
      throw StandardException.newException(SQLState.LANG_TABLE_FUNCTION_NOT_ALLOWED);
    }

    setType(dts);

    // For functions returning string types we should set the collation to match the
    // java method's schema DERBY-2972. This is propogated from
    // RoutineAliasInfo to javaNode.
    if (dts.getTypeId().isStringTypeId()) {
      this.setCollationInfo(
          javaNode.getCollationType(), StringDataValue.COLLATION_DERIVATION_IMPLICIT);
    }

    return this;
  }
  /**
   * Do code generation for this conversion of a value from the Java to the SQL domain.
   *
   * @param acb The ExpressionClassBuilder for the class we're generating
   * @param mb the method the expression will go into
   * @exception StandardException Thrown on error
   */
  public void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb)
      throws StandardException {
    TypeId resultType;
    String resultTypeName;

    /*
     ** Tell the Java node that it's value is being returned to the
     ** SQL domain.  This way, it knows whether the checking for a null
     ** receiver is to be done at the Java level or the SQL level.
     */
    javaNode.returnValueToSQLDomain();

    /* Generate the receiver, if any. */
    boolean hasReceiver = javaNode.generateReceiver(acb, mb);

    /*
     ** If the java expression has a receiver, we want to check whether
     ** it's null before evaluating the whole expression (to avoid
     ** a NullPointerException.
     */
    if (hasReceiver) {
      /*
       ** There is a receiver.  Generate a null SQL value to return
       ** in case the receiver is null.  First, create a field to hold
       ** the null SQL value.
       */
      String nullValueClass = getTypeCompiler().interfaceName();
      LocalField nullValueField = acb.newFieldDeclaration(Modifier.PRIVATE, nullValueClass);
      /*
       ** There is a receiver.  Generate the following to test
       ** for null:
       **
       **		(receiverExpression == null) ?
       */

      mb.conditionalIfNull();
      mb.getField(nullValueField);
      acb.generateNullWithExpress(mb, getTypeCompiler(), getTypeServices().getCollationType());

      /*
       ** We have now generated the expression to test, and the
       ** "true" side of the ?: operator.  Finish the "true" side
       ** so we can generate the "false" side.
       */
      mb.startElseCode();
    }

    resultType = getTypeId();
    TypeCompiler tc = getTypeCompiler();

    resultTypeName = tc.interfaceName();

    /* Allocate an object for re-use to hold the result of the conversion */
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);

    /* Generate the expression for the Java value under us */
    javaNode.generateExpression(acb, mb);

    /* Generate the SQL value, which is always nullable */
    acb.generateDataValue(mb, tc, getTypeServices().getCollationType(), field);

    /*
     ** If there was a receiver, the return value will be the result
     ** of the ?: operator.
     */
    if (hasReceiver) {
      mb.completeConditional();
    }
  }
 /**
  * Return the variant type for the underlying expression. The variant type can be: VARIANT -
  * variant within a scan (method calls and non-static field access) SCAN_INVARIANT - invariant
  * within a scan (column references from outer tables) QUERY_INVARIANT - invariant within the life
  * of a query (constant expressions)
  *
  * @return The variant type for the underlying expression.
  * @exception StandardException thrown on error
  */
 protected int getOrderableVariantType() throws StandardException {
   return javaNode.getOrderableVariantType();
 }
 /**
  * Categorize this predicate. Initially, this means building a bit map of the referenced tables
  * for each predicate. If the source of this ColumnReference (at the next underlying level) is not
  * a ColumnReference or a VirtualColumnNode then this predicate will not be pushed down.
  *
  * <p>For example, in: select * from (select 1 from s) a (x) where x = 1 we will not push down x =
  * 1. NOTE: It would be easy to handle the case of a constant, but if the inner SELECT returns an
  * arbitrary expression, then we would have to copy that tree into the pushed predicate, and that
  * tree could contain subqueries and method calls.
  *
  * @param referencedTabs JBitSet with bit map of referenced FromTables
  * @param simplePredsOnly Whether or not to consider method calls, field references and
  *     conditional nodes when building bit map
  * @return boolean Whether or not source.expression is a ColumnReference or a VirtualColumnNode.
  * @exception StandardException Thrown on error
  */
 public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
     throws StandardException {
   return javaNode.categorize(referencedTabs, simplePredsOnly);
 }
 /**
  * Remap all ColumnReferences in this tree to be clones of the underlying expression.
  *
  * @return ValueNode The remapped expression tree.
  * @exception StandardException Thrown on error
  */
 public ValueNode remapColumnReferencesToExpressions() throws StandardException {
   javaNode = javaNode.remapColumnReferencesToExpressions();
   return this;
 }
  /** Fill this node with a deep copy of the given node. */
  public void copyFrom(QueryTreeNode node) throws StandardException {
    super.copyFrom(node);

    SQLToJavaValueNode other = (SQLToJavaValueNode) node;
    this.value = (ValueNode) getNodeFactory().copyNode(other.value, getParserContext());
  }