Class CursorNode

All Implemented Interfaces:
Visitable

public class CursorNode extends DMLStatementNode
A CursorNode represents a result set that can be returned to a client. A cursor can be a named cursor created by the DECLARE CURSOR statement, or it can be an unnamed cursor associated with a SELECT statement (more precisely, a table expression that returns rows to the client). In the latter case, the cursor does not have a name.
  • Field Details

    • UNSPECIFIED

      static final int UNSPECIFIED
      See Also:
    • READ_ONLY

      public static final int READ_ONLY
      See Also:
    • UPDATE

      static final int UPDATE
      See Also:
    • name

      private String name
    • orderByList

      private OrderByList orderByList
    • offset

      private ValueNode offset
    • fetchFirst

      private ValueNode fetchFirst
    • hasJDBClimitClause

      private boolean hasJDBClimitClause
    • statementType

      private String statementType
    • updateMode

      private int updateMode
    • needTarget

      private boolean needTarget
    • updatableColumns

      private List<String> updatableColumns
      There can only be a list of updatable columns when FOR UPDATE is specified as part of the cursor specification.
    • updateTable

      private FromTable updateTable
    • statsToUpdate

      private ArrayList<TableDescriptor> statsToUpdate
      List of TableDescriptors for base tables whose associated indexes should be checked for stale statistics.
    • checkIndexStats

      private boolean checkIndexStats
    • indexOfSessionTableNamesInSavedObjects

      private int indexOfSessionTableNamesInSavedObjects
    • forMergeStatement

      private boolean forMergeStatement
  • Constructor Details

    • CursorNode

      CursorNode(String statementType, ResultSetNode resultSet, String name, OrderByList orderByList, ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause, int updateMode, String[] updatableColumns, boolean forMergeStatement, ContextManager cm)
      Constructor for a CursorNode
      Parameters:
      statementType - Type of statement (SELECT, UPDATE, INSERT)
      resultSet - A ResultSetNode specifying the result set for the cursor
      name - The name of the cursor, null if no name
      orderByList - The order by list for the cursor, null if no order by list
      offset - The value of a if present
      fetchFirst - The value of a if present
      hasJDBClimitClause - True if the offset/fetchFirst clauses come from JDBC limit/offset escape syntax
      updateMode - The user-specified update mode for the cursor, for example, CursorNode.READ_ONLY
      updatableColumns - The array of updatable columns specified by the user in the FOR UPDATE clause, null if no updatable columns specified. May only be provided if the updateMode parameter is CursorNode.UPDATE.
      forMergeStatement - True if this cursor is the driving left-join of a MERGE statement
      cm - The context manager
  • Method Details

    • toString

      public String toString()
      Convert this object to a String. See comments in QueryTreeNode.java for how this should be done for tree printing.
      Overrides:
      toString in class StatementNode
      Returns:
      This object as a String
    • statementToString

      String statementToString()
      Specified by:
      statementToString in class StatementNode
    • updateModeString

      private static String updateModeString(int updateMode)
      Support routine for translating an updateMode identifier to a String
      Parameters:
      updateMode - An updateMode identifier
      Returns:
      A String representing the update mode.
    • printSubNodes

      void printSubNodes(int depth)
      Prints the sub-nodes of this object. See QueryTreeNode.java for how tree printing is supposed to work.
      Overrides:
      printSubNodes in class DMLStatementNode
      Parameters:
      depth - The depth of this node in the tree
    • bindStatement

      public void bindStatement() throws StandardException
      Bind this CursorNode. This means looking up tables and columns and getting their types, and figuring out the result types of all expressions, as well as doing view resolution, permissions checking, etc. It also includes determining whether an UNSPECIFIED cursor is updatable or not, and verifying that an UPDATE cursor actually is.
      Overrides:
      bindStatement in class StatementNode
      Throws:
      StandardException - Thrown on error
    • collectTablesWithPossiblyStaleStats

      private void collectTablesWithPossiblyStaleStats() throws StandardException
      Collects table descriptors for base tables whose index statistics we want to check for staleness (or to create).
      Throws:
      StandardException
    • referencesSessionSchema

      public boolean referencesSessionSchema() throws StandardException
      Return true if the node references SESSION schema tables (temporary or permanent)
      Overrides:
      referencesSessionSchema in class QueryTreeNode
      Returns:
      true if references SESSION schema tables, else false
      Throws:
      StandardException - Thrown on error
    • getSessionSchemaTableNamesForCursor

      protected ArrayList<String> getSessionSchemaTableNamesForCursor() throws StandardException
      Throws:
      StandardException
    • determineUpdateMode

      private int determineUpdateMode(DataDictionary dataDictionary) throws StandardException
      Take a cursor and determine if it is UPDATE or READ_ONLY based on the shape of the cursor specification.

      The following conditions make a cursor read only:

      • if it says FOR READ ONLY
      • if it says ORDER BY
      • if its query specification is not read only. At present this is explicitly tested here, with these conditions. At some future point in time, this checking ought to be moved into the ResultSet nodes themselves. The conditions for a query spec. not to be read only include:
        • if it has a set operation such as UNION or INTERSECT, i.e. does not have a single outermost SELECT
        • if it does not have exactly 1 table in its FROM list; 0 tables would occur if we ever support a SELECT without a FROM e.g., for generating a row without an underlying table (like what we do for an INSERT of a VALUES list); >1 tables occurs when joins are in the tree.
        • if the table in its FROM list is not a base table (REMIND when views/from subqueries are added, this should be relaxed to be that the table is not updatable)
        • if it has a GROUP BY or HAVING (NOTE I am assuming that if and aggregate is detected in a SELECT w/o a GROUP BY, one has been added to show that the whole table is a group)
        • NOTE that cursors are updatable even if none of the columns in the select are updatable -- what they care about is the updatability of the columns of the target table.
      Returns:
      the known update mode for the cursor.
      Throws:
      StandardException - Thrown on error
    • optimizeStatement

      public void optimizeStatement() throws StandardException
      Optimize a DML statement (which is the only type of statement that should need optimizing, I think). This method over-rides the one in QueryTreeNode. This method takes a bound tree, and returns an optimized tree. It annotates the bound tree rather than creating an entirely new tree. Throws an exception if the tree is not bound, or if the binding is out of date.
      Overrides:
      optimizeStatement in class DMLStatementNode
      Throws:
      StandardException - Thrown on error
    • activationKind

      int activationKind()
      Returns the type of activation this class generates.
      Overrides:
      activationKind in class DMLStatementNode
      Returns:
      either (NEED_CURSOR_ACTIVATION
      Throws:
      StandardException - Thrown on error
    • generate

      void generate(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException
      Do code generation for this CursorNode
      Overrides:
      generate in class QueryTreeNode
      Parameters:
      acb - The ActivationClassBuilder for the class being built
      mb - The method the generated code is to go into
      Throws:
      StandardException - Thrown on error
    • getUpdateBaseTableName

      String getUpdateBaseTableName()
    • getUpdateExposedTableName

      String getUpdateExposedTableName() throws StandardException
      Throws:
      StandardException
    • getUpdateSchemaName

      String getUpdateSchemaName() throws StandardException
      Throws:
      StandardException
    • getUpdateMode

      int getUpdateMode()
    • needsSavepoint

      public boolean needsSavepoint()
      Returns whether or not this Statement requires a set/clear savepoint around its execution. The following statement "types" do not require them: Cursor - unnecessary and won't work in a read only environment Xact - savepoint will get blown away underneath us during commit/rollback
      Overrides:
      needsSavepoint in class StatementNode
      Returns:
      boolean Whether or not this Statement requires a set/clear savepoint
    • getCursorInfo

      public Object getCursorInfo() throws StandardException
      Get information about this cursor. For sps, this is info saved off of the original query tree (the one for the underlying query).
      Overrides:
      getCursorInfo in class StatementNode
      Returns:
      the cursor info
      Throws:
      StandardException - thrown if generation fails
    • bindUpdateColumns

      private void bindUpdateColumns(FromTable targetTable) throws StandardException
      Bind the update columns by their names to the target table of the cursor specification. Doesn't check for duplicates in the list, although it could... REVISIT: If the list is empty, should it expand it out? at present, it leaves it empty.
      Parameters:
      targetTable - The underlying target table
      Throws:
      StandardException - Thrown on error
    • getXML

      String getXML()
    • updateIndexStatisticsFor

      public TableDescriptor[] updateIndexStatisticsFor() throws StandardException
      Returns a list of base tables for which the index statistics of the associated indexes should be updated.
      Overrides:
      updateIndexStatisticsFor in class StatementNode
      Returns:
      A list of table descriptors (potentially empty).
      Throws:
      StandardException - if accessing the index descriptors of a base table fails
    • acceptChildren

      void acceptChildren(Visitor v) throws StandardException
      Accept the visitor for all visitable children of this node.
      Overrides:
      acceptChildren in class DMLStatementNode
      Parameters:
      v - the visitor
      Throws:
      StandardException - on error