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

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

/*

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

   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.sanity.SanityManager;

import org.apache.derby.iapi.services.loader.GeneratedClass;

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

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

import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;

import org.apache.derby.iapi.sql.depend.DependencyManager;

import org.apache.derby.iapi.reference.SQLState;

import org.apache.derby.iapi.sql.execute.ConstantAction;
import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;

import org.apache.derby.iapi.types.DataTypeDescriptor;
import org.apache.derby.iapi.sql.PreparedStatement;
import org.apache.derby.iapi.sql.ResultDescription;

import org.apache.derby.impl.sql.CursorInfo;

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

import java.util.Enumeration;

/**
* A ExecSPSNode is the root of a QueryTree
* that represents an EXECUTE STATEMENT
* statement.  It is a tad abnormal.  Duringa
* bind, it locates and retrieves the SPSDescriptor
* for the particular statement.  At generate time,
* it generates the prepared statement for the
* stored prepared statement and returns it (i.e.
* it effectively replaces itself with the appropriate
* prepared statement).
*
*/

public class ExecSPSNode extends StatementNode
{
  private TableName      name;
  private SPSDescriptor    spsd;
  private ExecPreparedStatement ps;

  /**
   * Initializer for a ExecSPSNode
   *
   * @param newObjectName    The name of the table to be created
   *
   * @exception StandardException    Thrown on error
   */

  public void init(
        Object     newObjectName)
  {
    this.name = (TableName) newObjectName;
  }

  /**
   * Bind this ExecSPSNode.  This means doing any static error
   * checking that can be done before actually creating the table.
   * For example, verifying that the ResultColumnList does not
   * contain any duplicate column names.
   *
   * @exception StandardException    Thrown on error
   */
  public void bindStatement() throws StandardException
  {
    /*
    ** Grab the compiler context each time we bind just
    ** to make sure we have the write one (even though
    ** we are caching it).
    */
    DataDictionary dd = getDataDictionary();

    String schemaName = name.getSchemaName();
    SchemaDescriptor sd = getSchemaDescriptor(name.getSchemaName());
    if (schemaName == null)
      name.setSchemaName(sd.getSchemaName());

    if (sd.getUUID() != null)
      spsd = dd.getSPSDescriptor(name.getTableName(), sd);

    if (spsd == null)
    {
      throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, "STATEMENT", name);
    }

    if (spsd.getType() == spsd.SPS_TYPE_TRIGGER)
    {
      throw StandardException.newException(SQLState.LANG_TRIGGER_SPS_CANNOT_BE_EXECED, name);
    }
   

    /*
    ** This execute statement is dependent on the
    ** stored prepared statement.  If for any reason
    ** the underlying statement is invalidated by
    ** the time we get to execution, the 'execute statement'
    ** will get invalidated when the underlying statement
    ** is invalidated.
    */
    getCompilerContext().createDependency(spsd);

  }

  /**
   * SPSes are atomic if its underlying statement is
   * atomic.
   *
   * @return true if the statement is atomic
   */ 
  public boolean isAtomic()
  {

    if (SanityManager.DEBUG)
    {
      SanityManager.ASSERT(ps != null,
        "statement expected to be bound before calling isAtomic()");
    }

    return ps.isAtomic();
  }

  /**
   * Do code generation for this statement.  Overrides
   * the normal generation path in StatementNode.
   *
   * @param  ignored - ignored (he he)
   *
   * @return    A GeneratedClass for this statement
   *
   * @exception StandardException    Thrown on error
   */
  public GeneratedClass generate(ByteArray ignored) throws StandardException
  {
    //Bug 4821 - commiting the nested transaction will release any bind time locks
    //This way we won't get lock time out errors while trying to update sysstatement
    //table during stale sps recompilation later in the getPreparedstatement() call.
    if (spsd.isValid() == false) {
      getLanguageConnectionContext().commitNestedTransaction();
      getLanguageConnectionContext().beginNestedTransaction(true);
   

    /*
    ** The following does a prepare on the underlying
    ** statement if necessary.  The returned statement
    ** is valid and its class is loaded up.
    */
    ps = spsd.getPreparedStatement();


    /*
    ** Set the saved constants from the prepared statement.
    ** Put them in the compilation context -- this is where
    ** they are expected.
    */
    getCompilerContext().setSavedObjects(ps.getSavedObjects());
    getCompilerContext().setCursorInfo(ps.getCursorInfo());
    GeneratedClass gc = ps.getActivationClass();
   
    return gc;
  }
   
  /**
   * Make the result description.  Really, we are just
   * copying it from the stored prepared statement.
   *
   * @return  the description
   */
  public ResultDescription makeResultDescription()
  {
    return ps.getResultDescription();
  }

  /**
   * Get information about this cursor.  For sps,
   * this is info saved off of the original query
   * tree (the one for the underlying query).
   *
   * @return  the cursor info
   */
  public Object getCursorInfo()
  {
    return ps.getCursorInfo();
  }

  /**
   * Return a description of the ? parameters for the statement
   * represented by this query tree.  Just return the params
   * stored with the prepared statement.
   *
   * @return  An array of DataTypeDescriptors describing the
   *    ? parameters for this statement.  It returns null
   *    if there are no parameters.
   *
   * @exception StandardException on error
   */
  public DataTypeDescriptor[]  getParameterTypes() throws StandardException
  {
    return spsd.getParams();
  }


  /**
   * Create the Constant information that will drive the guts of Execution.
   * This is assumed to be the first action on this node.
   *
   */
  public ConstantAction  makeConstantAction()
  {
    return ps.getConstantAction();
  }

  /**
   * We need a savepoint if we will do transactional work.
   * We'll ask the underlying statement if it needs
   * a savepoint and pass that back.  We have to do this
   * after generation because getting the PS now might
   * cause us to basically do DDL (for a stmt recompilation)
   * which is explicitly banned during binding.  So the
   * caller can only call this after generate() has retrieved
   * the target PS. 
   *
   * @return boolean  always true.
   */
  public boolean needsSavepoint()
  {
    if (SanityManager.DEBUG)
    {
      SanityManager.ASSERT(ps != null,
        "statement expected to be bound before calling needsSavepoint()");
    }

    return ps.needsSavepoint();
  }

  /** @see StatementNode#executeStatementName */
  public String executeStatementName()
  {
    return name.getTableName();
  }

  /** @see StatementNode#executeSchemaName */
  public String executeSchemaName()
  {
    return name.getSchemaName();
  }

  /**
   * Get the name of the SPS that is used
   * to execute this statement.  Only relevant
   * for an ExecSPSNode -- otherwise, returns null.
   *
   * @return the name of the underlying sps
   */
  public String getSPSName()
  {
    return spsd.getQualifiedName();
  }
   
  /*
   * Shouldn't be called
   */
  int activationKind()
  {
    if (SanityManager.DEBUG)
    {
      SanityManager.THROWASSERT("activationKind not expected "+
        "to be called for a stored prepared statement");
    }
     return StatementNode.NEED_PARAM_ACTIVATION;
  }
  /////////////////////////////////////////////////////////////////////
  //
  // PRIVATE
  //
  /////////////////////////////////////////////////////////////////////

   
  /////////////////////////////////////////////////////////////////////
  //
  // MISC
  //
  /////////////////////////////////////////////////////////////////////
  public String statementToString()
  {
    return "EXECUTE STATEMENT";
  }

  // called after bind only
  private final SPSDescriptor getSPSDescriptor()
  {
    return spsd;
  }
}
TOP

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

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.