Search in sources :

Example 41 with Trace

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;
                    }
                }
            }
        }
    }
}
Also used : Value(org.h2.value.Value) Data(org.h2.store.Data)

Example 42 with Trace

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;
        }
    }
}
Also used : DataReader(org.h2.store.DataReader) CompressLZF(org.h2.compress.CompressLZF) StatementBuilder(org.h2.util.StatementBuilder) Data(org.h2.store.Data) Row(org.h2.result.Row) SimpleRow(org.h2.result.SimpleRow)

Example 43 with Trace

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;
}
Also used : Trace(org.h2.message.Trace) Expression(org.h2.expression.Expression)

Example 44 with Trace

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;
}
Also used : Trace(org.h2.message.Trace) Index(org.h2.index.Index) Constraint(org.h2.constraint.Constraint)

Example 45 with Trace

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;
    }
}
Also used : StringWriter(java.io.StringWriter) SQLException(java.sql.SQLException) JdbcSQLException(org.h2.jdbc.JdbcSQLException) JdbcSQLException(org.h2.jdbc.JdbcSQLException) DbException(org.h2.message.DbException) SQLException(java.sql.SQLException) IOException(java.io.IOException) JdbcSQLException(org.h2.jdbc.JdbcSQLException) PrintWriter(java.io.PrintWriter)

Aggregations

SQLException (java.sql.SQLException)16 DbException (org.h2.message.DbException)14 Connection (java.sql.Connection)11 ResultSet (java.sql.ResultSet)10 PreparedStatement (java.sql.PreparedStatement)9 Statement (java.sql.Statement)8 IOException (java.io.IOException)7 Savepoint (java.sql.Savepoint)7 Random (java.util.Random)7 ArrayList (java.util.ArrayList)5 Properties (java.util.Properties)5 TraceSystem (org.h2.message.TraceSystem)5 Server (org.h2.tools.Server)5 ValueString (org.h2.value.ValueString)5 SQLClientInfoException (java.sql.SQLClientInfoException)4 SysProperties (org.h2.engine.SysProperties)4 JdbcConnection (org.h2.jdbc.JdbcConnection)4 SortedProperties (org.h2.util.SortedProperties)4 Value (org.h2.value.Value)4 Socket (java.net.Socket)3