提交 7398ebec authored 作者: Thomas Mueller's avatar Thomas Mueller

Constraints for local temporary tables now session scoped.

上级 6d50ee90
......@@ -18,7 +18,9 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>When using the auto-server mode, and if the lock file was modified in the future,
<ul><li>Constraints for local temporary tables now session scoped. So far they were global.
Thanks a lot to Eric Faulhaber for finding and fixing this problem!
</li><li>When using the auto-server mode, and if the lock file was modified in the future,
the wrong exception was thrown ('Connection is broken' instead of 'Error opening database: Lock file modified in the future').
</li></ul>
......
......@@ -78,7 +78,7 @@ public class AlterTableAddConstraint extends SchemaCommand {
private String generateConstraintName(Table table) {
if (constraintName == null) {
constraintName = getSchema().getUniqueConstraintName(table);
constraintName = getSchema().getUniqueConstraintName(session, table);
}
return constraintName;
}
......@@ -100,7 +100,7 @@ public class AlterTableAddConstraint extends SchemaCommand {
session.commit(true);
Database db = session.getDatabase();
Table table = getSchema().getTableOrView(session, tableName);
if (getSchema().findConstraint(constraintName) != null) {
if (getSchema().findConstraint(session, constraintName) != null) {
if (ifNotExists) {
return 0;
}
......@@ -248,7 +248,11 @@ public class AlterTableAddConstraint extends SchemaCommand {
}
// parent relationship is already set with addConstraint
constraint.setComment(comment);
db.addSchemaObject(session, constraint);
if (table.getTemporary() && !table.getGlobalTemporary()) {
session.addLocalTempTableConstraint(constraint);
} else {
db.addSchemaObject(session, constraint);
}
table.addConstraint(constraint);
return 0;
}
......
......@@ -35,7 +35,7 @@ public class AlterTableDropConstraint extends SchemaCommand {
public int update() throws SQLException {
session.commit(true);
Constraint constraint = getSchema().findConstraint(constraintName);
Constraint constraint = getSchema().findConstraint(session, constraintName);
if (constraint == null) {
if (!ifExists) {
throw Message.getSQLException(ErrorCode.CONSTRAINT_NOT_FOUND_1, constraintName);
......
......@@ -20,6 +20,7 @@ import org.h2.api.DatabaseEventListener;
import org.h2.command.dml.SetTypes;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.constraint.Constraint;
import org.h2.index.Cursor;
import org.h2.index.Index;
import org.h2.index.IndexType;
......@@ -1529,18 +1530,27 @@ public class Database implements DataHandler {
* @param obj the object to be removed
*/
public synchronized void removeSchemaObject(Session session, SchemaObject obj) throws SQLException {
if (obj.getType() == DbObject.TABLE_OR_VIEW) {
int type = obj.getType();
if (type == DbObject.TABLE_OR_VIEW) {
Table table = (Table) obj;
if (table.getTemporary() && !table.getGlobalTemporary()) {
session.removeLocalTempTable(table);
return;
}
} else if (obj.getType() == DbObject.INDEX) {
} else if (type == DbObject.INDEX) {
Index index = (Index) obj;
if (index.getTable().getTemporary() && !index.getTable().getGlobalTemporary()) {
Table table = index.getTable();
if (table.getTemporary() && !table.getGlobalTemporary()) {
session.removeLocalTempTableIndex(index);
return;
}
} else if (type == DbObject.CONSTRAINT) {
Constraint constraint = (Constraint) obj;
Table table = constraint.getTable();
if (table.getTemporary() && !table.getGlobalTemporary()) {
session.removeLocalTempTableConstraint(constraint);
return;
}
}
checkWritingAllowed();
Comment comment = findComment(obj);
......
......@@ -20,6 +20,7 @@ import org.h2.command.Prepared;
import org.h2.command.dml.SetTypes;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.constraint.Constraint;
import org.h2.index.Index;
import org.h2.jdbc.JdbcConnection;
import org.h2.log.InDoubtTransaction;
......@@ -67,6 +68,7 @@ public class Session implements SessionInterface {
private Exception stackTrace = new Exception();
private HashMap localTempTables;
private HashMap localTempTableIndexes;
private HashMap localTempTableConstraints;
private int throttle;
private long lastThrottle;
private Command currentCommand;
......@@ -266,6 +268,62 @@ public class Session implements SessionInterface {
index.removeChildrenAndResources(this);
}
}
/**
* Get the local temporary constraint if one exists with that name, or
* null if not.
*
* @param name the constraint name
* @return the constraint, or null
*/
public Constraint findLocalTempTableConstraint(String name) {
if (localTempTableConstraints == null) {
return null;
}
return (Constraint) localTempTableConstraints.get(name);
}
/**
* Get the map of constraints for all constraints on local, temporary
* tables, if any. The map's keys are the constraints' names.
*
* @return the map of constraints, or null
*/
public HashMap getLocalTempTableConstraints() {
if (localTempTableConstraints == null) {
return new HashMap();
}
return localTempTableConstraints;
}
/**
* Add a local temporary constraint to this session.
*
* @param constraint the constraint to add
* @throws SQLException if a constraint with the same name already exists
*/
public void addLocalTempTableConstraint(Constraint constraint) throws SQLException {
if (localTempTableConstraints == null) {
localTempTableConstraints = new HashMap();
}
String name = constraint.getName();
if (localTempTableConstraints.get(name) != null) {
throw Message.getSQLException(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraint.getSQL());
}
localTempTableConstraints.put(name, constraint);
}
/**
* Drop and remove the given local temporary constraint from this session.
*
* @param constraint the constraint
*/
public void removeLocalTempTableConstraint(Constraint constraint) throws SQLException {
if (localTempTableConstraints != null) {
localTempTableConstraints.remove(constraint.getName());
constraint.removeChildrenAndResources(this);
}
}
protected void finalize() {
if (!SysProperties.runFinalize) {
......
......@@ -262,11 +262,16 @@ public class Schema extends DbObjectBase {
* Try to find a constraint with this name. This method returns null if no
* object with this name exists.
*
* @param constraintName the object name
* @param session the session
* @param name the object name
* @return the object or null
*/
public Constraint findConstraint(String constraintName) {
return (Constraint) constraints.get(constraintName);
public Constraint findConstraint(Session session, String name) {
Constraint constraint = (Constraint) constraints.get(name);
if (constraint == null) {
constraint = session.findLocalTempTableConstraint(name);
}
return constraint;
}
/**
......@@ -287,41 +292,52 @@ public class Schema extends DbObjectBase {
*/
public void freeUniqueName(String name) {
if (name != null) {
temporaryUniqueNames.remove(name);
synchronized (temporaryUniqueNames) {
temporaryUniqueNames.remove(name);
}
}
}
private String getUniqueName(DbObject obj, HashMap map, String prefix) {
String hash = Integer.toHexString(obj.getName().hashCode()).toUpperCase();
String name = null;
for (int i = 1; i < hash.length(); i++) {
name = prefix + hash.substring(0, i);
if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
break;
}
name = null;
}
if (name == null) {
prefix = prefix + hash + "_";
for (int i = 0;; i++) {
name = prefix + i;
synchronized (temporaryUniqueNames) {
for (int i = 1; i < hash.length(); i++) {
name = prefix + hash.substring(0, i);
if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
break;
}
name = null;
}
if (name == null) {
prefix = prefix + hash + "_";
for (int i = 0;; i++) {
name = prefix + i;
if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
break;
}
}
}
temporaryUniqueNames.add(name);
}
temporaryUniqueNames.add(name);
return name;
}
/**
* Create a unique constraint name.
*
* @param session the session
* @param table the constraint table
* @return the unique name
*/
public String getUniqueConstraintName(Table table) {
return getUniqueName(table, constraints, "CONSTRAINT_");
public String getUniqueConstraintName(Session session, Table table) {
HashMap tableConstraints;
if (table.getTemporary() && !table.getGlobalTemporary()) {
tableConstraints = session.getLocalTempTableConstraints();
} else {
tableConstraints = constraints;
}
return getUniqueName(table, tableConstraints, "CONSTRAINT_");
}
/**
......
......@@ -31,6 +31,7 @@ public class TestTempTables extends TestBase {
deleteDb("tempTables");
Connection c1 = getConnection("tempTables");
Connection c2 = getConnection("tempTables");
testConstraints(c1, c2);
testTables(c1, c2);
testIndexes(c1, c2);
c1.close();
......@@ -38,6 +39,16 @@ public class TestTempTables extends TestBase {
deleteDb("tempTables");
}
private void testConstraints(Connection conn1, Connection conn2) throws SQLException {
Statement s1 = conn1.createStatement(), s2 = conn2.createStatement();
s1.execute("create local temporary table test(id int unique)");
s2.execute("create local temporary table test(id int unique)");
s1.execute("alter table test add constraint a unique(id)");
s2.execute("alter table test add constraint a unique(id)");
s1.execute("drop table test");
s2.execute("drop table test");
}
private void testIndexes(Connection conn1, Connection conn2) throws SQLException {
conn1.createStatement().executeUpdate("create local temporary table test(id int)");
conn1.createStatement().executeUpdate("create index idx_id on test(id)");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论