提交 5a86eaff authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 faebdbbf
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.result.LocalResult;
import org.h2.result.ResultInterface;
import org.h2.util.ObjectArray;
/**
* @author Thomas
*/
public abstract class Command implements CommandInterface {
protected Session session;
protected long startTime;
protected Trace trace;
private volatile boolean cancel;
public abstract boolean isTransactional();
public abstract boolean isQuery();
public abstract ObjectArray getParameters();
public Command(Parser parser) {
this.session = parser.getSession();
trace = session.getDatabase().getTrace(Trace.COMMAND);
}
public int update() throws SQLException {
throw Message.getSQLException(Message.METHOD_NOT_ALLOWED_FOR_QUERY);
}
public LocalResult query(int maxrows) throws SQLException {
throw Message.getSQLException(Message.METHOD_ONLY_ALLOWED_FOR_QUERY);
}
// TODO insert parameters into the original query, or allow this syntax
// if(parameters != null && parameters.size() > 0) {
// buff.append(" /* ");
// for(int i=0; i<parameters.size(); i++) {
// if(i>0) {
// buff.append(", ");
// }
// Parameter param = (Parameter) parameters.get(i);
// buff.append(i+1);
// buff.append(" = ");
// buff.append(param.getSQL());
// }
// buff.append(" */");
// }
public ResultInterface executeQuery(int maxrows, boolean scrollable) throws SQLException {
return executeQueryLocal(maxrows);
}
public LocalResult executeQueryLocal(int maxrows) throws SQLException {
startTime = System.currentTimeMillis();
Database database = session.getDatabase();
Object sync = Constants.MULTI_THREADED_KERNEL ? (Object)session : (Object)database;
synchronized (sync) {
try {
database.checkPowerOff();
session.setCurrentCommand(this);
LocalResult result = query(maxrows);
return result;
} catch(Throwable e) {
SQLException s = Message.convert(e);
database.exceptionThrown(s);
throw s;
} finally {
stop();
}
}
}
protected void start() {
startTime = System.currentTimeMillis();
}
public void checkCancelled() throws SQLException {
if (cancel) {
throw Message.getSQLException(Message.STATEMENT_WAS_CANCELLED);
}
session.throttle();
}
private void stop() throws SQLException {
session.setCurrentCommand(null);
if (!isTransactional()) {
// meta data changes need to commit in any case
session.commit();
} else if (session.getAutoCommit()) {
session.commit();
}
if (trace.info()) {
long time = System.currentTimeMillis() - startTime;
if (time > Constants.LONG_QUERY_LIMIT_MS) {
trace.info("long query: " + time);
}
}
}
public int executeUpdate() throws SQLException {
startTime = System.currentTimeMillis();
Database database = session.getDatabase();
Object sync = Constants.MULTI_THREADED_KERNEL ? (Object)session : (Object)database;
synchronized (sync) {
int rollback = session.getLogId();
session.setCurrentCommand(this);
try {
database.checkPowerOff();
int result = update();
return result;
} catch (SQLException e) {
database.exceptionThrown(e);
database.checkPowerOff();
session.rollbackTo(rollback);
throw e;
} finally {
stop();
}
}
}
public void close() {
// nothing to do
}
public void cancel() {
this.cancel = true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import java.sql.SQLException;
import org.h2.expression.Expression;
import org.h2.expression.Parameter;
import org.h2.result.LocalResult;
import org.h2.util.ObjectArray;
import org.h2.value.Value;
public class CommandContainer extends Command {
private Prepared prepared;
CommandContainer(Parser parser, Prepared prepared) {
super(parser);
prepared.setCommand(this);
this.prepared = prepared;
}
public ObjectArray getParameters() {
return prepared.getParameters();
}
public boolean isTransactional() {
return prepared.isTransactional();
}
public boolean isQuery() {
return prepared.isQuery();
}
private void recompileIfRequired() throws SQLException {
if(prepared == null || prepared.needRecompile()) {
// TODO test with 'always recompile'
prepared.setModificationId(0);
String sql = prepared.getSQL();
ObjectArray oldValues = prepared.getParameters();
Parser parser = new Parser(session);
prepared = parser.parseOnly(sql);
long mod = prepared.getModificationId();
prepared.setModificationId(0);
ObjectArray newParams = prepared.getParameters();
for(int i=0; i<newParams.size(); i++) {
Value v = ((Expression)oldValues.get(i)).getValue(session);
Parameter p = (Parameter) newParams.get(i);
p.setValue(v);
}
prepared.prepare();
prepared.setModificationId(mod);
}
}
public int update() throws SQLException {
recompileIfRequired();
// TODO query time: should keep lock time separate from running time
start();
prepared.checkParameters();
prepared.trace();
return prepared.update();
}
public LocalResult query(int maxrows) throws SQLException {
recompileIfRequired();
// TODO query time: should keep lock time separate from running time
start();
prepared.checkParameters();
prepared.trace();
return prepared.query(maxrows);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import java.sql.SQLException;
import org.h2.result.ResultInterface;
import org.h2.util.ObjectArray;
public interface CommandInterface {
boolean isQuery();
ObjectArray getParameters();
ResultInterface executeQuery(int maxRows, boolean scrollable) throws SQLException;
int executeUpdate() throws SQLException;
void close();
void cancel();
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import java.sql.SQLException;
import org.h2.result.LocalResult;
import org.h2.util.ObjectArray;
public class CommandList extends Command {
private Command command;
private String remaining;
// TODO lock if possible!
public CommandList(Parser parser, Command c, String remaining) {
super(parser);
this.command = c;
this.remaining = remaining;
}
public ObjectArray getParameters() {
return command.getParameters();
}
private void executeRemaining() throws SQLException {
Command command = session.prepareLocal(remaining);
if(command.isQuery()) {
command.query(0);
} else {
command.update();
}
}
public int update() throws SQLException {
int updateCount = command.executeUpdate();
executeRemaining();
return updateCount;
}
public LocalResult query(int maxrows) throws SQLException {
LocalResult result = command.query(maxrows);
executeRemaining();
return result;
}
public boolean isQuery() {
return command.isQuery();
}
public boolean isTransactional() {
return true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import java.io.IOException;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.SessionInterface;
import org.h2.engine.SessionRemote;
import org.h2.expression.ParameterInterface;
import org.h2.expression.ParameterRemote;
import org.h2.message.Trace;
import org.h2.result.ResultInterface;
import org.h2.result.ResultRemote;
import org.h2.util.ObjectArray;
import org.h2.value.Transfer;
public class CommandRemote implements CommandInterface {
private SessionRemote session;
private ObjectArray transferList;
private int id;
private boolean isQuery;
private ObjectArray parameters;
private Trace trace;
private String sql;
private int paramCount;
private void prepare(SessionRemote session) throws SQLException {
id = session.getNextId();
paramCount = 0;
for(int i=0; i<transferList.size(); i++) {
try {
Transfer transfer = (Transfer) transferList.get(i);
session.traceOperation("SESSION_PREPARE", id);
transfer.writeInt(SessionRemote.SESSION_PREPARE).writeInt(id).writeString(sql);
session.done(transfer);
isQuery = transfer.readBoolean();
paramCount = transfer.readInt();
} catch(IOException e) {
session.removeServer(i);
}
}
}
public CommandRemote(SessionRemote session, ObjectArray transferList, String sql) throws SQLException {
this.transferList = transferList;
trace = session.getTrace();
this.sql = sql;
parameters = new ObjectArray();
prepare(session);
for(int i=0; i<paramCount; i++) {
parameters.add(new ParameterRemote(i));
}
// set session late because prepare might fail - in this case we don't need to close the object
this.session = session;
}
public boolean isQuery() {
return isQuery;
}
public ObjectArray getParameters() {
return parameters;
}
public ResultInterface executeQuery(int maxRows, boolean scrollable) throws SQLException {
checkParameters();
synchronized(session) {
session.checkClosed();
if(id <= session.getCurrentId() - Constants.SERVER_CACHED_OBJECTS) {
// object is too old - we need to prepare again
prepare(session);
}
int objectId = session.getNextId();
ResultRemote result = null;
// TODO cluster: test sequences and so on
for(int i=0; i<transferList.size(); i++) {
Transfer transfer = (Transfer) transferList.get(i);
try {
// TODO cluster: support load balance with values for each server / auto detect
session.traceOperation("COMMAND_EXECUTE_QUERY", id);
transfer.writeInt(SessionRemote.COMMAND_EXECUTE_QUERY).writeInt(id).writeInt(objectId).writeInt(maxRows);
int readRows;
if(session.isClustered() || scrollable) {
readRows = Integer.MAX_VALUE;
} else {
readRows = Constants.SERVER_SMALL_RESULTSET_SIZE;
}
transfer.writeInt(readRows);
sendParameters(transfer);
session.done(transfer);
int columnCount = transfer.readInt();
if(result != null) {
result.close();
result = null;
}
result = new ResultRemote(session, transfer, objectId, columnCount, readRows);
} catch(IOException e) {
session.removeServer(i);
}
}
session.autoCommitIfCluster();
return result;
}
}
public int executeUpdate() throws SQLException {
checkParameters();
synchronized(session) {
session.checkClosed();
if(id <= session.getCurrentId() - Constants.SERVER_CACHED_OBJECTS) {
// object is too old - we need to prepare again
prepare(session);
}
int updateCount = 0;
boolean autoCommit = false;
for(int i=0; i<transferList.size(); i++) {
try {
Transfer transfer = (Transfer) transferList.get(i);
session.traceOperation("COMMAND_EXECUTE_UPDATE", id);
transfer.writeInt(SessionRemote.COMMAND_EXECUTE_UPDATE).writeInt(id);
sendParameters(transfer);
session.done(transfer);
updateCount = transfer.readInt();
autoCommit = transfer.readBoolean();
} catch(IOException e) {
session.removeServer(i);
}
}
session.setAutoCommit(autoCommit);
session.autoCommitIfCluster();
return updateCount;
}
}
private void checkParameters() throws SQLException {
int len = parameters.size();
for(int i=0; i<len; i++) {
ParameterInterface p = (ParameterInterface)parameters.get(i);
p.checkSet();
}
}
private void sendParameters(Transfer transfer) throws IOException, SQLException {
int len = parameters.size();
transfer.writeInt(len);
for(int i=0; i<len; i++) {
ParameterInterface p = (ParameterInterface)parameters.get(i);
transfer.writeValue(p.getParamValue());
}
}
public SessionInterface getSession() {
return session;
}
public void close() {
if(session == null || session.isClosed()) {
return;
}
synchronized(session) {
for(int i=0; i<transferList.size(); i++) {
try {
Transfer transfer = (Transfer) transferList.get(i);
session.traceOperation("COMMAND_CLOSE", id);
transfer.writeInt(SessionRemote.COMMAND_CLOSE).writeInt(id);
} catch (IOException e) {
// TODO cluster: do we need to to handle ioexception on close?
trace.error("close", e);
}
}
session = null;
}
}
// public void finalize() {
// if(!Database.RUN_FINALIZERS) {
// return;
// }
// close();
// }
public void cancel() {
// TODO server: support cancel
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import org.h2.engine.Session;
public class ParserInt extends Parser {
public ParserInt(Session session) {
super(session);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.Parameter;
import org.h2.message.Message;
import org.h2.result.LocalResult;
import org.h2.util.ObjectArray;
public abstract class Prepared {
protected String sql;
protected int headPos = -1;
protected Session session;
protected ObjectArray parameters;
private long modificationId;
private Command command;
private int objectId;
private boolean prepareAlways;
private int currentRowNumber;
public boolean needRecompile() throws SQLException {
Database db = session.getDatabase();
if(db == null) {
throw Message.getSQLException(Message.CONNECTION_BROKEN);
}
// TODO parser: currently, compiling every create/drop/... twice! because needRecompile return true even for the first execution
return Constants.RECOMPILE_ALWAYS || prepareAlways || modificationId < db.getModificationMetaId();
}
public abstract boolean isTransactional();
public Prepared(Session session) {
this.session = session;
modificationId = session.getDatabase().getModificationMetaId();
}
long getModificationId() {
return modificationId;
}
void setModificationId(long id) {
this.modificationId = id;
}
public void setParameterList(ObjectArray parameters) {
this.parameters = parameters;
}
public ObjectArray getParameters() {
return parameters;
}
protected void checkParameters() throws SQLException {
for (int i = 0; parameters != null && i < parameters.size(); i++) {
Parameter param = (Parameter) parameters.get(i);
param.checkSet();
}
}
public void setCommand(Command command) {
this.command = command;
}
public boolean isQuery() {
return false;
}
public void prepare() throws SQLException {
// nothing to do
}
public int update() throws SQLException {
throw Message.getSQLException(Message.METHOD_NOT_ALLOWED_FOR_QUERY);
}
public LocalResult query(int maxrows) throws SQLException {
throw Message.getSQLException(Message.METHOD_ONLY_ALLOWED_FOR_QUERY);
}
public void setSQL(String sql) {
this.sql = sql;
}
public String getSQL() {
return sql;
}
protected int getObjectId(boolean needFresh, boolean dataFile) {
Database db = session.getDatabase();
int id = objectId;
if(id == 0) {
id = db.allocateObjectId(needFresh, dataFile);
}
objectId = 0;
return id;
}
public String getPlan() {
return null;
}
protected void checkCancelled() throws SQLException {
// TODO strange code: probably checkCancelled should always be called on the session. fix & test after release 1.0
if(command != null) {
command.checkCancelled();
} else {
session.checkCancelled();
}
}
public void setObjectId(int i) {
this.objectId = i;
}
public void setHeadPos(int headPos) {
this.headPos = headPos;
}
public void setSession(Session currentSession) {
this.session = currentSession;
}
void trace() throws SQLException {
if(session.getTrace().info()) {
StringBuffer buff = new StringBuffer();
buff.append(sql);
if(parameters.size()>0) {
buff.append(" {");
for(int i=0; i<parameters.size(); i++) {
if(i>0) {
buff.append(", ");
}
buff.append(i+1);
buff.append(": ");
Expression e = (Expression) parameters.get(i);
buff.append(e.getValue(session).getSQL());
}
buff.append("};");
} else {
buff.append(';');
}
session.getTrace().infoSQL(buff.toString());
}
}
public void setPrepareAlways(boolean prepareAlways) {
this.prepareAlways = prepareAlways;
}
protected void setCurrentRowNumber(int rowNumber) {
this.currentRowNumber = rowNumber;
}
public int getCurrentRowNumber() {
return currentRowNumber;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.index.Index;
import org.h2.message.Message;
import org.h2.schema.Schema;
public class AlterIndexRename extends SchemaCommand {
private Index oldIndex;
private String newIndexName;
public AlterIndexRename(Session session, Schema schema) {
super(session, schema);
}
public void setOldIndex(Index index) {
oldIndex = index;
}
public void setNewName(String name) {
newIndexName = name;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
if(getSchema().findIndex(newIndexName) != null || newIndexName.equals(oldIndex.getName())) {
throw Message.getSQLException(Message.INDEX_ALREADY_EXISTS_1, newIndexName);
}
session.getUser().checkRight(oldIndex.getTable(), Right.ALL);
db.renameSchemaObject(session, oldIndex, newIndexName);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Sequence;
public class AlterSequence extends DefineCommand {
private Sequence sequence;
private boolean newStart;
private long start;
private boolean newIncrement;
private long increment;
public AlterSequence(Session session) {
super(session);
}
public void setSequence(Sequence sequence) {
this.sequence = sequence;
}
public void setStartWith(long start) {
newStart = true;
this.start = start;
}
public void setIncrement(long increment) throws SQLException {
newIncrement = true;
if(increment == 0) {
throw Message.getSQLException(Message.INVALID_VALUE_2, new String[]{"0", "INCREMENT"}, null);
}
this.increment = increment;
}
public int update() throws SQLException {
// TODO rights: what are the rights required for a sequence?
session.commit();
Database db = session.getDatabase();
if(newStart) {
sequence.setStartValue(start);
}
if(newIncrement) {
sequence.setIncrement(increment);
}
db.update(session, sequence);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.constraint.Constraint;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.schema.Schema;
/**
* @author Thomas
*/
public class AlterTableDropConstraint extends SchemaCommand {
private String constraintName;
public AlterTableDropConstraint(Session session, Schema schema) {
super(session, schema);
}
public void setConstraintName(String string) {
constraintName = string;
}
public int update() throws SQLException {
session.commit();
Constraint constraint = getSchema().getConstraint(constraintName);
session.getUser().checkRight(constraint.getTable(), Right.ALL);
session.getUser().checkRight(constraint.getRefTable(), Right.ALL);
session.getDatabase().removeSchemaObject(session, constraint);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Table;
/**
* @author Thomas
*/
public class AlterTableRename extends SchemaCommand {
private Table oldTable;
private String newTableName;
public AlterTableRename(Session session, Schema schema) {
super(session, schema);
}
public void setOldTable(Table table) {
oldTable = table;
}
public void setNewTableName(String name) {
newTableName = name;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
if(getSchema().findTableOrView(session, newTableName) != null || newTableName.equals(oldTable.getName())) {
throw Message.getSQLException(Message.TABLE_OR_VIEW_ALREADY_EXISTS_1, newTableName);
}
session.getUser().checkRight(oldTable, Right.ALL);
if(oldTable.getTemporary()) {
// TODO renaming a temporary table is not supported
throw Message.getUnsupportedException();
}
db.renameSchemaObject(session, oldTable, newTableName);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
public class AlterTableRenameColumn extends DefineCommand {
private Table table;
private Column column;
private String newName;
public AlterTableRenameColumn(Session session) {
super(session);
}
public void setTable(Table table) {
this.table = table;
}
public void setColumn(Column column) {
this.column = column;
}
public void setNewColumnName(String newName) {
this.newName = newName;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
session.getUser().checkRight(table, Right.ALL);
table.checkSupportAlter();
table.renameColumn(column, newName);
table.setModified();
db.update(session, table);
ObjectArray children = table.getChildren();
for(int i=0; i<children.size(); i++) {
DbObject child = (DbObject) children.get(i);
if(child.getCreateSQL() != null) {
db.update(session, child);
}
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.message.Message;
import org.h2.security.SHA256;
import org.h2.util.ByteUtils;
/**
* @author Thomas
*/
public class AlterUser extends DefineCommand {
public static final int SET_PASSWORD = 0, RENAME = 1, ADMIN = 2;
private int type;
private User user;
private String newName;
private byte[] userPasswordHash;
private byte[] salt;
private byte[] hash;
private boolean admin;
public AlterUser(Session session) {
super(session);
}
public void setType(int type) {
this.type = type;
}
public void setNewName(String newName) {
this.newName = newName;
}
public void setUser(User user) {
this.user = user;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public void setSalt(String s) throws SQLException {
salt = ByteUtils.convertStringToBytes(s);
}
public void setHash(String s) throws SQLException {
hash = ByteUtils.convertStringToBytes(s);
}
public void setPassword(String password) {
SHA256 sha = new SHA256();
String name = newName == null ? user.getName() : newName;
this.userPasswordHash = sha.getKeyPasswordHash(name, password.toCharArray());
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
switch(type) {
case SET_PASSWORD:
if(user != session.getUser()) {
session.getUser().checkAdmin();
}
if(hash!=null && salt !=null) {
user.setSaltAndHash(salt, hash);
} else {
user.setUserPasswordHash(userPasswordHash);
}
break;
case RENAME:
session.getUser().checkAdmin();
if(db.findUser(newName) != null || newName.equals(user.getName())) {
throw Message.getSQLException(Message.USER_ALREADY_EXISTS_1, newName);
}
db.renameDatabaseObject(session, user, newName);
break;
case ADMIN:
session.getUser().checkAdmin();
user.setAdmin(admin);
break;
default:
throw Message.getInternalError("type="+type);
}
db.update(session, user);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.table.TableView;
public class AlterView extends DefineCommand {
private TableView view;
public AlterView(Session session) {
super(session);
}
public void setView(TableView view) {
this.view= view;
}
public int update() throws SQLException {
session.commit();
session.getUser().checkRight(view, Right.ALL);
view.recompile(session);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.result.LocalResult;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.table.TableData;
import org.h2.util.ObjectArray;
public class Analyze extends DefineCommand {
private int sampleRows = Constants.SELECTIVITY_ANALYZE_SAMPLE_ROWS;
public Analyze(Session session) {
super(session);
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
session.getUser().checkAdmin();
ObjectArray tables = db.getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
// TODO do we need to lock the table?
for(int i=0; i<tables.size(); i++) {
Table table = (Table) tables.get(i);
if(!(table instanceof TableData)) {
continue;
}
Column[] columns = table.getColumns();
StringBuffer buff = new StringBuffer();
buff.append("SELECT ");
for(int j=0; j<columns.length; j++) {
if(j>0) {
buff.append(", ");
}
buff.append("SELECTIVITY(");
buff.append(columns[j].getSQL());
buff.append(")");
}
buff.append(" FROM ");
buff.append(table.getSQL());
if(sampleRows > 0) {
buff.append(" LIMIT 1 SAMPLE_SIZE ");
buff.append(sampleRows);
}
String sql = buff.toString();
Prepared command = session.prepare(sql);
LocalResult result = command.query(0);
result.next();
for(int j=0; j<columns.length; j++) {
int selectivity = result.currentRow()[j].getInt();
columns[j].setSelectivity(selectivity);
}
db.update(session, table);
}
return 0;
}
public void setTop(int top) {
this.sampleRows = top;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.message.Message;
import org.h2.schema.Constant;
import org.h2.schema.Schema;
import org.h2.value.Value;
public class CreateConstant extends SchemaCommand {
private String constantName;
private Expression expression;
private boolean ifNotExists;
public CreateConstant(Session session, Schema schema) {
super(session, schema);
}
public void setIfNotExists(boolean ifNotExists) {
// TODO constant: if exists - probably better use 'or replace'
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
session.commit();
session.getUser().checkAdmin();
Database db = session.getDatabase();
if(getSchema().findConstant(constantName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.CONSTANT_ALREADY_EXISTS_1,
constantName);
}
int id = getObjectId(false, true);
Constant constant = new Constant(getSchema(), id, constantName);
expression = expression.optimize(session);
Value value = expression.getValue(session);
constant.setValue(value);
db.addSchemaObject(session, constant);
return 0;
}
public void setConstantName(String constantName) {
this.constantName = constantName;
}
public void setExpression(Expression expr) {
this.expression = expr;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.FunctionAlias;
import org.h2.engine.Session;
import org.h2.message.Message;
public class CreateFunctionAlias extends DefineCommand {
private String aliasName;
private String javaClassMethod;
private boolean ifNotExists;
public CreateFunctionAlias(Session session) {
super(session);
}
public int update() throws SQLException {
session.commit();
session.getUser().checkAdmin();
Database db = session.getDatabase();
if(db.findFunctionAlias(aliasName) != null) {
if(!ifNotExists) {
throw Message.getSQLException(Message.FUNCTION_ALIAS_ALREADY_EXISTS_1, aliasName);
}
} else {
int id = getObjectId(false, true);
FunctionAlias functionAlias = new FunctionAlias(db, id, aliasName, javaClassMethod);
db.addDatabaseObject(session, functionAlias);
}
return 0;
}
public void setAliasName(String name) {
this.aliasName = name;
}
public void setJavaClassMethod(String string) {
this.javaClassMethod = string;
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.index.IndexType;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Column;
import org.h2.table.Table;
/**
* @author Thomas
*/
public class CreateIndex extends SchemaCommand {
private String tableName;
private String indexName;
private String[] columnNames;
private boolean primaryKey, unique, hash;
private boolean ifNotExists;
private String comment;
public CreateIndex(Session session, Schema schema) {
super(session, schema);
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public void setColumnNames(String[] columnNames) {
this.columnNames = columnNames;
}
public boolean getPrimaryKey() {
return primaryKey;
}
public String[] getColumnNames() {
return columnNames;
}
public int update() throws SQLException {
// TODO cancel: may support for index creation
session.commit();
Database db = session.getDatabase();
boolean persistent = db.isPersistent();
Table table = getSchema().getTableOrView(session, tableName);
session.getUser().checkRight(table, Right.ALL);
table.lock(session, true);
if(!table.isPersistent()) {
persistent = false;
}
int id = getObjectId(true, false);
if(indexName == null) {
indexName = getSchema().getUniqueIndexName("INDEX_");
}
if(getSchema().findIndex(indexName) != null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.INDEX_ALREADY_EXISTS_1, indexName);
}
IndexType indexType;
if(primaryKey) {
if(table.findPrimaryKey() != null) {
throw Message.getSQLException(Message.SECOND_PRIMARY_KEY);
}
indexType = IndexType.createPrimaryKey(persistent, hash);
} else if(unique) {
indexType = IndexType.createUnique(persistent, hash);
} else {
indexType = IndexType.createNonUnique(persistent);
}
Column[] columns = table.getColumns(columnNames);
table.addIndex(session, indexName, id, columns, indexType, headPos, comment);
return 0;
}
public void setPrimaryKey(boolean b) {
this.primaryKey = b;
}
public void setUnique(boolean b) {
this.unique = b;
}
public void setHash(boolean b) {
this.hash = b;
}
public boolean getHash() {
return hash;
}
public void setComment(String comment) {
this.comment = comment;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.TableLink;
/**
* @author Thomas
*/
public class CreateLinkedTable extends SchemaCommand {
private String tableName;
private String driver, url, user, password, originalTable;
private boolean ifNotExists;
private String comment;
public CreateLinkedTable(Session session, Schema schema) {
super(session, schema);
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public void setDriver(String driver) {
this.driver = driver;
}
public void setOriginalTable(String originalTable) {
this.originalTable = originalTable;
}
public void setPassword(String password) {
this.password = password;
}
public void setUrl(String url) {
this.url = url;
}
public void setUser(String user) {
this.user = user;
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
session.getUser().checkAdmin();
if(getSchema().findTableOrView(session, tableName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.TABLE_OR_VIEW_ALREADY_EXISTS_1,
tableName);
}
int id = getObjectId(false, true);
TableLink table = new TableLink(getSchema(), id, tableName, driver, url, user, password, originalTable);
table.setComment(comment);
db.addSchemaObject(session, table);
return 0;
}
public void setComment(String comment) {
this.comment = comment;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Role;
import org.h2.engine.Session;
import org.h2.message.Message;
public class CreateRole extends DefineCommand {
private String roleName;
private boolean ifNotExists;
public CreateRole(Session session) {
super(session);
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public void setRoleName(String name) {
this.roleName = name;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
if(db.findUser(roleName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.USER_ALREADY_EXISTS_1, roleName);
}
if(db.findRole(roleName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.ROLE_ALREADY_EXISTS_1, roleName);
}
int id = getObjectId(false, true);
Role role = new Role(db, id, roleName, false);
db.addDatabaseObject(session, role);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.message.Message;
import org.h2.schema.Schema;
public class CreateSchema extends DefineCommand {
private String schemaName;
private String authorization;
private boolean ifNotExists;
public CreateSchema(Session session) {
super(session);
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
User user = db.getUser(authorization);
user.checkAdmin();
if(db.findSchema(schemaName) != null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.SCHEMA_ALREADY_EXISTS_1, schemaName);
}
int id = getObjectId(true, true);
Schema schema = new Schema(db, id, schemaName, user, false);
db.addDatabaseObject(session, schema);
return 0;
}
public void setSchemaName(String name) {
this.schemaName = name;
}
public void setAuthorization(String userName) {
this.authorization = userName;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.schema.Sequence;
public class CreateSequence extends SchemaCommand {
private String sequenceName;
private boolean ifNotExists;
private long start = 1;
private long increment = 1;
private boolean belongsToTable;
public CreateSequence(Session session, Schema schema) {
super(session, schema);
}
public void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
if(getSchema().findSequence(sequenceName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.SEQUENCE_ALREADY_EXISTS_1, sequenceName);
}
int id = getObjectId(false, true);
Sequence sequence = new Sequence(getSchema(), id, sequenceName, belongsToTable);
sequence.setStartValue(start);
sequence.setIncrement(increment);
db.addSchemaObject(session, sequence);
return 0;
}
public void setStartWith(long start) {
this.start = start;
}
public void setIncrement(long increment) {
this.increment = increment;
}
public boolean getBelongsToTable() {
return belongsToTable;
}
public void setBelongsToTable(boolean belongsToTable) {
this.belongsToTable = belongsToTable;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.command.dml.Insert;
import org.h2.command.dml.Query;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.index.Index;
import org.h2.index.IndexType;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.schema.Sequence;
import org.h2.table.Column;
import org.h2.table.TableData;
import org.h2.util.ObjectArray;
/**
* @author Thomas
*/
public class CreateTable extends SchemaCommand {
private String tableName;
private ObjectArray constraintCommands = new ObjectArray();
private ObjectArray columns = new ObjectArray();
private String[] pkColumnNames;
private boolean ifNotExists;
private boolean persistent = true;
private boolean hashPrimaryKey;
private ObjectArray sequences;
private boolean temporary;
private boolean globalTemporary;
private boolean onCommitDrop;
private boolean onCommitTruncate;
private Query asQuery;
private String comment;
public CreateTable(Session session, Schema schema) {
super(session, schema);
}
public void setQuery(Query query) {
this.asQuery = query;
}
public void setTemporary(boolean temporary) {
this.temporary = temporary;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public void addColumn(Column column) {
columns.add(column);
}
public void addConstraintCommand(Prepared command) throws SQLException {
if(command instanceof CreateIndex) {
CreateIndex create = (CreateIndex) command;
if(create.getPrimaryKey()) {
setPrimaryKeyColumnNames(create.getColumnNames());
setHashPrimaryKey(create.getHash());
} else {
constraintCommands.add(command);
}
} else {
constraintCommands.add(command);
}
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
// TODO rights: what rights are required to create a table?
session.commit();
Database db = session.getDatabase();
if(!db.isPersistent()) {
persistent = false;
}
if(getSchema().findTableOrView(session, tableName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.TABLE_OR_VIEW_ALREADY_EXISTS_1, tableName);
}
if(asQuery != null) {
generateColumnFromQuery();
}
if (pkColumnNames != null) {
int len = pkColumnNames.length;
for(int i=0; i<columns.size(); i++) {
Column c = (Column) columns.get(i);
for(int j=0; j<len; j++) {
if(c.getName().equals(pkColumnNames[j])) {
c.setNullable(false);
}
}
}
}
sequences = new ObjectArray();
for(int i=0; i<columns.size(); i++) {
Column c = (Column) columns.get(i);
if(c.getAutoIncrement()) {
int objId = getObjectId(true, true);
c.convertAutoIncrementToSequence(session, getSchema(), objId);
}
Sequence seq = c.getSequence();
if(seq != null) {
sequences.add(seq);
}
}
int id = getObjectId(true, true);
TableData table = new TableData(getSchema(), tableName, id, columns, persistent);
table.setComment(comment);
table.setTemporary(temporary);
table.setGlobalTemporary(globalTemporary);
if(temporary && !globalTemporary) {
if(onCommitDrop) {
table.setOnCommitDrop(true);
}
if(onCommitTruncate) {
table.setOnCommitTruncate(true);
}
session.addLocalTempTable(table);
} else {
db.addSchemaObject(session, table);
}
try {
for(int i=0; i<columns.size(); i++) {
Column c = (Column) columns.get(i);
c.prepareExpression(session);
}
if (pkColumnNames != null) {
Column[] pk =table.getColumns(pkColumnNames);
int indexId = getObjectId(true, false);
table.addIndex(session, null, indexId, pk, IndexType.createPrimaryKey(persistent, hashPrimaryKey), Index.EMPTY_HEAD, null);
}
for(int i=0; i<sequences.size(); i++) {
Sequence sequence = (Sequence) sequences.get(i);
table.addSequence(sequence);
}
for(int i=0; i<constraintCommands.size(); i++) {
Prepared command = (Prepared) constraintCommands.get(i);
command.update();
}
if(asQuery != null) {
Insert insert = new Insert(session);
insert.setTable(table);
insert.setQuery(asQuery);
insert.prepare();
insert.update();
}
} catch(SQLException e) {
db.checkPowerOff();
db.removeSchemaObject(session, table);
throw e;
}
return 0;
}
private void generateColumnFromQuery() throws SQLException {
asQuery.prepare();
int columnCount = asQuery.getColumnCount();
ObjectArray expressions = asQuery.getExpressions();
for(int i=0; i<columnCount; i++) {
Expression expr = (Expression) expressions.get(i);
int type = expr.getType();
String name = expr.getColumnName();
long precision = expr.getPrecision();
int scale = expr.getScale();
Column col = new Column(name, type, precision, scale);
addColumn(col);
}
}
public void setPrimaryKeyColumnNames(String[] colNames) throws SQLException {
if(pkColumnNames != null) {
if(colNames.length != pkColumnNames.length) {
throw Message.getSQLException(Message.SECOND_PRIMARY_KEY);
}
for(int i=0; i<colNames.length; i++) {
if(!colNames[i].equals(pkColumnNames[i])) {
throw Message.getSQLException(Message.SECOND_PRIMARY_KEY);
}
}
}
this.pkColumnNames = colNames;
}
public void setPersistent(boolean persistent) {
this.persistent = persistent;
}
public void setHashPrimaryKey(boolean b) {
this.hashPrimaryKey = b;
}
public void setGlobalTemporary(boolean globalTemporary) {
this.globalTemporary = globalTemporary;
}
public void setOnCommitDrop() {
this.onCommitDrop = true;
}
public void setOnCommitTruncate() {
this.onCommitTruncate = true;
}
public void setComment(String comment) {
this.comment = comment;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.schema.TriggerObject;
import org.h2.table.Table;
/**
* @author Thomas
*/
public class CreateTrigger extends SchemaCommand {
// TODO implement drop trigger
private String triggerName;
private boolean ifNotExists;
private boolean before;
private int typeMask;
private boolean rowBased;
private int queueSize = TriggerObject.DEFAULT_QUEUE_SIZE;
private boolean noWait;
private String tableName;
private String triggerClassName;
public CreateTrigger(Session session, Schema schema) {
super(session, schema);
}
public void setBefore(boolean before) {
this.before = before;
}
public void setTriggerClassName(String triggerClassName) {
this.triggerClassName = triggerClassName;
}
public void setTypeMask(int typeMask) {
this.typeMask = typeMask;
}
public void setRowBased(boolean rowBased) {
this.rowBased = rowBased;
}
public void setQueueSize(int size) {
this.queueSize = size;
}
public void setNoWait(boolean noWait) {
this.noWait = noWait;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public void setTriggerName(String name) {
this.triggerName = name;
}
public void setIfNotExists(boolean ifNotExists) {
// TODO trigger: if exists - probably better use 'or replace'
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
// TODO rights: what rights are required to create a trigger?
session.commit();
Database db = session.getDatabase();
if(getSchema().findTrigger(triggerName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.TRIGGER_ALREADY_EXISTS_1,
triggerName);
}
int id = getObjectId(false, true);
Table table = getSchema().getTableOrView(session, tableName);
TriggerObject trigger = new TriggerObject(getSchema(), id, triggerName, table);
trigger.setBefore(before);
trigger.setNoWait(noWait);
trigger.setQueueSize(queueSize);
trigger.setRowBased(rowBased);
trigger.setTriggerClassName(session, triggerClassName);
trigger.setTypeMask(typeMask);
db.addSchemaObject(session, trigger);
table.addTrigger(trigger);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.message.Message;
import org.h2.security.SHA256;
import org.h2.util.ByteUtils;
public class CreateUser extends DefineCommand {
private String userName;
private boolean admin;
private byte[] userPasswordHash;
private byte[] salt;
private byte[] hash;
private boolean ifNotExists;
private String comment;
public CreateUser(Session session) {
super(session);
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
SHA256 sha = new SHA256();
this.userPasswordHash = sha.getKeyPasswordHash(userName, password.toCharArray());
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
if(db.findUser(userName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.USER_ALREADY_EXISTS_1, userName);
}
int id = getObjectId(false, true);
User user = new User(db, id, userName, false);
user.setAdmin(admin);
user.setComment(comment);
if(hash!=null && salt !=null) {
user.setSaltAndHash(salt, hash);
} else {
user.setUserPasswordHash(userPasswordHash);
}
db.addDatabaseObject(session, user);
return 0;
}
public void setSalt(String s) throws SQLException {
salt = ByteUtils.convertStringToBytes(s);
}
public void setHash(String s) throws SQLException {
hash = ByteUtils.convertStringToBytes(s);
}
public void setAdmin(boolean b) {
admin = b;
}
public void setComment(String comment) {
this.comment = comment;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.UserDataType;
import org.h2.message.Message;
import org.h2.table.Column;
public class CreateUserDataType extends DefineCommand {
private String typeName;
private Column column;
private boolean ifNotExists;
public CreateUserDataType(Session session) {
super(session);
}
public void setTypeName(String name) {
this.typeName = name;
}
public void setColumn(Column column) {
this.column = column;
}
public void setIfNotExists(boolean ifNotExists) {
// TODO user data type: if exists - probably better use 'or replace'
this.ifNotExists = ifNotExists;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
session.getUser().checkAdmin();
if(db.findUserDataType(typeName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.USER_DATA_TYPE_ALREADY_EXISTS_1,
typeName);
}
int id = getObjectId(false, true);
UserDataType type = new UserDataType(db, id, typeName);
type.setColumn(column);
db.addDatabaseObject(session, type);
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.command.dml.Query;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.TableView;
public class CreateView extends SchemaCommand {
private Query select;
private String viewName;
private boolean ifNotExists;
private boolean force;
private String selectSQL;
private String[] columnNames;
private String comment;
public CreateView(Session session, Schema schema) {
super(session, schema);
}
public void setViewName(String name) {
viewName = name;
}
public void setSelect(Query select) {
this.select = select;
}
public int update() throws SQLException {
// TODO rights: what rights are required to create a view?
session.commit();
Database db = session.getDatabase();
if(getSchema().findTableOrView(session, viewName)!=null) {
if (ifNotExists) {
return 0;
}
throw Message.getSQLException(Message.VIEW_ALREADY_EXISTS_1,
viewName);
}
int id = getObjectId(true, true);
String querySQL;
if(select == null && force) {
querySQL = selectSQL;
} else {
querySQL = select.getSQL();
}
TableView view = new TableView(getSchema(), id, viewName, querySQL, null, columnNames, session);
view.setComment(comment);
db.addSchemaObject(session, view);
return 0;
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
public void setForce(boolean force) {
this.force = force;
}
public void setSelectSQL(String selectSQL) {
this.selectSQL = selectSQL;
}
public void setColumnNames(String[] cols) {
this.columnNames = cols;
}
public void setComment(String comment) {
this.comment = comment;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import org.h2.command.Prepared;
import org.h2.engine.Session;
public abstract class DefineCommand extends Prepared {
public DefineCommand(Session session) {
super(session);
}
public boolean isTransactional() {
return false;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Constant;
import org.h2.schema.Schema;
public class DropConstant extends SchemaCommand {
private String constantName;
private boolean ifExists;
public DropConstant(Session session, Schema schema) {
super(session, schema);
}
public void setIfExists(boolean b) {
ifExists = b;
}
public void setConstantName(String constantName) {
this.constantName = constantName;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
Constant constant = getSchema().findConstant(constantName);
if(constant == null) {
if(!ifExists) {
throw Message.getSQLException(Message.CONSTANT_NOT_FOUND_1, constantName);
}
} else {
db.removeSchemaObject(session, constant);
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.schema.Schema;
import org.h2.schema.SchemaObject;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
public class DropDatabase extends DefineCommand {
private boolean dropAllObjects;
private boolean deleteFiles;
public DropDatabase(Session session) {
super(session);
}
public int update() throws SQLException {
if(dropAllObjects) {
dropAllObjects();
}
if(deleteFiles) {
session.getDatabase().setDeleteFilesOnDisconnect(true);
}
return 0;
}
private void dropAllObjects() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
ObjectArray list;
// TODO local temp tables are not removed
list = db.getAllSchemas();
for(int i=0; i<list.size(); i++) {
Schema schema = (Schema) list.get(i);
if(schema.canDrop()) {
db.removeDatabaseObject(session, schema);
}
}
list = db.getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
for(int i=0; i<list.size(); i++) {
Table t = (Table) list.get(i);
if(t.getName() != null && Table.VIEW.equals(t.getTableType())) {
db.removeSchemaObject(session, t);
}
}
for(int i=0; i<list.size(); i++) {
Table t = (Table) list.get(i);
if(t.getName() != null && Table.TABLE_LINK.equals(t.getTableType())) {
db.removeSchemaObject(session, t);
}
}
for(int i=0; i<list.size(); i++) {
Table t = (Table) list.get(i);
if(t.getName() != null && Table.TABLE.equals(t.getTableType())) {
db.removeSchemaObject(session, t);
}
}
list = db.getAllSchemaObjects(DbObject.SEQUENCE);
// maybe constraints and triggers on system tables will be allowed in the future
list.addAll(db.getAllSchemaObjects(DbObject.CONSTRAINT));
list.addAll(db.getAllSchemaObjects(DbObject.TRIGGER));
for(int i=0; i<list.size(); i++) {
SchemaObject obj = (SchemaObject) list.get(i);
db.removeSchemaObject(session, obj);
}
list = db.getAllUsers();
for(int i=0; i<list.size(); i++) {
User user = (User) list.get(i);
if(user != session.getUser()) {
db.removeDatabaseObject(session, user);
}
}
list = db.getAllRoles();
list.addAll(db.getAllRights());
list.addAll(db.getAllFunctionAliases());
for(int i=0; i<list.size(); i++) {
DbObject obj = (DbObject) list.get(i);
db.removeDatabaseObject(session, obj);
}
}
public void setDropAllObjects(boolean b) {
this.dropAllObjects = b;
}
public void setDeleteFiles(boolean b) {
this.deleteFiles = b;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.FunctionAlias;
import org.h2.engine.Session;
import org.h2.message.Message;
public class DropFunctionAlias extends DefineCommand {
private String aliasName;
private boolean ifExists;
public DropFunctionAlias(Session session) {
super(session);
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
FunctionAlias functionAlias = db.findFunctionAlias(aliasName);
if(functionAlias == null) {
if(!ifExists) {
throw Message.getSQLException(Message.FUNCTION_ALIAS_NOT_FOUND_1, aliasName);
}
} else {
db.removeDatabaseObject(session, functionAlias);
}
return 0;
}
public void setAliasName(String name) {
this.aliasName = name;
}
public void setIfExists(boolean ifExists) {
this.ifExists = ifExists;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.constraint.Constraint;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.index.Index;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
/**
* @author Thomas
*/
public class DropIndex extends SchemaCommand {
private String indexName;
private boolean ifExists;
public DropIndex(Session session, Schema schema) {
super(session, schema);
}
public void setIfExists(boolean b) {
ifExists = b;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
Index index = getSchema().findIndex(indexName);
if(index == null) {
if(!ifExists) {
throw Message.getSQLException(Message.INDEX_NOT_FOUND_1, indexName);
}
} else {
Table table = index.getTable();
ObjectArray constraints = table.getConstraints();
for(int i=0; constraints != null && i<constraints.size(); i++) {
Constraint cons = (Constraint) constraints.get(i);
if(cons.usesIndex(index)) {
throw Message.getSQLException(Message.INDEX_BELONGS_TO_CONSTRAINT_1, indexName);
}
}
session.getUser().checkRight(index.getTable(), Right.ALL);
index.getTable().setModified();
db.removeSchemaObject(session, index);
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Role;
import org.h2.engine.Session;
import org.h2.message.Message;
public class DropRole extends DefineCommand {
private String roleName;
private boolean ifExists;
public DropRole(Session session) {
super(session);
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
if(roleName.equals(Constants.PUBLIC_ROLE_NAME)) {
throw Message.getSQLException(Message.ROLE_CAN_NOT_BE_DROPPED_1, roleName);
}
Role role = db.findRole(roleName);
if(role == null) {
if(!ifExists) {
throw Message.getSQLException(Message.ROLE_NOT_FOUND_1, roleName);
}
} else {
db.removeDatabaseObject(session, role);
}
return 0;
}
public void setIfExists(boolean ifExists) {
this.ifExists = ifExists;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
public class DropSchema extends DefineCommand {
private String schemaName;
private boolean ifExists;
public DropSchema(Session session) {
super(session);
}
public void setSchemaName(String name) {
this.schemaName = name;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
Schema schema = db.findSchema(schemaName);
if(schema == null) {
if(!ifExists) {
throw Message.getSQLException(Message.SCHEMA_NOT_FOUND_1, schemaName);
}
} else {
if(!schema.canDrop()) {
throw Message.getSQLException(Message.SCHEMA_CAN_NOT_BE_DROPPED_1, schemaName);
}
db.removeDatabaseObject(session, schema);
}
return 0;
}
public void setIfExists(boolean ifExists) {
this.ifExists = ifExists;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.schema.Sequence;
public class DropSequence extends SchemaCommand {
private String sequenceName;
private boolean ifExists;
public DropSequence(Session session, Schema schema) {
super(session, schema);
}
public void setIfExists(boolean b) {
ifExists = b;
}
public void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
public int update() throws SQLException {
// TODO rights: what are the rights required for a sequence?
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
Sequence sequence = getSchema().findSequence(sequenceName);
if(sequence == null) {
if(!ifExists) {
throw Message.getSQLException(Message.SEQUENCE_NOT_FOUND_1, sequenceName);
}
} else {
if(sequence.getBelongsToTable()) {
throw Message.getSQLException(Message.SEQUENCE_BELONGS_TO_A_TABLE_1, sequenceName);
}
db.removeSchemaObject(session, sequence);
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Table;
/**
* @author Thomas
*/
public class DropTable extends SchemaCommand {
private boolean ifExists;
private String tableName;
private Table table;
private DropTable next;
public DropTable(Session session, Schema schema) {
super(session, schema);
}
public void addNextDropTable(DropTable next) {
if(this.next == null) {
this.next = next;
} else {
this.next.addNextDropTable(next);
}
}
public void setIfExists(boolean b) {
ifExists = b;
if(next != null) {
next.setIfExists(b);
}
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
private void prepareDrop() throws SQLException {
table = getSchema().findTableOrView(session, tableName);
// TODO drop table: drops views as well (is this ok?)
if(table == null) {
if(!ifExists) {
throw Message.getSQLException(Message.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
} else {
session.getUser().checkRight(table, Right.ALL);
if(!table.canDrop()) {
throw Message.getSQLException(Message.CANT_DROP_TABLE_1, tableName);
}
table.lock(session, true);
}
if(next != null) {
next.prepareDrop();
}
}
private void executeDrop() throws SQLException {
// need to get the table again, because it may be dropped already meanwhile (dependent object, or same object)
table = getSchema().findTableOrView(session, tableName);
if(table != null) {
table.setModified();
Database db = session.getDatabase();
db.removeSchemaObject(session, table);
}
if(next != null) {
next.executeDrop();
}
}
public int update() throws SQLException {
session.commit();
prepareDrop();
executeDrop();
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.schema.TriggerObject;
import org.h2.table.Table;
public class DropTrigger extends SchemaCommand {
private String triggerName;
private boolean ifExists;
public DropTrigger(Session session, Schema schema) {
super(session, schema);
}
public void setIfExists(boolean b) {
ifExists = b;
}
public void setTriggerName(String triggerName) {
this.triggerName = triggerName;
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
TriggerObject trigger = getSchema().findTrigger(triggerName);
if(trigger == null) {
if(!ifExists) {
throw Message.getSQLException(Message.TRIGGER_NOT_FOUND_1, triggerName);
}
} else {
Table table = trigger.getTable();
session.getUser().checkRight(table, Right.ALL);
db.removeSchemaObject(session, trigger);
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.message.Message;
public class DropUser extends DefineCommand {
private boolean ifExists;
private String userName;
public DropUser(Session session) {
super(session);
}
public void setIfExists(boolean b) {
ifExists = b;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
User user = db.findUser(userName);
if(user == null) {
if(!ifExists) {
throw Message.getSQLException(Message.USER_NOT_FOUND_1, userName);
}
} else {
if(user == session.getUser()) {
throw Message.getSQLException(Message.CANT_DROP_CURRENT_USER);
}
db.removeDatabaseObject(session, user);
}
return 0;
}
public boolean isTransactional() {
return false;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.UserDataType;
import org.h2.message.Message;
public class DropUserDataType extends DefineCommand {
private String typeName;
private boolean ifExists;
public DropUserDataType(Session session) {
super(session);
}
public void setIfExists(boolean ifExists) {
this.ifExists = ifExists;
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
UserDataType type = db.findUserDataType(typeName);
if(type == null) {
if(!ifExists) {
throw Message.getSQLException(Message.USER_DATA_TYPE_NOT_FOUND_1, typeName);
}
} else {
db.removeDatabaseObject(session, type);
}
return 0;
}
public void setTypeName(String name) {
this.typeName = name;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Table;
public class DropView extends SchemaCommand {
private String viewName;
private boolean ifExists;
public DropView(Session session, Schema schema) {
super(session, schema);
}
public void setIfExists(boolean b) {
ifExists = b;
}
public void setViewName(String viewName) {
this.viewName = viewName;
}
public int update() throws SQLException {
// TODO rights: what rights are required to drop a view?
session.commit();
Table view = getSchema().findTableOrView(session, viewName);
if(view == null) {
if(!ifExists) {
throw Message.getSQLException(Message.VIEW_NOT_FOUND_1, viewName);
}
} else {
if(!view.getTableType().equals(Table.VIEW)) {
throw Message.getSQLException(Message.VIEW_NOT_FOUND_1, viewName);
}
session.getUser().checkRight(view, Right.ALL);
view.lock(session, true);
session.getDatabase().removeSchemaObject(session, view);
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Right;
import org.h2.engine.RightOwner;
import org.h2.engine.Role;
import org.h2.engine.Session;
import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
public class GrantRevoke extends DefineCommand {
public static final int GRANT = 0, REVOKE = 1;
private ObjectArray roleNames;
private int operationType;
private int rightMask;
private ObjectArray tables = new ObjectArray();
private RightOwner grantee;
public GrantRevoke(Session session) {
super(session);
}
public void setOperationType(int operationType) {
this.operationType = operationType;
}
public void addRight(int right) {
this.rightMask |= right;
}
public void addRoleName(String roleName) {
if(roleNames == null) {
roleNames = new ObjectArray();
}
roleNames.add(roleName);
}
public void setGranteeName(String granteeName) throws JdbcSQLException {
Database db = session.getDatabase();
grantee = db.findUser(granteeName);
if(grantee == null) {
grantee = db.findRole(granteeName);
if(grantee == null) {
throw Message.getSQLException(Message.USER_OR_ROLE_NOT_FOUND_1, granteeName);
}
}
}
public int update() throws SQLException {
session.getUser().checkAdmin();
session.commit();
Database db = session.getDatabase();
if(roleNames != null) {
for(int i=0; i<roleNames.size(); i++) {
String name = (String) roleNames.get(i);
Role grantedRole = db.findRole(name);
if (grantedRole == null) {
throw Message.getSQLException(Message.ROLE_NOT_FOUND_1, name);
}
if(operationType == GRANT) {
grantRole(grantedRole);
} else if (operationType == REVOKE) {
revokeRole(grantedRole);
} else {
throw Message.getInternalError("type="+operationType);
}
}
} else {
if(operationType == GRANT) {
grantRight();
} else if (operationType == REVOKE) {
revokeRight();
} else {
throw Message.getInternalError("type="+operationType);
}
}
return 0;
}
private void grantRight() throws SQLException {
Database db = session.getDatabase();
for(int i=0; i<tables.size(); i++) {
Table table = (Table) tables.get(i);
Right right = grantee.getRightForTable(table);
if(right == null) {
int id = getObjectId(true, true);
right = new Right(db, id, grantee, rightMask, table);
grantee.grantRight(table, right);
db.addDatabaseObject(session, right);
} else {
right.setRightMask(right.getRightMask() | rightMask);
}
}
}
private void grantRole(Role grantedRole) throws SQLException {
if(grantee.isRoleGranted(grantedRole)) {
throw Message.getSQLException(Message.ROLE_ALREADY_GRANTED_1, grantedRole.getSQL());
}
if(grantee instanceof Role) {
Role granteeRole = (Role) grantee;
if(grantedRole.isRoleGranted(granteeRole)) {
// TODO role: should be 'cyclic role grants are not allowed'
throw Message.getSQLException(Message.ROLE_ALREADY_GRANTED_1, grantedRole.getSQL());
}
}
Database db = session.getDatabase();
int id = getObjectId(true, true);
Right right = new Right(db, id, grantee, grantedRole);
db.addDatabaseObject(session, right);
grantee.grantRole(session, grantedRole, right);
}
private void revokeRight() throws SQLException {
for(int i=0; i<tables.size(); i++) {
Table table = (Table) tables.get(i);
Right right = grantee.getRightForTable(table);
if(right == null) {
throw Message.getSQLException(Message.RIGHT_NOT_FOUND);
}
int mask = right.getRightMask();
if((mask & rightMask) != rightMask) {
throw Message.getSQLException(Message.RIGHT_NOT_FOUND);
}
int newRight = mask ^ rightMask;
Database db = session.getDatabase();
if(newRight == 0) {
db.removeDatabaseObject(session, right);
} else {
right.setRightMask(newRight);
db.update(session, right);
}
}
}
private void revokeRole(Role grantedRole) throws SQLException {
Right right = grantee.getRightForRole(grantedRole);
if(right == null) {
throw Message.getSQLException(Message.RIGHT_NOT_FOUND);
}
Database db = session.getDatabase();
db.removeDatabaseObject(session, right);
}
public boolean isTransactional() {
return false;
}
public void addTable(Table table) {
tables.add(table);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Session;
import org.h2.schema.Schema;
public abstract class SchemaCommand extends DefineCommand {
private Schema schema;
public SchemaCommand(Session session, Schema schema) {
super(session);
this.schema = schema;
}
protected Schema getSchema() throws SQLException {
return schema;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Comment;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.message.Message;
import org.h2.table.Table;
public class SetComment extends DefineCommand {
private String schemaName;
private String objectName;
private boolean column;
private String columnName;
private int objectType;
private Expression expr;
public SetComment(Session session) {
super(session);
}
public int update() throws SQLException {
session.commit();
Database db = session.getDatabase();
session.getUser().checkAdmin();
DbObject object = null;
int errorCode = Message.GENERAL_ERROR_1;
if(schemaName == null) {
schemaName = session.getCurrentSchemaName();
}
switch(objectType) {
case DbObject.CONSTANT:
object = db.getSchema(schemaName).getConstant(session, objectName);
break;
case DbObject.CONSTRAINT:
object = db.getSchema(schemaName).getConstraint(objectName);
break;
case DbObject.FUNCTION_ALIAS:
schemaName = null;
object = db.findFunctionAlias(objectName);
errorCode = Message.FUNCTION_ALIAS_NOT_FOUND_1;
break;
case DbObject.INDEX:
object = db.getSchema(schemaName).getIndex(objectName);
break;
case DbObject.ROLE:
schemaName = null;
object = db.findRole(objectName);
errorCode = Message.ROLE_NOT_FOUND_1;
break;
case DbObject.SCHEMA:
schemaName = null;
object = db.findSchema(objectName);
errorCode = Message.SCHEMA_NOT_FOUND_1;
break;
case DbObject.SEQUENCE:
object = db.getSchema(schemaName).getSequence(objectName);
break;
case DbObject.TABLE_OR_VIEW:
object = db.getSchema(schemaName).getTableOrView(session, objectName);
break;
case DbObject.TRIGGER:
object = db.getSchema(schemaName).findTrigger(objectName);
errorCode = Message.TRIGGER_NOT_FOUND_1;
break;
case DbObject.USER:
schemaName = null;
object = db.getUser(objectName);
break;
case DbObject.USER_DATATYPE:
schemaName = null;
object = db.findUserDataType(objectName);
errorCode = Message.USER_DATA_TYPE_ALREADY_EXISTS_1;
break;
}
if(object == null) {
throw Message.getSQLException(errorCode, objectName);
}
String text = expr.getValue(session).getString();
if(column) {
Table table = (Table) object;
table.getColumn(columnName).setComment(text);
} else {
object.setComment(text);
}
if(column || objectType == DbObject.TABLE_OR_VIEW || objectType == DbObject.USER || objectType == DbObject.INDEX || objectType == DbObject.CONSTRAINT) {
db.update(session, object);
} else {
Comment comment = db.findComment(object);
if(comment == null) {
if(text == null) {
// reset a non-existing comment - nothing to do
} else {
int id = getObjectId(false, false);
comment = new Comment(db, id, object);
comment.setCommentText(text);
db.addDatabaseObject(session, comment);
}
} else {
if(text == null) {
db.removeDatabaseObject(session, comment);
} else {
comment.setCommentText(text);
db.update(session, comment);
}
}
}
return 0;
}
public void setCommentExpression(Expression expr) {
this.expr = expr;
}
public void setObjectName(String objectName) {
this.objectName = objectName;
}
public void setObjectType(int objectType) {
this.objectType = objectType;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public void setColumn(boolean column) {
this.column = column;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import java.sql.SQLException;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Table;
public class TruncateTable extends SchemaCommand {
private String tableName;
public TruncateTable(Session session, Schema schema) {
super(session, schema);
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public int update() throws SQLException {
session.commit();
Table table = getSchema().getTableOrView(session, tableName);
if(!table.canTruncate()) {
throw Message.getSQLException(Message.CANT_TRUNCATE_1, tableName);
} else {
session.getUser().checkRight(table, Right.DELETE);
table.lock(session, true);
table.truncate(session);
}
return 0;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.result.LocalResult;
import org.h2.table.Column;
import org.h2.util.ObjectArray;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueResultSet;
/**
* @author Thomas
*/
public class Call extends Prepared {
private Expression value;
private ObjectArray expressions;
public Call(Session session) {
super(session);
}
public LocalResult query(int maxrows) throws SQLException {
setCurrentRowNumber(1);
Value v = value.getValue(session);
if(v.getType() == Value.RESULT_SET) {
return LocalResult.read(session, ((ValueResultSet)v).getResultSet());
} else if(v.getType() == Value.ARRAY) {
Value[] list = ((ValueArray)v).getList();
ObjectArray expr = new ObjectArray();
for(int i = 0; i<list.length; i++) {
Value e = list[i];
Column col = new Column("C" + (i+1), e.getType(), e.getPrecision(), e.getScale());
expr.add(new ExpressionColumn(session.getDatabase(), null, col));
}
LocalResult result = new LocalResult(session, expr, list.length);
result.addRow(list);
result.done();
return result;
}
LocalResult result = new LocalResult(session, expressions, 1);
Value[] row = new Value[1];
row[0] = v;
result.addRow(row);
result.done();
return result;
}
public void prepare() throws SQLException {
value = value.optimize(session);
expressions = new ObjectArray();
expressions.add(value);
}
public void setValue(Expression expression) {
value = expression;
}
public boolean isQuery() {
return true;
}
public boolean isTransactional() {
return true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.result.Row;
import org.h2.store.UndoLogRecord;
import org.h2.table.PlanItem;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
/**
* @author Thomas
*/
public class Delete extends Prepared {
private Expression condition;
private TableFilter tableFilter;
public Delete(Session session) {
super(session);
}
public void setTableFilter(TableFilter tableFilter) {
this.tableFilter = tableFilter;
}
public void setCondition(Expression condition) {
this.condition = condition;
}
public int update() throws SQLException {
tableFilter.startQuery();
tableFilter.reset();
Table table = tableFilter.getTable();
session.getUser().checkRight(table, Right.DELETE);
table.fireBefore(session);
table.lock(session, true);
ObjectArray rows = new ObjectArray();
setCurrentRowNumber(0);
while (tableFilter.next()) {
checkCancelled();
setCurrentRowNumber(rows.size()+1);
if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
Row row = tableFilter.get();
rows.add(row);
}
}
if(table.fireRow()) {
for (int i = 0; i < rows.size(); i++) {
checkCancelled();
Row row = (Row) rows.get(i);
table.fireBeforeRow(session, row, null);
}
}
for (int i = 0; i < rows.size(); i++) {
checkCancelled();
Row row = (Row) rows.get(i);
table.removeRow(session, row);
session.log(new UndoLogRecord(table, UndoLogRecord.DELETE, row));
}
if(table.fireRow()) {
for (int i = 0; i < rows.size(); i++) {
checkCancelled();
Row row = (Row) rows.get(i);
table.fireAfterRow(session, row, null);
}
}
table.fireAfter(session);
return rows.size();
}
public String getPlan() {
StringBuffer buff = new StringBuffer();
buff.append("DELETE FROM ");
buff.append(tableFilter.getPlanSQL(false));
if(condition != null) {
buff.append("\nWHERE " + StringUtils.unEnclose(condition.getSQL()));
}
return buff.toString();
}
public void prepare() throws SQLException {
if (condition != null) {
condition.mapColumns(tableFilter, 0);
condition = condition.optimize(session);
condition.createIndexConditions(tableFilter);
}
PlanItem item = tableFilter.getBestPlanItem(session);
tableFilter.setPlanItem(item);
tableFilter.prepare();
}
public boolean isTransactional() {
return true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.engine.Session;
import org.h2.expression.ExpressionColumn;
import org.h2.result.LocalResult;
import org.h2.table.Column;
import org.h2.util.ObjectArray;
import org.h2.value.Value;
import org.h2.value.ValueString;
public class ExplainPlan extends Prepared {
private Prepared command;
private LocalResult result;
public ExplainPlan(Session session) {
super(session);
}
public void setCommand(Prepared command) {
this.command = command;
}
public void prepare() throws SQLException {
command.prepare();
}
public LocalResult query(int maxrows) throws SQLException {
// TODO rights: are rights required for explain?
ObjectArray expressions = new ObjectArray();
Column column = new Column("PLAN", Value.STRING, 0, 0);
ExpressionColumn expr = new ExpressionColumn(session.getDatabase(), null, column);
expressions.add(expr);
result = new LocalResult(session, expressions, 1);
String plan = command.getPlan();
add(plan);
result.done();
return result;
}
private void add(String text) throws SQLException {
Value[] row = new Value[1];
Value value = ValueString.get(text);
row[0] = value;
result.addRow(row);
}
public boolean isQuery() {
return true;
}
public boolean isTransactional() {
return true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.command.Command;
import org.h2.command.Prepared;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.message.Message;
import org.h2.result.LocalResult;
import org.h2.result.Row;
import org.h2.store.UndoLogRecord;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.Value;
/**
* @author Thomas
*/
public class Insert extends Prepared {
private Table table;
private Column[] columns;
private ObjectArray list = new ObjectArray();
private Query query;
public Insert(Session session) {
super(session);
}
public void setCommand(Command command) {
super.setCommand(command);
if(query != null) {
query.setCommand(command);
}
}
public void setTable(Table table) {
this.table = table;
}
public void setColumns(Column[] columns) {
this.columns = columns;
}
public void setQuery(Query query) {
this.query = query;
}
public void addRow(Expression[] expr) {
list.add(expr);
}
public int update() throws SQLException {
int count;
session.getUser().checkRight(table, Right.INSERT);
setCurrentRowNumber(0);
if(list.size() > 0) {
count = 0;
for(int x=0; x<list.size(); x++) {
Expression[] expr = (Expression[])list.get(x);
Row newRow = table.getTemplateRow();
setCurrentRowNumber(x+1);
for (int i = 0; i < columns.length; i++) {
Column c = columns[i];
int index = c.getColumnId();
Expression e = expr[i];
if(e != null) {
// e can be null (DEFAULT)
e = e.optimize(session);
Value v = e.getValue(session).convertTo(c.getType());
newRow.setValue(index, v);
}
}
// TODO insert: set default values before calling triggers?
checkCancelled();
table.fireBefore(session);
table.validateConvertUpdateSequence(session, newRow);
table.fireBeforeRow(session, null, newRow);
table.lock(session, true);
table.addRow(session, newRow);
session.log(new UndoLogRecord(table, UndoLogRecord.INSERT, newRow));
table.fireAfter(session);
table.fireAfterRow(session, null, newRow);
count++;
}
} else {
LocalResult rows = query.query(0);
count = 0;
table.fireBefore(session);
table.lock(session, true);
while(rows.next()) {
checkCancelled();
count++;
Value[] r = rows.currentRow();
Row newRow = table.getTemplateRow();
setCurrentRowNumber(count);
for (int j = 0; j < columns.length; j++) {
Column c = columns[j];
int index = c.getColumnId();
Value v = r[j].convertTo(c.getType());
newRow.setValue(index, v);
}
table.validateConvertUpdateSequence(session, newRow);
table.fireBeforeRow(session, null, newRow);
table.addRow(session, newRow);
session.log(new UndoLogRecord(table, UndoLogRecord.INSERT, newRow));
table.fireAfterRow(session, null, newRow);
}
rows.close();
table.fireAfter(session);
}
return count;
}
public String getPlan() {
StringBuffer buff = new StringBuffer();
buff.append("INSERT INTO ");
buff.append(table.getSQL());
buff.append('(');
for(int i=0; i<columns.length; i++) {
if(i>0) {
buff.append(", ");
}
buff.append(columns[i].getSQL());
}
buff.append(")\n");
if(list.size() > 0) {
buff.append("VALUES ");
for(int x=0; x<list.size(); x++) {
Expression[] expr = (Expression[])list.get(x);
if(x > 0) {
buff.append(", ");
}
buff.append("(");
for (int i = 0; i < columns.length; i++) {
if(i>0) {
buff.append(", ");
}
Expression e = expr[i];
if(e == null) {
buff.append("DEFAULT");
} else {
buff.append(StringUtils.unEnclose(e.getSQL()));
}
}
buff.append(')');
}
} else {
buff.append(query.getPlan());
}
return buff.toString();
}
public void prepare() throws SQLException {
if (columns == null) {
if(list.size() > 0 && ((Expression[])list.get(0)).length == 0) {
// special case where table is used as a sequence
columns = new Column[0];
} else {
columns = table.getColumns();
}
}
if(list.size() > 0) {
for(int x=0; x<list.size(); x++) {
Expression[] expr = (Expression[])list.get(x);
if(expr.length != columns.length) {
throw Message.getSQLException(Message.COLUMN_COUNT_DOES_NOT_MATCH);
}
for(int i=0; i<expr.length; i++) {
Expression e = expr[i];
if(e != null) {
expr[i] = e.optimize(session);
}
}
}
} else {
query.prepare();
if(query.getColumnCount() != columns.length) {
throw Message.getSQLException(Message.COLUMN_COUNT_DOES_NOT_MATCH);
}
}
}
public boolean isTransactional() {
return true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.command.Command;
import org.h2.command.Prepared;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.Parameter;
import org.h2.index.Index;
import org.h2.message.Message;
import org.h2.result.LocalResult;
import org.h2.result.Row;
import org.h2.store.UndoLogRecord;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.Value;
/**
* @author Thomas
*/
public class Merge extends Prepared {
private Table table;
private Column[] columns;
private Column[] keys;
private ObjectArray list = new ObjectArray();
private Query query;
private Prepared update;
public Merge(Session session) {
super(session);
}
public void setCommand(Command command) {
super.setCommand(command);
if(query != null) {
query.setCommand(command);
}
}
public void setTable(Table table) {
this.table = table;
}
public void setColumns(Column[] columns) {
this.columns = columns;
}
public void setKeys(Column[] keys) {
this.keys = keys;
}
public void setQuery(Query query) {
this.query = query;
}
public void addRow(Expression[] expr) {
list.add(expr);
}
public int update() throws SQLException {
int count;
session.getUser().checkRight(table, Right.INSERT);
session.getUser().checkRight(table, Right.UPDATE);
if(keys == null) {
Index idx = table.getPrimaryKey();
if(idx == null) {
throw Message.getSQLException(Message.CONSTRAINT_NOT_FOUND_1, "PRIMARY KEY");
}
keys = idx.getColumns();
}
StringBuffer buff = new StringBuffer("UPDATE ");
buff.append(table.getSQL());
buff.append(" SET ");
for(int i=0; i<columns.length; i++) {
if(i>0) {
buff.append(", ");
}
buff.append(columns[i].getSQL());
buff.append("=?");
}
buff.append(" WHERE ");
for(int i=0; i<keys.length; i++) {
if(i>0) {
buff.append(" AND ");
}
buff.append(keys[i].getSQL());
buff.append("=?");
}
String sql = buff.toString();
update = session.prepare(sql);
setCurrentRowNumber(0);
if(list.size() > 0) {
count = 0;
for(int x=0; x<list.size(); x++) {
setCurrentRowNumber(x+1);
Expression[] expr = (Expression[])list.get(x);
Row newRow = table.getTemplateRow();
for (int i = 0; i < columns.length; i++) {
Column c = columns[i];
int index = c.getColumnId();
Expression e = expr[i];
if(e != null) {
// e can be null (DEFAULT)
Value v = expr[i].getValue(session).convertTo(c.getType());
newRow.setValue(index, v);
}
}
merge(newRow);
count++;
}
} else {
LocalResult rows = query.query(0);
count = 0;
table.fireBefore(session);
table.lock(session, true);
while(rows.next()) {
checkCancelled();
count++;
Value[] r = rows.currentRow();
Row newRow = table.getTemplateRow();
setCurrentRowNumber(count);
for (int j = 0; j < columns.length; j++) {
Column c = columns[j];
int index = c.getColumnId();
Value v = r[j].convertTo(c.getType());
newRow.setValue(index, v);
}
merge(newRow);
}
rows.close();
table.fireAfter(session);
}
return count;
}
private void merge(Row row) throws SQLException {
ObjectArray k = update.getParameters();
for(int i=0; i<columns.length; i++) {
Column col = columns[i];
Value v = row.getValue(col.getColumnId());
Parameter p = (Parameter) k.get(i);
p.setValue(v);
}
for(int i=0; i<keys.length; i++) {
Column col = keys[i];
Value v = row.getValue(col.getColumnId());
if(v == null) {
throw Message.getSQLException(Message.COLUMN_CONTAINS_NULL_VALUES_1, col.getSQL());
}
Parameter p = (Parameter) k.get(columns.length + i);
p.setValue(v);
}
int count = update.update();
if(count == 0) {
table.fireBefore(session);
table.validateConvertUpdateSequence(session, row);
table.fireBeforeRow(session, null, row);
table.lock(session, true);
table.addRow(session, row);
session.log(new UndoLogRecord(table, UndoLogRecord.INSERT, row));
table.fireAfter(session);
table.fireAfterRow(session, null, row);
} else if(count != 1) {
throw Message.getSQLException(Message.DUPLICATE_KEY_1, table.getSQL());
}
}
public String getPlan() {
StringBuffer buff = new StringBuffer();
buff.append("MERGE INTO ");
buff.append(table.getSQL());
buff.append('(');
for(int i=0; i<columns.length; i++) {
if(i>0) {
buff.append(", ");
}
buff.append(columns[i].getSQL());
}
buff.append(")");
if(keys != null) {
buff.append(" KEY(");
for(int i=0; i<keys.length; i++) {
if(i>0) {
buff.append(", ");
}
buff.append(keys[i].getSQL());
}
buff.append(")");
}
buff.append('\n');
if(list.size() > 0) {
buff.append("VALUES ");
for(int x=0; x<list.size(); x++) {
Expression[] expr = (Expression[])list.get(x);
if(x > 0) {
buff.append(", ");
}
buff.append("(");
for (int i = 0; i < columns.length; i++) {
if(i>0) {
buff.append(", ");
}
Expression e = expr[i];
if(e == null) {
buff.append("DEFAULT");
} else {
buff.append(StringUtils.unEnclose(e.getSQL()));
}
}
buff.append(')');
}
} else {
buff.append(query.getPlan());
}
return buff.toString();
}
public void prepare() throws SQLException {
if (columns == null) {
if(list.size() > 0 && ((Expression[])list.get(0)).length == 0) {
// special case where table is used as a sequence
columns = new Column[0];
} else {
columns = table.getColumns();
}
}
if(list.size() > 0) {
for(int x=0; x<list.size(); x++) {
Expression[] expr = (Expression[])list.get(x);
if(expr.length != columns.length) {
throw Message.getSQLException(Message.COLUMN_COUNT_DOES_NOT_MATCH);
}
for(int i=0; i<expr.length; i++) {
Expression e = expr[i];
if(e != null) {
expr[i] = e.optimize(session);
}
}
}
} else {
query.prepare();
if(query.getColumnCount() != columns.length) {
throw Message.getSQLException(Message.COLUMN_COUNT_DOES_NOT_MATCH);
}
}
}
public boolean isTransactional() {
return true;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import org.h2.command.Prepared;
import org.h2.engine.Session;
public class NoOperation extends Prepared {
public NoOperation(Session session) {
super(session);
}
public int update() {
return 0;
}
public boolean isQuery() {
return false;
}
public boolean isTransactional() {
return true;
}
public boolean needRecompile() {
return false;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.sql.SQLException;
import java.util.BitSet;
import java.util.Enumeration;
import java.util.Random;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.table.Plan;
import org.h2.table.PlanItem;
import org.h2.table.TableFilter;
import org.h2.util.Permutations;
public class Optimizer {
private static final int MAX_BRUTE_FORCE_FILTERS=7;
private static final int MAX_BRUTE_FORCE=2000;
private static final int MAX_GENETIC=2000;
private long start;
private BitSet switched;
// possible plans for filters:
// 1 filter 1 plan
// 2 filters 2 plans
// 3 filters 6 plans
// 4 filters 24 plans
// 5 filters 120 plans
// 6 filters 720 plans
// 7 filters 5040 plans
// 8 filters 40320 plan
// 9 filters 362880 plans
// 10 filters 3628800 filters
// 1 of 1, 2, 3, 4, 5, 6 filters: 1, 2, 3, 4, 5, 6
// 2 of 2, 3, 4, 5, 6 filters: 2, 6, 12, 20, 30
// 3 of 3, 4, 5, 6 filters: 6, 24, 75, 120
// 4 of 4, 5, 6 filters: 24, 120, 260
private TableFilter[] filters;
private Expression condition;
private Session session;
private Plan bestPlan;
private TableFilter topFilter;
private double cost;
private Random random;
private int getMaxBruteForceFilters(int filterCount) {
int i = 0, j = filterCount, total = filterCount;
while(j>0 && total < MAX_BRUTE_FORCE) {
j--;
total *= j;
i++;
}
return i;
}
Optimizer(TableFilter[] filters, Expression condition, Session session) {
this.filters = filters;
this.condition = condition;
this.session = session;
}
private void calculateBestPlan() throws SQLException {
start = System.currentTimeMillis();
cost = -1;
if(filters.length==1) {
testPlan(filters);
} else if (filters.length <= MAX_BRUTE_FORCE_FILTERS) {
calculateBruteForceAll();
} else {
calculateBruteForceSome();
random = new Random(0);
calculateGenetic();
// TODO optimizer: how to use rule based optimizer?
}
}
private boolean canStop(int x) {
if((x & 127) == 0) {
long t = System.currentTimeMillis() - start;
// don't calculate for simple queries (no rows or so)
if(cost >= 0 && 10*t > cost) {
return true;
}
}
return false;
}
private void calculateBruteForceAll() throws SQLException {
Enumeration en = new Permutations(filters);
for(int x=0; en.hasMoreElements(); x++) {
if(canStop(x)) {
break;
}
Object[] f = (Object[]) en.nextElement();
TableFilter[] ftry = new TableFilter[filters.length];
System.arraycopy(f, 0, ftry, 0, filters.length);
testPlan(ftry);
}
}
private void calculateBruteForceSome() throws SQLException {
int bruteForce = getMaxBruteForceFilters(filters.length);
TableFilter[] ftry = new TableFilter[filters.length];
Enumeration en = new Permutations(filters, bruteForce);
for(int x=0; en.hasMoreElements(); x++) {
if(canStop(x)) {
break;
}
Object[] f = (Object[]) en.nextElement();
System.arraycopy(f, 0, ftry, 0, bruteForce);
// find out what filters are not used yet
for(int i=0; i<filters.length; i++) {
filters[i].setUsed(false);
}
for(int i=0; i<f.length; i++) {
ftry[i].setUsed(true);
}
// fill the remaining elements with the unused elements (greedy)
for(int i=bruteForce; i<filters.length; i++) {
double costPart = -1.0;
int bestPart = -1;
for(int j=0; j<filters.length; j++) {
if(!filters[j].getUsed()) {
if(i==filters.length-1) {
bestPart = j;
break;
}
ftry[i] = filters[j];
Plan part = new Plan(ftry, i+1, condition);
double costNow = part.calculateCost(session);
if (costPart < 0 || costNow < costPart) {
costPart = costNow;
bestPart = j;
}
}
}
filters[bestPart].setUsed(true);
ftry[i] = filters[bestPart];
}
testPlan(ftry);
}
}
private void calculateGenetic() throws SQLException {
TableFilter[] fbest = new TableFilter[filters.length];
TableFilter[] ftry = new TableFilter[filters.length];
for(int x=0; x<MAX_GENETIC; x++) {
if(canStop(x)) {
break;
}
boolean generateRandom = (x & 127) == 0;
if(!generateRandom) {
System.arraycopy(fbest, 0, ftry, 0, filters.length);
if(!shuffleTwo(ftry)) {
generateRandom = true;
}
}
if(generateRandom) {
switched = new BitSet();
System.arraycopy(filters, 0, fbest, 0, filters.length);
shuffleAll(fbest);
System.arraycopy(fbest, 0, ftry, 0, filters.length);
}
if(testPlan(ftry)) {
switched = new BitSet();
System.arraycopy(ftry, 0, fbest, 0, filters.length);
}
}
}
private boolean testPlan(TableFilter[] ftry) throws SQLException {
Plan p = new Plan(ftry, ftry.length, condition);
double costNow = p.calculateCost(session);
if (cost < 0 || costNow < cost) {
cost = costNow;
bestPlan = p;
return true;
}
return false;
}
private void shuffleAll(TableFilter[] f) {
for(int i=0; i<f.length-1; i++) {
int j = i + random.nextInt(f.length - i);
if(j != i) {
TableFilter temp = f[i];
f[i] = f[j];
f[j] = temp;
}
}
}
private boolean shuffleTwo(TableFilter[] f) {
int a = 0, b = 0, i = 0;
for(; i<20; i++) {
a = random.nextInt(f.length);
b = random.nextInt(f.length);
if(a==b) {
continue;
}
if(a<b) {
int temp = a;
a = b;
b = temp;
}
int s = a * f.length + b;
if(switched.get(s)) {
continue;
}
switched.set(s);
break;
}
if(i==20) {
return false;
}
TableFilter temp = f[a];
f[a] = f[b];
f[b] = temp;
return true;
}
void optimize() throws SQLException {
calculateBestPlan();
bestPlan.removeUnusableIndexConditions();
TableFilter[] f2 = bestPlan.getFilters();
topFilter = f2[0];
for (int i = 0; i < f2.length - 1; i++) {
f2[i].addJoin(f2[i + 1], false, null);
}
for (int i = 0; i < f2.length; i++) {
PlanItem item = bestPlan.getItem(f2[i]);
f2[i].setPlanItem(item);
}
}
public TableFilter getTopFilter() {
return topFilter;
}
double getCost() {
return cost;
}
}
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.SQLException;
import org.h2.command.Prepared;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.util.ScriptReader;
import org.h2.util.StringUtils;
public class RunScript extends ScriptBase {
private String charset = StringUtils.getDefaultCharset();
public RunScript(Session session) {
super(session);
}
public int update() throws SQLException {
session.getUser().checkAdmin();
int count = 0;
try {
openInput();
Reader reader = new InputStreamReader(in, charset);
ScriptReader r = new ScriptReader(reader);
while(true) {
String sql = r.readStatement();
if(sql == null) {
break;
}
execute(sql);
count++;
}
reader.close();
} catch(IOException e) {
throw Message.convert(e);
} finally {
closeIO();
}
return count;
}
private void execute(String sql) throws SQLException {
try {
Prepared command = session.prepare(sql);
if(command.isQuery()) {
command.query(0);
} else {
command.update();
}
if(session.getAutoCommit()) {
session.commit();
}
} catch(SQLException e) {
throw Message.addSQL(e, sql);
}
}
public void setCharset(String charset) {
this.charset = charset;
}
}
差异被折叠。
差异被折叠。
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import org.h2.expression.Expression;
/**
* @author Thomas
*/
public class SelectOrderBy {
public Expression expression;
public int column;
public boolean descending;
public boolean nullsFirst;
public boolean nullsLast;
}
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论