You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dy...@apache.org on 2008/02/27 14:53:11 UTC
svn commit: r631593 - in /db/derby/code/trunk/java:
client/org/apache/derby/client/am/ client/org/apache/derby/client/net/
drda/org/apache/derby/impl/drda/ engine/org/apache/derby/iapi/jdbc/
engine/org/apache/derby/impl/jdbc/ testing/org/apache/derbyTe...
Author: dyre
Date: Wed Feb 27 05:52:59 2008
New Revision: 631593
URL: http://svn.apache.org/viewvc?rev=631593&view=rev
Log:
DERBY-3192: Cache session data in the client driver
Piggy-backs the current isolation level and the current schema onto
messages going back to the client. The client caches this information so that
it can be returned to a user (app) without an extra round-trip.
See also http://wiki.apache.org/db-derby/Derby3192Writeup
Patch file: derby-3192-mark2.v8.diff
Added:
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/PiggyBackedSessionData.java (with props)
Modified:
db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
db/derby/code/trunk/java/client/org/apache/derby/client/am/ConnectionCallbackInterface.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePointNameTable.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionReply.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetReply.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementReply.java
db/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnectionReply.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePointNameTable.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/Database.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CacheSessionDataTest.java
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java Wed Feb 27 05:52:59 2008
@@ -27,6 +27,7 @@
import org.apache.derby.shared.common.reference.SQLState;
import java.sql.SQLException;
+import org.apache.derby.shared.common.sanity.SanityManager;
public abstract class Connection implements java.sql.Connection,
ConnectionCallbackInterface {
@@ -93,7 +94,24 @@
protected boolean open_ = true;
private boolean availableForReuse_ = false;
- public int isolation_ = Configuration.defaultIsolation;
+ /**
+ * Constant indicating that isolation_ has not been updated through
+ * piggy-backing, (or that the previously stored value was invalidated,
+ * e.g. by an XA state change).
+ */
+ private static final int TRANSACTION_UNKNOWN = -1;
+ /**
+ * Cached copy of the isolation level. Kept in sync with server through
+ * piggy-backing.
+ */
+ private int isolation_ = TRANSACTION_UNKNOWN;
+
+ /**
+ * Cached copy of the schema name. Updated through piggy-backing and used
+ * to implement statement caching.
+ */
+ private String currentSchemaName_ = null;
+
public boolean autoCommit_ = true;
protected boolean inUnitOfWork_ = false; // This means a transaction is in progress.
@@ -274,7 +292,8 @@
// property: open_
// this should already be true
- isolation_ = Configuration.defaultIsolation;
+ isolation_ = TRANSACTION_UNKNOWN;
+ currentSchemaName_ = null;
autoCommit_ = true;
inUnitOfWork_ = false;
@@ -311,7 +330,8 @@
// property: open_
// this should already be true
- isolation_ = Configuration.defaultIsolation;
+ isolation_ = TRANSACTION_UNKNOWN;
+ currentSchemaName_ = null;
autoCommit_ = true;
inUnitOfWork_ = false;
@@ -975,7 +995,9 @@
// transaction so we have to clean up locally.
completeLocalCommit();
- isolation_ = level;
+ if (SanityManager.DEBUG && supportsSessionDataCaching()) {
+ SanityManager.ASSERT(isolation_ == level);
+ }
}
catch ( SqlException se )
{
@@ -983,6 +1005,13 @@
}
}
+ /**
+ * Finds out if the underlaying database connection supports session data
+ * caching.
+ * @return true if sessionData is supported
+ */
+ protected abstract boolean supportsSessionDataCaching();
+
public int getTransactionIsolation() throws SQLException {
// Store the current auto-commit value and use it to restore
@@ -997,6 +1026,15 @@
agent_.logWriter_.traceExit(this, "getTransactionIsolation", isolation_);
}
+ if (isolation_ != TRANSACTION_UNKNOWN) {
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(supportsSessionDataCaching(),
+ "Cannot return cached isolation when caching is " +
+ "not supported!");
+ }
+ return isolation_;
+ }
+
// Set auto-commit to false when executing the statement as we do not want to
// cause an auto-commit from getTransactionIsolation() method.
autoCommit_ = false;
@@ -1007,6 +1045,14 @@
// also happen when isolation is set using SQL instead of JDBC. So we try to get the
// value from the server by calling the "current isolation" function. If we fail to
// get the value, return the value stored in the client's connection object.
+ // DERBY-3192 - Cache session data in the client driver allows
+ // the re-introduction of isolation level caching. Changes to the
+ // isolation level triggered from SQL are now handled by
+ // piggybacking the modified isolation level on messages going
+ // back to the client.
+ // The XA-problem is handled by letting XA state changes set the
+ // cached isolation level to TRANSACTION_UNKNOWN which will trigger
+ // a refresh from the server.
if (getTransactionIsolationStmt == null ||
!(getTransactionIsolationStmt.openOnClient_ &&
getTransactionIsolationStmt.openOnServer_)) {
@@ -1020,13 +1066,35 @@
rs = getTransactionIsolationStmt.executeQuery("values current isolation");
rs.next();
String isolationStr = rs.getString(1);
- isolation_ = translateIsolation(isolationStr);
+
+ int isolation = translateIsolation(isolationStr);
+ if (isolation_ == TRANSACTION_UNKNOWN &&
+ supportsSessionDataCaching()) {
+ // isolation_ will be TRANSACTION_UNKNOWN if the connection has
+ // been reset on
+ // the client. The server will not observe a
+ // change in isolation level so no information is
+ // piggy-backed. Update the cached value here, rather than
+ // waiting for the isolation to change on the server.
+ isolation_ = isolation;
+ }
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(!supportsSessionDataCaching() ||
+ (isolation_ == isolation),
+ "Cached isolation_ not updated, (isolation_="+
+ isolation_+")!=(isolation="+isolation+")");
+ SanityManager.ASSERT(supportsSessionDataCaching() ||
+ (isolation_ == TRANSACTION_UNKNOWN),
+ "isolation_ modified when caching is not supported");
+ }
rs.close();
// So... of we did not have an active transaction before
// the query, we pretend to still not have an open
// transaction. The result set is closed, so this should
// not be problematic. DERBY-2084
inUnitOfWork_ = savedInUnitOfWork;
+
+ return isolation;
}
catch ( SqlException se )
{
@@ -1038,11 +1106,44 @@
if(rs != null)
rs.close();
}
-
- return isolation_;
}
/**
+ * Returns the current schema (the schema that would be used for
+ * compilation. This is not part of the java.sql.Connection interface, and
+ * is only intended for use with statement caching.
+ * @return the name of the current schema
+ * @throws java.sql.SQLException
+ */
+ public String getCurrentSchemaName() throws SQLException {
+ try {
+ checkForClosedConnection();
+ } catch (SqlException se) {
+ throw se.getSQLException();
+ }
+ if (currentSchemaName_ == null) {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this,
+ "getCurrentSchemaName() executes query");
+ }
+ java.sql.Statement s = createStatement();
+ java.sql.ResultSet rs = s.executeQuery("VALUES CURRENT SCHEMA");
+ rs.next();
+ String schema = rs.getString(1);
+ rs.close();
+ s.close();
+ return schema;
+ }
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(supportsSessionDataCaching(),
+ "A cached schema name ("+currentSchemaName_+
+ ") is not expected when session data caching is not" +
+ "supported");
+ }
+ return currentSchemaName_;
+ }
+
+ /**
* Translates the isolation level from a SQL string to the JDBC int value
*
* @param isolationStr SQL isolation string
@@ -1969,6 +2070,20 @@
} else if (sqlca.getSqlCode() < 0) {
agent_.accumulateReadException(new SqlException(agent_.logWriter_, sqlca));
}
+ }
+
+ public void completePiggyBackIsolation(int pbIsolation) {
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(supportsSessionDataCaching());
+ }
+ isolation_ = pbIsolation;
+ }
+
+ public void completePiggyBackSchema(String pbSchema) {
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(supportsSessionDataCaching());
+ }
+ currentSchemaName_ = pbSchema;
}
public abstract void addSpecialRegisters(String s);
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ConnectionCallbackInterface.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ConnectionCallbackInterface.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ConnectionCallbackInterface.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ConnectionCallbackInterface.java Wed Feb 27 05:52:59 2008
@@ -44,4 +44,18 @@
*
*/
public void completeAbnormalUnitOfWork(UnitOfWorkListener uwl);
+
+ /**
+ * Completes piggy-backing of the new current isolation level by
+ * updating the cached copy in am.Connection.
+ * @param pbIsolation new isolation level from the server
+ */
+ public void completePiggyBackIsolation(int pbIsolation);
+
+ /**
+ * Completes piggy-backing of the new current schema by updating
+ * the cached copy in am.Connection.
+ * @param pbSchema new current schema from the server
+ */
+ public void completePiggyBackSchema(String pbSchema);
}
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java Wed Feb 27 05:52:59 2008
@@ -599,6 +599,16 @@
// FDOCA data
static final int FDODTA = 0x147A;
+ // --- Product-specific 0xC000-0xFFFF ---
+ // Piggy-backed session data (product-specific)
+ static final int PBSD = 0xC000;
+
+ // Isolation level as a byte (product-specific)
+ static final int PBSD_ISO = 0xC001;
+
+ // Current schema as UTF8 String (product-specific)
+ static final int PBSD_SCHEMA = 0xC002;
+
//--------------------------ddm error code points---------------------------------
// Syntax Error Code. DSS header length less than 6.
static int SYNERRCD_DSS_LESS_THAN_6 = 0x01;
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePointNameTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePointNameTable.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePointNameTable.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePointNameTable.java Wed Feb 27 05:52:59 2008
@@ -85,6 +85,9 @@
put(new Integer(CodePoint.PRCCNVRM), "PRCCNVRM");
put(new Integer(CodePoint.EXCSQLSET), "EXCSQLSET");
put(new Integer(CodePoint.EXTDTA), "EXTDTA");
+ put(new Integer(CodePoint.PBSD), "PBSD");
+ put(new Integer(CodePoint.PBSD_ISO), "PBSD_ISO");
+ put(new Integer(CodePoint.PBSD_SCHEMA), "PBSD_SCHEMA");
}
String lookup(int codePoint) {
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java Wed Feb 27 05:52:59 2008
@@ -1740,6 +1740,18 @@
/**
+ * Check whether the server supports session data caching
+ * @return true session data caching is supported
+ */
+ protected final boolean supportsSessionDataCaching() {
+
+ NetDatabaseMetaData metadata =
+ (NetDatabaseMetaData) databaseMetaData_;
+
+ return metadata.serverSupportsSessionDataCaching();
+ }
+
+ /**
* Returns if a transaction is in process
* @return open
*/
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionReply.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionReply.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionReply.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionReply.java Wed Feb 27 05:52:59 2008
@@ -2130,7 +2130,11 @@
// This method handles the parsing of all command replies and reply data
// for the SYNCCTL command.
- protected int parseSYNCCTLreply(ConnectionCallbackInterface connection) throws DisconnectException {
+ protected int parseSYNCCTLreply(ConnectionCallbackInterface connection)
+ throws DisconnectException {
+ if (peekCodePoint() == CodePoint.PBSD) {
+ parsePBSD();
+ }
return 0;
}
@@ -3301,6 +3305,35 @@
int count = ((rowsetSqlca == null) ? 0 : rowsetSqlca.length);
for (int i = row; i < count; i++) {
rowsetSqlca[i] = null;
+ }
+ }
+
+ /**
+ * Parse a PBSD - PiggyBackedSessionData code point. Can contain one or
+ * both of, a PBSD_ISO code point followed by a byte representing the jdbc
+ * isolation level, and a PBSD_SCHEMA code point followed by the name of the
+ * current schema as an UTF-8 String.
+ * @throws org.apache.derby.client.am.DisconnectException
+ */
+ protected void parsePBSD() throws DisconnectException {
+ parseLengthAndMatchCodePoint(CodePoint.PBSD);
+ int peekCP = peekCodePoint();
+ while (peekCP != END_OF_SAME_ID_CHAIN) {
+ parseLengthAndMatchCodePoint(peekCP);
+ switch (peekCP) {
+ case CodePoint.PBSD_ISO:
+ netAgent_.netConnection_.
+ completePiggyBackIsolation(readUnsignedByte());
+ break;
+ case CodePoint.PBSD_SCHEMA:
+ netAgent_.netConnection_.
+ completePiggyBackSchema
+ (readString(getDdmLength(), "UTF-8"));
+ break;
+ default:
+ parseCommonError(peekCP);
+ }
+ peekCP = peekCodePoint();
}
}
}
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java Wed Feb 27 05:52:59 2008
@@ -31,6 +31,11 @@
private boolean supportsLayerBStreaming_;
+ /**
+ * True if the server supports session data caching
+ */
+ private boolean supportsSessionDataCaching_;
+
public NetDatabaseMetaData(NetAgent netAgent, NetConnection netConnection) {
// Consider setting product level during parse
super(netAgent, netConnection, new ProductLevel(netConnection.productID_,
@@ -86,6 +91,9 @@
supportsLayerBStreaming_ =
productLevel_.greaterThanOrEqualTo(10, 3, 0);
+
+ supportsSessionDataCaching_ =
+ productLevel_.greaterThanOrEqualTo(10, 4, 0);
}
/**
@@ -102,4 +110,11 @@
return supportsLayerBStreaming_;
}
+ /**
+ * Check if server supports session data caching
+ * @return true if the server supports this
+ */
+ final boolean serverSupportsSessionDataCaching() {
+ return supportsSessionDataCaching_;
+ }
}
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetReply.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetReply.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetReply.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetReply.java Wed Feb 27 05:52:59 2008
@@ -126,6 +126,9 @@
parseRDBUPDRM();
peekCP = peekCodePoint();
}
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
+ }
return;
}
do {
@@ -175,10 +178,15 @@
if (peekCP == CodePoint.RDBUPDRM) {
found = true;
parseRDBUPDRM();
+ peekCP = peekCodePoint();
}
if (!found) {
parseFetchError(resultSetI);
+ }
+
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
}
if (longBufferForDecryption_ != null) {
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementReply.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementReply.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementReply.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementReply.java Wed Feb 27 05:52:59 2008
@@ -211,12 +211,21 @@
break;
}
+ peekCP = peekCodePoint();
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
+ }
}
- // Parse the reply for the Open Query Command.
- // This method handles the parsing of all command replies and reply data for the opnqry command.
- // will be replaced by parseOPNQRYreply (see parseOPNQRYreplyProto)
- private void parseOPNQRYreply(StatementCallbackInterface statementI) throws DisconnectException {
+ /**
+ * Parse the reply for the Open Query Command. This method handles the
+ * parsing of all command replies and reply data for the opnqry command.
+ * will be replaced by parseOPNQRYreply (see parseOPNQRYreplyProto)
+ * @param statementI statement to invoke callbacks on
+ * @throws org.apache.derby.client.am.DisconnectException
+ */
+ private void parseOPNQRYreply(StatementCallbackInterface statementI)
+ throws DisconnectException {
int peekCP = peekCodePoint();
if (peekCP == CodePoint.OPNQRYRM) {
@@ -238,6 +247,9 @@
peekCP = peekCodePoint();
}
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
+ }
}
// Called by NETSetClientPiggybackCommand.read()
@@ -288,6 +300,11 @@
peekCP = peekCodePoint();
if (peekCP == CodePoint.RDBUPDRM) {
parseRDBUPDRM();
+ peekCP = peekCodePoint();
+ }
+
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
}
return;
}
@@ -302,6 +319,7 @@
NetSqlca netSqlca = parseSQLCARD(null);
statementI.completeExecute(netSqlca);
+ peekCP = peekCodePoint();
} else if (peekCP == CodePoint.SQLDTARD) {
// in the case of singleton select or if a stored procedure was called which had
// parameters but no result sets, an SQLSTARD may be returned
@@ -332,6 +350,10 @@
parseExecuteError(statementI);
}
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
+ peekCP = peekCodePoint();
+ }
}
protected void parseResultSetProcedure(StatementCallbackInterface statementI) throws DisconnectException {
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnectionReply.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnectionReply.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnectionReply.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnectionReply.java Wed Feb 27 05:52:59 2008
@@ -219,6 +219,9 @@
netAgent_.netConnection_.xares_.addSpecialRegisters(s);
peekCP = peekCodePoint();
}
+ if (peekCP == CodePoint.PBSD) {
+ parsePBSD();
+ }
return retval;
}
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java Wed Feb 27 05:52:59 2008
@@ -295,4 +295,7 @@
}
+ protected boolean supportsSessionDataCaching() {
+ return (clientType == DNC_CLIENT && greaterThanOrEqualTo(10, 4, 0));
+ }
}
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java Wed Feb 27 05:52:59 2008
@@ -680,6 +680,16 @@
// FDOCA Triplet offset
static final int FDOTRPOFF = 0x212A;
+ // --- Product-specific 0xC000-0xFFFF ---
+ // Piggy-backed session data (product-specific)
+ static final int PBSD = 0xC000;
+
+ // Isolation level as a byte (product-specific)
+ static final int PBSD_ISO = 0xC001;
+
+ // Current schema as UTF8 String (product-specific)
+ static final int PBSD_SCHEMA = 0xC002;
+
//--------------------------ddm error code points---------------------------------
static final int SYNERRCD_DSS_LESS_THAN_6 = 0x01;
static final int SYNERRCD_DSS_LENGTH_BYTE_NUMBER_MISMATCH = 0x02;
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePointNameTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePointNameTable.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePointNameTable.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePointNameTable.java Wed Feb 27 05:52:59 2008
@@ -157,6 +157,9 @@
put (new Integer (CodePoint.UOWDSP), "UOWDSP");
put (new Integer (CodePoint.USRID), "USRID");
put (new Integer (CodePoint.VALNSPRM), "VALNSPRM");
+ put (new Integer (CodePoint.PBSD), "PBSD");
+ put (new Integer (CodePoint.PBSD_ISO), "PBSD_ISO");
+ put (new Integer (CodePoint.PBSD_SCHEMA), "PBSD_SCHEMA");
}
String lookup (int codePoint)
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Wed Feb 27 05:52:59 2008
@@ -17,11 +17,7 @@
limitations under the License.
*/
-/**
- * This class translates DRDA protocol from an application requester to JDBC
- * for Derby and then translates the results from Derby to DRDA
- * for return to the application requester.
- */
+
package org.apache.derby.impl.drda;
import java.io.ByteArrayInputStream;
@@ -34,7 +30,6 @@
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
-import java.sql.Driver;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -70,6 +65,11 @@
import org.apache.derby.jdbc.InternalDriver;
import org.apache.derby.iapi.jdbc.EnginePreparedStatement;
+/**
+ * This class translates DRDA protocol from an application requester to JDBC
+ * for Derby and then translates the results from Derby to DRDA
+ * for return to the application requester.
+ */
class DRDAConnThread extends Thread {
private static final String leftBrace = "{";
@@ -724,6 +724,7 @@
}
// Send any warnings if JCC can handle them
checkWarning(null, null, stmt.getResultSet(), 0, false, sendWarningsOnCNTQRY);
+ writePBSD();
}
}
catch(SQLException e)
@@ -754,6 +755,7 @@
// we need to set update count in SQLCARD
checkWarning(null, database.getDefaultStatement().getStatement(),
null, updateCount, true, true);
+ writePBSD();
} catch (SQLException e)
{
writer.clearDSSesBackToMark(writerMark);
@@ -851,6 +853,7 @@
}
}
}
+ writePBSD();
}
catch (SQLException e)
{
@@ -991,6 +994,7 @@
DRDAStatement curStmt = database.getCurrentStatement();
if (curStmt != null)
curStmt.rsSuspend();
+ writePBSD();
} catch (SQLException e)
{
skipRemainder(true);
@@ -1007,11 +1011,46 @@
if (xaProto == null)
xaProto = new DRDAXAProtocol(this);
xaProto.parseSYNCCTL();
+ try {
+ writePBSD();
+ } catch (SQLException se) {
+ server.consoleExceptionPrint(se);
+ errorInChain(se);
+ }
break;
default:
codePointNotSupported(codePoint);
}
+ if (SanityManager.DEBUG) {
+ String cpStr = new CodePointNameTable().lookup(codePoint);
+ try {
+ PiggyBackedSessionData pbsd =
+ database.getPiggyBackedSessionData(false);
+ if (pbsd != null) {
+ // Session data has already been piggy-backed. Refresh
+ // the data from the connection, to make sure it has
+ // not changed behind our back.
+ pbsd.refresh();
+ if (codePoint != CodePoint.SYNCCTL) {
+ // We expect the session attributes to have changed
+ // after SYNCCTL, but this is handled by the client
+ // and is not a problem
+ SanityManager.ASSERT(!pbsd.isModified(),
+ "Unexpected PBSD modification: " + pbsd +
+ " after codePoint " + cpStr);
+ }
+ }
+ // Not having a pbsd here is ok. No data has been
+ // piggy-backed and the client has no cached values.
+ // If needed it will send an explicit request to get
+ // session data
+ } catch (SQLException sqle) {
+ SanityManager.THROWASSERT("Unexpected exception after " +
+ "codePoint "+cpStr, sqle);
+ }
+ }
+
// Set the correct chaining bits for whatever
// reply DSS(es) we just wrote. If we've reached
// the end of the chain, this method will send
@@ -2613,6 +2652,54 @@
stmt.setOutovr_drdaType(outovr_drdaType);
}
}
+
+ /**
+ * Piggy-back any modified session attributes on the current message. Writes
+ * a PBSD conataining one or both of PBSD_ISO and PBSD_SCHEMA. PBSD_ISO is
+ * followed by the jdbc isolation level as an unsigned byte. PBSD_SCHEMA is
+ * followed by the name of the current schema as an UTF-8 String.
+ * @throws java.sql.SQLException
+ * @throws org.apache.derby.impl.drda.DRDAProtocolException
+ */
+ private void writePBSD() throws SQLException, DRDAProtocolException
+ {
+ if (!appRequester.supportsSessionDataCaching()) {
+ return;
+ }
+ PiggyBackedSessionData pbsd = database.getPiggyBackedSessionData(true);
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(pbsd != null, "pbsd is not expected to be null");
+ }
+
+ pbsd.refresh();
+ if (pbsd.isModified()) {
+ writer.createDssReply();
+ writer.startDdm(CodePoint.PBSD);
+
+ if (pbsd.isIsoModified()) {
+ writer.writeScalar1Byte(CodePoint.PBSD_ISO, pbsd.getIso());
+ }
+
+ if (pbsd.isSchemaModified()) {
+ writer.startDdm(CodePoint.PBSD_SCHEMA);
+ writer.writeString(pbsd.getSchema());
+ writer.endDdm();
+ }
+ writer.endDdmAndDss();
+ }
+ pbsd.setUnmodified();
+ if (SanityManager.DEBUG) {
+ PiggyBackedSessionData pbsdNew =
+ database.getPiggyBackedSessionData(true);
+ SanityManager.ASSERT(pbsdNew == pbsd,
+ "pbsdNew and pbsd are expected to reference " +
+ "the same object");
+ pbsd.refresh();
+ SanityManager.ASSERT
+ (!pbsd.isModified(),
+ "pbsd=("+pbsd+") is not expected to be modified");
+ }
+ }
/**
* Write OPNQRYRM - Open Query Complete
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/Database.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/Database.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/Database.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/Database.java Wed Feb 27 05:52:59 2008
@@ -122,6 +122,10 @@
final void setConnection(EngineConnection conn)
throws SQLException
{
+ if (this.conn != conn) {
+ // Need to drop the pb session data when switching connections
+ pbsd_ = null;
+ }
this.conn = conn;
if(conn != null)
defaultStatement.setStatement(conn);
@@ -451,5 +455,27 @@
userId = null;
password = null;
securityMechanism = 0;
+ }
+
+ /**
+ * Piggy-backed session data. Null if no piggy-backing
+ * has happened yet. Lazy initialization is acceptable since the client's
+ * cache initially is empty so that any request made prior to the first
+ * round of piggy-backing will trigger an actual request to the server.
+ */
+ private PiggyBackedSessionData pbsd_ = null;
+
+ /**
+ * Get a reference (handle) to the PiggyBackedSessionData object. Null will
+ * be returned either if Database.conn is not a valid connection, or if the
+ * create argument is false and no object has yet been created.
+ * @param createOnDemand if true create the PiggyBackedSessionData on demand
+ * @return a reference to the PBSD object or null
+ * @throws java.sql.SQLException
+ */
+ public PiggyBackedSessionData getPiggyBackedSessionData(
+ boolean createOnDemand) throws SQLException {
+ pbsd_ = PiggyBackedSessionData.getInstance(pbsd_, conn, createOnDemand);
+ return pbsd_;
}
}
Added: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/PiggyBackedSessionData.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/PiggyBackedSessionData.java?rev=631593&view=auto
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/PiggyBackedSessionData.java (added)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/PiggyBackedSessionData.java Wed Feb 27 05:52:59 2008
@@ -0,0 +1,148 @@
+/*
+
+ Derby - Class org.apache.derby.impl.drda.PiggyBackedSessionData
+
+ 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.drda;
+
+import java.sql.SQLException;
+import org.apache.derby.iapi.jdbc.EngineConnection;
+
+
+/**
+ * Tracks the most recently piggy-backed session attributes, and provides
+ * methods to determine if they have been modified and need to be re-sent
+ * to the client.
+ */
+class PiggyBackedSessionData {
+ private int iso_;
+ private boolean isoMod_;
+
+ private String schema_;
+ private boolean schemaMod_;
+
+ private final EngineConnection conn_;
+
+ /**
+ * Get a reference (handle) to the PiggyBackedSessionData object. Null will
+ * be returned either if the conn argument is not valid, or if the
+ * createOnDemand argument is false and the existing argument is null.
+ * @param existing the PBSD object from the previous piggybacking or null if
+ * none has yet taken place
+ * @param conn the current EngineConnection
+ * @param createOnDemand if true; create the instance when needed
+ * @return a reference to the PBSD object or null
+ * @throws java.sql.SQLException
+ */
+ public static PiggyBackedSessionData getInstance(
+ PiggyBackedSessionData existing, EngineConnection conn,
+ boolean createOnDemand) throws SQLException {
+ if (conn == null || conn.isClosed() ||
+ (existing != null && existing.conn_ != conn)) {
+ return null;
+ }
+ if (existing == null && createOnDemand) {
+ return new PiggyBackedSessionData(conn);
+ }
+ return existing;
+ }
+
+ /**
+ * Constructs a new instance with an associated EngineConnection.
+ * A newly constructed instance is invalid. refresh() must be called before
+ * the xModified() methods can be used.
+ * @param conn the connection to obtain data from
+ */
+ private PiggyBackedSessionData(EngineConnection conn) throws SQLException {
+ conn_ = conn;
+ iso_ = -1; // Initialize to an illegal value
+ }
+
+ /**
+ * Refresh with the latest session attribute values from
+ * the connection. Any changes will be reflected in the corresponding
+ * xModified() methods, until setUnmodified() is called.
+ */
+ public void refresh() throws SQLException {
+ setUnmodified();
+ int iso = conn_.getTransactionIsolation();
+ if (iso != iso_) {
+ isoMod_ = true;
+ iso_ = iso;
+ }
+ String schema = conn_.getCurrentSchemaName();
+ if (!schema.equals(schema_)) {
+ schemaMod_ = true;
+ schema_ = schema;
+ }
+ }
+
+ /**
+ * Clear the modified status. Called after session attributes have
+ * been sent to the client so that the xModified methods will
+ * return false.
+ */
+ public void setUnmodified() {
+ isoMod_ = false;
+ schemaMod_ = false;
+ }
+
+ /**
+ * @return true if the isolation level was modified by the last call
+ * to fetchLatest
+ */
+ public boolean isIsoModified() {
+ return isoMod_;
+ }
+
+ /**
+ * @return true if the current schema name was modified by the last
+ * call to fetchLatest
+ */
+ public boolean isSchemaModified() {
+ return schemaMod_;
+ }
+
+ /**
+ * @return true if any piggy-backed session attribute was modified by
+ * the last call to fetchLatest
+ */
+ public boolean isModified() {
+ return (isoMod_ || schemaMod_);
+ }
+
+ /**
+ * @return the saved jdbc isolation level
+ */
+ public int getIso() {
+ return iso_;
+ }
+
+ /**
+ * @return the saved schema name
+ */
+ public String getSchema() {
+ return schema_;
+ }
+
+ public String toString() {
+ return "iso:" + iso_ + (isoMod_ ? "(M)" : "") + " schema:" + schema_ +
+ (schemaMod_ ? "(M)" : "");
+ }
+}
Propchange: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/PiggyBackedSessionData.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java Wed Feb 27 05:52:59 2008
@@ -637,4 +637,22 @@
//underlying EmbedConnection object.
return getRealConnection().getLOBMapping(key);
}
+
+ /**
+ * Obtain the name of the current schema. Not part of the
+ * java.sql.Connection interface, but is accessible through the
+ * EngineConnection interface, so that the NetworkServer can get at the
+ * current schema for piggy-backing
+ * @return the current schema name
+ * @throws java.sql.SQLException
+ */
+ public String getCurrentSchemaName() throws SQLException {
+ try {
+ return getRealConnection().getCurrentSchemaName();
+ }
+ catch (SQLException se) {
+ notifyException(se);
+ throw se;
+ }
+ }
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java Wed Feb 27 05:52:59 2008
@@ -92,4 +92,12 @@
* @return the LOB Object corresponding to this locator.
*/
public Object getLOBMapping(int key) throws SQLException;
+
+ /**
+ * Obtain the name of the current schema, so that the NetworkServer can
+ * use it for piggy-backing
+ * @return the current schema name
+ * @throws java.sql.SQLException
+ */
+ public String getCurrentSchemaName() throws SQLException;
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java Wed Feb 27 05:52:59 2008
@@ -2863,4 +2863,15 @@
public void cancelRunningStatement() {
getLanguageConnection().getStatementContext().cancel();
}
+
+ /**
+ * Obtain the name of the current schema. Not part of the
+ * java.sql.Connection interface, but is accessible through the
+ * EngineConnection interface, so that the NetworkServer can get at the
+ * current schema for piggy-backing
+ * @return the current schema name
+ */
+ public String getCurrentSchemaName() {
+ return getLanguageConnection().getCurrentSchemaName();
+ }
}
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CacheSessionDataTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CacheSessionDataTest.java?rev=631593&r1=631592&r2=631593&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CacheSessionDataTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CacheSessionDataTest.java Wed Feb 27 05:52:59 2008
@@ -31,6 +31,7 @@
import java.sql.Statement;
import java.sql.Types;
import java.sql.ResultSet;
+import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.derbyTesting.junit.BaseJDBCTestCase;
@@ -212,10 +213,38 @@
".getCycleIsolationJDBC'");
s.execute("CREATE FUNCTION GET_CYCLE_ISOLATION_SQL " +
- "() RETURNS VARCHAR(2) READS SQL DATA LANGUAGE JAVA PARAMETER " +
- "STYLE JAVA EXTERNAL NAME '" +
+ "() RETURNS VARCHAR(2) READS SQL DATA LANGUAGE JAVA " +
+ "PARAMETER STYLE JAVA EXTERNAL NAME '" +
CacheSessionDataTest.class.getName() +
".getCycleIsolationSQL'");
+
+ // Schema testing
+ s.execute("CREATE SCHEMA FOO");
+ String unicodeschema = "\u00bbMY\u20ac\u00ab";
+ s.execute("CREATE SCHEMA \"" + unicodeschema + "\"");
+
+ s.execute("CREATE PROCEDURE APP.SET_SCHEMA (SCHEMANAME " +
+ "VARCHAR(128)) MODIFIES SQL DATA LANGUAGE JAVA " +
+ "PARAMETER STYLE JAVA EXTERNAL NAME '" +
+ CacheSessionDataTest.class.getName() + ".setSchema'");
+
+ s.execute("CREATE FUNCTION APP.GET_SCHEMA_TRANSITION " +
+ "(SCHEMANAME VARCHAR(128)) RETURNS VARCHAR(128) READS " +
+ "SQL DATA LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL " +
+ "NAME '" + CacheSessionDataTest.class.getName() +
+ ".getSchemaTransition'");
+
+ s.execute("CREATE TABLE APP.LARGE(X VARCHAR(32000), " +
+ "SCHEMANAME VARCHAR(128), Y VARCHAR(32000))");
+
+ char[] carray = new char[32000];
+ Arrays.fill(carray, 'x');
+ String xs = new String(carray);
+ Arrays.fill(carray, 'y');
+ String ys = new String(carray);
+
+ s.execute("INSERT INTO APP.LARGE (SELECT '" + xs + "', " +
+ "SCHEMANAME, " + " '" + ys + "' FROM SYS.SYSSCHEMAS)");
}
};
} // End baseSuite
@@ -341,6 +370,41 @@
return sqlName;
}
+ /**
+ * Implementation of the SQL procedure SET_SCHEMA.
+ * Sets a different schema on the default Connection.
+ * @param schemaName name of the new schema
+ * @throws java.sql.SQLException
+ */
+ public static void setSchema(String schemaName)
+ throws SQLException {
+ Connection c = DriverManager.getConnection("jdbc:default:connection");
+ Statement s = c.createStatement();
+ s.execute("SET SCHEMA " + schemaName);
+ s.close();
+ }
+
+ /**
+ * Implementation of the SQL function GET_SCHEMA_TRANSITION.
+ * Sets the current schema to the name given as argument and returns the
+ * schema transition.
+ * @param nextSchema schema to transition to
+ * @return a string of the form oldSchema->newSchema
+ * @throws java.sql.SQLException
+ */
+ public static String getSchemaTransition(String nextSchema)
+ throws SQLException {
+ Connection c = DriverManager.getConnection("jdbc:default:connection");
+ Statement s = c.createStatement();
+ ResultSet rs = s.executeQuery("VALUES CURRENT SCHEMA");
+ rs.next();
+ String prevSchema = rs.getString(1);
+ rs.close();
+ s.execute("SET SCHEMA \"" + nextSchema + "\"");
+ s.close();
+ return (prevSchema + "->" + nextSchema);
+ }
+
// Utilities
private static IsoLevel[] isoLevels;
private static int isolationIndex = -1;
@@ -384,6 +448,21 @@
assertEquals(serverJdbc, client);
}
+ private void verifyCachedSchema(Connection c) throws SQLException {
+ if (c instanceof org.apache.derby.client.am.Connection) {
+ String cached =
+ ((org.apache.derby.client.am.Connection) c).
+ getCurrentSchemaName();
+ Statement s = c.createStatement();
+ ResultSet rs = s.executeQuery("VALUES CURRENT SCHEMA");
+ rs.next();
+ String reported = rs.getString(1);
+ assertEquals(reported, cached);
+ } else {
+ println("Cannot verify cached schema for "+c.getClass());
+ }
+ }
+
// Test cases (fixtures)
// Change the isolation level using SQL
public void testChangeIsoLevelStatementSQL() throws SQLException {
@@ -728,7 +807,8 @@
preparedCursorTest("BIG", ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
- public void testLargePreparedScrollInsensitiveReadOnly() throws SQLException {
+ public void testLargePreparedScrollInsensitiveReadOnly()
+ throws SQLException {
preparedCursorTest("BIG", ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
@@ -736,12 +816,90 @@
preparedCursorTest("BIG", ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
}
- public void testLargePreparedScrollSensitiveUpdatable() throws SQLException {
+ public void testLargePreparedScrollSensitiveUpdatable()
+ throws SQLException {
preparedCursorTest("BIG", ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
}
- public void testLargePreparedScrollInsensitiveUpdatable() throws SQLException {
+ public void testLargePreparedScrollInsensitiveUpdatable()
+ throws SQLException {
preparedCursorTest("BIG", ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
+ }
+
+ // Test that the current schema is piggy-backed correctly
+ public void testSetSchema() throws SQLException {
+ Statement s = createStatement();
+ s.execute("SET SCHEMA FOO");
+ verifyCachedSchema(getConnection());
+ s.execute("SET SCHEMA \"\u00bbMY\u20ac\u00ab\"");
+ verifyCachedSchema(getConnection());
+ }
+ public void testPreparedSetSchema() throws SQLException {
+ PreparedStatement ps = prepareStatement("SET SCHEMA ?");
+ ps.setString(1, "FOO");
+ ps.execute();
+ verifyCachedSchema(getConnection());
+ ps.setString(1, "\u00bbMY\u20ac\u00ab");
+ ps.execute();
+ verifyCachedSchema(getConnection());
+ }
+ public void testSetSchemaProcedure() throws SQLException {
+ Statement s = createStatement();
+ s.execute("CALL APP.SET_SCHEMA('FOO')");
+ verifyCachedSchema(getConnection());
+ s.execute("CALL APP.SET_SCHEMA('\"\u00bbMY\u20ac\u00ab\"')");
+ verifyCachedSchema(getConnection());
+ }
+ public void testPreparedSetSchemaProcedure() throws SQLException {
+ CallableStatement cs = prepareCall("CALL APP.SET_SCHEMA(?)");
+ cs.setString(1, "FOO");
+ cs.execute();
+ verifyCachedSchema(getConnection());
+ cs.setString(1, "\"\u00bbMY\u20ac\u00ab\"");
+ cs.execute();
+ verifyCachedSchema(getConnection());
+ }
+
+ public void testSetSchemaFunction() throws SQLException {
+ Statement s = createStatement();
+ ResultSet rs = s.executeQuery("SELECT " +
+ "APP.GET_SCHEMA_TRANSITION(SCHEMANAME) FROM SYS.SYSSCHEMAS");
+ while (rs.next()) {
+ assertTrue(rs.getString(1).length() > 2);
+ verifyCachedSchema(getConnection());
+ }
+ }
+
+ public void testPreparedSetSchemaFunction() throws SQLException {
+ PreparedStatement ps = prepareStatement("SELECT " +
+ "APP.GET_SCHEMA_TRANSITION(SCHEMANAME) FROM SYS.SYSSCHEMAS");
+ ResultSet rs = ps.executeQuery();
+ while (rs.next()) {
+ assertTrue(rs.getString(1).length() > 2);
+ verifyCachedSchema(getConnection());
+ }
+ }
+
+ public void testSetSchemaFunctionLarge() throws SQLException {
+ Statement s = createStatement();
+ ResultSet rs = s.executeQuery("SELECT X, " +
+ "APP.GET_SCHEMA_TRANSITION(SCHEMANAME), " +
+ "Y FROM APP.LARGE");
+ while (rs.next()) {
+ assertTrue(rs.getString(2).length() > 2);
+ verifyCachedSchema(getConnection());
+ }
+ }
+
+ public void testPreparedSetSchemaFunctionLarge() throws SQLException {
+ PreparedStatement ps = prepareStatement("SELECT X, " +
+ "APP.GET_SCHEMA_TRANSITION(SCHEMANAME), " +
+ "Y FROM APP.LARGE");
+ ResultSet rs = ps.executeQuery();
+ while (rs.next()) {
+ assertTrue(rs.getString(2).length() > 2);
+ verifyCachedSchema(getConnection());
+ }
}
}