📄 jdbcconnection.java
字号:
/*
* jdbcConnection.java
*
* Copyright (c) 2001, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This package is based on HypersonicSQL, originally developed by Thomas Mueller.
*
*/
package org.hsqldb;
import java.sql.*;
import java.util.*;
import java.io.*;
import java.net.*;
/**
* <P>A connection (session) with a specific
* database. Within the context of a Connection, SQL statements are
* executed and results are returned.
*
* <P>A Connection's database is able to provide information
* describing its tables, its supported SQL grammar, its stored
* procedures, the capabilities of this connection, and so on. This
* information is obtained with the <code>getMetaData</code> method.
*
* <P><B>Note:</B> By default the Connection automatically commits
* changes after executing each statement. If auto commit has been
* disabled, an explicit commit must be done or database changes will
* not be saved.
* <P><font color="#009900">
* To connect to a HSQL database, the following code may be used:
* <pre>
* Class.forName("org.hsqldb.jdbcDriver");
* Connection c=DriverManager.getConnection(url,user,password);
* </pre>
* For HSQL, the url must start with jdbc:hsqldb.
* The url for an In-Memory database is <code>jdbc:hsqldb:.</code>
* The url for a standalone database is jdbc:hsqldb:name
* where name is the filename of the database, including path. For example:
* <code>jdbc:hsqldb:test</code> will connect to a database called
* 'test', with the files test.properties, test.data and test.script.
* For more information about the internal file structure of HSQL,
* please read the documentation, page 'Files'.
* </font><P>
* @see jdbcStatement
* @see jdbcResultSet
* @see jdbcDatabaseMetaData
*/
public class jdbcConnection implements Connection {
private boolean bClosed;
private boolean bAutoCommit;
private String sDatabaseName;
private final static int HTTP = 0, STANDALONE = 1, INTERNAL = 2, HSQL = 3;
private int iType;
private Database dDatabase;
private Channel cChannel;
Socket sSocket;
DataOutputStream dOutput;
DataInputStream dInput;
public static final int DEFAULT_HSQL_PORT = 9001;
private static Hashtable tDatabase = new Hashtable();
private static Hashtable iUsageCount = new Hashtable();
/**
* Creates a <code>Statement</code> object for sending
* SQL statements to the database.
* SQL statements without parameters are normally
* executed using Statement objects.
*
* @return a new Statement object
*/
public Statement createStatement() {
if (Trace.TRACE) {
Trace.trace();
}
if (bClosed) {
return null;
}
return new jdbcStatement(this);
}
/**
* Creates a <code>PreparedStatement</code> object for sending
* parameterized SQL statements to the database.
*
* A SQL statement with or without IN parameters can be stored in
* a PreparedStatement object. This object can then be used to execute
* this statement multiple times.
* <P><font color="#009900">
* In HSQL, the statement is not sent to the database until
* the <code>PreparedStatement</code> is executed. Other drivers may send
* the statment to the database when this function is called. This has
* no direct effect on users; however, it does affect which method throws
* certain SQLExceptions.
* </font><P>
* @param sql a SQL statement that may contain one or more '?' IN
* parameter placeholders
* @return a new PreparedStatement object containing the
* pre-compiled statement
*/
public PreparedStatement prepareStatement(String sql) {
if (Trace.TRACE) {
Trace.trace(sql);
}
if (bClosed) {
return null;
}
return new jdbcPreparedStatement(this, sql);
}
/**
* Creates a <code>CallableStatement</code> object for calling
* database stored procedures.
* The CallableStatement provides
* methods for setting up its IN and OUT parameters, and
* methods for executing the call to a stored procedure.
*
* <P><B>Note:</B> This method is optimized for handling stored
* procedure call statements.
* <P><font color="#009900">
* HSQL does not send the call
* statement to the database when the method <code>prepareCall</code>
* is done; it waits until the CallableStatement is executed. This has
* no direct effect on users; however, it does affect which method
* throws certain SQLExceptions.
* </font><P>
* @param sql a SQL statement that may contain one or more '?'
* parameter placeholders. Typically this statement is a JDBC
* function call escape string.
* @return a new CallableStatement object containing the
* pre-compiled SQL statement
*/
public CallableStatement prepareCall(String sql) {
if (Trace.TRACE) {
Trace.trace(sql);
}
if (bClosed) {
return null;
}
return new jdbcPreparedStatement(this, sql);
}
/**
* Converts the given SQL statement into the system's native SQL grammar.
* <P><font color="#009900">
* HSQL does convert the JDBC sql grammar into its system's
* native SQL grammar prior to sending it; this method returns the
* native form of the statement that the driver would have sent.
* </font><P>
* @param sql a SQL statement that may contain one or more '?'
* parameter placeholders
* @return the native form of this statement
*/
public String nativeSQL(String sql) {
if (sql.indexOf('{') == -1) {
return sql;
}
char s[] = sql.toCharArray();
boolean changed = false;
int state = 0;
int len = s.length;
for (int i = 0; i < len; i++) {
char c = s[i];
switch (state) {
case 0: // normal
if (c == '\'') {
state = 1;
} else if (c == '"') {
state = 2;
} else if (c == '{') {
s[i] = ' ';
changed = true;
String sub = sql.substring(i + 1).toUpperCase();
if (sub.startsWith("?=")) {
i += 2;
} else if (sub.startsWith("CALL")) {
i += 4;
} else if (sub.startsWith("ESCAPE")) {
i += 6;
}
state = 3;
}
break;
case 1: // inside ' '
case 5: // inside { } and ' '
if (c == '\'') {
state -= 1;
}
break;
case 2: // inside " "
case 6: // inside { } and " "
if (c == '"') {
state -= 2;
}
break;
case 3: // inside { } before whitespace
if (c == ' ') {
state = 4;
} else {
s[i] = ' ';
changed = true;
}
break;
case 4: // inside { } after whitespace
if (c == '\'') {
state = 5;
} else if (c == '"') {
state = 6;
} else if (c == '}') {
s[i] = ' ';
changed = true;
state = 0;
}
}
}
if (changed) {
sql = new String(s);
if (Trace.TRACE) {
Trace.trace(s + " > " + sql);
}
}
return sql;
}
/**
* Sets this connection's auto-commit mode.
* If a connection is in auto-commit mode, then all its SQL
* statements will be executed and committed as individual
* transactions. Otherwise, its SQL statements are grouped into
* transactions that are terminated by a call to either
* the method <code>commit</code> or the method <code>rollback</code>.
* By default, new connections are in auto-commit
* mode.
*
* The commit occurs when the statement completes or the next
* execute occurs, whichever comes first. In the case of
* statements returning a ResultSet, the statement completes when
* the last row of the ResultSet has been retrieved or the
* ResultSet has been closed. In advanced cases, a single
* statement may return multiple results as well as output
* parameter values. In these cases the commit occurs when all results and
* output parameter values have been retrieved.
*
* @param autoCommit true enables auto-commit; false disables
* auto-commit.
* @exception SQLException if a database access error occurs
*/
public void setAutoCommit(boolean autoCommit) throws SQLException {
bAutoCommit = autoCommit;
execute("SET AUTOCOMMIT " + (bAutoCommit ? "TRUE" : "FALSE"));
}
/**
* Gets the current auto-commit state.
*
* @return the current state of auto-commit mode
* @see #setAutoCommit
*/
public boolean getAutoCommit() {
if (Trace.TRACE) {
Trace.trace();
}
return bAutoCommit;
}
/**
* Makes all changes made since the previous
* commit/rollback permanent and releases any database locks
* currently held by the Connection. This method should be
* used only when auto-commit mode has been disabled.
*
* @exception SQLException if a database access error occurs
* @see #setAutoCommit
*/
public void commit() throws SQLException {
execute("COMMIT");
}
/**
* Drops all changes made since the previous
* commit/rollback and releases any database locks currently held
* by this Connection. This method should be used only when auto-
* commit has been disabled.
*
* @exception SQLException if a database access error occurs
* @see #setAutoCommit
*/
public void rollback() throws SQLException {
execute("ROLLBACK");
}
/**
* Releases a Connection's database and JDBC resources
* immediately instead of waiting for
* them to be automatically released.
*
* <P><B>Note:</B> A Connection is automatically closed when it is
* garbage collected.
*
* @exception SQLException if a database access error occurs
*/
public void close() throws SQLException {
if (Trace.TRACE) {
Trace.trace();
}
if (bClosed) {
return;
}
if ((iType == STANDALONE) || (iType == INTERNAL)) {
closeStandalone();
} else {
execute("DISCONNECT");
}
bClosed = true;
}
/**
* Tests to see if a Connection is closed.
*
* @return true if the connection is closed; false if it's still open
*/
public boolean isClosed() {
if (Trace.TRACE) {
Trace.trace();
}
return bClosed;
}
/**
* Gets the metadata regarding this connection's database.
* A Connection's database is able to provide information
* describing its tables, its supported SQL grammar, its stored
* procedures, the capabilities of this connection, and so on. This
* information is made available through a DatabaseMetaData
* object.
*
* @return a DatabaseMetaData object for this Connection
*/
public DatabaseMetaData getMetaData() {
if (Trace.TRACE) {
Trace.trace();
}
return new jdbcDatabaseMetaData(this);
}
/**
* Puts this connection in read-only mode as a hint to enable
* database optimizations.
*
* <P><B>Note:</B> This method should not be called while in the
* middle of a transaction.
* <P><font color="#009900">
* HSQL will in this case commit the transaction automatically.
* <P>
* In HSQL, additionally the whole database can be put in
* read-only mode by manually adding the line 'readonly=true' to the
* .properties file. All connections are then automatically readonly.
* The database files will then be opened in readonly mode, and it is
* thus possible to create a CD with this database.
* </font><P>
* @param readOnly true enables read-only mode; false disables
* read-only mode.
* @exception SQLException if a database access error occurs
*/
public void setReadOnly(boolean readonly) throws SQLException {
execute("SET READONLY " + (readonly ? "TRUE" : "FALSE"));
}
/**
* Tests to see if the connection is in read-only mode.
*
* @return true if connection is read-only and false otherwise
* @exception SQLException if a database access error occurs
*/
public boolean isReadOnly() throws SQLException {
String s =
"SELECT * FROM SYSTEM_CONNECTIONINFO WHERE KEY='READONLY'";
ResultSet r = execute(s);
r.next();
return r.getString(2).equals("TRUE");
}
/**
* Sets a catalog name in order to select
* a subspace of this Connection's database in which to work.
* <P><font color="#009900">
* HSQL does not support catalogs and ignores
* this request.
* </font><P>
*/
public void setCatalog(String catalog) {
if (Trace.TRACE) {
Trace.trace(catalog);
}
}
/**
* Returns the Connection's current catalog name.
*
* @return the current catalog name or null
*/
public String getCatalog() {
if (Trace.TRACE) {
Trace.trace();
}
return null;
}
/**
* Attempts to change the transaction
* isolation level to the one given.
* The constants defined in the interface <code>Connection</code>
* are the possible transaction isolation levels.
*
* <P><B>Note:</B> This method should not be called while
* in the middle of a transaction.
* <P><font color="#009900">
* HSQL currently ignores this call.
* </font><P>
* @param level one of the TRANSACTION_* isolation values with the
* exception of TRANSACTION_NONE; some databases may not support
* other values
* @see DatabaseMetaData#supportsTransactionIsolationLevel
*/
public void setTransactionIsolation(int level) {
if (Trace.TRACE) {
Trace.trace(level);
}
}
/**
* Gets this Connection's current transaction isolation level.
*
* @return the current TRANSACTION_* mode value
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -