📄 connectionjdbc2.java
字号:
// jTDS JDBC Driver for Microsoft SQL Server and Sybase
// Copyright (C) 2004 The jTDS Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
package net.sourceforge.jtds.jdbc;
import java.lang.ref.WeakReference;
import java.sql.CallableStatement;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Types;
import java.sql.ResultSet;
import java.net.UnknownHostException;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.HashSet;
import java.util.Random;
import net.sourceforge.jtds.jdbc.cache.*;
import net.sourceforge.jtds.util.*;
/**
* jTDS implementation of the java.sql.Connection interface.
* <p>
* Implementation notes:
* <ol>
* <li>Environment setting code carried over from old jTDS otherwise
* generally a new implementation of Connection.
* <li>Connection properties and SQLException text messages are loaded from
* a properties file.
* <li>Character set choices are also loaded from a resource file and the original
* Encoder class has gone.
* <li>Prepared SQL statements are converted to procedures in the prepareSQL method.
* <li>Use of Stored procedures is optional and controlled via connection property.
* <li>This Connection object maintains a table of weak references to associated
* statements. This allows the connection object to control the statements (for
* example to close them) but without preventing them being garbage collected in
* a pooled environment.
* </ol>
*
* @author Mike Hutchinson
* @author Alin Sinpalean
* @version $Id: ConnectionJDBC2.java,v 1.119 2007/07/08 21:43:02 bheineman Exp $
*/
public class ConnectionJDBC2 implements java.sql.Connection {
/**
* SQL query to determine the server charset on Sybase.
*/
private static final String SYBASE_SERVER_CHARSET_QUERY
= "select name from master.dbo.syscharsets where id ="
+ " (select value from master.dbo.sysconfigures where config=131)";
/**
* SQL query to determine the server charset on MS SQL Server 6.5.
*/
private static final String SQL_SERVER_65_CHARSET_QUERY
= "select name from master.dbo.syscharsets where id ="
+ " (select csid from master.dbo.syscharsets, master.dbo.sysconfigures"
+ " where config=1123 and id = value)";
/** Sybase initial connection string. */
private static final String SYBASE_INITIAL_SQL = "SET TRANSACTION ISOLATION LEVEL 1\r\n" +
"SET CHAINED OFF\r\n" +
"SET QUOTED_IDENTIFIER ON\r\n"+
"SET TEXTSIZE 2147483647";
/**
* SQL Server initial connection string. Also contains a
* <code>SELECT @@MAX_PRECISION</code> query to retrieve
* the maximum precision for DECIMAL/NUMERIC data. */
private static final String SQL_SERVER_INITIAL_SQL = "SELECT @@MAX_PRECISION\r\n" +
"SET TRANSACTION ISOLATION LEVEL READ COMMITTED\r\n" +
"SET IMPLICIT_TRANSACTIONS OFF\r\n" +
"SET QUOTED_IDENTIFIER ON\r\n"+
"SET TEXTSIZE 2147483647";
/**
* SQL Server custom transaction isolation level.
*/
public static final int TRANSACTION_SNAPSHOT = 4096;
/*
* Conection attributes
*/
/** The orginal connection URL. */
private final String url;
/** The server host name. */
private String serverName;
/** The server port number. */
private int portNumber;
/** The make of SQL Server (sybase/microsoft). */
private int serverType;
/** The SQL Server instance. */
private String instanceName;
/** The requested database name. */
private String databaseName;
/** The current database name. */
private String currentDatabase;
/** The Windows Domain name. */
private String domainName;
/** The database user ID. */
private String user;
/** The user password. */
private String password;
/** The server character set. */
private String serverCharset;
/** The application name. */
private String appName;
/** The program name. */
private String progName;
/** Workstation ID. */
private String wsid;
/** The server message language. */
private String language;
/** The client MAC Address. */
private String macAddress;
/** The server protocol version. */
private int tdsVersion;
/** The network TCP/IP socket. */
private final SharedSocket socket;
/** The cored TDS protocol object. */
private final TdsCore baseTds;
/** The initial network packet size. */
private int netPacketSize = TdsCore.MIN_PKT_SIZE;
/** User requested packet size. */
private int packetSize;
/** SQL Server 2000 collation. */
private byte collation[];
/** True if user specifies an explicit charset. */
private boolean charsetSpecified;
/** The database product name eg SQL SERVER. */
private String databaseProductName;
/** The product version eg 11.92. */
private String databaseProductVersion;
/** The major version number eg 11. */
private int databaseMajorVersion;
/** The minor version number eg 92. */
private int databaseMinorVersion;
/** True if this connection is closed. */
private boolean closed;
/** True if this connection is read only. */
private boolean readOnly;
/** List of statements associated with this connection. */
private final ArrayList statements = new ArrayList();
/** Default transaction isolation level. */
private int transactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED;
/** Default auto commit state. */
private boolean autoCommit = true;
/** Diagnostc messages for this connection. */
private final SQLDiagnostic messages;
/** Connection's current rowcount limit. */
private int rowCount;
/** Connection's current maximum field size limit. */
private int textSize;
/** Maximum decimal precision. */
private int maxPrecision = TdsData.DEFAULT_PRECISION_38; // Sybase default
/** Stored procedure unique ID number. */
private int spSequenceNo = 1;
/** Cursor unique ID number. */
private int cursorSequenceNo = 1;
/** Procedures in this transaction. */
private final ArrayList procInTran = new ArrayList();
/** Java charset for encoding. */
private CharsetInfo charsetInfo;
/** Method for preparing SQL used in Prepared Statements. */
private int prepareSql;
/** The amount of LOB data to buffer in memory. */
private long lobBuffer;
/** The maximum number of statements to keep open. */
private int maxStatements;
/** Statement cache.*/
private StatementCache statementCache;
/** Send parameters as unicode. */
private boolean useUnicode = true;
/** Use named pipe IPC instead of TCP/IP sockets. */
private boolean namedPipe;
/** Only return the last update count. */
private boolean lastUpdateCount;
/** TCP_NODELAY */
private boolean tcpNoDelay = true;
/** Login timeout value in seconds or 0. */
private int loginTimeout;
/** Sybase capability mask.*/
private int sybaseInfo;
/** True if running distributed transaction. */
private boolean xaTransaction;
/** Current emulated XA State eg start/end/prepare etc. */
private int xaState;
/** Current XA Transaction ID. */
private Object xid;
/** True if driver should emulate distributed transactions. */
private boolean xaEmulation = true;
/** Mutual exclusion lock to control access to connection. */
private final Semaphore mutex = new Semaphore(1);
/** Socket timeout value in seconds or 0. */
private int socketTimeout;
/** SSL setting. */
private String ssl;
/** The maximum size of a batch. */
private int batchSize;
/** Use metadata cache for prepared statements. */
private boolean useMetadataCache;
/** Use fast forward cursors for forward only result sets. */
private boolean useCursors;
/** The directory to buffer data to */
private File bufferDir;
/** The global buffer memory limit for all connections (in kilobytes). */
private int bufferMaxMemory;
/** The minimum number of packets per statement to buffer to memory. */
private int bufferMinPackets;
/** Map large types (IMAGE and TEXT/NTEXT) to LOBs by default. */
private boolean useLOBs;
/** A cached <code>TdsCore</code> instance to reuse on new statements. */
private TdsCore cachedTds;
/** The local address to bind to when connecting to a database via TCP/IP. */
private String bindAddress;
/** Force use of jCIFS library on Windows when connecting via named pipes. */
private boolean useJCIFS;
/** When doing NTLM authentication, send NTLMv2 response rather than regular response */
private boolean useNTLMv2 = false;
/**
* Default constructor.
* <p/>
* Used for testing.
*/
private ConnectionJDBC2() {
url = null;
socket = null;
baseTds = null;
messages = null;
}
/**
* Create a new database connection.
*
* @param url The connection URL starting jdbc:jtds:.
* @param info The additional connection properties.
* @throws SQLException
*/
ConnectionJDBC2(String url, Properties info)
throws SQLException {
this.url = url;
//
// Extract properties into instance variables
//
unpackProperties(info);
this.messages = new SQLDiagnostic(serverType);
//
// Get the instance port, if it is specified.
// Named pipes use instance names differently.
//
if (instanceName.length() > 0 && !namedPipe) {
final MSSqlServerInfo msInfo = new MSSqlServerInfo(serverName);
portNumber = msInfo.getPortForInstance(instanceName);
if (portNumber == -1) {
throw new SQLException(
Messages.get("error.msinfo.badinst", serverName, instanceName),
"08003");
}
}
SharedSocket.setMemoryBudget(bufferMaxMemory * 1024);
SharedSocket.setMinMemPkts(bufferMinPackets);
SQLWarning warn;
try {
Object timer = null;
if (loginTimeout > 0) {
// Start a login timer
timer = TimerThread.getInstance().setTimer(loginTimeout * 1000,
new TimerThread.TimerListener() {
public void timerExpired() {
if (socket != null) {
socket.forceClose();
}
}
});
}
if (namedPipe) {
// Use named pipe
socket = createNamedPipe(this);
} else {
// Use plain TCP/IP socket
socket = new SharedSocket(this);
}
if (timer != null && TimerThread.getInstance().hasExpired(timer)) {
// If the timer has expired during the connection phase, close
// the socket and throw an exception
socket.forceClose();
throw new IOException("Login timed out");
}
if ( charsetSpecified ) {
loadCharset(serverCharset);
} else {
// Need a default charset to process login packets for TDS 4.2/5.0
// Will discover the actual serverCharset later
loadCharset("iso_1");
serverCharset = ""; // But don't send charset name to server!
}
//
// Create TDS protocol object
//
baseTds = new TdsCore(this, messages);
//
// Negotiate SSL connection if required
//
if (tdsVersion >= Driver.TDS80 && !namedPipe) {
baseTds.negotiateSSL(instanceName, ssl);
}
//
// Now try to login
//
baseTds.login(serverName,
databaseName,
user,
password,
domainName,
serverCharset,
appName,
progName,
wsid,
language,
macAddress,
packetSize);
if (timer != null) {
// Cancel loginTimer
TimerThread.getInstance().cancelTimer(timer);
}
//
// Save any login warnings so that they will not be overwritten by
// the internal configuration SQL statements e.g. setCatalog() etc.
//
warn = messages.warnings;
// Update the tdsVersion with the value in baseTds. baseTds sets
// the TDS version for the socket and there are no other objects
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -