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