Package org.apache.derby.iapi.services.compiler

Examples of org.apache.derby.iapi.services.compiler.MethodBuilder


   *
   * @return  The field that holds the indexable row
   */
  private LocalField generateIndexableRow(ExpressionClassBuilder acb, int numberOfColumns)
  {
    MethodBuilder mb = acb.getConstructor();
    /*
    ** Generate a call to get an indexable row
    ** with the given number of columns
    */
    acb.pushGetExecutionFactoryExpression(mb); // instance
    mb.push(numberOfColumns);
    mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecutionFactory, "getIndexableRow", ClassName.ExecIndexRow, 1);

    /*
    ** Assign the indexable row to a field, and put this assignment into
    ** the constructor for the activation class.  This way, we only have
    ** to get the row once.
    */
    LocalField field =
      acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecIndexRow);
   
    mb.setField(field);

    return field;
  }
View Full Code Here


                  Optimizable optTable,
                  LocalField rowField,
                  boolean isStartKey)
      throws StandardException
  {
    MethodBuilder mb;
   
    /* Code gets generated in constructor if comparison against
     * a constant, otherwise gets generated in the current
     * statement block.
     */
    boolean withKnownConstant = false;
    if (pred.compareWithKnownConstant(optTable, false))
    {
      withKnownConstant = true;
      mb = acb.getConstructor();
    }
    else
    {
      mb = exprFun;
    }

    int[]  baseColumns = optTable.getTrulyTheBestAccessPath().
                getConglomerateDescriptor().
                  getIndexDescriptor().baseColumnPositions();
    boolean[]  isAscending = optTable.getTrulyTheBestAccessPath().
                getConglomerateDescriptor().
                  getIndexDescriptor().isAscending();

    /* If the predicate is an IN-list probe predicate then we are
     * using it as a start/stop key "placeholder", to be over-ridden
     * at execution time.  Put differently, we want to generate
     * "column = ?" as a start/stop key and then use the "?" value
     * as a placeholder into which we'll plug the various IN values
     * at execution time.
     *
     * In that case "isIn" will be false here, which is fine: there's
     * no need to generate dynamic start/stop keys like we do for
     * "normal" IN lists because we're just using the key as a place-
     * holder.  So by generating the probe predicate ("column = ?")
     * as a normal one-sided start/stop key, we get our requisite
     * execution-time placeholder and that's that.  For more on how
     * we use this "placeholder", see MultiProbeTableScanResultSet.
     *
     * Note that we generate the corresponding IN-list values
     * separately (see generateInListValues() in this class).
     */
    boolean isIn = pred.getAndNode().getLeftOperand() instanceof InListOperatorNode;

    /*
    ** Generate statements of the form
    **
    ** r.setColumn(columnNumber, columnExpression);
    **
    ** and put the generated statement in the allocator function.
    */
    mb.getField(rowField);
    mb.push(columnNumber + 1);

    // second arg
    if (isIn)
    {
      pred.getSourceInList().generateStartStopKey(
        isAscending[columnNumber], isStartKey, acb, mb);
    }
    else
      pred.generateExpressionOperand(optTable, baseColumns[columnNumber], acb, mb);

    mb.upCast(ClassName.DataValueDescriptor);

    mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);

    /* Also tell the row if this column uses ordered null semantics */
    if (!isIn)
    {
      RelationalOperator relop = pred.getRelop();
      boolean setOrderedNulls = relop.orderedNulls();

      /* beetle 4464, performance work.  If index column is not nullable
             * (which is frequent), we should treat it as though nulls are
             * ordered (indeed because they don't exist) so that we do not have
             * to check null at scan time for each row, each column.  This is
             * an overload to "is null" operator, so that we have less overhead,
             * provided that they don't interfere.  It doesn't interfere if it
             * doesn't overload if key is null.  If key is null, but operator
       * is not orderedNull type (is null), skipScan will use this flag
             * (false) to skip scan.
       */
      if ((! setOrderedNulls) &&
                 ! relop.getColumnOperand(optTable).getTypeServices().isNullable())
      {
        if (withKnownConstant)
          setOrderedNulls = true;
        else
        {
          ValueNode keyExp =
                        relop.getExpressionOperand(
                            optTable.getTableNumber(),
                            baseColumns[columnNumber],
                            (FromTable)optTable);

          if (keyExp instanceof ColumnReference)
            setOrderedNulls =
                            ! ((ColumnReference) keyExp).getTypeServices().isNullable();
        }
      }
      if (setOrderedNulls)
      {
        mb.getField(rowField);
        mb.push(columnNumber);
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecIndexRow, "orderedNulls", "void", 1);
      }
    }
  }
