📄 connectionjdbc2.java
字号:
* Called by the protcol to change the current database context.
*
* @param newDb The new database selected on the server.
* @param oldDb The old database as known by the server.
* @throws SQLException
*/
protected void setDatabase(final String newDb, final String oldDb)
throws SQLException {
if (currentDatabase != null && !oldDb.equalsIgnoreCase(currentDatabase)) {
throw new SQLException(Messages.get("error.connection.dbmismatch",
oldDb, databaseName),
"HY096");
}
currentDatabase = newDb;
if (Logger.isActive()) {
Logger.println("Changed database from " + oldDb + " to " + newDb);
}
}
/**
* Update the connection instance with information about the server.
*
* @param databaseProductName The server name eg SQL Server.
* @param databaseMajorVersion The major version eg 11
* @param databaseMinorVersion The minor version eg 92
* @param buildNumber The server build number.
*/
protected void setDBServerInfo(String databaseProductName,
int databaseMajorVersion,
int databaseMinorVersion,
int buildNumber) {
this.databaseProductName = databaseProductName;
this.databaseMajorVersion = databaseMajorVersion;
this.databaseMinorVersion = databaseMinorVersion;
if (tdsVersion >= Driver.TDS70) {
StringBuffer buf = new StringBuffer(10);
if (databaseMajorVersion < 10) {
buf.append('0');
}
buf.append(databaseMajorVersion).append('.');
if (databaseMinorVersion < 10) {
buf.append('0');
}
buf.append(databaseMinorVersion).append('.');
buf.append(buildNumber);
while (buf.length() < 10) {
buf.insert(6, '0');
}
this.databaseProductVersion = buf.toString();
} else {
databaseProductVersion =
databaseMajorVersion + "." + databaseMinorVersion;
}
}
/**
* Removes a statement object from the list maintained by the connection
* and cleans up the statement cache if necessary.
* <p>
* Synchronized because it accesses the statement list, the statement cache
* and the <code>baseTds</code>.
*
* @param statement the statement to remove
*/
synchronized void removeStatement(JtdsStatement statement)
throws SQLException {
// Remove the JtdsStatement from the statement list
synchronized (statements) {
for (int i = 0; i < statements.size(); i++) {
WeakReference wr = (WeakReference) statements.get(i);
if (wr != null) {
Statement stmt = (Statement) wr.get();
// Remove the statement if found but also remove all
// statements that have already been garbage collected
if (stmt == null || stmt == statement) {
statements.set(i, null);
}
}
}
}
if (statement instanceof JtdsPreparedStatement) {
// Clean up the prepared statement cache; getObsoleteHandles will
// decrement the usage count for the set of used handles
Collection handles = statementCache.getObsoleteHandles(
((JtdsPreparedStatement) statement).handles);
if (handles != null) {
if (serverType == Driver.SQLSERVER) {
// SQL Server unprepare
StringBuffer cleanupSql = new StringBuffer(handles.size() * 32);
for (Iterator iterator = handles.iterator(); iterator.hasNext(); ) {
ProcEntry pe = (ProcEntry) iterator.next();
// Could get put back if in a transaction that is
// rolled back
pe.appendDropSQL(cleanupSql);
}
if (cleanupSql.length() > 0) {
baseTds.executeSQL(cleanupSql.toString(), null, null, true, 0,
-1, -1, true);
baseTds.clearResponseQueue();
}
} else {
// Sybase unprepare
for (Iterator iterator = handles.iterator(); iterator.hasNext(); ) {
ProcEntry pe = (ProcEntry)iterator.next();
if (pe.toString() != null) {
// Remove the Sybase light weight proc
baseTds.sybaseUnPrepare(pe.toString());
}
}
}
}
}
}
/**
* Adds a statement object to the list maintained by the connection.
* <p/>
* WeakReferences are used so that statements can still be closed and
* garbage collected even if not explicitly closed by the connection.
*
* @param statement statement to add
*/
void addStatement(JtdsStatement statement) {
synchronized (statements) {
for (int i = 0; i < statements.size(); i++) {
WeakReference wr = (WeakReference) statements.get(i);
if (wr == null) {
statements.set(i, new WeakReference(statement));
return;
}
}
statements.add(new WeakReference(statement));
}
}
/**
* Checks that the connection is still open.
*
* @throws SQLException if the connection is closed
*/
void checkOpen() throws SQLException {
if (closed) {
throw new SQLException(
Messages.get("error.generic.closed", "Connection"), "HY010");
}
}
/**
* Checks that this connection is in local transaction mode.
*
* @param method the method name being tested
* @throws SQLException if in XA distributed transaction mode
*/
void checkLocal(String method) throws SQLException {
if (xaTransaction) {
throw new SQLException(
Messages.get("error.connection.badxaop", method), "HY010");
}
}
/**
* Reports that user tried to call a method which has not been implemented.
*
* @param method the method name to report in the error message
* @throws SQLException always, with the not implemented message
*/
static void notImplemented(String method) throws SQLException {
throw new SQLException(
Messages.get("error.generic.notimp", method), "HYC00");
}
/**
* Retrieves the DBMS major version.
*
* @return the version as an <code>int</code>
*/
public int getDatabaseMajorVersion() {
return this.databaseMajorVersion;
}
/**
* Retrieves the DBMS minor version.
*
* @return the version as an <code>int</code>
*/
public int getDatabaseMinorVersion() {
return this.databaseMinorVersion;
}
/**
* Retrieves the DBMS product name.
*
* @return the name as a <code>String</code>
*/
String getDatabaseProductName() {
return this.databaseProductName;
}
/**
* Retrieves the DBMS product version.
*
* @return the version as a <code>String</code>
*/
String getDatabaseProductVersion() {
return this.databaseProductVersion;
}
/**
* Retrieves the original connection URL.
*
* @return the connection url as a <code>String</code>
*/
String getURL() {
return this.url;
}
/**
* Retrieves the host and port for this connection.
* <p>
* Used to identify same resource manager in XA transactions.
*
* @return the hostname and port as a <code>String</code>
*/
public String getRmHost() {
return serverName + ':' + portNumber;
}
/**
* Forces the closed status on the statement if an I/O error has occurred.
*/
void setClosed() {
closed = true;
// Make sure we release the socket and all data buffered at the socket
// level
try {
socket.close();
} catch (IOException e) {
// Ignore; shouldn't happen anyway
}
}
/**
* Invokes the <code>xp_jtdsxa</code> extended stored procedure on the
* server.
* <p/>
* Synchronized because it accesses the <code>baseTds</code>.
*
* @param args the arguments eg cmd, rmid, flags etc.
* @param data option byte data eg open string xid etc.
* @return optional byte data eg OLE cookie
* @throws SQLException if an error condition occurs
*/
synchronized byte[][] sendXaPacket(int args[], byte[] data)
throws SQLException {
ParamInfo params[] = new ParamInfo[6];
params[0] = new ParamInfo(Types.INTEGER, null, ParamInfo.RETVAL);
params[1] = new ParamInfo(Types.INTEGER, new Integer(args[1]), ParamInfo.INPUT);
params[2] = new ParamInfo(Types.INTEGER, new Integer(args[2]), ParamInfo.INPUT);
params[3] = new ParamInfo(Types.INTEGER, new Integer(args[3]), ParamInfo.INPUT);
params[4] = new ParamInfo(Types.INTEGER, new Integer(args[4]), ParamInfo.INPUT);
params[5] = new ParamInfo(Types.VARBINARY, data, ParamInfo.OUTPUT);
//
// Execute our extended stored procedure (let's hope it is installed!).
//
baseTds.executeSQL(null, "master..xp_jtdsxa", params, false, 0, -1, -1,
true);
//
// Now process results
//
ArrayList xids = new ArrayList();
while (!baseTds.isEndOfResponse()) {
if (baseTds.getMoreResults()) {
// This had better be the results from a xa_recover command
while (baseTds.getNextRow()) {
Object row[] = baseTds.getRowData();
if (row.length == 1 && row[0] instanceof byte[]) {
xids.add(row[0]);
}
}
}
}
messages.checkErrors();
if (params[0].getOutValue() instanceof Integer) {
// Should be return code from XA command
args[0] = ((Integer)params[0].getOutValue()).intValue();
} else {
args[0] = -7; // XAException.XAER_RMFAIL
}
if (xids.size() > 0) {
// List of XIDs from xa_recover
byte list[][] = new byte[xids.size()][];
for (int i = 0; i < xids.size(); i++) {
list[i] = (byte[])xids.get(i);
}
return list;
} else
if (params[5].getOutValue() instanceof byte[]) {
// xa_open the xa connection ID
// xa_start OLE Transaction cookie
byte cookie[][] = new byte[1][];
cookie[0] = (byte[])params[5].getOutValue();
return cookie;
} else {
// All other cases
return null;
}
}
/**
* Enlists the current connection in a distributed transaction.
*
* @param oleTranID the OLE transaction cookie or null to delist
* @throws SQLException if an error condition occurs
*/
synchronized void enlistConnection(byte[] oleTranID)
throws SQLException {
if (oleTranID != null) {
// TODO: Stored procs are no good but maybe prepare will be OK.
this.prepareSql = TdsCore.EXECUTE_SQL;
baseTds.enlistConnection(1, oleTranID);
xaTransaction = true;
} else {
baseTds.enlistConnection(1, null);
xaTransaction = false;
}
}
/**
* Sets the XA transaction ID when running in emulation mode.
*
* @param xid the XA Transaction ID
*/
void setXid(Object xid) {
this.xid = xid;
xaTransaction = xid != null;
}
/**
* Gets the XA transaction ID when running in emulation mode.
*
* @return the transaction ID as an <code>Object</code>
*/
Object getXid() {
return xid;
}
/**
* Sets the XA state variable.
*
* @param value the XA state value
*/
void setXaState(int value) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -