*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ---------------
* SSConnection.java
* ---------------
* Author: Volker Berlin
*
*/
package smallsql.database;
import java.io.RandomAccessFile;
import java.sql.*;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
public class SSConnection implements Connection {
private Database database;
private boolean autoCommit = true;
int isolationLevel = TRANSACTION_READ_COMMITTED; int serializeCount;
private List commitPages = new ArrayList();
private long transactionTime;
private SSDatabaseMetaData metadata;
private int holdability;
final Logger log = new Logger();
SSConnection( Properties props ) throws SQLException{
String name = props.getProperty("dbpath");
boolean create = "true".equals(props.getProperty("create"));
database = Database.getDatabase(name, this, create);
metadata = new SSDatabaseMetaData(this);
}
Database getDatabase(boolean returnNull) throws SQLException{
if(!returnNull && database == null) throw Utils.createSQLException("You are not connected with a Database.");
return database;
}
public Statement createStatement() throws SQLException {
return new SSStatement(this);
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
return new SSPreparedStatement( this, sql);
}
public CallableStatement prepareCall(String sql) throws SQLException {
return new SSCallableStatement( this, sql);
}
public String nativeSQL(String sql) throws SQLException {
return sql;
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
if(log.isLogging()) log.println("AutoCommit:"+autoCommit);
if(this.autoCommit != autoCommit){
commit();
this.autoCommit = autoCommit;
}
}
public boolean getAutoCommit() throws SQLException {
return autoCommit;
}
void add(StorePage storePage) throws SQLException{
testClosedConnection();
commitPages.add(storePage);
}
public void commit() throws SQLException {
try{
log.println("Commit");
testClosedConnection();
synchronized(commitPages){
int count = commitPages.size();
for(int i=0; i<count; i++){
StorePage page = (StorePage)commitPages.get(i);
page.commit();
}
for(int i=0; i<count; i++){
StorePage page = (StorePage)commitPages.get(i);
page.freeLock();
}
commitPages.clear();
transactionTime = System.currentTimeMillis();
}
}catch(Throwable e){
rollback();
throw Utils.createSQLException(e);
}
}
void rollbackFile(RandomAccessFile raFile) throws SQLException{
testClosedConnection();
for(int i=commitPages.size()-1; i>=0; i--){
StorePage page = (StorePage)commitPages.get(i);
if(page.raFile == raFile){
page.rollback();
page.freeLock();
}
}
}
void rollback(int savepoint) throws SQLException{
testClosedConnection();
for(int i = commitPages.size()-1; i>=savepoint; i--){
StorePage page = (StorePage)commitPages.remove(i);
page.rollback();
page.freeLock();
}
}
public void rollback() throws SQLException {
log.println("Rollback");
testClosedConnection();
synchronized(commitPages){
int count = commitPages.size();
for(int i=0; i<count; i++){
StorePage page = (StorePage)commitPages.get(i);
page.rollback();
page.freeLock();
}
commitPages.clear();
transactionTime = System.currentTimeMillis();
}
}
public void close() throws SQLException {
rollback();
database = null;
commitPages = null;
Database.closeConnection(this);
}
final void testClosedConnection() throws SQLException{
if(isClosed()) throw Utils.createSQLException("Connection was closed.");
}
public boolean isClosed() throws SQLException {
return (commitPages == null);
}
public DatabaseMetaData getMetaData() throws SQLException {
return metadata;
}
public void setReadOnly(boolean readOnly) throws SQLException {
}
public boolean isReadOnly() throws SQLException {
return false;
}
public void setCatalog(String catalog) throws SQLException {
if(isClosed()) throw Utils.createSQLException("Connection is allready closed");
database = Database.getDatabase(catalog, this, false);
}
public String getCatalog() throws SQLException {
if(database == null)
return "";
return database.getName();
}
public void setTransactionIsolation(int level) throws SQLException {
if(!metadata.supportsTransactionIsolationLevel(level))
throw Utils.createSQLException("Unknow Transaction Isolation Level:"+level);
isolationLevel = level;
}
public int getTransactionIsolation() throws SQLException {
return isolationLevel;
}
public SQLWarning getWarnings() throws SQLException {
return null;
}
public void clearWarnings() throws SQLException {
}
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSStatement( this, resultSetType, resultSetConcurrency);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSPreparedStatement( this, sql, resultSetType, resultSetConcurrency);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSCallableStatement( this, sql, resultSetType, resultSetConcurrency);
}
public Map getTypeMap() throws SQLException {
return null;
}
public void setTypeMap(Map map) throws SQLException {
}
public void setHoldability(int holdability) throws SQLException {
this.holdability = holdability;
}
public int getHoldability() throws SQLException {
return holdability;
}
int getSavepoint() throws SQLException{
testClosedConnection();
return commitPages.size();
}
public Savepoint setSavepoint() throws SQLException {
return new SSSavepoint(getSavepoint(), null, transactionTime);
}
public Savepoint setSavepoint(String name) throws SQLException {
return new SSSavepoint(getSavepoint(), name, transactionTime);
}
public void rollback(Savepoint savepoint) throws SQLException {
if(savepoint instanceof SSSavepoint){
if(((SSSavepoint)savepoint).transactionTime != transactionTime){
throw Utils.createSQLException("Savepoint is not valid for this transaction.");
}
rollback( savepoint.getSavepointId() );
return;
}
throw Utils.createSQLException("Savepoint is not valid for this driver."+savepoint);
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
if(savepoint instanceof SSSavepoint){
((SSSavepoint)savepoint).transactionTime = 0;
return;
}
throw Utils.createSQLException("Savepoint is not valid for this driver."+savepoint);
}
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return new SSStatement( this, resultSetType, resultSetConcurrency);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return new SSPreparedStatement( this, sql);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return new SSCallableStatement( this, sql, resultSetType, resultSetConcurrency);
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return new SSPreparedStatement( this, sql);
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return new SSPreparedStatement( this, sql);
}
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return new SSPreparedStatement( this, sql);
}
}