View Full Code Here

    else
    {
      // this sets up the method and the static field.
      // generates:
      //   Object userExprFun { }
      MethodBuilder userExprFun = acb.newUserExprFun();

      // restriction knows it is returning its value;

      /* generates:
       *    return  <restriction.generate(acb)>;
       * and adds it to userExprFun
       * NOTE: The explicit cast to DataValueDescriptor is required
       * since the restriction may simply be a boolean column or subquery
       * which returns a boolean.  For example:
       *    where booleanColumn
       */
      restriction.generateExpression(acb, userExprFun);
      userExprFun.methodReturn();

      // we are done modifying userExprFun, complete it.
      userExprFun.complete();

         // restriction is used in the final result set as an access of the new static
         // field holding a reference to this new method.
      // generates:
      //  ActivationClass.userExprFun
      // which is the static field that "points" to the userExprFun
      // that evaluates the where clause.
         acb.pushMethodReference(mb, userExprFun);
    }

    /* Determine whether or not reflection is needed for the projection.
     * Reflection is not needed if all of the columns map directly to source
     * columns.
     */
    if (reflectionNeededForProjection())
    {
      // for the resultColumns, we generate a userExprFun
      // that creates a new row from expressions against
      // the current row of the child's result.
      // (Generate optimization: see if we can simply
      // return the current row -- we could, but don't, optimize
      // the function call out and have execution understand
      // that a null function pointer means take the current row
      // as-is, with the performance trade-off as discussed above.)

      /* Generate the Row function for the projection */
      resultColumns.generateCore(acb, mb, false);
    }
    else
    {
         mb.pushNull(ClassName.GeneratedMethod);
    }
   
    mb.push(resultSetNumber);

    // if there is no constant restriction, we just want to pass null.
    if (constantRestriction == null)
    {
         mb.pushNull(ClassName.GeneratedMethod);
    }
    else
    {
      // this sets up the method and the static field.
      // generates:
      //   userExprFun { }
      MethodBuilder userExprFun = acb.newUserExprFun();

      // restriction knows it is returning its value;

      /* generates:
       *    return <restriction.generate(acb)>;
       * and adds it to userExprFun
       * NOTE: The explicit cast to DataValueDescriptor is required
       * since the restriction may simply be a boolean column or subquery
       * which returns a boolean.  For example:
       *    where booleanColumn
       */
      constantRestriction.generateExpression(acb, userExprFun);

      userExprFun.methodReturn();

      // we are done modifying userExprFun, complete it.
      userExprFun.complete();

         // restriction is used in the final result set as an access
      // of the new static field holding a reference to this new method.
      // generates:
      //  ActivationClass.userExprFun
View Full Code Here

       //   return fieldX;
       // }
       // static Method exprN = method pointer to exprN;

       // this sets up the method and the static field.
       MethodBuilder userExprFun = acb.newUserExprFun();

    /* Declare the field */
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecRow);

    // Generate the code to create the row in the constructor
    genCreateRow(acb, field, "getValueRow", ClassName.ExecRow, size());

    ResultColumn rc;
    int size = size();

    MethodBuilder cb = acb.getConstructor();

    for (int index = 0; index < size; index++)
    {
        // generate statements of the form
      // fieldX.setColumn(columnNumber, (DataValueDescriptor) columnExpr);
      // and add them to exprFun.
      rc = (ResultColumn) elementAt(index);

      /* If we are not generating nulls, then we can skip this RC if
       * it is simply propagating a column from the source result set.
       */
      if (!genNulls)
      {
        ValueNode sourceExpr = rc.getExpression();

        if (sourceExpr instanceof VirtualColumnNode && ! ( ((VirtualColumnNode) sourceExpr).getCorrelated()))
        {
          continue;
        }

        if (sourceExpr instanceof ColumnReference && ! ( ((ColumnReference) sourceExpr).getCorrelated()))
        {
          continue;
        }
      }


            // row add is 1-based, and iterator index is 0-based
      if (SanityManager.DEBUG)
      {
        if (index + 1 != rc.getVirtualColumnId())
        {
          SanityManager.THROWASSERT(
            "VirtualColumnId (" +
            rc.getVirtualColumnId() +
            ") does not agree with position within Vector (" +
            (index + 1) +
            ")");
        }
      }

      // we need the expressions to be Columns exactly.

      /* SPECIAL CASE:  Expression is a non-null constant.
       *  Generate the setColumn() call in the constructor
       *  so that it will only be executed once per instantiation.
       *
        * Increase the statement counter in constructor.  Code size in
        * constructor can become too big (more than 64K) for Java compiler
        * to handle (beetle 4293).  We set constant columns in other
        * methods if constructor has too many statements already.
        */
      if ( (! genNulls) &&
         (rc.getExpression() instanceof ConstantNode) &&
         ! ((ConstantNode) rc.getExpression()).isNull() &&
         ! cb.statementNumHitLimit(1))
      {


        cb.getField(field); // instance
        cb.push(index + 1); // first arg;

        rc.generateExpression(acb, cb);
        cb.cast(ClassName.DataValueDescriptor); // second arg
        cb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
        continue;
      }

      userExprFun.getField(field); // instance
      userExprFun.push(index + 1); // arg1
View Full Code Here

       //   return fieldX;
       // }
       // static Method exprN = method pointer to exprN;

       // this sets up the method and the static field
       MethodBuilder exprFun = acb.newExprFun();

    // Allocate the right type of row, depending on
    // whether we're scanning an index or a heap.
    if (indexRow)
    {
      rowAllocatorMethod = "getIndexableRow";
      rowAllocatorType = ClassName.ExecIndexRow;
    }
    else
    {
      rowAllocatorMethod = "getValueRow";
      rowAllocatorType = ClassName.ExecRow;
    }
    numCols = size();

    /* Declare the field */
    LocalField lf = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecRow);
    // Generate the code to create the row in the constructor
    genCreateRow(acb, lf, rowAllocatorMethod, rowAllocatorType, highestColumnNumber + 1);

    // now we fill in the body of the function

    int colNum;

    // If there is a referenced column map, the first column to fill
    // in is the first one in the bit map - otherwise, it is
    // column 0.
    if (referencedCols != null)
      colNum = referencedCols.anySetBit();
    else
      colNum = 0;

    for (int index = 0; index < numCols; index++)
    {
      ResultColumn rc = ((ResultColumn) elementAt(index));

      /* Special code generation for RID since expression is CurrentRowLocationNode.
       * Really need yet another node type that does its own code generation.
       */
      if (rc.getExpression() instanceof CurrentRowLocationNode)
      {
        ConglomerateController cc = null;
        int savedItem;
        RowLocation rl;
       
        cc = getLanguageConnectionContext().
            getTransactionCompile().openConglomerate(
              conglomerateId,
                            false,
              0,
              TransactionController.MODE_RECORD,
              TransactionController.ISOLATION_READ_COMMITTED);
        try
        {
          rl = cc.newRowLocationTemplate();
        }
        finally
        {
          if (cc != null)
          {
            cc.close();
          }
        }

        savedItem = acb.addItem(rl);
               
        // get the RowLocation template
        exprFun.getField(lf); // instance for setColumn
        exprFun.push(highestColumnNumber + 1); // first arg

        exprFun.pushThis(); // instance for getRowLocationTemplate
        exprFun.push(savedItem); // first arg
        exprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Activation, "getRowLocationTemplate",
                  ClassName.RowLocation, 1);

        exprFun.upCast(ClassName.DataValueDescriptor);
        exprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn",
                      "void", 2);
        continue;
      }

      /* Skip over those columns whose source is the immediate
       * child result set.  (No need to generate a wrapper
       * for a SQL NULL when we are smart enough not to pass
       * that wrapper to the store.)
       * NOTE: Believe it or not, we have to check for the case
       * where referencedCols is not null, but no bits are set.
       * This can happen when we need to get all of the columns
       * from the heap due to a check constraint.
       */
      if (propagatedCols != null &&
        propagatedCols.getNumBitsSet() != 0)
      {
        /* We can skip this RC if it is simply propagating
         * a column from the source result set.
         */
        ValueNode sourceExpr = rc.getExpression();

        if (sourceExpr instanceof VirtualColumnNode)
        {
          // There is a referenced columns bit set, so use
          // it to figure out what the next column number is.
          // colNum = referencedCols.anySetBit(colNum);
          continue;
        }
      }

      // generate the column space creation call
           // generate statements of the form
        // r.setColumn(columnNumber, columnShape);
        //
        // This assumes that there are no "holes" in the column positions,
        // and that column positions reflect the stored format/order
      exprFun.getField(lf); // instance
      exprFun.push(colNum + 1); // first arg
      rc.generateHolder(acb, exprFun);

      exprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);

      // If there is a bit map of referenced columns, use it to
      // figure out what the next column is, otherwise just go
      // to the next column.
      if (referencedCols != null)
        colNum = referencedCols.anySetBit(colNum);
      else
        colNum++;
      }
     
    // generate:
    // return fieldX;
    // and add to the end of exprFun's body.
    exprFun.getField(lf);
    exprFun.methodReturn();

    // we are done putting stuff in exprFun:
    exprFun.complete();

    return exprFun;
  }
