Package org.apache.derby.impl.sql.compile

Source Code of org.apache.derby.impl.sql.compile.ExpressionClassBuilder

/*

   Derby - Class org.apache.derby.impl.sql.compile.ExpressionClassBuilder

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/

package org.apache.derby.impl.sql.compile;


import org.apache.derby.iapi.services.compiler.ClassBuilder;
import org.apache.derby.iapi.services.compiler.MethodBuilder;
import org.apache.derby.iapi.services.compiler.JavaFactory;
import org.apache.derby.iapi.services.compiler.LocalField;
import org.apache.derby.iapi.reference.ClassName;

import org.apache.derby.iapi.services.sanity.SanityManager;

import org.apache.derby.iapi.sql.compile.CompilerContext;
import org.apache.derby.iapi.sql.compile.ExpressionClassBuilderInterface;

import org.apache.derby.iapi.sql.execute.ResultSetFactory;
import org.apache.derby.iapi.sql.execute.ExecutionFactory;
import org.apache.derby.iapi.sql.execute.ExecIndexRow;

import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.sql.ParameterValueSet;
import org.apache.derby.iapi.sql.Row;

import org.apache.derby.iapi.sql.execute.ExecRow;

import org.apache.derby.impl.sql.compile.OrderedColumnList;
import org.apache.derby.impl.sql.compile.ResultColumnList;
import org.apache.derby.impl.sql.execute.IndexColumnOrder;
import org.apache.derby.iapi.store.access.ColumnOrdering;

import org.apache.derby.iapi.types.DataValueDescriptor;
import org.apache.derby.iapi.types.DataTypeDescriptor;
import org.apache.derby.iapi.types.DataValueFactory;
import org.apache.derby.iapi.types.TypeId;

import org.apache.derby.iapi.sql.compile.TypeCompiler;

import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.util.ByteArray;

import org.apache.derby.iapi.services.loader.ClassFactory;
import org.apache.derby.iapi.services.loader.GeneratedClass;
import org.apache.derby.iapi.services.loader.GeneratedByteCode;
import org.apache.derby.iapi.services.loader.GeneratedMethod;

import java.lang.reflect.Modifier;
import org.apache.derby.iapi.services.classfile.VMOpcode;

import org.apache.derby.iapi.services.monitor.Monitor;

import org.apache.derby.iapi.services.io.FormatableArrayHolder;

import java.io.Serializable;

/**
* ExpressionClassBuilder
* provides an interface to satisfy generation's
* common tasks in building classes that involve expressions.
* This is the common superclass of ActivationClassBuilder and
* FilterClassBuilder. See the documentation on ActivationClassBuilder.
*
*/
abstract  class ExpressionClassBuilder implements ExpressionClassBuilderInterface
{
  ///////////////////////////////////////////////////////////////////////
  //
  // CONSTANTS
  //
  ///////////////////////////////////////////////////////////////////////

  static final protected String currentDatetimeFieldName = "cdt";

  ///////////////////////////////////////////////////////////////////////
  //
  // STATE
  //
  ///////////////////////////////////////////////////////////////////////

  protected ClassBuilder cb;
  protected GeneratedClass gc;
  protected int nextExprNum;
  protected int nextNonFastExpr;
  protected int nextFieldNum;
  protected MethodBuilder constructor;
  CompilerContext myCompCtx;
  MethodBuilder executeMethod; // to find it fast

  protected LocalField cdtField;

  //protected final JavaFactory javaFac;

  private String currentRowScanResultSetName;


  ///////////////////////////////////////////////////////////////////////
  //
  // CONSTRUCTORS
  //
  ///////////////////////////////////////////////////////////////////////

  /**
   * By the time this is done, it has constructed the following class:
   * <pre>
   *    public class #className extends #superClass {
   *    public #className() { super(); }
   *    }
   * </pre>
   *
   * @exception StandardException thrown on failure
   */
  ExpressionClassBuilder (String superClass, String className, CompilerContext cc )
    throws StandardException
  {
    int modifiers = Modifier.PUBLIC | Modifier.FINAL;

    myCompCtx = cc;
    JavaFactory javaFac = myCompCtx.getJavaFactory();

    if ( className == null ) { className = myCompCtx.getUniqueClassName(); }

    // start the class
    cb = javaFac.newClassBuilder(myCompCtx.getClassFactory(),
      getPackageName(), modifiers,
      className, superClass);

    beginConstructor();
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // ABSTRACT METHODS TO BE IMPLEMENTED BY CHILDREN
  //
  ///////////////////////////////////////////////////////////////////////

  /**
   * Get the name of the package that the generated class will live in.
   *
   *  @return  name of package that the generated class will live in.
   */
  abstract  String  getPackageName();

  /**
   * Get the number of ExecRows that must be allocated
   *
   *  @return  number of ExecRows that must be allocated
   *
   *   @exception StandardException thrown on failure
   */
  abstract  int    getRowCount()
     throws StandardException;

  /**
   * Sets the number of subqueries under this expression
   *
   *
   *   @exception StandardException thrown on failure
   */
  abstract  void   setNumSubqueries()
     throws StandardException;

  ///////////////////////////////////////////////////////////////////////
  //
  // ACCESSORS
  //
  ///////////////////////////////////////////////////////////////////////

  /**
    Return the base class of the activation's hierarchy
    (the subclass of Object).

    This class is expected to hold methods used by all
    compilation code, such as datatype compilation code,
    e.g. getDataValueFactory.
   */
  abstract String getBaseClassName();

  MethodBuilder getConstructor() {
    return constructor;
  }

  ClassBuilder getClassBuilder() {
    return cb;
  }

  /**
     * Get the execute method in order to add code to it.
     * Added code will be executed for each execution
     * of the activation. StatementNode completes the
     * execute method so that code added by other nodes
     * will be executed before the ResultSet is created
     * using fillResultSet.
   */
  MethodBuilder getExecuteMethod() {
    return executeMethod;
  }


  ///////////////////////////////////////////////////////////////////////
  //
  // CONSTRUCTOR MANAGEMENT
  //
  ///////////////////////////////////////////////////////////////////////

  private  final void  beginConstructor()
  {
    // create a constructor that just calls super. 
    MethodBuilder realConstructor =
      cb.newConstructorBuilder(Modifier.PUBLIC);
    realConstructor.callSuper();
    realConstructor.methodReturn();
    realConstructor.complete();

    constructor = cb.newMethodBuilder(Modifier.PUBLIC, "void", "postConstructor");
    constructor.addThrownException(ClassName.StandardException);
  }

  /**
   * Finish the constructor by newing the array of Rows and putting a return
   * at the end of it.
   *
   * @exception StandardException thrown on failure
   */

  void finishConstructor()
     throws StandardException
  {
    int        numResultSets;

    /* Set the number of subqueries */
    setNumSubqueries();

    numResultSets = getRowCount();

    /* Generate the new of ExecRow[numResultSets] when there are ResultSets
     * which return Rows.
     */
    if (numResultSets >= 1)
    {
      addNewArrayOfRows(numResultSets);
    }

    /* Generated code is:
     *    return;
     */
    constructor.methodReturn();
    constructor.complete();
  }

  /**
   * Generate the assignment for row = new ExecRow[numResultSets]
   *
   * @param numResultSets  The size of the array.
   */
  private void addNewArrayOfRows(int numResultSets)
  {
    /* Generated code is:
     *    row = new ExecRow[numResultSets];
     */

    constructor.pushThis();
    constructor.pushNewArray(ClassName.ExecRow, numResultSets);
    constructor.putField(ClassName.BaseActivation, "row", ClassName.ExecRow + "[]");
    constructor.endStatement();
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // ADD FIELDS TO GENERATED CLASS
  //
  ///////////////////////////////////////////////////////////////////////

  /**
   * Add a field declaration to the generated class
   *
   * @param modifiers  The | of the modifier values such as public, static, etc.
   * @param type    The type of the field in java language.
   * @param name    The name of the field.
   *
   * @return None.
   */
  LocalField newFieldDeclaration(int modifiers, String type, String name)
  {
    return cb.addField(type, name, modifiers);
  }

  /**
   * Add an arbitrarily named field to the generated class.
   *
   * This is used to generate fields where the caller doesn't care what
   * the field is named.  It is especially useful for generating arbitrary
   * numbers of fields, where the caller doesn't know in advance how many
   * fields will be used.  For example, it is used for generating fields
   * to hold intermediate values from expressions.
   *
   * @param modifiers  The | of the modifier values such as public, static, etc.
   * @param type    The type of the field in java language.
   *
   * @return  The name of the new field
   */

  LocalField newFieldDeclaration(int modifiers, String type)
  {
    return cb.addField(type, newFieldName(), modifiers);
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // ADD FUNCTIONS TO GENERATED CLASS
  //
  ///////////////////////////////////////////////////////////////////////

  /**
   * Activations might have need of internal functions
   * that are not used by the result sets, but by other
   * activation functions. Thus, we make it possible
   * for functions to be generated directly as well
   * as through the newExprFun interface.  newExprFun
   * should be used when a static field pointing to the
   * expression function is needed.
   * <p>
   * The generated function will generally have a generated name
   * that can be viewed through the MethodBuilder interface.
   * This name is generated to ensure uniqueness from other
   * function names in the activation class. If you pass in a function
   * name, think carefully about whether it will collide with other names.
   *
   * @param returnType the return type of the function
   * @param modifiers the modifiers on the function
   *
   * @see #newExprFun
   */
  MethodBuilder newGeneratedFun(String returnType, int modifiers) {

    return newGeneratedFun(returnType, modifiers,
                 (String[]) null);
  }

  MethodBuilder newGeneratedFun(String returnType,
                     int modifiers,
                     String[] params) {

    String exprName = "g".concat(Integer.toString(nextNonFastExpr++));
    return newGeneratedFun(exprName, returnType, modifiers,
                 params);

  }

  private MethodBuilder newGeneratedFun(String exprName, String returnType,
                     int modifiers,
                     String[] params) {



    //
    // create a new method supplying the given modifiers and return Type
    // Java: #modifiers #returnType #exprName { }
    //
    MethodBuilder exprMethod;
    if (params == null)
    {
      exprMethod = cb.newMethodBuilder(modifiers, returnType, exprName);
    }
    else
    {
      exprMethod = cb.newMethodBuilder(modifiers, returnType,
                         exprName, params);
    }

    //
    // declare it to throw StandardException
    // Java: #modifiers #returnType #exprName throws StandardException { }
    //
    exprMethod.addThrownException(ClassName.StandardException);

    return exprMethod;
  }

  /**
   * "ExprFun"s are the "expression functions" that
   * are specific to a given JSQL statement. For example,
   * an ExprFun is generated to evaluate the where clause
   * of a select statement and return a boolean result.
   * <p>
   *
   * All methods return by this are expected to be called
   * via the GeneratedMethod interface. Thus the methods
   * are public and return java.lang.Object.
   * <p>
   * Once the exprfun has been created, the
   * caller will need to add statements to it,
   * minimally a return statement.
   * <p>
   * ExprFuns  return Object types, since they
   * are invoked through reflection and thus their
   * return type would get wrapped in an object anyway.
   * For example: return java.lang.Boolean, not boolean.
   */
  MethodBuilder newExprFun()
  {
    // get next generated function
    String exprName = "e".concat(Integer.toString(nextExprNum++));

    return newGeneratedFun(exprName, "java.lang.Object", Modifier.PUBLIC, (String[]) null);
  }

  /**
    Push an expression that is a GeneratedMethod reference to the
    passed in method. aka. a "function pointer".
  */
  void pushMethodReference(MethodBuilder mb, MethodBuilder exprMethod) {

    mb.pushThis(); // instance
    mb.push(exprMethod.getName()); // arg
    mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.GeneratedByteCode,
        "getMethod",
        ClassName.GeneratedMethod,
        1
        );
  }

  /**
   * Start a user expression.  The difference between a normal expression
   * (returned by newExprFun)
   * and a user expression is that a user expression catches all exceptions
   * (because we don't want random exceptions thrown from user methods to
   * propagate to the rest of the system.
   *
   * @return  A new MethodBuilder
   */
  MethodBuilder newUserExprFun() {

    MethodBuilder mb = newExprFun();
    mb.addThrownException("java.lang.Exception");
    return mb;
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // CURRENT DATE/TIME SUPPORT
  //
  ///////////////////////////////////////////////////////////////////////

  /**
    This utility method returns an expression for CURRENT_DATE.
    Get the expression this way, because the activation needs to
    generate support information for CURRENT_DATE,
    that would otherwise be painful to create manually.
   */
  void getCurrentDateExpression(MethodBuilder mb) {
    // do any needed setup
    LocalField lf = getCurrentSetup();

    // generated Java:
    //    this.cdt.getCurrentDate();
    mb.getField(lf);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "getCurrentDate", "java.sql.Date", 0);
  }

  /**
    This utility method returns an expression for CURRENT_TIME.
    Get the expression this way, because the activation needs to
    generate support information for CURRENT_TIME,
    that would otherwise be painful to create manually.
   */
  void getCurrentTimeExpression(MethodBuilder mb) {
    // do any needed setup
    LocalField lf = getCurrentSetup();

    // generated Java:
    //    this.cdt.getCurrentTime();
    mb.getField(lf);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "getCurrentTime", "java.sql.Time", 0);
  }

  /**
    This utility method generates an expression for CURRENT_TIMESTAMP.
    Get the expression this way, because the activation needs to
    generate support information for CURRENT_TIMESTAMP,
    that would otherwise be painful to create manually.
   */
  void getCurrentTimestampExpression(MethodBuilder mb) {
    // do any needed setup
    LocalField lf = getCurrentSetup();

    // generated Java:
    //    this.cdt.getCurrentTimestamp();
    mb.getField(lf);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null,
      "getCurrentTimestamp", "java.sql.Timestamp", 0);
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // COLUMN ORDERING
  //
  ///////////////////////////////////////////////////////////////////////

    /**
    These utility methods buffers compilation from the IndexColumnOrder
    class.

    They create an ordering based on their parameter, stuff that into
    the prepared statement, and then return the entry # for
    use in the generated code.

    We could write another utility method to generate code to
    turn an entry # back into an object, but so far no-one needs it.
 
    WARNING: this is a crafty method that ASSUMES that
    you want every column in the list ordered, and that every
    column in the list is the entire actual result colunm.
    It is only useful for DISTINCT in select. 
   */
  FormatableArrayHolder getColumnOrdering(ResultColumnList rclist)
  {
    IndexColumnOrder[] ordering;
    int numCols = (rclist == null) ? 0 : rclist.size();
    //skip the columns which are not exclusively part of the insert list
    //ie columns with default and autoincrement. These columns will not
    //be part of ordering.
    int numRealCols = 0;
    for (int i=0; i<numCols; i++)
    {
      if (!(rclist.getResultColumn(i+1).isGeneratedForUnmatchedColumnInInsert()))
        numRealCols++;
    }

    ordering = new IndexColumnOrder[numRealCols];
    for (int i=0, j=0; i<numCols; i++)
    {
      if (!(rclist.getResultColumn(i+1).isGeneratedForUnmatchedColumnInInsert()))
      {
        ordering[j] = new IndexColumnOrder(i);
        j++;
      }
    }
    return new FormatableArrayHolder(ordering);
  }

  /**
   * Add a column to the existing Ordering list.  Takes
   * a column id and only adds it if it isn't in the list.
   *
   *
   * @return the ColumnOrdering array
   */
  FormatableArrayHolder addColumnToOrdering(
            FormatableArrayHolder orderingHolder,
            int columnNum)
  {
    /*
    ** We don't expect a lot of order by columns, so
    ** linear search.
    */
    ColumnOrdering[] ordering = (ColumnOrdering[])orderingHolder.
                    getArray(ColumnOrdering.class);
    int length = ordering.length;
    for (int i = 0; i < length; i++)
    {
      if (ordering[i].getColumnId() == columnNum)
        return orderingHolder;
    }

    /*
    ** Didn't find it.  Allocate a bigger array
    ** and add it to the end
    */
    IndexColumnOrder[] newOrdering = new IndexColumnOrder[length+1];
    System.arraycopy(ordering, 0, newOrdering, 0, length);
    newOrdering[length] = new IndexColumnOrder(columnNum);
   
    return new FormatableArrayHolder(newOrdering);
 


  FormatableArrayHolder getColumnOrdering(OrderedColumnList  oclist) {
    int numCols = (oclist == null) ? 0 : oclist.size();

    if (numCols == 0)
    {
      return new FormatableArrayHolder(new IndexColumnOrder[0]);
    }

    return new FormatableArrayHolder(oclist.getColumnOrdering());
  }

  int addItem(Object o)
  {
    if (SanityManager.DEBUG)
    {
      if ((o != null) && !(o instanceof Serializable))
      {
        SanityManager.THROWASSERT(
          "o (" + o.getClass().getName() +
          ") expected to be instanceof java.io.Serializable");
      }
    }
    return myCompCtx.addSavedObject(o);
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // Caching resuable Expressions
  //
  ///////////////////////////////////////////////////////////////////////

  /**
   * Get/reuse the Expression for getting the DataValueFactory
   */
  private Object getDVF;
  void pushDataValueFactory(MethodBuilder mb)
  {
    // generates:
    //     getDataValueFactory()
    //

    if (getDVF == null) {
      getDVF = mb.describeMethod(VMOpcode.INVOKEVIRTUAL,
                    getBaseClassName(),
                    "getDataValueFactory",
                    ClassName.DataValueFactory);
    }

    mb.pushThis();
    mb.callMethod(getDVF);
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // RESULT SET SUPPORT
  //
  ///////////////////////////////////////////////////////////////////////

  /**
    This is a utility method to get a common expression --
    "BaseActivation.getResultSetFactory()".
    <p>
    BaseActivation gets the factory from the context and
    caches it for faster retrieval.
   */
  private Object getRSF;
  void pushGetResultSetFactoryExpression(MethodBuilder mb) {
    // generated Java:
    //  this.getResultSetFactory()
    //
    if (getRSF == null) {
      getRSF = mb.describeMethod(VMOpcode.INVOKEVIRTUAL, getBaseClassName(),
          "getResultSetFactory",
          ClassName.ResultSetFactory);
    }
    mb.pushThis();
    mb.callMethod(getRSF);
  }

  /**
    This is a utility method to get a common expression --
    "BaseActivation.getExecutionFactory()".
    REVISIT: could the same expression objects be reused within
    the tree and have the correct java generated each time?
    <p>
    BaseActivation gets the factory from the context and
    caches it for faster retrieval.
   */
  private Object getEF;
  void pushGetExecutionFactoryExpression(MethodBuilder mb) {
    if (getEF == null) {
      getEF = mb.describeMethod(VMOpcode.INVOKEVIRTUAL, getBaseClassName(),
          "getExecutionFactory",
          ClassName.ExecutionFactory);
    }

    // generated Java:
    //  this.getExecutionFactory()
    //
    mb.pushThis();
    mb.callMethod(getEF);
  }

  /**
   * Generate a reference to the row array that
   * all activations use.
   *
   * @param eb the expression block
   *
   * @return expression
   */
  //private void pushRowArrayReference(MethodBuilder mb)
  //{    
    // PUSHCOMPILE - cache
  //  mb.pushThis();
  //  mb.getField(ClassName.BaseActivation, "row", ClassName.ExecRow + "[]");
  //}

  /**
   * Generate a reference to a colunm in a result set.
   *
   * @param rsNumber the result set number
   * @param colId the column number
   */
  void pushColumnReference(MethodBuilder mb, int rsNumber, int colId)
  {
    mb.pushThis();
    mb.push(rsNumber);
    mb.push(colId);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "getColumnFromRow",
            ClassName.DataValueDescriptor, 2);

    //System.out.println("pushColumnReference ");
    //pushRowArrayReference(mb);
    //mb.getArrayElement(rsNumber); // instance for getColumn
    //mb.push(colId); // first arg
    //mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "getColumn", ClassName.DataValueDescriptor, 1);
  }

  /**
   * Generate a reference to the parameter value
   * set that all activations use.
   *
   */
  void pushPVSReference(MethodBuilder mb)
  {
    // PUSHCOMPILER-WASCACHED
    mb.pushThis();
    mb.getField(ClassName.BaseActivation, "pvs", ClassName.ParameterValueSet);
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // CLASS IMPLEMENTATION
  //
  ///////////////////////////////////////////////////////////////////////

  /*
    The first time a current datetime is needed, create the class
    level support for it.
   */
  protected LocalField getCurrentSetup() {
    if (cdtField != null)
      return cdtField;

    // generated Java:
    // 1) the field "cdt" is created:
    //    private CurrentDatetime cdt;
    cdtField = newFieldDeclaration(
      Modifier.PRIVATE,
      ClassName.CurrentDatetime,
      currentDatetimeFieldName);

    // 2) the constructor gets a statement to init CurrentDatetime:
    //    cdt = new CurrentDatetime();

    constructor.pushNewStart(ClassName.CurrentDatetime);
    constructor.pushNewComplete(0);
    constructor.setField(cdtField);

    return cdtField;
  }

  /**
   * generated the next field name available.
   * these are of the form 'e#', where # is
   * incremented each time.
   * This shares the name space with the expression methods
   * as Java allows names and fields to have the same name.
   * This reduces the number of constant pool entries created
   * for a generated class file.
   */
  private String newFieldName()
  {
    return "e".concat(Integer.toString(nextFieldNum++));
  }


  ///////////////////////////////////////////////////////////////////////
  //
  // DEBUG
  //
  ///////////////////////////////////////////////////////////////////////


  ///////////////////////////////////////////////////////////////////////
  //
  // DATATYPES
  //
  ///////////////////////////////////////////////////////////////////////
  /**
   * Get the TypeCompiler associated with the given TypeId
   *
   * @param typeId  The TypeId to get a TypeCompiler for
   *
   * @return  The corresponding TypeCompiler
   *
   */
  protected TypeCompiler getTypeCompiler(TypeId typeId)
  {
    return myCompCtx.getTypeCompilerFactory().getTypeCompiler(typeId);
  }

  ///////////////////////////////////////////////////////////////////////
  //
  // GENERATE BYTE CODE
  //
  ///////////////////////////////////////////////////////////////////////

  /**
   * Take the generated class, and turn it into an
   * actual class.
   * <p> This method assumes, does not check, that
   * the class and its parts are all complete.
    *
   * @param savedBytes place to save generated bytes.
   *  if null, it is ignored
   * @exception StandardException thrown when exception occurs
   */
  GeneratedClass getGeneratedClass(ByteArray savedBytes) throws StandardException {
    if (gc != null) return gc;

    if (savedBytes != null)
    {
      ByteArray classBytecode = cb.getClassBytecode();

      // note: be sure to set the length since
      // the class builder allocates the byte array
      // in big chunks
      savedBytes.setBytes(classBytecode.getArray());
      savedBytes.setLength(classBytecode.getLength());
    }

      gc =  cb.getGeneratedClass();

    return gc; // !! yippee !! here it is...
  }

  /**
   * Get a "this" expression declared as an Activation.
   * This is the commonly used type of the this expression.
   *
   */
  void pushThisAsActivation(MethodBuilder mb) {
    // PUSHCOMPILER - WASCACHED
    mb.pushThis();
    mb.upCast(ClassName.Activation);
  }

  /**
    Generate a Null data value.
    Nothing is required on the stack, a SQL null data value
    is pushed.
  */
  void generateNull(MethodBuilder mb, TypeCompiler tc, int collationType) {
    pushDataValueFactory(mb);
    mb.pushNull(tc.interfaceName());
    tc.generateNull(mb, collationType);
  }

  /**
    Generate a Null data value.
    The express value is required on the stack and will be popped, a SQL null data value
    is pushed.
  */
  void generateNullWithExpress(MethodBuilder mb, TypeCompiler tc,
      int collationType) {
    pushDataValueFactory(mb);
    mb.swap(); // need the dvf as the instance
    mb.cast(tc.interfaceName());
    tc.generateNull(mb, collationType);
  }

  /**
    Generate a data value.
    The value is to be set in the SQL data value is required
    on the stack and will be popped, a SQL data value
    is pushed.
  */
  void generateDataValue(MethodBuilder mb, TypeCompiler tc,
      int collationType, LocalField field) {
    pushDataValueFactory(mb);
    mb.swap(); // need the dvf as the instance
    tc.generateDataValue(mb, collationType, field);
  }

 
  /**
   *generates a variable name for the rowscanresultset.
   *This can not be a fixed name because in cases like
   *cascade delete same activation class will be dealing
   * more than one RowScanResultSets for dependent tables.
  */

  String newRowLocationScanResultSetName()
  {
    currentRowScanResultSetName = newFieldName();
    return currentRowScanResultSetName;
  }

  // return the Name of ResultSet with the RowLocations to be modified (deleted or updated).
  String getRowLocationScanResultSetName()
  {
    return currentRowScanResultSetName;
  }

 
}








TOP

Related Classes of org.apache.derby.impl.sql.compile.ExpressionClassBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.