package org.krakenapps.sqlengine.bdb;
import java.io.File;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.krakenapps.sqlengine.CursorHandle;
import org.krakenapps.sqlengine.DatabaseHandle;
import org.krakenapps.sqlengine.Session;
import org.krakenapps.sqlengine.TableHandle;
import org.krakenapps.sqlengine.TableHandleEventListener;
import org.krakenapps.sqlengine.TableSchemaManager;
import org.krakenapps.sqlparser.SqlParser;
import org.krakenapps.sqlparser.ast.AlterTableStatement;
import org.krakenapps.sqlparser.ast.DescTableStatement;
import org.krakenapps.sqlparser.ast.DropTableStatement;
import org.krakenapps.sqlparser.ast.ShowTablesStatement;
import org.krakenapps.sqlparser.ast.TableDefinition;
import com.sleepycat.je.CheckpointConfig;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
public class DatabaseHandleImpl implements DatabaseHandle, TableHandleEventListener {
private String databaseName;
private Environment env;
private SqlParser parser;
private TableSchemaManager tableSchemaManager;
private Set<TableHandle> openedTables;
public DatabaseHandleImpl(String databaseName) {
this.parser = new SqlParser();
this.databaseName = databaseName;
this.openedTables = Collections.newSetFromMap(new ConcurrentHashMap<TableHandle, Boolean>());
File home = new File("data/kraken-sqlengine/" + databaseName);
home.mkdirs();
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
envConfig.setTransactional(true);
this.env = new Environment(home, envConfig);
this.tableSchemaManager = new TableSchemaManagerImpl(this);
}
@Override
public TableSchemaManager getTableSchemaManager() {
return tableSchemaManager;
}
@Override
public int execute(Session session, String sql) throws SQLException {
Object stmt = null;
try {
stmt = parser.eval(sql);
} catch (ParseException e) {
throw new SQLException("invalid sql syntax: " + sql);
}
if (stmt instanceof TableDefinition) {
DdlHandler.handleCreateTable(this, (TableDefinition) stmt);
return 0;
} else if (stmt instanceof AlterTableStatement) {
DdlHandler.handleAlterTable(this, (AlterTableStatement) stmt);
return 0;
} else if (stmt instanceof DropTableStatement) {
DdlHandler.handleDropTable(this, (DropTableStatement) stmt);
return 0;
}
return -1;
}
@Override
public CursorHandle openFor(Session session, String sql) throws SQLException {
try {
ResultMetadata metadata = new ResultMetadata();
Iterator<Row> it = handle(sql, metadata);
return new CursorImpl(metadata, it);
} catch (Exception e) {
throw new SQLException(e.getMessage(), e);
}
}
private Iterator<Row> handle(String sql, ResultMetadata metadata) throws SQLException {
Object stmt = null;
try {
stmt = parser.eval(sql);
} catch (ParseException e) {
throw new SQLException("invalid sql syntax [" + sql + "]");
}
if (stmt instanceof ShowTablesStatement) {
return DdlHandler.handleShowTable(this, (ShowTablesStatement) stmt, metadata);
} else if (stmt instanceof DescTableStatement) {
return DdlHandler.handleDescTable(this, (DescTableStatement) stmt, metadata);
}
throw new SQLException("not implemented yet");
}
@Override
public String getName() {
return databaseName;
}
@Override
public TableHandle openTable(String tableName) {
return openTable(tableName, false);
}
@Override
public TableHandle openTable(String tableName, boolean allowCreate) {
return open(tableName, allowCreate);
}
@Override
public TableHandle createTable(String tableName) {
return open(tableName, true);
}
private TableHandle open(String tableName, boolean allowCreate) {
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(allowCreate);
dbConfig.setTransactional(true);
Database db = env.openDatabase(null, tableName, dbConfig);
env.checkpoint(new CheckpointConfig().setForce(true));
TableHandle handle = new TableHandleImpl(db);
// add to handle map
openedTables.add(handle);
handle.addListener(this);
return handle;
}
@Override
public void close() {
env.close();
}
//
// receives table handle closed event
//
@Override
public void onClose(TableHandle handle) {
openedTables.remove(handle);
}
}