View Full Code Here

    throws StandardException
  {
    // Create the row in the constructor
    //   fieldX = getExecutionFactory().getValueRow(# cols);

    MethodBuilder cb = acb.getConstructor();

    acb.pushGetExecutionFactoryExpression(cb); // instance
    cb.push(numCols);
    cb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
              rowAllocatorMethod, rowAllocatorType, 1);
    cb.setField(field);
    /* Increase the statement counter in constructor.  Code size in
     * constructor can become too big (more than 64K) for Java compiler
     * to handle (beetle 4293).  We set constant columns in other
     * methods if constructor has too many statements already.
     */
    cb.statementNumHitLimit(1);    // ignore return value
  }
View Full Code Here

    else
    {
      // this sets up the method and the static field.
      // generates:
      //   Object userExprFun { }
      MethodBuilder userExprFun = acb.newUserExprFun();

      // join clause knows it is returning its value;

      /* generates:
       *    return <joinClause.generate(acb)>;
       * and adds it to userExprFun
       */
      joinClause.generate(acb, userExprFun);
      userExprFun.methodReturn();

      // we are done modifying userExprFun, complete it.
      userExprFun.complete();

         // join clause is used in the final result set as an access of the new static
         // field holding a reference to this new method.
      // generates:
      //  ActivationClass.userExprFun
View Full Code Here

        String vtiType = version2 ?
                "java.sql.PreparedStatement" : "java.sql.ResultSet";
    // this sets up the method and the static field.
    // generates:
    //   java.sql.ResultSet userExprFun { }
    MethodBuilder userExprFun = acb.newGeneratedFun(
                vtiType, Modifier.PUBLIC);
    userExprFun.addThrownException("java.lang.Exception");


    // If it's a re-useable PreparedStatement then hold onto it.
    LocalField psHolder = reuseablePs ? acb.newFieldDeclaration(Modifier.PRIVATE, "java.sql.PreparedStatement") : null;

    if (reuseablePs) {

      userExprFun.getField(psHolder);
      userExprFun.conditionalIfNull();
    }

    newInvocation.generateExpression(acb, userExprFun);
        userExprFun.upCast(vtiType);

    if (reuseablePs) {

      userExprFun.putField(psHolder);

      userExprFun.startElseCode();

      userExprFun.getField(psHolder);

      userExprFun.completeConditional();
    }

    userExprFun.methodReturn();



    // newInvocation knows it is returning its value;

    /* generates:
     *    return <newInvocation.generate(acb)>;
     */
    // we are done modifying userExprFun, complete it.
    userExprFun.complete();

       // constructor is used in the final result set as an access of the new static
    // field holding a reference to this new method.
    // generates:
    //  ActivationClass.userExprFun
    // which is the static field that "points" to the userExprFun
    // that evaluates the where clause.
    acb.pushMethodReference(mb, userExprFun);


    // now add in code to close the reusable PreparedStatement when
    // the activation is closed.
    if (reuseablePs) {
      MethodBuilder closeActivationMethod = acb.getCloseActivationMethod();

      closeActivationMethod.getField(psHolder);
      closeActivationMethod.conditionalIfNull();
        // do nothing
        closeActivationMethod.push(0); // work around for no support for real if statements
      closeActivationMethod.startElseCode();
        closeActivationMethod.getField(psHolder);
        closeActivationMethod.callMethod(VMOpcode.INVOKEINTERFACE, "java.sql.Statement",
          "close", "void", 0);
        closeActivationMethod.push(0);

      closeActivationMethod.completeConditional();
      closeActivationMethod.endStatement();
    }

  }
