jtopenlite.com.ibm.jtopenlite.database.jdbc.JDBCStatement 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
///////////////////////////////////////////////////////////////////////////////
//
// JTOpenLite
//
// Filename: JDBCStatement.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) 2011-2012 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.jtopenlite.database.jdbc;
import com.ibm.jtopenlite.Conv;
import com.ibm.jtopenlite.database.*;
import java.io.*;
import java.sql.*;
public class JDBCStatement implements Statement, DatabaseSQLCommunicationsAreaCallback//, DatabaseDescribeCallback
{
public final static int TYPE_UNKNOWN = 0;
public final static int TYPE_INSERT_UPDATE_DELETE = 1;
public final static int TYPE_SELECT = 2;
public final static int TYPE_CALL = 3;
public final static int TYPE_COMMIT = 4;
public final static int TYPE_ROLLBACK = 5;
public final static int TYPE_CONNECT = 6;
public final static int TYPE_BLOCKED_INSERT = 7;
public static int getStatementType(String sql) throws SQLException
{
// Check for null string
if (sql == null) JDBCError.throwSQLException(JDBCError.EXC_SYNTAX_ERROR );
String st = sql.toUpperCase().trim();
while (st.length() > 0 && st.charAt(0) == '(') st = st.substring(1).trim();
int sqlStatementType = st.startsWith("SELECT") || st.startsWith("VALUES") ? TYPE_SELECT :
st.startsWith("INSERT") || st.startsWith("UPDATE") || st.startsWith("DELETE") ? TYPE_INSERT_UPDATE_DELETE :
st.startsWith("CALL") ? TYPE_CALL :
st.startsWith("COMMIT") ? TYPE_COMMIT :
st.startsWith("ROLLBACK") ? TYPE_ROLLBACK :
st.startsWith("CONNECT") || st.startsWith("SET") || st.startsWith("RELEASE") || st.startsWith("DISCONNECT") ? TYPE_CONNECT :
st.startsWith("BLOCKED INSERT") ? TYPE_BLOCKED_INSERT : TYPE_UNKNOWN;
// Check for statement too long
if (st.length() > (2097152 /* maximum bytes */ / 2)) {
JDBCError.throwSQLException(JDBCError.EXC_SQL_STATEMENT_TOO_LONG);
}
return sqlStatementType;
}
JDBCConnection conn_;
DatabaseRequestAttributes statementAttributes_; // Used to hold statement type
DatabaseRequestAttributes attribs_;
int rpbID_;
int fetchSize_;
String cursorName_ = null;
JDBCResultSet currentResultSet_;
boolean closed_;
String generatedKey_;
int updateCount_ = -1;
int lastUpdateCount_ = -1;
int resultSetsCount_ = -1;
int lastSQLCode_;
String lastSQLState_;
String statementName_ = null;
String catalog_ = null;
boolean poolable_ = false; /* Default is false */
public JDBCStatement(JDBCConnection conn, String statementName,
String cursorName, int rpbID) throws SQLException {
cursorName_ = cursorName;
statementName_ = statementName;
if (rpbID != 0) {
DatabaseRequestAttributes rpb = new DatabaseRequestAttributes();
rpb.setCursorName(cursorName);
rpb.setPrepareStatementName(statementName);
conn.createRequestParameterBlock(rpb, rpbID);
attribs_ = rpb;
statementAttributes_ = rpb.copy();
}
conn_ = conn;
rpbID_ = rpbID;
}
public void newSQLCommunicationsAreaData(int sqlCode, String sqlState, String generatedKey, int updateCount, int resultSetsCount)
{
if (sqlCode == 0)
{
generatedKey_ = generatedKey;
}
else
{
generatedKey_ = null;
}
lastUpdateCount_ = updateCount;
lastSQLCode_ = sqlCode;
lastSQLState_ = sqlState;
resultSetsCount_ = resultSetsCount;
}
int getLastSQLCode()
{
return lastSQLCode_;
}
String getLastSQLState()
{
return lastSQLState_;
}
DatabaseConnection getDatabaseConnection()
{
return conn_.getDatabaseConnection();
}
DatabaseRequestAttributes getRequestAttributes()
{
attribs_.clear();
return attribs_;
}
/**
* Not implemented.
**/
public void addBatch(String sql) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public void cancel() throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public void clearBatch() throws SQLException
{
throw new NotImplementedException();
}
/**
* Warning are not supported. This is a noop.
**/
public void clearWarnings() throws SQLException
{
}
public void close() throws SQLException
{
if (closed_) return;
try
{
generatedKey_ = null;
if (currentResultSet_ != null)
{
currentResultSet_.close();
currentResultSet_ = null;
}
attribs_.clear();
conn_.getDatabaseConnection().deleteRequestParameterBlock(attribs_, rpbID_);
conn_.freeRPBID(rpbID_);
if (statementName_ != null) {
conn_.freeStatementAndCursorNames(statementName_, cursorName_);
}
statementName_ = null;
cursorName_ = null;
}
catch (IOException io)
{
throw JDBCConnection.convertException(io, lastSQLCode_, lastSQLState_);
}
finally
{
closed_ = true;
}
}
public boolean execute(String sql) throws SQLException
{
return execute(sql, Statement.NO_GENERATED_KEYS);
}
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
if (currentResultSet_ != null)
{
currentResultSet_.close();
currentResultSet_ = null;
}
int statementType = getStatementType(sql);
if (statementType == TYPE_SELECT) {
currentResultSet_ = (JDBCResultSet) executeQuery(sql);
return true;
}
DatabaseConnection conn = conn_.getDatabaseConnection();
conn.setSQLCommunicationsAreaCallback(this);
DatabaseExecuteImmediateAttributes deia = getRequestAttributes();//conn_.getRequestAttributes();
deia.setSQLStatementText(sql);
if (statementType == TYPE_CALL) {
deia.setSQLStatementType(TYPE_CALL);
deia.setOpenAttributes(0x80); /* READ */
deia.setPrepareOption(0); /* normal prepare */
}
/* switch (autoGeneratedKeys)
{
case Statement.NO_GENERATED_KEYS:
conn.setSQLCommunicationsAreaCallback(null);
break;
case Statement.RETURN_GENERATED_KEYS:
conn.setSQLCommunicationsAreaCallback(this);
break;
default:
throw new SQLException("Bad value for autoGeneratedKeys parameter");
}
*/
boolean resultSetAvailable = false;
try
{
conn.setCurrentRequestParameterBlockID(rpbID_);
generatedKey_ = null;
conn.executeImmediate(deia);
updateCount_ = lastUpdateCount_;
//
// Todo: Need to check for result sets
//
if ( resultSetsCount_ > 0) {
resultSetAvailable = true;
DatabaseOpenAndDescribeAttributes oada = getRequestAttributes();
oada.setOpenAttributes(0x80);
oada.setScrollableCursorFlag(0);
oada.setVariableFieldCompression(0xe8);
if (catalog_ == null) {
catalog_ = conn_.getCatalog();
}
JDBCResultSetMetaData md = new JDBCResultSetMetaData(conn.getInfo().getServerCCSID(), conn_.getCalendar(), catalog_);
try {
conn.setCurrentRequestParameterBlockID(rpbID_);
if (currentResultSet_ != null) {
currentResultSet_.close();
currentResultSet_ = null;
}
conn.openAndDescribe(oada, md);
} catch (IOException io) {
throw JDBCConnection.convertException(io, lastSQLCode_, lastSQLState_);
}
currentResultSet_ = new JDBCResultSet(this, md, statementName_, cursorName_, fetchSize_);
updateCount_ = -1;
}
}
catch (IOException io)
{
throw JDBCConnection.convertException(io, lastSQLCode_, lastSQLState_);
}
finally
{
// conn.setSQLCommunicationsAreaCallback(null);
}
return resultSetAvailable;
}
/**
* Not implemented.
**/
public boolean execute(String sql, int[] columnIndices) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public boolean execute(String sql, String[] columnNames) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public int[] executeBatch() throws SQLException
{
throw new NotImplementedException();
}
public ResultSet executeQuery(String sql) throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
if (currentResultSet_ != null)
{
currentResultSet_.close();
currentResultSet_ = null;
}
if (catalog_ == null) {
catalog_ = conn_.getCatalog();
}
DatabaseConnection conn = conn_.getDatabaseConnection();
conn.setSQLCommunicationsAreaCallback(this);
// DatabasePrepareAttributes pea = getRequestAttributes(); //conn_.getRequestAttributes();
DatabasePrepareAndDescribeAttributes pea = getRequestAttributes();
pea.setExtendedSQLStatementText(sql);
// pea.setPrepareOption(0x01); // Enhanced.
// Verify that the statement could return a result set
int statementType = getStatementType(sql);
switch (statementType) {
case TYPE_SELECT:
// Only request extended column descriptor for select statements (not call )
pea.setOpenAttributes(0x80);
pea.setExtendedColumnDescriptorOption(0xF1);
case TYPE_CALL:
break;
default:
// Not a query -- throw an exception
throw new SQLException("Not a query");
}
pea.setSQLStatementType(statementType); // SELECT. This has to be set in order to get extended column metadata back.
try
{
conn.setCurrentRequestParameterBlockID(rpbID_);
generatedKey_ = null;
// conn.prepare(pea);
JDBCResultSetMetaData md = new JDBCResultSetMetaData(conn.getInfo().getServerCCSID(), conn_.getCalendar(), catalog_);
conn.prepareAndDescribe(pea, md, null); // Just a plain prepare doesn't give us extended column metadata back.
if (statementType == TYPE_SELECT) {
DatabaseOpenAndDescribeAttributes oada = (DatabaseOpenAndDescribeAttributes)pea;
if (fetchSize_ > 0) oada.setBlockingFactor(fetchSize_);
oada.setDescribeOption(0xD5);
oada.setScrollableCursorFlag(0);
oada.setVariableFieldCompression(0xe8);
conn.openAndDescribe(oada, null);
currentResultSet_ = new JDBCResultSet(this, md, statementName_, cursorName_, fetchSize_);
updateCount_ = -1;
return currentResultSet_;
} else {
DatabaseExecuteAttributes dea = getRequestAttributes();
// Flags set by normal toolbox
((DatabaseOpenAndDescribeAttributes)dea).setScrollableCursorFlag(0);
((DatabaseOpenAndDescribeAttributes)dea).setResultSetHoldabilityOption(0xe8); /* Y */
((DatabaseOpenAndDescribeAttributes)dea).setVariableFieldCompression(0xe8);
if (fetchSize_ > 0) ((DatabaseOpenAndDescribeAttributes)dea).setBlockingFactor(fetchSize_);
dea.setSQLStatementType(JDBCStatement.TYPE_CALL);
conn.execute(dea);
// TODO: Determine if result set is available from the call. If so, then call openDescribe using the existing cursor name if it exists
if (resultSetsCount_ > 0) {
DatabaseOpenAndDescribeAttributes oada = getRequestAttributes();
oada.setOpenAttributes(0x80);
oada.setScrollableCursorFlag(0);
oada.setVariableFieldCompression(0xe8);
if (catalog_ == null) {
catalog_ = conn_.getCatalog();
}
md = new JDBCResultSetMetaData(conn.getInfo().getServerCCSID(), conn_.getCalendar(), catalog_);
conn.setCurrentRequestParameterBlockID(rpbID_);
if (currentResultSet_ != null)
{
currentResultSet_.close();
currentResultSet_ = null;
}
conn.openAndDescribe(oada, md);
currentResultSet_ = new JDBCResultSet(this, md, statementName_, cursorName_, fetchSize_);
updateCount_ = -1;
return currentResultSet_;
} else {
// Did not return result set
JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return null;
}
}
}
catch (IOException io)
{
throw JDBCConnection.convertException(io, lastSQLCode_, lastSQLState_);
}
}
public int executeUpdate(String sql) throws SQLException
{
return executeUpdate(sql, Statement.NO_GENERATED_KEYS);
}
public int executeUpdate(String sql, int autoGeneratedKeys)
throws SQLException {
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
if (currentResultSet_ != null) {
currentResultSet_.close();
currentResultSet_ = null;
}
// Check statement
getStatementType(sql);
DatabaseConnection conn = conn_.getDatabaseConnection();
conn.setSQLCommunicationsAreaCallback(this);
DatabasePrepareAndExecuteAttributes pea = getRequestAttributes();
pea.setExtendedSQLStatementText(sql);
pea.setOpenAttributes(0x80);
pea.setDescribeOption(0xD5);
pea.setScrollableCursorFlag(0);
/*
* switch (autoGeneratedKeys) { case Statement.NO_GENERATED_KEYS:
* conn.setSQLCommunicationsAreaCallback(null); break; case
* Statement.RETURN_GENERATED_KEYS:
* conn.setSQLCommunicationsAreaCallback(this); break; default: throw
* new SQLException("Bad value for autoGeneratedKeys parameter"); }
*/
try {
conn.setCurrentRequestParameterBlockID(rpbID_);
generatedKey_ = null;
updateCount_ = 0;
conn.setSQLCommunicationsAreaCallback(this);
try {
conn.prepareAndExecute(pea, null);
updateCount_ = lastUpdateCount_;
} finally {
// conn.setSQLCommunicationsAreaCallback(null);
}
} catch (IOException io) {
throw JDBCConnection.convertException(io, lastSQLCode_,
lastSQLState_);
} finally {
// conn.setSQLCommunicationsAreaCallback(null);
}
return updateCount_;
}
/**
* Not implemented.
**/
public int executeUpdate(String sql, int[] columnIndices) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
throw new NotImplementedException();
}
public Connection getConnection() throws SQLException
{
// Return connection -- even if closed
// if (closed_) throw new SQLException("Statement closed");
//
return conn_;
}
public int getFetchDirection() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return ResultSet.FETCH_FORWARD;
}
public int getFetchSize() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return fetchSize_;
}
public ResultSet getGeneratedKeys() throws SQLException
{
if (generatedKey_ != null)
{
// The SQLCA contains a 30-digit packed decimal, but I'm always going to treat
// this as a long, until I see a case where a generated key is bigger than a long.
if (catalog_ == null) {
catalog_ = conn_.getCatalog();
}
JDBCResultSetMetaData md = new JDBCResultSetMetaData(37, conn_.getCalendar(), catalog_);
md.resultSetDescription(1, 0, 0, 0, 0, 8);
md.fieldDescription(0, 492, 8, 0, 0, 0, 0, 0, 0); // BIGINT
md.fieldName(0, "GENERATED_KEY");
JDBCResultSet rs = new JDBCResultSet(this, md, null, null, 0);
rs.newResultData(1, 1, 8);
rs.newRowData(0, Conv.longToByteArray(new Long(generatedKey_).longValue()));
return rs;
}
return null;
}
/**
* Retrieves the maximum number of bytes that can be returned for character and binary column values in a ResultSet object produced by this Statement object.
*
**/
public int getMaxFieldSize() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return 0;
}
/**
* Retrieves the maximum number of rows that a ResultSet object produced by this Statement object can contain.
* @return 0 -- there is no limit
**/
public int getMaxRows() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return 0;
}
/**
* Not implemented.
**/
public boolean getMoreResults() throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public boolean getMoreResults(int current) throws SQLException
{
throw new NotImplementedException();
}
/**
* Retrieves the number of seconds the driver will wait for a Statement object to execute
* @return 0: This driver does not support query timeout. .
**/
public int getQueryTimeout() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return 0;
}
public ResultSet getResultSet() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return currentResultSet_;
}
/**
* Retrieves the result set concurrency for ResultSet objects generated by this Statement object.
* @return ResultSet.CONCUR_READ_ONLY: This driver only supports READ_ONLY cursors.
**/
public int getResultSetConcurrency() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return ResultSet.CONCUR_READ_ONLY;
}
/**
* Retrieves the result set holdability for ResultSet objects generated by this Statement object.
* returns ResultSet.HOLD_CURSORS_OVER_COMMIT
**/
public int getResultSetHoldability() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
public int getResultSetType() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return ResultSet.TYPE_FORWARD_ONLY;
}
public int getUpdateCount() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return updateCount_;
}
/**
* Not implemented, but we return null to avoid problems with existing applications
**/
public SQLWarning getWarnings() throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return null;
}
/**
* Not implemented.
**/
public void setCursorName(String name) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public void setEscapeProcessing(boolean enable) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public void setFetchDirection(int direction) throws SQLException
{
throw new NotImplementedException();
}
public void setFetchSize(int rows) throws SQLException
{
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
if (rows < 0) throw new SQLException("Bad value for fetch size: "+rows);
fetchSize_ = rows;
}
/**
* Not implemented.
**/
public void setMaxFieldSize(int max) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public void setMaxRows(int max) throws SQLException
{
throw new NotImplementedException();
}
/**
* Not implemented.
**/
public void setQueryTimeout(int seconds) throws SQLException
{
throw new NotImplementedException();
}
public boolean isClosed() {
return closed_;
}
protected void setCursorNameInternal(String cursorName) {
cursorName_ = cursorName;
}
public boolean isPoolable() throws SQLException {
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
return poolable_;
}
public void setPoolable(boolean poolable) throws SQLException {
if (closed_) JDBCError.throwSQLException(JDBCError.EXC_FUNCTION_SEQUENCE);
poolable_ = poolable;
}
public void setCatalog(String catalog) {
catalog_ = catalog;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy