use of org.h2.message.Trace in project h2database by h2database.
the class Recover method dumpPageDataLeaf.
private void dumpPageDataLeaf(PrintWriter writer, Data s, boolean last, long pageId, int columnCount, int entryCount) {
long[] keys = new long[entryCount];
int[] offsets = new int[entryCount];
long next = 0;
if (!last) {
next = s.readInt();
writer.println("-- next: " + next);
}
int empty = pageSize;
for (int i = 0; i < entryCount; i++) {
keys[i] = s.readVarLong();
int off = s.readShortInt();
empty = Math.min(off, empty);
offsets[i] = off;
}
stat.pageDataRows += pageSize - empty;
empty = empty - s.length();
stat.pageDataHead += s.length();
stat.pageDataEmpty += empty;
if (trace) {
writer.println("-- empty: " + empty);
}
if (!last) {
Data s2 = Data.create(this, pageSize);
s.setPos(pageSize);
long parent = pageId;
while (true) {
checkParent(writer, parent, new int[] { (int) next }, 0);
parent = next;
seek(next);
store.readFully(s2.getBytes(), 0, pageSize);
s2.reset();
int type = s2.readByte();
s2.readShortInt();
s2.readInt();
if (type == (Page.TYPE_DATA_OVERFLOW | Page.FLAG_LAST)) {
int size = s2.readShortInt();
writer.println("-- chain: " + next + " type: " + type + " size: " + size);
s.checkCapacity(size);
s.write(s2.getBytes(), s2.length(), size);
break;
} else if (type == Page.TYPE_DATA_OVERFLOW) {
next = s2.readInt();
if (next == 0) {
writeDataError(writer, "next:0", s2.getBytes());
break;
}
int size = pageSize - s2.length();
writer.println("-- chain: " + next + " type: " + type + " size: " + size + " next: " + next);
s.checkCapacity(size);
s.write(s2.getBytes(), s2.length(), size);
} else {
writeDataError(writer, "type: " + type, s2.getBytes());
break;
}
}
}
for (int i = 0; i < entryCount; i++) {
long key = keys[i];
int off = offsets[i];
if (trace) {
writer.println("-- [" + i + "] storage: " + storageId + " key: " + key + " off: " + off);
}
s.setPos(off);
Value[] data = createRecord(writer, s, columnCount);
if (data != null) {
createTemporaryTable(writer);
writeRow(writer, s, data);
if (remove && storageId == 0) {
String sql = data[3].getString();
if (sql.startsWith("CREATE USER ")) {
int saltIndex = Utils.indexOf(s.getBytes(), "SALT ".getBytes(), off);
if (saltIndex >= 0) {
String userName = sql.substring("CREATE USER ".length(), sql.indexOf("SALT ") - 1);
if (userName.startsWith("IF NOT EXISTS ")) {
userName = userName.substring("IF NOT EXISTS ".length());
}
if (userName.startsWith("\"")) {
// TODO doesn't work for all cases ("" inside
// user name)
userName = userName.substring(1, userName.length() - 1);
}
byte[] userPasswordHash = SHA256.getKeyPasswordHash(userName, "".toCharArray());
byte[] salt = MathUtils.secureRandomBytes(Constants.SALT_LEN);
byte[] passwordHash = SHA256.getHashWithSalt(userPasswordHash, salt);
StringBuilder buff = new StringBuilder();
buff.append("SALT '").append(StringUtils.convertBytesToHex(salt)).append("' HASH '").append(StringUtils.convertBytesToHex(passwordHash)).append('\'');
byte[] replacement = buff.toString().getBytes();
System.arraycopy(replacement, 0, s.getBytes(), saltIndex, replacement.length);
seek(pageId);
store.write(s.getBytes(), 0, pageSize);
if (trace) {
out.println("User: " + userName);
}
remove = false;
}
}
}
}
}
}
use of org.h2.message.Trace in project h2database by h2database.
the class Recover method dumpPageLogStream.
private void dumpPageLogStream(PrintWriter writer, int logKey, int logFirstTrunkPage, int logFirstDataPage, long pageCount) throws IOException {
Data s = Data.create(this, pageSize);
DataReader in = new DataReader(new PageInputStream(writer, this, store, logKey, logFirstTrunkPage, logFirstDataPage, pageSize));
writer.println("---- Transaction log ----");
CompressLZF compress = new CompressLZF();
while (true) {
int x = in.readByte();
if (x < 0) {
break;
}
if (x == PageLog.NOOP) {
// ignore
} else if (x == PageLog.UNDO) {
int pageId = in.readVarInt();
int size = in.readVarInt();
byte[] data = new byte[pageSize];
if (size == 0) {
in.readFully(data, pageSize);
} else if (size == 1) {
// empty
} else {
byte[] compressBuffer = new byte[size];
in.readFully(compressBuffer, size);
try {
compress.expand(compressBuffer, 0, size, data, 0, pageSize);
} catch (ArrayIndexOutOfBoundsException e) {
throw DbException.convertToIOException(e);
}
}
String typeName = "";
int type = data[0];
boolean last = (type & Page.FLAG_LAST) != 0;
type &= ~Page.FLAG_LAST;
switch(type) {
case Page.TYPE_EMPTY:
typeName = "empty";
break;
case Page.TYPE_DATA_LEAF:
typeName = "data leaf " + (last ? "(last)" : "");
break;
case Page.TYPE_DATA_NODE:
typeName = "data node " + (last ? "(last)" : "");
break;
case Page.TYPE_DATA_OVERFLOW:
typeName = "data overflow " + (last ? "(last)" : "");
break;
case Page.TYPE_BTREE_LEAF:
typeName = "b-tree leaf " + (last ? "(last)" : "");
break;
case Page.TYPE_BTREE_NODE:
typeName = "b-tree node " + (last ? "(last)" : "");
break;
case Page.TYPE_FREE_LIST:
typeName = "free list " + (last ? "(last)" : "");
break;
case Page.TYPE_STREAM_TRUNK:
typeName = "log trunk";
break;
case Page.TYPE_STREAM_DATA:
typeName = "log data";
break;
default:
typeName = "ERROR: unknown type " + type;
break;
}
writer.println("-- undo page " + pageId + " " + typeName);
if (trace) {
Data d = Data.create(null, data);
dumpPage(writer, d, pageId, pageCount);
}
} else if (x == PageLog.ADD) {
int sessionId = in.readVarInt();
setStorage(in.readVarInt());
Row row = PageLog.readRow(RowFactory.DEFAULT, in, s);
writer.println("-- session " + sessionId + " table " + storageId + " + " + row.toString());
if (transactionLog) {
if (storageId == 0 && row.getColumnCount() >= 4) {
int tableId = (int) row.getKey();
String sql = row.getValue(3).getString();
String name = extractTableOrViewName(sql);
if (row.getValue(2).getInt() == DbObject.TABLE_OR_VIEW) {
tableMap.put(tableId, name);
}
writer.println(sql + ";");
} else {
String tableName = tableMap.get(storageId);
if (tableName != null) {
StatementBuilder buff = new StatementBuilder();
buff.append("INSERT INTO ").append(tableName).append(" VALUES(");
for (int i = 0; i < row.getColumnCount(); i++) {
buff.appendExceptFirst(", ");
buff.append(row.getValue(i).getSQL());
}
buff.append(");");
writer.println(buff.toString());
}
}
}
} else if (x == PageLog.REMOVE) {
int sessionId = in.readVarInt();
setStorage(in.readVarInt());
long key = in.readVarLong();
writer.println("-- session " + sessionId + " table " + storageId + " - " + key);
if (transactionLog) {
if (storageId == 0) {
int tableId = (int) key;
String tableName = tableMap.get(tableId);
if (tableName != null) {
writer.println("DROP TABLE IF EXISTS " + tableName + ";");
}
} else {
String tableName = tableMap.get(storageId);
if (tableName != null) {
String sql = "DELETE FROM " + tableName + " WHERE _ROWID_ = " + key + ";";
writer.println(sql);
}
}
}
} else if (x == PageLog.TRUNCATE) {
int sessionId = in.readVarInt();
setStorage(in.readVarInt());
writer.println("-- session " + sessionId + " table " + storageId + " truncate");
if (transactionLog) {
writer.println("TRUNCATE TABLE " + storageId);
}
} else if (x == PageLog.COMMIT) {
int sessionId = in.readVarInt();
writer.println("-- commit " + sessionId);
} else if (x == PageLog.ROLLBACK) {
int sessionId = in.readVarInt();
writer.println("-- rollback " + sessionId);
} else if (x == PageLog.PREPARE_COMMIT) {
int sessionId = in.readVarInt();
String transaction = in.readString();
writer.println("-- prepare commit " + sessionId + " " + transaction);
} else if (x == PageLog.NOOP) {
// nothing to do
} else if (x == PageLog.CHECKPOINT) {
writer.println("-- checkpoint");
} else if (x == PageLog.FREE_LOG) {
int size = in.readVarInt();
StringBuilder buff = new StringBuilder("-- free");
for (int i = 0; i < size; i++) {
buff.append(' ').append(in.readVarInt());
}
writer.println(buff);
} else {
writer.println("-- ERROR: unknown operation " + x);
break;
}
}
}
use of org.h2.message.Trace in project h2database by h2database.
the class Plan method calculateCost.
/**
* Calculate the cost of this query plan.
*
* @param session the session
* @return the cost
*/
public double calculateCost(Session session) {
Trace t = session.getTrace();
if (t.isDebugEnabled()) {
t.debug("Plan : calculate cost for plan {0}", Arrays.toString(allFilters));
}
double cost = 1;
boolean invalidPlan = false;
final HashSet<Column> allColumnsSet = ExpressionVisitor.allColumnsForTableFilters(allFilters);
for (int i = 0; i < allFilters.length; i++) {
TableFilter tableFilter = allFilters[i];
if (t.isDebugEnabled()) {
t.debug("Plan : for table filter {0}", tableFilter);
}
PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i, allColumnsSet);
planItems.put(tableFilter, item);
if (t.isDebugEnabled()) {
t.debug("Plan : best plan item cost {0} index {1}", item.cost, item.getIndex().getPlanSQL());
}
cost += cost * item.cost;
setEvaluatable(tableFilter, true);
Expression on = tableFilter.getJoinCondition();
if (on != null) {
if (!on.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) {
invalidPlan = true;
break;
}
}
}
if (invalidPlan) {
cost = Double.POSITIVE_INFINITY;
}
if (t.isDebugEnabled()) {
session.getTrace().debug("Plan : plan cost {0}", cost);
}
for (TableFilter f : allFilters) {
setEvaluatable(f, false);
}
return cost;
}
use of org.h2.message.Trace in project h2database by h2database.
the class Table method getBestPlanItem.
/**
* Get the best plan for the given search mask.
*
* @param session the session
* @param masks per-column comparison bit masks, null means 'always false',
* see constants in IndexCondition
* @param filters all joined table filters
* @param filter the current table filter index
* @param sortOrder the sort order
* @param allColumnsSet the set of all columns
* @return the plan item
*/
public PlanItem getBestPlanItem(Session session, int[] masks, TableFilter[] filters, int filter, SortOrder sortOrder, HashSet<Column> allColumnsSet) {
PlanItem item = new PlanItem();
item.setIndex(getScanIndex(session));
item.cost = item.getIndex().getCost(session, null, filters, filter, null, allColumnsSet);
Trace t = session.getTrace();
if (t.isDebugEnabled()) {
t.debug("Table : potential plan item cost {0} index {1}", item.cost, item.getIndex().getPlanSQL());
}
ArrayList<Index> indexes = getIndexes();
IndexHints indexHints = getIndexHints(filters, filter);
if (indexes != null && masks != null) {
for (int i = 1, size = indexes.size(); i < size; i++) {
Index index = indexes.get(i);
if (isIndexExcludedByHints(indexHints, index)) {
continue;
}
double cost = index.getCost(session, masks, filters, filter, sortOrder, allColumnsSet);
if (t.isDebugEnabled()) {
t.debug("Table : potential plan item cost {0} index {1}", cost, index.getPlanSQL());
}
if (cost < item.cost) {
item.cost = cost;
item.setIndex(index);
}
}
}
return item;
}
use of org.h2.message.Trace in project h2database by h2database.
the class TcpServerThread method sendError.
private void sendError(Throwable t) {
try {
SQLException e = DbException.convert(t).getSQLException();
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String trace = writer.toString();
String message;
String sql;
if (e instanceof JdbcSQLException) {
JdbcSQLException j = (JdbcSQLException) e;
message = j.getOriginalMessage();
sql = j.getSQL();
} else {
message = e.getMessage();
sql = null;
}
transfer.writeInt(SessionRemote.STATUS_ERROR).writeString(e.getSQLState()).writeString(message).writeString(sql).writeInt(e.getErrorCode()).writeString(trace).flush();
} catch (Exception e2) {
if (!transfer.isClosed()) {
server.traceError(e2);
}
// if writing the error does not work, close the connection
stop = true;
}
}
Aggregations