View Full Code Here

  private void generateMinion(ExpressionClassBuilder acb,
                   MethodBuilder mb, boolean genChildResultSet)
                  throws StandardException
  {
    MethodBuilder  userExprFun;
    ValueNode  searchClause = null;
    ValueNode  equijoinClause = null;


    /* The tableProperties, if non-null, must be correct to get this far.
     * We simply call verifyProperties to set initialCapacity and
     * loadFactor.
     */
    verifyProperties(getDataDictionary());

    // build up the tree.

    /* Put the predicates back into the tree */
    if (searchPredicateList != null)
    {
      // Remove any redundant predicates before restoring
      searchPredicateList.removeRedundantPredicates();
      searchClause = searchPredicateList.restorePredicates();
      /* Allow the searchPredicateList to get garbage collected now
       * that we're done with it.
       */
      searchPredicateList = null;
    }

    // for the single table predicates, we generate an exprFun
    // that evaluates the expression of the clause
    // against the current row of the child's result.
    // if the restriction is empty, simply pass null
    // to optimize for run time performance.

       // generate the function and initializer:
       // Note: Boolean lets us return nulls (boolean would not)
       // private Boolean exprN()
       // {
       //   return <<searchClause.generate(ps)>>;
       // }
       // static Method exprN = method pointer to exprN;





    // Map the result columns to the source columns
    int[] mapArray = resultColumns.mapSourceColumns();
    int mapArrayItem = acb.addItem(new ReferencedColumnsDescriptorImpl(mapArray));

    // Save the hash key columns

    FormatableIntHolder[] fihArray =
        FormatableIntHolder.getFormatableIntHolders(hashKeyColumns());
    FormatableArrayHolder hashKeyHolder = new FormatableArrayHolder(fihArray);
    int hashKeyItem = acb.addItem(hashKeyHolder);

    /* Generate the HashTableResultSet:
     *  arg1: childExpress - Expression for childResultSet
     *  arg2: searchExpress - Expression for single table predicates
     *  arg3  : equijoinExpress - Qualifier[] for hash table look up
     *  arg4: projectExpress - Expression for projection, if any
     *  arg5: resultSetNumber
     *  arg6: mapArrayItem - item # for mapping of source columns
     *  arg7: reuseResult - whether or not the result row can be reused
     *            (ie, will it always be the same)
     *  arg8: hashKeyItem - item # for int[] of hash column #s
     *  arg9: removeDuplicates - don't remove duplicates in hash table (for now)
     *  arg10: maxInMemoryRowCount - max row size for in-memory hash table
     *  arg11: initialCapacity - initialCapacity for java.util.Hashtable
     *  arg12  : loadFactor - loadFactor for java.util.Hashtable
     *  arg13: estimated row count
     *  arg14: estimated cost
     *  arg15: close method
     */

    acb.pushGetResultSetFactoryExpression(mb);

    if (genChildResultSet)
      childResult.generateResultSet(acb, mb);
    else
      childResult.generate((ActivationClassBuilder) acb, mb);

    /* Get the next ResultSet #, so that we can number this ResultSetNode, its
     * ResultColumnList and ResultSet.
     */
    assignResultSetNumber();

    /* Set the point of attachment in all subqueries attached
     * to this node.
     */
    if (pSubqueryList != null && pSubqueryList.size() > 0)
    {
      pSubqueryList.setPointOfAttachment(resultSetNumber);
      if (SanityManager.DEBUG)
      {
        SanityManager.ASSERT(pSubqueryList.size() == 0,
          "pSubqueryList.size() expected to be 0");
      }
    }
    if (rSubqueryList != null && rSubqueryList.size() > 0)
    {
      rSubqueryList.setPointOfAttachment(resultSetNumber);
      if (SanityManager.DEBUG)
      {
        SanityManager.ASSERT(rSubqueryList.size() == 0,
          "rSubqueryList.size() expected to be 0");
      }
    }

    // Get the final cost estimate based on child's cost.
    costEstimate = childResult.getFinalCostEstimate();

    // if there is no searchClause, we just want to pass null.
    if (searchClause == null)
    {
         mb.pushNull(ClassName.GeneratedMethod);
    }
    else
    {
      // this sets up the method and the static field.
      // generates:
      //   DataValueDescriptor userExprFun { }
      userExprFun = acb.newUserExprFun();

      // searchClause knows it is returning its value;

      /* generates:
       *    return <searchClause.generate(acb)>;
       * and adds it to userExprFun
       * NOTE: The explicit cast to DataValueDescriptor is required
       * since the searchClause may simply be a boolean column or subquery
       * which returns a boolean.  For example:
       *    where booleanColumn
       */

      searchClause.generateExpression(acb, userExprFun);
      userExprFun.methodReturn();


      /* PUSHCOMPILER
      userSB.newReturnStatement(searchClause.generateExpression(acb, userSB));
      */

      // we are done modifying userExprFun, complete it.
      userExprFun.complete();

         // searchClause is used in the final result set as an access of the new static
         // field holding a reference to this new method.
      // generates:
      //  ActivationClass.userExprFun
View Full Code Here

  public void generateQualMethod(ExpressionClassBuilder acb,
                    MethodBuilder mb,
                    Optimizable optTable)
            throws StandardException
  {
    MethodBuilder qualMethod = acb.newUserExprFun();

    /* Generate a method that returns that expression */
    acb.generateNull(qualMethod, operand.getTypeCompiler(),
        operand.getTypeServices().getCollationType());
    qualMethod.methodReturn();
    qualMethod.complete();

    /* Return an expression that evaluates to the GeneratedMethod */
    acb.pushMethodReference(mb, qualMethod);
  }
View Full Code Here

TOP

Related Classes of org.apache.derby.iapi.services.compiler.MethodBuilder

Copyright © 2018 www.massapicom. 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.