提交 12b01b74 authored 作者: Thomas Mueller's avatar Thomas Mueller

With version 1.3.156, the DB2 mode could not be used with CLOB and BLOB data.…

With version 1.3.156, the DB2 mode could not be used with CLOB and BLOB data. When upgrading from an older 1.3.x version to version 1.3.156, CLOB and BLOB data was lost in many cases.
上级 980d4471
......@@ -447,11 +447,6 @@ public interface CommandInterface {
*/
int SHUTDOWN_DEFRAG = 84;
/**
* The type of a ALTER TABLE ADD IF NOT EXISTS statement.
*/
int ALTER_TABLE_ADD_COLUMN_IF_NOT_EXISTS = 85;
/**
* Get command type.
*
......
......@@ -4799,6 +4799,7 @@ public class Parser {
AlterTableRename command = new AlterTableRename(session, getSchema());
command.setOldTable(table);
command.setNewTableName(newName);
command.setHidden(readIf("HIDDEN"));
return command;
} else if (readIf("DROP")) {
if (readIf("CONSTRAINT")) {
......@@ -4817,10 +4818,14 @@ public class Parser {
return command;
} else {
readIf("COLUMN");
boolean ifExists = readIfExists(false);
AlterTableAlterColumn command = new AlterTableAlterColumn(session, table.getSchema());
command.setType(CommandInterface.ALTER_TABLE_DROP_COLUMN);
String columnName = readColumnIdentifier();
command.setTable(table);
if (ifExists && !table.doesColumnExist(columnName)) {
return new NoOperation(session);
}
command.setOldColumn(table.getColumn(columnName));
return command;
}
......@@ -4914,9 +4919,8 @@ public class Parser {
boolean ifNotExists = readIfNoExists();
Schema schema = table.getSchema();
AlterTableAlterColumn command = new AlterTableAlterColumn(session, schema);
command.setType(ifNotExists ?
CommandInterface.ALTER_TABLE_ADD_COLUMN_IF_NOT_EXISTS :
CommandInterface.ALTER_TABLE_ADD_COLUMN);
command.setIfNotExists(ifNotExists);
command.setType(CommandInterface.ALTER_TABLE_ADD_COLUMN);
command.setTable(table);
String columnName = readColumnIdentifier();
Column column = parseColumnForTable(columnName, true);
......@@ -5124,13 +5128,7 @@ public class Parser {
command.setIfNotExists(ifNotExists);
command.setTableName(tableName);
command.setComment(readCommentIf());
if (readIf("AS")) {
if (readIf("SORTED")) {
command.setSortedInsertMode(true);
}
command.setQuery(parseSelect());
} else {
read("(");
if (readIf("(")) {
if (!readIf(")")) {
do {
DefineCommand c = parseAlterTableAddConstraintIf(tableName, schema);
......@@ -5202,12 +5200,6 @@ public class Parser {
}
} while (readIfMore());
}
if (readIf("AS")) {
if (readIf("SORTED")) {
command.setSortedInsertMode(true);
}
command.setQuery(parseSelect());
}
}
if (readIf("ENGINE")) {
command.setTableEngine(readUniqueIdentifier());
......@@ -5238,6 +5230,12 @@ public class Parser {
if (readIf("HIDDEN")) {
command.setHidden(true);
}
if (readIf("AS")) {
if (readIf("SORTED")) {
command.setSortedInsertMode(true);
}
command.setQuery(parseSelect());
}
return command;
}
......
......@@ -54,6 +54,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
private Expression defaultExpression;
private Expression newSelectivity;
private String addBefore;
private boolean ifNotExists;
public AlterTableAlterColumn(Session session, Schema schema) {
super(session, schema);
......@@ -124,17 +125,13 @@ public class AlterTableAlterColumn extends SchemaCommand {
break;
}
case CommandInterface.ALTER_TABLE_ADD_COLUMN: {
if (ifNotExists && table.doesColumnExist(newColumn.getName())) {
break;
}
convertAutoIncrementColumn(newColumn);
copyData();
break;
}
case CommandInterface.ALTER_TABLE_ADD_COLUMN_IF_NOT_EXISTS: {
if (!table.doesColumnExist(newColumn.getName())) {
convertAutoIncrementColumn(newColumn);
copyData();
}
break;
}
case CommandInterface.ALTER_TABLE_DROP_COLUMN: {
if (table.getColumns().length == 1) {
throw DbException.get(ErrorCode.CANNOT_DROP_LAST_COLUMN, oldColumn.getSQL());
......@@ -253,8 +250,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
if (type == CommandInterface.ALTER_TABLE_DROP_COLUMN) {
int position = oldColumn.getColumnId();
newColumns.remove(position);
} else if (type == CommandInterface.ALTER_TABLE_ADD_COLUMN
|| type == CommandInterface.ALTER_TABLE_ADD_COLUMN_IF_NOT_EXISTS) {
} else if (type == CommandInterface.ALTER_TABLE_ADD_COLUMN) {
int position;
if (addBefore == null) {
position = columns.length;
......@@ -281,6 +277,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
data.temporary = table.isTemporary();
data.persistData = table.isPersistData();
data.persistIndexes = table.isPersistIndexes();
data.isHidden = table.isHidden();
data.create = true;
data.session = session;
Table newTable = getSchema().createTable(data);
......@@ -292,8 +289,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
if (columnList.length() > 0) {
columnList.append(", ");
}
if ((type == CommandInterface.ALTER_TABLE_ADD_COLUMN
|| type == CommandInterface.ALTER_TABLE_ADD_COLUMN_IF_NOT_EXISTS) && nc == newColumn) {
if (type == CommandInterface.ALTER_TABLE_ADD_COLUMN && nc == newColumn) {
Expression def = nc.getDefaultExpression();
columnList.append(def == null ? "NULL" : def.getSQL());
} else {
......@@ -460,4 +456,8 @@ public class AlterTableAlterColumn extends SchemaCommand {
return type;
}
public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}
}
......@@ -23,6 +23,7 @@ public class AlterTableRename extends SchemaCommand {
private Table oldTable;
private String newTableName;
private boolean hidden;
public AlterTableRename(Session session, Schema schema) {
super(session, schema);
......@@ -39,12 +40,21 @@ public class AlterTableRename extends SchemaCommand {
public int update() {
session.commit(true);
Database db = session.getDatabase();
if (getSchema().findTableOrView(session, newTableName) != null || newTableName.equals(oldTable.getName())) {
session.getUser().checkRight(oldTable, Right.ALL);
Table t = getSchema().findTableOrView(session, newTableName);
if (t != null && hidden && newTableName.equals(oldTable.getName())) {
if (!t.isHidden()) {
t.setHidden(hidden);
oldTable.setHidden(true);
db.update(session, oldTable);
}
return 0;
}
if (t != null || newTableName.equals(oldTable.getName())) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, newTableName);
}
session.getUser().checkRight(oldTable, Right.ALL);
if (oldTable.isTemporary()) {
throw DbException.getUnsupportedException("TEMP TABLE");
throw DbException.getUnsupportedException("temp table");
}
db.renameSchemaObject(session, oldTable, newTableName);
return 0;
......@@ -54,4 +64,8 @@ public class AlterTableRename extends SchemaCommand {
return CommandInterface.ALTER_TABLE_RENAME;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
}
......@@ -100,9 +100,11 @@ public class LobStorage {
stat.execute("CREATE INDEX IF NOT EXISTS " +
"INFORMATION_SCHEMA.INDEX_LOB_TABLE ON " + LOBS + "(TABLE)");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_MAP +
"(LOB BIGINT, SEQ INT, OFFSET BIGINT, HASH INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ)) HIDDEN");
stat.execute("ALTER TABLE " + LOB_MAP +
" ADD IF NOT EXISTS OFFSET BIGINT BEFORE HASH");
"(LOB BIGINT, SEQ INT, POS BIGINT, HASH INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ)) HIDDEN");
// TODO the column name OFFSET was used in version 1.3.156, so this can be remove in a later version
stat.execute("ALTER TABLE " + LOB_MAP + " RENAME TO " + LOB_MAP + " HIDDEN");
stat.execute("ALTER TABLE " + LOB_MAP + " ADD IF NOT EXISTS POS BIGINT BEFORE HASH");
stat.execute("ALTER TABLE " + LOB_MAP + " DROP COLUMN IF EXISTS \"OFFSET\"");
stat.execute("CREATE INDEX IF NOT EXISTS " +
"INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON " + LOB_MAP + "(BLOCK, LOB)");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_DATA +
......@@ -213,31 +215,31 @@ public class LobStorage {
}
/**
* Retrieve the sequence id and offset that is smaller than the requested
* offset. Those values can be used to quickly skip to a given position
* Retrieve the sequence id and position that is smaller than the requested
* position. Those values can be used to quickly skip to a given position
* without having to read all data.
*
* @param lob the lob
* @param offset the required offset
* @param pos the required position
* @return null if the data is not available, or an array of two elements:
* the sequence, and the offset
*/
long[] skipBuffer(long lob, long offset) throws SQLException {
long[] skipBuffer(long lob, long pos) throws SQLException {
synchronized (handler) {
String sql = "SELECT MAX(SEQ), MAX(OFFSET) FROM " + LOB_MAP +
" WHERE LOB = ? AND OFFSET < ?";
String sql = "SELECT MAX(SEQ), MAX(POS) FROM " + LOB_MAP +
" WHERE LOB = ? AND POS < ?";
PreparedStatement prep = prepare(sql);
prep.setLong(1, lob);
prep.setLong(2, offset);
prep.setLong(2, pos);
ResultSet rs = prep.executeQuery();
rs.next();
int seq = rs.getInt(1);
offset = rs.getLong(2);
pos = rs.getLong(2);
boolean wasNull = rs.wasNull();
rs.close();
reuse(sql, prep);
// upgraded: offset not set
return wasNull ? null : new long[]{seq, offset};
return wasNull ? null : new long[]{seq, pos};
}
}
......@@ -273,12 +275,12 @@ public class LobStorage {
if (n > BLOCK_LENGTH) {
long toPos = length - remainingBytes + n;
try {
long[] seqOffset = skipBuffer(lob, toPos);
if (seqOffset == null) {
long[] seqPos = skipBuffer(lob, toPos);
if (seqPos == null) {
return super.skip(n);
}
seq = (int) seqOffset[0];
n = toPos - seqOffset[1];
seq = (int) seqPos[0];
n = toPos - seqPos[1];
} catch (SQLException e) {
throw DbException.convertToIOException(e);
}
......@@ -541,8 +543,8 @@ public class LobStorage {
try {
init();
long lobId = getNextLobId();
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, OFFSET, HASH, BLOCK) " +
"SELECT ?, SEQ, OFFSET, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?";
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) " +
"SELECT ?, SEQ, POS, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?";
PreparedStatement prep = prepare(sql);
prep.setLong(1, lobId);
prep.setLong(2, oldLobId);
......@@ -590,11 +592,11 @@ public class LobStorage {
*
* @param lobId the lob id
* @param seq the sequence number
* @param offset the offset within the lob
* @param pos the position within the lob
* @param b the data
* @param compressAlgorithm the compression algorithm (may be null)
*/
void storeBlock(long lobId, int seq, long offset, byte[] b, String compressAlgorithm) throws SQLException {
void storeBlock(long lobId, int seq, long pos, byte[] b, String compressAlgorithm) throws SQLException {
long block;
boolean blockExists = false;
if (compressAlgorithm != null) {
......@@ -629,11 +631,11 @@ public class LobStorage {
prep.execute();
reuse(sql, prep);
}
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, OFFSET, HASH, BLOCK) VALUES(?, ?, ?, ?, ?)";
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) VALUES(?, ?, ?, ?, ?)";
PreparedStatement prep = prepare(sql);
prep.setLong(1, lobId);
prep.setInt(2, seq);
prep.setLong(3, offset);
prep.setLong(3, pos);
prep.setLong(4, hash);
prep.setLong(5, block);
prep.execute();
......
......@@ -1072,4 +1072,8 @@ public abstract class Table extends SchemaObjectBase {
return isHidden;
}
public void setHidden(boolean hidden) {
this.isHidden = hidden;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论