com.ibm.as400.access.JDCursor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: JDCursor.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2001 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
This class implements a cursor on the IBM i system. NOTE: Creating this
object does not explicitly create the cursor on the system.
**/
class JDCursor
{
// Open attributes.
private static final int OPEN_READONLY_ = 0x80;
private static final int OPEN_ALL_ = 0xF0;
private static final int FULL_OPEN_ = 0x01; // @W1a
// Reuse flags. These describe how to close a cursor.
static final int REUSE_NO = 0xF0;
static final int REUSE_YES = 0xF1;
static final int REUSE_RESULT_SET = 0xF2;
private boolean closed_;
private AS400JDBCConnection connection_;
private int id_;
private boolean lazyClose_; // @E2A
private String name_;
private int concurrency_; // @E4A
private int holdable_ = -1; //@cur
private int scrollable_ = -1; //@cur
private int updatable_ = -1; //@cur (if on 550 hostserver, can use this instead of concurrency_)
private int sensitive_ = -1; //@cur
private int isolationLevel_ = -1; //@isol
private boolean extendedMetaData_ = false;
private DBReplyRequestedDS openReply = null;
private DBExtendedColumnDescriptors extendedColumnDescriptors_ = null;
/**
Constructs a JDCursor object.
@param connection Connection to the system.
@param id The id.
@param name Cursor name.
@param concurrency The concurrency
**/
JDCursor (AS400JDBCConnection connection,
int id,
String name,
// @E3D boolean lazyClose,
int concurrency) // @E4A
throws SQLException // @E6A
{
closed_ = true;
concurrency_ = concurrency; // @E4A
connection_ = connection;
id_ = id;
name_ = name;
lazyClose_ = connection_.getProperties().getBoolean(JDProperties.LAZY_CLOSE); // @E2A
// @E3D lazyClose_ = lazyClose; // @E3A
}
/**
Closes the cursor.
@param reuseFlag One of REUSE_*.
@exception SQLException If an error occurs.
**/
//
// Implementation note:
//
// It is a requirement to not get replies during a finalize()
// method. Since Statement.finalize() calls this method,
// this requirement applies here, too.
//
void close (int reuseFlag)
throws SQLException
{
// Close the cursor for good. This makes sure that
// the cursor is not left around.
DBSQLRequestDS request = null; //@P0A
boolean keepDS = false; //@P1A
try
{
request = DBDSPool.getDBSQLRequestDS (DBSQLRequestDS.FUNCTIONID_CLOSE, id_, 0, 0); //@P0C
request.setReuseIndicator (reuseFlag);
if (lazyClose_) // @E2A
{
keepDS = true; //@P1A
connection_.sendAndHold(request, id_); // @E2A
}
else
{ // @E2A
connection_.send (request, id_);
}
}
catch (DBDataStreamException e)
{
JDError.throwSQLException (JDError.EXC_INTERNAL, e); // @E5C
}
finally
{
if (request != null && !keepDS) { request.returnToPool(); request = null; } //@P1C
}
if (openReply != null) {
openReply.returnToPool(); openReply = null;
}
closed_ = true;
if (JDTrace.isTraceOn())
{
JDTrace.logInformation (this, "Closing with reuse flag = " + reuseFlag);
JDTrace.logClose (this);
}
}
/**
Returns the cursor name.
@return The cursor name.
**/
String getName ()
{
return name_;
}
/**
Returns the open attributes appropriate for the the
SQL statement.
@param sqlStatement a SQL statement.
@param blockCriteria block criteria.
@return the open attributes.
@exception SQLException If an error occurrs.
**/
//
// Implementation note: Cursors perform better on
// the system when read only, so set the open
// attributes to read only in as many cases as
// possible. (Of course, not when the user needs
// to update using the cursor.)
//
int getOpenAttributes (JDSQLStatement sqlStatement,
String blockCriteria)
throws SQLException
{
int returnValue = OPEN_ALL_; // @W1a
// If we are opening a cursor on a subsequent
// result set returned by a stored procedure,
// then it is read only.
if (sqlStatement == null)
returnValue = OPEN_READONLY_; // @W1c
// If we are opening a cursor on a result set
// returned by a stored procedure, then it is
// read only.
else if (sqlStatement.isProcedureCall ()) // @W1c
returnValue = OPEN_READONLY_; // @W1c
// For SELECTs, the cursor is read only when
// the cursor or connection is read only and
// when we are record blocking. Note that record
// blocking implies a read only cursor.
// Change for J3 -- a system change in mod 5 allows updatable cursors
// even when the select statement does not specific "for update". The
// J3 change takes this into consideration. The J3 change is to add
// !(concurrency_ == ResultSet.CONCUR_UPDATABLE)) to the check.
else if (
sqlStatement.isSelect () // @W1c
&& (! blockCriteria.equalsIgnoreCase (JDProperties.BLOCK_CRITERIA_NONE))
&& ((connection_.isReadOnly()) || ((! sqlStatement.isForUpdate ()) && (!(concurrency_ == ResultSet.CONCUR_UPDATABLE)))) // @J3C
)
returnValue = OPEN_READONLY_; // @W1c
// the "ServerLevel > 9" in the following check makes sure we are running
// to a v5r1 or later version of the AS/400.
if ((connection_.getProperties().getBoolean(JDProperties.FULL_OPEN)) && // @W1a
(connection_.getServerFunctionalLevel() >= 9)) // @W1a
returnValue = returnValue | FULL_OPEN_; // @W1a
// return OPEN_ALL_; // @W1d
return returnValue; // @W1a
}
// @E1A @E4C
/**
Returns the cursor concurrency.
@return The cursor concurrency.
**/
int getConcurrency()
{
return concurrency_;
}
/**
Indicates if the cursor is closed.
@return true if the cursor is closed; false otherwise.
**/
boolean isClosed ()
{
return closed_;
}
/**
* Set the extendedColumnDescriptrs from the reply
* @param reply
*/
//@P6A
void setExtendedColumnDescriptorsFromReply( DBReplyRequestedDS reply) {
if (extendedMetaData_) {
extendedColumnDescriptors_ = reply.getExtendedColumnDescriptors();
} else {
extendedColumnDescriptors_ =null;
}
}
/**
Opens the cursor and describes the data format.
@param openAttributes The open attributes.
@param scrollable true if the cursor should be
scrollable, false otherwise.
@return The data format.
@exception SQLException If an error occurs.
**/
DBDataFormat openDescribe (int openAttributes,
int resultSetType) //@KBC
throws SQLException
{
DBDataFormat dataFormat = null;
try
{
DBSQLRequestDS request = null; //@P0A
try
{
int requestedORS = DBSQLRequestDS.ORS_BITMAP_RETURN_DATA
+ DBSQLRequestDS.ORS_BITMAP_DATA_FORMAT
+ DBSQLRequestDS.ORS_BITMAP_SQLCA;
if (extendedMetaData_) {
requestedORS = requestedORS + DBSQLRequestDS.ORS_BITMAP_EXTENDED_COLUMN_DESCRIPTORS;
}
request = DBDSPool.getDBSQLRequestDS ( //@P0C
DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE,
id_, requestedORS, // @E1A
0); //@isol Note: ORS_BITMAP_CURSOR_ATTRIBUTES not needed here since it is specified by callers before this point
request.setOpenAttributes (openAttributes);
//@F1 Even though multiple cases were required in AS400JDBCStatement, scrollable is
//@F1 always false when openDescribe is called, so the cursor is always forward-only
//@F1 and we need less cases here. More cases would need to be added if the value
//@F1 of scrollable was not always false (between sensitive and insensitive
//@F1 resultSetType). Right now, the value of false for scrollable always indicates
//@F1 forward-only (not scrollable). If this changed, instead of a boolean, we'd need
//@F1 an int with sensitive/insensitive/forward-only passed in as the choices to this
//@F1 method.
//@F1 If we are pre-V5R2, send what we always have.
/* @KBD if (connection_.getVRM() < JDUtilities.vrm520) //@F1A
{
request.setScrollableCursorFlag (scrollable ? 1 : 0);
}
else
{ //else check value of "cursor sensitivity" property
if (!scrollable)
{
// If the property is set to the default value, send same value we always have.
String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@F1A
if (cursorSensitivity.equalsIgnoreCase(JDProperties.CURSOR_SENSITIVITY_ASENSITIVE)) //@F1A
request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_ASENSITIVE); //@F1A
else if (cursorSensitivity.equalsIgnoreCase(JDProperties.CURSOR_SENSITIVITY_INSENSITIVE)) //@F1A
request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_INSENSITIVE); //@F1A
else //@F1A
request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_SENSITIVE); //@F1A
} //@F1A
else //add more cases if this method starts being called with scrollable not always equal to false //@F1A
request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_SCROLLABLE_ASENSITIVE); //@F1A
}
*/
String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@F8A
if(connection_.getVRM() <= JDUtilities.vrm520) //@KBA
{
//@KBA IF pre-V5R3 always set to NOT SCROLLABLE ASENSITIVE
//if(resultSetType == ResultSet.TYPE_FORWARD_ONLY) //@KBA
request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_ASENSITIVE); //@KBA Option 0
//else //@KBA
// request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_SCROLLABLE_ASENSITIVE); //@KBA Option 1
} //@KBA
else {
/* @H1A Use common routine to determine scrollability */
request.setScrollableCursorFlag (
AS400JDBCResultSet.getDBSQLRequestDSCursorType(cursorSensitivity, resultSetType, ResultSet.CONCUR_READ_ONLY));
} //@KBA
if (openReply != null) { openReply.returnToPool(); openReply =null; }
openReply = connection_.sendAndReceive (request, id_); //@P0C
int errorClass = openReply.getErrorClass();
int returnCode = openReply.getReturnCode();
if (errorClass != 0)
JDError.throwSQLException (this, connection_, id_, errorClass, returnCode);
processConcurrencyOverride(openAttributes, openReply); // @E1A @E4C
dataFormat = openReply.getDataFormat ();
setExtendedColumnDescriptorsFromReply( openReply); //@P6A
// @550A NOTE: openDescribe() currently is only called for a result set returned from a CallableStatement
// if that were to change, this method needs to be modified so that it correctly indicates to the data format
// when the data is from a stored procedure result set.
dataFormat.setCSRSData(true); // @550A indicate to the data format that this data is associated with a stored procedure result set
}
finally
{
if (request != null) { request.returnToPool(); request = null; }
// if (openReply != null) { openReply.returnToPool(); openReply = null; }
}
}
catch (DBDataStreamException e)
{
JDError.throwSQLException (JDError.EXC_INTERNAL, e); // @E5C
}
closed_ = false;
if (JDTrace.isTraceOn())
JDTrace.logOpen (this, null); // @J33a
return dataFormat;
}
// @E1A @E4C
/**
Processes a potential cursor concurrency override from a reply.
It is assumed that the reply contains a SQLCA. This means
that you have to include the SQLCA bit as part of the ORS
bitmap in the request.
@param openAttributes The requested open attributes.
@param reply The reply.
**/
void processConcurrencyOverride(int openAttributes, DBBaseReplyDS reply)
throws DBDataStreamException
{
// If the system overrides our open attributes, reflect that fact.
DBReplySQLCA sqlca = reply.getSQLCA ();
switch (sqlca.getWarn5())
{
case (byte)0xF1: // EBCDIC'1' Read only
case (byte)0xF2: // EBCDIC'2' Read and deleteable
concurrency_ = ResultSet.CONCUR_READ_ONLY;
break;
case (byte)0xF4: // EBCDIC'4' Read, deleteable, and updateable
concurrency_ = ResultSet.CONCUR_UPDATABLE;
break;
/* @E7D - We should not do an override if this is an old system.
default: // Old system (without override indication)
switch(openAttributes) {
case OPEN_READONLY_:
concurrency_ = ResultSet.CONCUR_READ_ONLY;
break;
case OPEN_ALL_:
default:
concurrency_ = ResultSet.CONCUR_UPDATABLE;
break;
}
break;
*/
}
}
//@cur new method
/**
Processes a cursor attributes from a reply.
@param reply The reply.
**/
void processCursorAttributes(DBBaseReplyDS reply)
throws SQLException
{
holdable_ = reply.getCursorAttributeHoldable();
scrollable_ = reply.getCursorAttributeScrollable();
updatable_ = reply.getCursorAttributeUpdatable();
sensitive_ = reply.getCursorAttributeSensitive();
isolationLevel_ = reply.getCursorIsolationLevel(); //@isol
}
//@cur new method
/**
Returns the cursor attribute holdable.
@return The server attribute holdable. (1 is holdable, 0 is not holdable)
**/
public int getCursorAttributeHoldable()
{
return holdable_;
}
//@cur new method
/**
Returns the cursor attribute Scrollable.
@return The server attribute Scrollable. (1 is Scrollable, 0 is not Scrollable)
**/
public int getCursorAttributeScrollable()
{
return scrollable_;
}
//@cur new method
/**
Returns the cursor attribute Updatable.
@return The server attribute Updatable. (1 is Updatable, 0 is not Updatable)
**/
public int getCursorAttributeUpdatable()
{
return updatable_;
}
//@cur new method
/**
Returns the cursor attribute Sensitive.
@return The server attribute Sensitive. (1 is Sensitive, 0 is not Sensitive)
**/
public int getCursorAttributeSensitive()
{
return sensitive_;
}
//@isol new method
/**
Returns the cursor isolation level.
@return The cursor isolation level.
**/
public int getCursorIsolationLevel()
{
return isolationLevel_;
}
/**
* Sets whether extended metadata should be requested when the cursor is
* opened.
* @param extendedMetaData
*/
void setExtendedMetaData(boolean extendedMetaData) {
extendedMetaData_=extendedMetaData;
}
/**
Set the cursor name.
@param name The cursor name.
**/
void setName (String name)
{
name_ = name;
if (JDTrace.isTraceOn())
JDTrace.logProperty (this, "setName", "Name", name_);
}
/**
Sets the state of the cursor. This is useful when a
request implicitly opens or closes the cursor.
@param closed true for close, or false for open
**/
void setState (boolean closed)
{
closed_ = closed;
if (JDTrace.isTraceOn())
{
if (closed_)
JDTrace.logClose (this);
else
JDTrace.logOpen (this, null); // @J33a
}
}
/**
* Returns the extended column descriptors
*/
DBExtendedColumnDescriptors getExtendedColumnDescriptors() {
return extendedColumnDescriptors_;
}
/**
Returns the cursor name.
@return the cursor name.
**/
public String toString ()
{
return name_;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy