提交 73c1cc8c authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 e756cf88
...@@ -4174,16 +4174,20 @@ public class Parser { ...@@ -4174,16 +4174,20 @@ public class Parser {
} }
if (readIf("PRIMARY")) { if (readIf("PRIMARY")) {
read("KEY"); read("KEY");
CreateIndex command = new CreateIndex(session, schema); AlterTableAddConstraint command = new AlterTableAddConstraint(session, schema);
command.setType(AlterTableAddConstraint.PRIMARY_KEY);
command.setComment(comment); command.setComment(comment);
command.setConstraintName(constraintName); command.setConstraintName(constraintName);
command.setTableName(tableName); command.setTableName(tableName);
command.setPrimaryKey(true);
if (readIf("HASH")) { if (readIf("HASH")) {
command.setHash(true); command.setPrimaryKeyHash(true);
} }
read("("); read("(");
command.setIndexColumns(parseIndexColumnList()); command.setIndexColumns(parseIndexColumnList());
if (readIf("INDEX")) {
String indexName = readIdentifierWithSchema();
command.setIndex(getSchema().findIndex(indexName));
}
return command; return command;
} else if (database.getMode().indexDefinitionInCreateTable && (readIf("INDEX") || readIf("KEY"))) { } else if (database.getMode().indexDefinitionInCreateTable && (readIf("INDEX") || readIf("KEY"))) {
// MySQL // MySQL
...@@ -4335,7 +4339,11 @@ public class Parser { ...@@ -4335,7 +4339,11 @@ public class Parser {
if (column.getAutoIncrement()) { if (column.getAutoIncrement()) {
IndexColumn[] cols = new IndexColumn[]{new IndexColumn()}; IndexColumn[] cols = new IndexColumn[]{new IndexColumn()};
cols[0].columnName = column.getName(); cols[0].columnName = column.getName();
command.setPrimaryKeyColumns(cols); AlterTableAddConstraint pk = new AlterTableAddConstraint(session, schema);
pk.setType(AlterTableAddConstraint.PRIMARY_KEY);
pk.setTableName(tableName);
pk.setIndexColumns(cols);
command.addConstraintCommand(pk);
} }
command.addColumn(column); command.addColumn(column);
String constraintName = null; String constraintName = null;
...@@ -4344,12 +4352,15 @@ public class Parser { ...@@ -4344,12 +4352,15 @@ public class Parser {
} }
if (readIf("PRIMARY")) { if (readIf("PRIMARY")) {
read("KEY"); read("KEY");
if (readIf("HASH")) { boolean hash = readIf("HASH");
command.setHashPrimaryKey(true);
}
IndexColumn[] cols = new IndexColumn[]{new IndexColumn()}; IndexColumn[] cols = new IndexColumn[]{new IndexColumn()};
cols[0].columnName = column.getName(); cols[0].columnName = column.getName();
command.setPrimaryKeyColumns(cols); AlterTableAddConstraint pk = new AlterTableAddConstraint(session, schema);
pk.setPrimaryKeyHash(hash);
pk.setType(AlterTableAddConstraint.PRIMARY_KEY);
pk.setTableName(tableName);
pk.setIndexColumns(cols);
command.addConstraintCommand(pk);
} else if (readIf("UNIQUE")) { } else if (readIf("UNIQUE")) {
AlterTableAddConstraint unique = new AlterTableAddConstraint(session, schema); AlterTableAddConstraint unique = new AlterTableAddConstraint(session, schema);
unique.setConstraintName(constraintName); unique.setConstraintName(constraintName);
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package org.h2.command.ddl; package org.h2.command.ddl;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
...@@ -13,6 +12,7 @@ import org.h2.constraint.Constraint; ...@@ -13,6 +12,7 @@ import org.h2.constraint.Constraint;
import org.h2.constraint.ConstraintCheck; import org.h2.constraint.ConstraintCheck;
import org.h2.constraint.ConstraintReferential; import org.h2.constraint.ConstraintReferential;
import org.h2.constraint.ConstraintUnique; import org.h2.constraint.ConstraintUnique;
import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject; import org.h2.engine.DbObject;
import org.h2.engine.Right; import org.h2.engine.Right;
...@@ -48,6 +48,7 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -48,6 +48,7 @@ public class AlterTableAddConstraint extends SchemaCommand {
private Index index, refIndex; private Index index, refIndex;
private String comment; private String comment;
private boolean checkExisting; private boolean checkExisting;
private boolean primaryKeyKash;
public AlterTableAddConstraint(Session session, Schema schema) { public AlterTableAddConstraint(Session session, Schema schema) {
super(session, schema); super(session, schema);
...@@ -61,29 +62,64 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -61,29 +62,64 @@ public class AlterTableAddConstraint extends SchemaCommand {
} }
public int update() throws SQLException { public int update() throws SQLException {
try {
return tryUpdate();
} finally {
getSchema().freeUniqueName(constraintName);
}
}
public int tryUpdate() throws SQLException {
session.commit(true); session.commit(true);
Database db = session.getDatabase(); Database db = session.getDatabase();
Table table = getSchema().getTableOrView(session, tableName); Table table = getSchema().getTableOrView(session, tableName);
if (getSchema().findConstraint(constraintName) != null) { if (getSchema().findConstraint(constraintName) != null) {
throw Message.getSQLException(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraintName); throw Message.getSQLException(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraintName);
} }
Constraint constraint;
session.getUser().checkRight(table, Right.ALL); session.getUser().checkRight(table, Right.ALL);
table.lock(session, true, true); table.lock(session, true, true);
Constraint constraint;
switch (type) { switch (type) {
case CHECK: { case PRIMARY_KEY: {
int id = getObjectId(true, true); IndexColumn.mapColumns(indexColumns, table);
String name = generateConstraintName(table, id); index = table.findPrimaryKey();
ConstraintCheck check = new ConstraintCheck(getSchema(), id, name, table); ObjectArray constraints = table.getConstraints();
TableFilter filter = new TableFilter(session, table, null, false, null); for (int i = 0; constraints != null && i < constraints.size(); i++) {
checkExpression.mapColumns(filter, 0); Constraint c = (Constraint) constraints.get(i);
checkExpression = checkExpression.optimize(session); if (Constraint.PRIMARY_KEY.equals(c.getConstraintType())) {
check.setExpression(checkExpression); throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY);
check.setTableFilter(filter); }
constraint = check; }
if (checkExisting) { if (index != null) {
check.checkExistingData(session); // if there is an index, it must match with the one declared
// we don't test ascending / descending
IndexColumn[] pkCols = index.getIndexColumns();
if (pkCols.length != indexColumns.length) {
throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY);
}
for (int i = 0; i < pkCols.length; i++) {
if (pkCols[i].column != indexColumns[i].column) {
throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY);
}
}
}
if (index == null) {
IndexType indexType = IndexType.createPrimaryKey(table.isPersistent(), primaryKeyKash);
String indexName = getSchema().getUniqueIndexName(table, Constants.PREFIX_PRIMARY_KEY);
int id = getObjectId(true, false);
try {
index = table.addIndex(session, indexName, id, indexColumns, indexType, Index.EMPTY_HEAD, null);
} finally {
getSchema().freeUniqueName(indexName);
}
} }
index.getIndexType().setBelongsToConstraint(true);
int constraintId = getObjectId(true, true);
String name = generateConstraintName(table, constraintId);
ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true);
pk.setColumns(indexColumns);
pk.setIndex(index, true);
constraint = pk;
break; break;
} }
case UNIQUE: { case UNIQUE: {
...@@ -107,6 +143,21 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -107,6 +143,21 @@ public class AlterTableAddConstraint extends SchemaCommand {
constraint = unique; constraint = unique;
break; break;
} }
case CHECK: {
int id = getObjectId(true, true);
String name = generateConstraintName(table, id);
ConstraintCheck check = new ConstraintCheck(getSchema(), id, name, table);
TableFilter filter = new TableFilter(session, table, null, false, null);
checkExpression.mapColumns(filter, 0);
checkExpression = checkExpression.optimize(session);
check.setExpression(checkExpression);
check.setTableFilter(filter);
constraint = check;
if (checkExisting) {
check.checkExistingData(session);
}
break;
}
case REFERENTIAL: { case REFERENTIAL: {
Table refTable = refSchema.getTableOrView(session, refTableName); Table refTable = refSchema.getTableOrView(session, refTableName);
session.getUser().checkRight(refTable, Right.ALL); session.getUser().checkRight(refTable, Right.ALL);
...@@ -187,7 +238,13 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -187,7 +238,13 @@ public class AlterTableAddConstraint extends SchemaCommand {
indexType.setBelongsToConstraint(true); indexType.setBelongsToConstraint(true);
String prefix = constraintName == null ? "CONSTRAINT" : constraintName; String prefix = constraintName == null ? "CONSTRAINT" : constraintName;
String indexName = getSchema().getUniqueIndexName(t, prefix + "_INDEX_"); String indexName = getSchema().getUniqueIndexName(t, prefix + "_INDEX_");
return t.addIndex(session, indexName, indexId, cols, indexType, Index.EMPTY_HEAD, null); Index idx;
try {
idx = t.addIndex(session, indexName, indexId, cols, indexType, Index.EMPTY_HEAD, null);
} finally {
getSchema().freeUniqueName(indexName);
}
return idx;
} }
public void setDeleteAction(int action) { public void setDeleteAction(int action) {
...@@ -282,6 +339,10 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -282,6 +339,10 @@ public class AlterTableAddConstraint extends SchemaCommand {
this.type = type; this.type = type;
} }
public int getType() {
return type;
}
public void setCheckExpression(Expression expression) { public void setCheckExpression(Expression expression) {
this.checkExpression = expression; this.checkExpression = expression;
} }
...@@ -294,6 +355,10 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -294,6 +355,10 @@ public class AlterTableAddConstraint extends SchemaCommand {
this.indexColumns = indexColumns; this.indexColumns = indexColumns;
} }
public IndexColumn[] getIndexColumns() {
return indexColumns;
}
public void setRefTableName(Schema refSchema, String ref) { public void setRefTableName(Schema refSchema, String ref) {
this.refSchema = refSchema; this.refSchema = refSchema;
this.refTableName = ref; this.refTableName = ref;
...@@ -319,4 +384,12 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -319,4 +384,12 @@ public class AlterTableAddConstraint extends SchemaCommand {
this.checkExisting = b; this.checkExisting = b;
} }
public void setPrimaryKeyHash(boolean b) {
this.primaryKeyKash = b;
}
public boolean getPrimaryKeyHash() {
return primaryKeyKash;
}
} }
...@@ -7,12 +7,10 @@ package org.h2.command.ddl; ...@@ -7,12 +7,10 @@ package org.h2.command.ddl;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constraint.ConstraintUnique; import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Right; import org.h2.engine.Right;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.schema.Schema; import org.h2.schema.Schema;
...@@ -31,7 +29,6 @@ public class CreateIndex extends SchemaCommand { ...@@ -31,7 +29,6 @@ public class CreateIndex extends SchemaCommand {
private boolean primaryKey, unique, hash; private boolean primaryKey, unique, hash;
private boolean ifNotExists; private boolean ifNotExists;
private String comment; private String comment;
private String constraintName;
public CreateIndex(Session session, Schema schema) { public CreateIndex(Session session, Schema schema) {
super(session, schema); super(session, schema);
...@@ -61,13 +58,6 @@ public class CreateIndex extends SchemaCommand { ...@@ -61,13 +58,6 @@ public class CreateIndex extends SchemaCommand {
return indexColumns; return indexColumns;
} }
private String generateConstraintName(DbObject obj, int id) throws SQLException {
if (constraintName == null) {
constraintName = getSchema().getUniqueConstraintName(obj);
}
return constraintName;
}
public int update() throws SQLException { public int update() throws SQLException {
// TODO cancel: may support for index creation // TODO cancel: may support for index creation
session.commit(true); session.commit(true);
...@@ -80,8 +70,10 @@ public class CreateIndex extends SchemaCommand { ...@@ -80,8 +70,10 @@ public class CreateIndex extends SchemaCommand {
persistent = false; persistent = false;
} }
int id = getObjectId(true, false); int id = getObjectId(true, false);
if (indexName == null) { if (primaryKey) {
indexName = getSchema().getUniqueIndexName(table, "INDEX_"); indexName = getSchema().getUniqueIndexName(table, Constants.PREFIX_PRIMARY_KEY);
} else if (indexName == null) {
indexName = getSchema().getUniqueIndexName(table, Constants.PREFIX_INDEX);
} }
if (getSchema().findIndex(indexName) != null) { if (getSchema().findIndex(indexName) != null) {
if (ifNotExists) { if (ifNotExists) {
...@@ -101,20 +93,7 @@ public class CreateIndex extends SchemaCommand { ...@@ -101,20 +93,7 @@ public class CreateIndex extends SchemaCommand {
indexType = IndexType.createNonUnique(persistent); indexType = IndexType.createNonUnique(persistent);
} }
IndexColumn.mapColumns(indexColumns, table); IndexColumn.mapColumns(indexColumns, table);
Index index = table.addIndex(session, indexName, id, indexColumns, indexType, headPos, comment); table.addIndex(session, indexName, id, indexColumns, indexType, headPos, comment);
int todo;
// if (primaryKey) {
// // TODO this code is a copy of CreateTable (primaryKey creation)
// // for primary keys, create a constraint as well
// String name = generateConstraintName(table, id);
// int constraintId = getObjectId(true, true);
// ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true);
// pk.setColumns(index.getIndexColumns());
// pk.setIndex(index, true);
// pk.setComment(comment);
// db.addSchemaObject(session, pk);
// table.addConstraint(pk);
// }
return 0; return 0;
} }
...@@ -138,8 +117,4 @@ public class CreateIndex extends SchemaCommand { ...@@ -138,8 +117,4 @@ public class CreateIndex extends SchemaCommand {
this.comment = comment; this.comment = comment;
} }
public void setConstraintName(String constraintName) {
this.constraintName = constraintName;
}
} }
...@@ -10,12 +10,9 @@ import org.h2.command.Prepared; ...@@ -10,12 +10,9 @@ import org.h2.command.Prepared;
import org.h2.command.dml.Insert; import org.h2.command.dml.Insert;
import org.h2.command.dml.Query; import org.h2.command.dml.Query;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constraint.ConstraintUnique;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.index.Index;
import org.h2.index.IndexType;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.schema.Sequence; import org.h2.schema.Sequence;
...@@ -37,7 +34,6 @@ public class CreateTable extends SchemaCommand { ...@@ -37,7 +34,6 @@ public class CreateTable extends SchemaCommand {
private IndexColumn[] pkColumns; private IndexColumn[] pkColumns;
private boolean ifNotExists; private boolean ifNotExists;
private boolean persistent = true; private boolean persistent = true;
private boolean hashPrimaryKey;
private boolean temporary; private boolean temporary;
private boolean globalTemporary; private boolean globalTemporary;
private boolean onCommitDrop; private boolean onCommitDrop;
...@@ -68,17 +64,20 @@ public class CreateTable extends SchemaCommand { ...@@ -68,17 +64,20 @@ public class CreateTable extends SchemaCommand {
public void addConstraintCommand(Prepared command) throws SQLException { public void addConstraintCommand(Prepared command) throws SQLException {
if (command instanceof CreateIndex) { if (command instanceof CreateIndex) {
CreateIndex create = (CreateIndex) command;
if (create.getPrimaryKey()) {
setPrimaryKeyColumns(create.getIndexColumns());
setHashPrimaryKey(create.getHash());
} else {
constraintCommands.add(command); constraintCommands.add(command);
}
} else { } else {
AlterTableAddConstraint con = (AlterTableAddConstraint) command;
boolean alreadySet;
if (con.getType() == AlterTableAddConstraint.PRIMARY_KEY) {
alreadySet = setPrimaryKeyColumns(con.getIndexColumns());
} else {
alreadySet = false;
}
if (!alreadySet) {
constraintCommands.add(command); constraintCommands.add(command);
} }
} }
}
public void setIfNotExists(boolean ifNotExists) { public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists; this.ifNotExists = ifNotExists;
...@@ -144,22 +143,6 @@ public class CreateTable extends SchemaCommand { ...@@ -144,22 +143,6 @@ public class CreateTable extends SchemaCommand {
Column c = (Column) columns.get(i); Column c = (Column) columns.get(i);
c.prepareExpression(session); c.prepareExpression(session);
} }
if (pkColumns != null) {
IndexColumn.mapColumns(pkColumns, table);
int indexId = getObjectId(true, false);
Index index = table.addIndex(session, null, indexId, pkColumns, IndexType.createPrimaryKey(persistent, hashPrimaryKey),
Index.EMPTY_HEAD, null);
// TODO this code is a copy of CreateIndex (if primaryKey)
int todo;
// String name = getSchema().getUniqueConstraintName(table);
// int constraintId = getObjectId(true, true);
// ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true);
// pk.setColumns(index.getIndexColumns());
// pk.setIndex(index, true);
// pk.setComment(comment);
// db.addSchemaObject(session, pk);
// table.addConstraint(pk);
}
for (int i = 0; i < sequences.size(); i++) { for (int i = 0; i < sequences.size(); i++) {
Sequence sequence = (Sequence) sequences.get(i); Sequence sequence = (Sequence) sequences.get(i);
table.addSequence(sequence); table.addSequence(sequence);
...@@ -214,7 +197,13 @@ public class CreateTable extends SchemaCommand { ...@@ -214,7 +197,13 @@ public class CreateTable extends SchemaCommand {
} }
} }
public void setPrimaryKeyColumns(IndexColumn[] columns) throws SQLException { /**
* Sets the primary key columns, but also check if an primary key with different columns is already defined.
*
* @param columns the primary key columns
* @return true if the same primary key columns where already set
*/
private boolean setPrimaryKeyColumns(IndexColumn[] columns) throws SQLException {
if (pkColumns != null) { if (pkColumns != null) {
if (columns.length != pkColumns.length) { if (columns.length != pkColumns.length) {
throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY); throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY);
...@@ -224,18 +213,16 @@ public class CreateTable extends SchemaCommand { ...@@ -224,18 +213,16 @@ public class CreateTable extends SchemaCommand {
throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY); throw Message.getSQLException(ErrorCode.SECOND_PRIMARY_KEY);
} }
} }
return true;
} }
this.pkColumns = columns; this.pkColumns = columns;
return false;
} }
public void setPersistent(boolean persistent) { public void setPersistent(boolean persistent) {
this.persistent = persistent; this.persistent = persistent;
} }
public void setHashPrimaryKey(boolean b) {
this.hashPrimaryKey = b;
}
public void setGlobalTemporary(boolean globalTemporary) { public void setGlobalTemporary(boolean globalTemporary) {
this.globalTemporary = globalTemporary; this.globalTemporary = globalTemporary;
} }
......
...@@ -47,17 +47,27 @@ public class DropIndex extends SchemaCommand { ...@@ -47,17 +47,27 @@ public class DropIndex extends SchemaCommand {
} }
} else { } else {
Table table = index.getTable(); Table table = index.getTable();
session.getUser().checkRight(index.getTable(), Right.ALL);
Constraint pkConstraint = null;
ObjectArray constraints = table.getConstraints(); ObjectArray constraints = table.getConstraints();
for (int i = 0; constraints != null && i < constraints.size(); i++) { for (int i = 0; constraints != null && i < constraints.size(); i++) {
Constraint cons = (Constraint) constraints.get(i); Constraint cons = (Constraint) constraints.get(i);
if (cons.usesIndex(index)) { if (cons.usesIndex(index)) {
// can drop primary key index (for compatibility)
if (Constraint.PRIMARY_KEY.equals(cons.getConstraintType())) {
pkConstraint = cons;
} else {
throw Message.getSQLException(ErrorCode.INDEX_BELONGS_TO_CONSTRAINT_1, indexName); throw Message.getSQLException(ErrorCode.INDEX_BELONGS_TO_CONSTRAINT_1, indexName);
} }
} }
session.getUser().checkRight(index.getTable(), Right.ALL); }
index.getTable().setModified(); index.getTable().setModified();
if (pkConstraint != null) {
db.removeSchemaObject(session, pkConstraint);
} else {
db.removeSchemaObject(session, index); db.removeSchemaObject(session, index);
} }
}
return 0; return 0;
} }
......
...@@ -116,7 +116,8 @@ public class Constants { ...@@ -116,7 +116,8 @@ public class Constants {
public static final int DEFAULT_MAX_LENGTH_CLIENTSIDE_LOB = 65536; public static final int DEFAULT_MAX_LENGTH_CLIENTSIDE_LOB = 65536;
public static final int SALT_LEN = 8; public static final int SALT_LEN = 8;
public static final int DEFAULT_DATA_PAGE_SIZE = 512; public static final int DEFAULT_DATA_PAGE_SIZE = 512;
public static final String PRIMARY_KEY_PREFIX = "PRIMARY_KEY_"; public static final String PREFIX_PRIMARY_KEY = "PRIMARY_KEY_";
public static final String PREFIX_INDEX = "INDEX_";
public static final int LOCK_SLEEP = 1000; public static final int LOCK_SLEEP = 1000;
// TODO for testing, the lock timeout is smaller than for interactive use cases // TODO for testing, the lock timeout is smaller than for interactive use cases
......
...@@ -2686,4 +2686,3 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat ...@@ -2686,4 +2686,3 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
} }
} }
...@@ -6,6 +6,7 @@ package org.h2.schema; ...@@ -6,6 +6,7 @@ package org.h2.schema;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
...@@ -40,6 +41,13 @@ public class Schema extends DbObjectBase { ...@@ -40,6 +41,13 @@ public class Schema extends DbObjectBase {
private HashMap constraints = new HashMap(); private HashMap constraints = new HashMap();
private HashMap constants = new HashMap(); private HashMap constants = new HashMap();
/*
* Set of returned unique names that are not yet stored
* (to avoid returning the same unique name twice when multiple threads
* concurrently create objects).
*/
private HashSet temporaryUniqueNames = new HashSet();
public Schema(Database database, int id, String schemaName, User owner, boolean system) { public Schema(Database database, int id, String schemaName, User owner, boolean system) {
super(database, id, schemaName, Trace.SCHEMA); super(database, id, schemaName, Trace.SCHEMA);
this.owner = owner; this.owner = owner;
...@@ -139,6 +147,7 @@ public class Schema extends DbObjectBase { ...@@ -139,6 +147,7 @@ public class Schema extends DbObjectBase {
throw Message.getInternalError("object already exists"); throw Message.getInternalError("object already exists");
} }
map.put(name, obj); map.put(name, obj);
freeUniqueName(name);
} }
public void rename(SchemaObject obj, String newName) throws SQLException { public void rename(SchemaObject obj, String newName) throws SQLException {
...@@ -153,8 +162,10 @@ public class Schema extends DbObjectBase { ...@@ -153,8 +162,10 @@ public class Schema extends DbObjectBase {
} }
} }
map.remove(obj.getName()); map.remove(obj.getName());
freeUniqueName(obj.getName());
obj.rename(newName); obj.rename(newName);
map.put(newName, obj); map.put(newName, obj);
freeUniqueName(newName);
} }
public Table findTableOrView(Session session, String name) { public Table findTableOrView(Session session, String name) {
...@@ -185,22 +196,34 @@ public class Schema extends DbObjectBase { ...@@ -185,22 +196,34 @@ public class Schema extends DbObjectBase {
return (Constant) constants.get(constantName); return (Constant) constants.get(constantName);
} }
public void freeUniqueName(String name) {
if (name != null) {
temporaryUniqueNames.remove(name);
}
}
private String getUniqueName(DbObject obj, HashMap map, String prefix) { private String getUniqueName(DbObject obj, HashMap map, String prefix) {
String hash = Integer.toHexString(obj.getName().hashCode()).toUpperCase(); String hash = Integer.toHexString(obj.getName().hashCode()).toUpperCase();
String name = null;
for (int i = 1; i < hash.length(); i++) { for (int i = 1; i < hash.length(); i++) {
String name = prefix + hash.substring(0, i); name = prefix + hash.substring(0, i);
if (map.get(name) == null) { if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
return name; break;
} }
name = null;
} }
if (name == null) {
prefix = prefix + hash + "_"; prefix = prefix + hash + "_";
for (int i = 0;; i++) { for (int i = 0;; i++) {
String name = prefix + i; name = prefix + i;
if (map.get(name) == null) { if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
return name; break;
} }
} }
} }
temporaryUniqueNames.add(name);
return name;
}
public String getUniqueConstraintName(DbObject obj) { public String getUniqueConstraintName(DbObject obj) {
return getUniqueName(obj, constraints, "CONSTRAINT_"); return getUniqueName(obj, constraints, "CONSTRAINT_");
...@@ -265,6 +288,7 @@ public class Schema extends DbObjectBase { ...@@ -265,6 +288,7 @@ public class Schema extends DbObjectBase {
throw Message.getInternalError("not found: " + objName); throw Message.getInternalError("not found: " + objName);
} }
map.remove(objName); map.remove(objName);
freeUniqueName(objName);
} }
public TableData createTable(String tempName, int id, ObjectArray newColumns, boolean persistent, boolean clustered) public TableData createTable(String tempName, int id, ObjectArray newColumns, boolean persistent, boolean clustered)
......
...@@ -819,6 +819,9 @@ class WebThread extends Thread implements DatabaseEventListener { ...@@ -819,6 +819,9 @@ class WebThread extends Thread implements DatabaseEventListener {
e.printStackTrace(new PrintWriter(writer)); e.printStackTrace(new PrintWriter(writer));
String stackTrace = writer.toString(); String stackTrace = writer.toString();
stackTrace = PageParser.escapeHtml(stackTrace); stackTrace = PageParser.escapeHtml(stackTrace);
if (isH2) {
stackTrace = linkToSource(stackTrace);
}
stackTrace = StringUtils.replaceAll(stackTrace, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;"); stackTrace = StringUtils.replaceAll(stackTrace, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
String message = PageParser.escapeHtml(e.getMessage()); String message = PageParser.escapeHtml(e.getMessage());
String error = "<a class=\"error\" href=\"#\" onclick=\"var x=document.getElementById('st" + id String error = "<a class=\"error\" href=\"#\" onclick=\"var x=document.getElementById('st" + id
...@@ -837,6 +840,49 @@ class WebThread extends Thread implements DatabaseEventListener { ...@@ -837,6 +840,49 @@ class WebThread extends Thread implements DatabaseEventListener {
} }
} }
private String linkToSource(String s) {
try {
StringBuffer result = new StringBuffer(s.length());
int idx = s.indexOf("<br />");
result.append(s.substring(0, idx));
while (true) {
int start = s.indexOf("org.h2.", idx);
if (start < 0) {
result.append(s.substring(idx));
break;
}
result.append(s.substring(idx, start));
int end = s.indexOf(')', start);
if (end < 0) {
result.append(s.substring(idx));
break;
}
String element = s.substring(start, end);
int open = element.lastIndexOf('(');
int dotMethod = element.lastIndexOf('.', open - 1);
int dotClass = element.lastIndexOf('.', dotMethod - 1);
String packageName = element.substring(0, dotClass);
int colon = element.lastIndexOf(':');
String file = element.substring(open + 1, colon);
String lineNumber = element.substring(colon + 1, element.length());
String fullFileName = packageName.replace('.', '/') + "/" + file;
result.append("<a href=\"http://h2database.com/html/source.html?file=");
result.append(fullFileName);
result.append("&line=");
result.append(lineNumber);
result.append("&build=");
result.append(Constants.BUILD_ID);
result.append("\">");
result.append(element);
result.append("</a>");
idx = end;
}
return result.toString();
} catch (Throwable t) {
return s;
}
}
private String formatAsError(String s) { private String formatAsError(String s) {
return "<div class=\"error\">"+s+"</div>"; return "<div class=\"error\">"+s+"</div>";
} }
......
...@@ -31,7 +31,6 @@ public class IndexColumn { ...@@ -31,7 +31,6 @@ public class IndexColumn {
} }
public static IndexColumn[] wrap(Column[] columns) { public static IndexColumn[] wrap(Column[] columns) {
int testDelete_;
IndexColumn[] list = new IndexColumn[columns.length]; IndexColumn[] list = new IndexColumn[columns.length];
for (int i = 0; i < list.length; i++) { for (int i = 0; i < list.length; i++) {
list[i] = new IndexColumn(); list[i] = new IndexColumn();
......
...@@ -447,7 +447,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -447,7 +447,7 @@ public abstract class Table extends SchemaObjectBase {
if (index != null) { if (index != null) {
return index; return index;
} }
throw Message.getSQLException(ErrorCode.INDEX_NOT_FOUND_1, Constants.PRIMARY_KEY_PREFIX); throw Message.getSQLException(ErrorCode.INDEX_NOT_FOUND_1, Constants.PREFIX_PRIMARY_KEY);
} }
public void validateConvertUpdateSequence(Session session, Row row) throws SQLException { public void validateConvertUpdateSequence(Session session, Row row) throws SQLException {
......
...@@ -151,7 +151,6 @@ public class TableData extends Table implements RecordReader { ...@@ -151,7 +151,6 @@ public class TableData extends Table implements RecordReader {
public Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType, public Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType,
int headPos, String indexComment) throws SQLException { int headPos, String indexComment) throws SQLException {
if (indexType.isPrimaryKey()) { if (indexType.isPrimaryKey()) {
indexName = getSchema().getUniqueIndexName(this, Constants.PRIMARY_KEY_PREFIX);
for (int i = 0; i < cols.length; i++) { for (int i = 0; i < cols.length; i++) {
Column column = cols[i].column; Column column = cols[i].column;
if (column.getNullable()) { if (column.getNullable()) {
...@@ -202,6 +201,7 @@ public class TableData extends Table implements RecordReader { ...@@ -202,6 +201,7 @@ public class TableData extends Table implements RecordReader {
throw Message.getInternalError("rowcount remaining=" + remaining + " " + getName()); throw Message.getInternalError("rowcount remaining=" + remaining + " " + getName());
} }
} catch (SQLException e) { } catch (SQLException e) {
getSchema().freeUniqueName(indexName);
try { try {
index.remove(session); index.remove(session);
} catch (SQLException e2) { } catch (SQLException e2) {
......
...@@ -151,17 +151,23 @@ java org.h2.test.TestAll timer ...@@ -151,17 +151,23 @@ java org.h2.test.TestAll timer
/* /*
create table bla (id integer not null);
alter table bla add constraint pk primary key (id);
-- doesn't create a constraint!
alter table bla drop constraint pk;
alter table bla drop primary key;
drop table bla;
-- PostgreSQL, Derby, HSQLDB: works
-- MySQL: does not work
implement max_query_time and use it for TestCrashAPI implement max_query_time and use it for TestCrashAPI
Value too long for column DESC. But which value?
org.h2.jdbc.JdbcSQLException: Value too long for column DESC
[90005-64]
at org.h2.message.Message.getSQLException(Message.java:89)
at org.h2.message.Message.getSQLException(Message.java:93)
at org.h2.message.Message.getSQLException(Message.java:71)
at org.h2.table.Column.validateConvertUpdateSequence(Column.java:226)
at org.h2.table.Table.validateConvertUpdateSequence(Table.java:331)
at org.h2.command.dml.Insert.update(Insert.java:111)
at org.h2.command.CommandContainer.update(CommandContainer.java:68)
CREATE {[UNIQUE [HASH]] INDEX [[IF NOT EXISTS] newIndexName]
| PRIMARY KEY [HASH]} ON (columnName [,...])
There is missing name of table
adjust cache memory usage adjust cache memory usage
simple pure java config file (interpreted) simple pure java config file (interpreted)
...@@ -182,6 +188,8 @@ Roadmap: ...@@ -182,6 +188,8 @@ Roadmap:
Move Maven 2 repository from hsql.sf.net to h2database.sf.net Move Maven 2 repository from hsql.sf.net to h2database.sf.net
History: History:
Primary keys are now considered constraints and can have a constraint name.
H2 Console: stack traces are now links to the source code in the source repository (H2 database only)
Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes
......
...@@ -320,7 +320,7 @@ public abstract class TestBase { ...@@ -320,7 +320,7 @@ public abstract class TestBase {
} }
protected void checkContains(String result, String contains) throws Exception { protected void checkContains(String result, String contains) throws Exception {
if(result.indexOf(contains) < 0) { if (result.indexOf(contains) < 0) {
error(result + " does not contain: " + contains); error(result + " does not contain: " + contains);
} }
} }
......
...@@ -495,7 +495,7 @@ public class TestCases extends TestBase { ...@@ -495,7 +495,7 @@ public class TestCases extends TestBase {
conn.createStatement().execute("CREATE TABLE TEST_SEQ(ID INT IDENTITY, NAME VARCHAR(255))"); conn.createStatement().execute("CREATE TABLE TEST_SEQ(ID INT IDENTITY, NAME VARCHAR(255))");
conn.createStatement().execute("CREATE TABLE TEST(ID INT PRIMARY KEY)"); conn.createStatement().execute("CREATE TABLE TEST(ID INT PRIMARY KEY)");
conn.createStatement().execute("ALTER TABLE TEST RENAME TO TEST2"); conn.createStatement().execute("ALTER TABLE TEST RENAME TO TEST2");
conn.createStatement().execute("CREATE TABLE TEST_B(ID INT PRIMARY KEY, NAME VARCHAR, UNIQUE(NAME));"); conn.createStatement().execute("CREATE TABLE TEST_B(ID INT PRIMARY KEY, NAME VARCHAR, UNIQUE(NAME))");
conn.close(); conn.close();
conn = getConnection("cases"); conn = getConnection("cases");
conn.createStatement().execute("INSERT INTO TEST_SEQ(NAME) VALUES('Hi')"); conn.createStatement().execute("INSERT INTO TEST_SEQ(NAME) VALUES('Hi')");
......
...@@ -743,21 +743,21 @@ public class TestMetaData extends TestBase { ...@@ -743,21 +743,21 @@ public class TestMetaData extends TestBase {
* null, * null,
* null * null
*/}, */},
{ catalog, Constants.SCHEMA_MAIN, "TX2", "FALSE", catalog, "PRIMARY_KEY_146", { catalog, Constants.SCHEMA_MAIN, "TX2", "FALSE", catalog, "PRIMARY_KEY_14",
"" + DatabaseMetaData.tableIndexOther, "1", "C", "A" /* "" + DatabaseMetaData.tableIndexOther, "1", "C", "A" /*
* , * ,
* null, * null,
* null, * null,
* null * null
*/}, */},
{ catalog, Constants.SCHEMA_MAIN, "TX2", "FALSE", catalog, "PRIMARY_KEY_146", { catalog, Constants.SCHEMA_MAIN, "TX2", "FALSE", catalog, "PRIMARY_KEY_14",
"" + DatabaseMetaData.tableIndexOther, "2", "A", "A" /* "" + DatabaseMetaData.tableIndexOther, "2", "A", "A" /*
* , * ,
* null, * null,
* null, * null,
* null * null
*/}, */},
{ catalog, Constants.SCHEMA_MAIN, "TX2", "FALSE", catalog, "PRIMARY_KEY_146", { catalog, Constants.SCHEMA_MAIN, "TX2", "FALSE", catalog, "PRIMARY_KEY_14",
"" + DatabaseMetaData.tableIndexOther, "3", "B", "A"/* "" + DatabaseMetaData.tableIndexOther, "3", "B", "A"/*
* , * ,
* null, * null,
...@@ -787,9 +787,10 @@ public class TestMetaData extends TestBase { ...@@ -787,9 +787,10 @@ public class TestMetaData extends TestBase {
*/}, }); */}, });
trace("getPrimaryKeys"); trace("getPrimaryKeys");
rs = meta.getPrimaryKeys(null, null, "T_2"); rs = meta.getPrimaryKeys(null, null, "T_2");
testResultSetOrdered(rs, new String[][] { { catalog, Constants.SCHEMA_MAIN, "T_2", "A", "2", "PRIMARY_KEY_14" }, testResultSetOrdered(rs, new String[][] {
{ catalog, Constants.SCHEMA_MAIN, "T_2", "B", "3", "PRIMARY_KEY_14" }, { catalog, Constants.SCHEMA_MAIN, "T_2", "A", "2", "PRIMARY_KEY_1" },
{ catalog, Constants.SCHEMA_MAIN, "T_2", "C", "1", "PRIMARY_KEY_14" }, }); { catalog, Constants.SCHEMA_MAIN, "T_2", "B", "3", "PRIMARY_KEY_1" },
{ catalog, Constants.SCHEMA_MAIN, "T_2", "C", "1", "PRIMARY_KEY_1" }, });
stat.executeUpdate("DROP TABLE TX2"); stat.executeUpdate("DROP TABLE TX2");
stat.executeUpdate("DROP TABLE T_2"); stat.executeUpdate("DROP TABLE T_2");
stat.executeUpdate("CREATE TABLE PARENT(ID INT PRIMARY KEY)"); stat.executeUpdate("CREATE TABLE PARENT(ID INT PRIMARY KEY)");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论