提交 1234ad70 authored 作者: Thomas Mueller Graf's avatar Thomas Mueller Graf

Formatting

上级 5c555202
......@@ -7,7 +7,7 @@ SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...]
FROM tableExpression [,...] [ WHERE expression ]
[ GROUP BY expression [,...] ] [ HAVING expression ]
[ { UNION [ ALL ] | MINUS | EXCEPT | INTERSECT } select ] [ ORDER BY order [,...] ]
[ [ LIMIT expression ] [ OFFSET expression ] [ SAMPLE_SIZE rowCountInt ] ]
[ [ LIMIT expression ] [ OFFSET expression ] [ SAMPLE_SIZE rowCountInt ] ]
[ FOR UPDATE ]
","
Selects data from a table or multiple tables.
......
......@@ -1885,8 +1885,8 @@ public class Parser {
parseJoinTableFilter(filter, command);
} while (readIf(","));
// Parser can reorder joined table filters, need to explicitly sort them to
// get the order as it was in the original query.
// Parser can reorder joined table filters, need to explicitly sort them
// to get the order as it was in the original query.
if (session.isForceJoinOrder()) {
sortTableFilters(command.getTopFilters());
}
......
......@@ -232,7 +232,8 @@ class Optimizer {
/**
* Calculate the best query plan to use.
*
* @param parse If we do not need to really get the best plan because it is a view parsing stage.
* @param parse If we do not need to really get the best plan because it is
* a view parsing stage.
*/
void optimize(boolean parse) {
if (parse) {
......
......@@ -73,7 +73,7 @@ public abstract class Query extends Prepared {
/**
* Check if this is a UNION query.
*
*
* @return {@code true} if this is a UNION query
*/
public abstract boolean isUnion();
......
......@@ -963,7 +963,7 @@ public class Select extends Query {
TableFilter f = getTopTableFilter();
do {
if (f.getNestedJoin() != null) {
// we do not support batching with nested joins
// we do not support batching with nested joins
return;
}
list.add(f);
......
......@@ -302,6 +302,13 @@ public class Database implements DataHandler {
}
}
/**
* Create a new row for a table.
*
* @param data the values
* @param memory whether the row is in memory
* @return the created row
*/
public Row createRow(Value[] data, int memory) {
return rowFactory.createRow(data, memory);
}
......
......@@ -170,15 +170,33 @@ public class Session extends SessionWithState {
return joinBatchEnabled;
}
/**
* Create a new row for a table.
*
* @param data the values
* @param memory whether the row is in memory
* @return the created row
*/
public Row createRow(Value[] data, int memory) {
return database.createRow(data, memory);
}
/**
* Add a subquery info on top of the subquery info stack.
*
* @param masks the mask
* @param filters the filters
* @param filter the filter index
* @param sortOrder the sort order
*/
public void pushSubQueryInfo(int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder) {
subQueryInfo = new SubQueryInfo(subQueryInfo, masks, filters, filter, sortOrder);
}
/**
* Remove the current subquery info from the stack.
*/
public void popSubQueryInfo() {
subQueryInfo = subQueryInfo.getUpper();
}
......@@ -198,8 +216,15 @@ public class Session extends SessionWithState {
return parsingView != 0;
}
/**
* Optimize a query. This will remember the subquery info, clear it, prepare
* the query, and reset the subquery info.
*
* @param query the query to prepare
*/
public void optimizeQueryExpression(Query query) {
// we have to hide current subQueryInfo if we are going to optimize query expression
// we have to hide current subQueryInfo if we are going to optimize
// query expression
SubQueryInfo tmp = subQueryInfo;
subQueryInfo = null;
preparingQueryExpression++;
......@@ -1376,10 +1401,19 @@ public class Session extends SessionWithState {
}
}
/**
* Get the view cache for this session. There are two caches: the subquery
* cache (which is only use for a single query, has no bounds, and is
* cleared after use), and the cache for regular views.
*
* @param subQuery true to get the subquery cache
* @return the view cache
*/
public Map<Object, ViewIndex> getViewIndexCache(boolean subQuery) {
if (subQuery) {
// for sub-queries we don't need to use LRU because the cache should not
// grow too large for a single query (we drop the whole cache in the end of prepareLocal)
// for sub-queries we don't need to use LRU because the cache should
// not grow too large for a single query (we drop the whole cache in
// the end of prepareLocal)
if (subQueryIndexCache == null) {
subQueryIndexCache = New.hashMap();
}
......@@ -1572,6 +1606,9 @@ public class Session extends SessionWithState {
closeTemporaryResults();
}
/**
* Clear the view cache for this session.
*/
public void clearViewIndexCache() {
viewIndexCache = null;
}
......
......@@ -153,15 +153,17 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
* b-tree range index. This is the estimated cost required to search one
* row, and then iterate over the given number of rows.
*
* @param masks the IndexCondition search masks, one for each Column in the table
* @param masks the IndexCondition search masks, one for each column in the
* table
* @param rowCount the number of rows in the index
* @param filters all joined table filters
* @param filter the current table filter index
* @param sortOrder the sort order
* @return the estimated cost
*/
protected final long getCostRangeIndex(int[] masks, long rowCount, TableFilter[] filters, int filter,
SortOrder sortOrder, boolean isScanIndex) {
protected final long getCostRangeIndex(int[] masks, long rowCount,
TableFilter[] filters, int filter, SortOrder sortOrder,
boolean isScanIndex) {
rowCount += Constants.COST_ROW_OFFSET;
int totalSelectivity = 0;
long rowsCost = rowCount;
......@@ -175,7 +177,8 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
rowsCost = 3;
break;
}
totalSelectivity = 100 - ((100 - totalSelectivity) * (100 - column.getSelectivity()) / 100);
totalSelectivity = 100 - ((100 - totalSelectivity) *
(100 - column.getSelectivity()) / 100);
long distinctRows = rowCount * totalSelectivity / 100;
if (distinctRows <= 0) {
distinctRows = 1;
......@@ -279,7 +282,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
}
return rc;
}
@Override
public int compareRows(SearchRow rowData, SearchRow compare) {
if (rowData == compare) {
......
......@@ -258,11 +258,12 @@ public interface Index extends SchemaObject {
void setSortedInsertMode(boolean sortedInsertMode);
/**
* Creates new lookup batch. Note that returned {@link IndexLookupBatch} instance
* can be used multiple times.
* Creates new lookup batch. Note that returned {@link IndexLookupBatch}
* instance can be used multiple times.
*
* @param filter Table filter.
* @return Created batch or {@code null} if batched lookup is not supported by this index.
* @return created batch or {@code null} if batched lookup is not supported
* by this index.
*/
IndexLookupBatch createLookupBatch(TableFilter filter);
}
......@@ -10,13 +10,14 @@ import java.util.concurrent.Future;
import org.h2.result.SearchRow;
/**
* Support for asynchronous batched lookups in indexes. The flow is the following:
* H2 engine will be calling {@link #addSearchRows(SearchRow, SearchRow)} until
* method {@link #isBatchFull()}} will return {@code true} or there are no more
* search rows to add. Then method {@link #find()} will be called to execute batched lookup.
* Note that a single instance of {@link IndexLookupBatch} can be reused for multiple
* sequential batched lookups, moreover it can be reused for multiple queries for
* the same prepared statement.
* Support for asynchronous batched lookups in indexes. The flow is the
* following: H2 engine will be calling
* {@link #addSearchRows(SearchRow, SearchRow)} until method
* {@link #isBatchFull()} will return {@code true} or there are no more search
* rows to add. Then method {@link #find()} will be called to execute batched
* lookup. Note that a single instance of {@link IndexLookupBatch} can be reused
* for multiple sequential batched lookups, moreover it can be reused for
* multiple queries for the same prepared statement.
*
* @see Index#createLookupBatch(org.h2.table.TableFilter)
* @author Sergi Vladykin
......@@ -27,8 +28,8 @@ public interface IndexLookupBatch {
*
* @param first the first row, or null for no limit
* @param last the last row, or null for no limit
* @return {@code false} if this search row pair is known to produce no results
* and thus the given row pair was not added
* @return {@code false} if this search row pair is known to produce no
* results and thus the given row pair was not added
* @see Index#find(org.h2.table.TableFilter, SearchRow, SearchRow)
*/
boolean addSearchRows(SearchRow first, SearchRow last);
......@@ -42,10 +43,11 @@ public interface IndexLookupBatch {
boolean isBatchFull();
/**
* Execute batched lookup and return future cursor for each provided
* search row pair. Note that this method must return exactly the same number
* of future cursors in result list as number of {@link #addSearchRows(SearchRow, SearchRow)}
* calls has been done before {@link #find()} call exactly in the same order.
* Execute batched lookup and return future cursor for each provided search
* row pair. Note that this method must return exactly the same number of
* future cursors in result list as number of
* {@link #addSearchRows(SearchRow, SearchRow)} calls has been done before
* {@link #find()} call exactly in the same order.
*
* @return List of future cursors for collected search rows.
*/
......@@ -59,7 +61,8 @@ public interface IndexLookupBatch {
String getPlanSQL();
/**
* Reset this batch to clear state. This method will be called before and after each query execution.
* Reset this batch to clear state. This method will be called before and
* after each query execution.
*
* @param beforeQuery if it is being called before query execution
*/
......
......@@ -69,12 +69,14 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
columns = new Column[0];
this.createSession = null;
this.indexMasks = null;
// this is a main index of TableView, it does not need eviction time stamp
// this is a main index of TableView, it does not need eviction time
// stamp
evaluatedAt = Long.MIN_VALUE;
}
/**
* Constructor for plan item generation. Over this index the query will be executed.
* Constructor for plan item generation. Over this index the query will be
* executed.
*
* @param view the table view
* @param index the view index
......@@ -97,9 +99,10 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
if (!recursive) {
query = getQuery(session, masks, filters, filter, sortOrder);
}
// we don't need eviction for recursive views since we can't calculate their cost
// if it is a sub-query we don't need eviction as well because the whole ViewIndex cache
// is getting dropped in Session.prepareLocal
// we don't need eviction for recursive views since we can't calculate
// their cost if it is a sub-query we don't need eviction as well
// because the whole ViewIndex cache is getting dropped in
// Session.prepareLocal
evaluatedAt = recursive || view.getTopQuery() != null ? Long.MAX_VALUE : System.nanoTime();
}
......
......@@ -13,7 +13,8 @@ import java.nio.ByteBuffer;
public class WriteBuffer {
/**
* The maximum size of the buffer in order to be re-used after a clear operation.
* The maximum size of the buffer in order to be re-used after a clear
* operation.
*/
private static final int MAX_REUSE_CAPACITY = 4 * 1024 * 1024;
......
......@@ -237,9 +237,10 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
}
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return SpatialTreeIndex.getCostRangeIndex(masks, table.getRowCountApproximation(), columns);
public double getCost(Session session, int[] masks, TableFilter[] filters,
int filter, SortOrder sortOrder) {
return SpatialTreeIndex.getCostRangeIndex(masks,
table.getRowCountApproximation(), columns);
}
@Override
......
......@@ -113,7 +113,7 @@
90084=Kann das letzte Feld nicht löschen {0}
90085=Index {0} gehört zur Bedingung {1}
90086=Klasse {0} nicht gefunden
90087=Method {0} with matching arguments not found
90087=Methode {0} nicht gefunden
90088=Unbekannter Modus {0}
90089=Textvergleich-Modus kann nicht geändert werden wenn eine Daten-Tabelle existiert : {0}
90090=Schema {0} kann nicht gelöscht werden
......
......@@ -7,7 +7,7 @@ SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...]
FROM tableExpression [,...] [ WHERE expression ]
[ GROUP BY expression [,...] ] [ HAVING expression ]
[ { UNION [ ALL ] | MINUS | EXCEPT | INTERSECT } select ] [ ORDER BY order [,...] ]
[ LIMIT expression [ OFFSET expression ] [ SAMPLE_SIZE rowCountInt ] ]
[ [ LIMIT expression ] [ OFFSET expression ] [ SAMPLE_SIZE rowCountInt ] ]
[ FOR UPDATE ]
","
Selects data from a table or multiple tables."
......
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import org.h2.value.Value;
......@@ -16,9 +21,9 @@ public abstract class RowFactory {
/**
* Create new row.
*
* @param data row values
* @param memory memory
* @return created row
* @param data the values
* @param memory whether the row is in memory
* @return the created row
*/
public abstract Row createRow(Value[] data, int memory);
......
......@@ -87,8 +87,10 @@ public final class JoinBatch {
*/
public JoinBatch(int filtersCount, TableFilter additionalFilter) {
if (filtersCount > 32) {
// This is because we store state in a 64 bit field, 2 bits per joined table.
throw DbException.getUnsupportedException("Too many tables in join (at most 32 supported).");
// This is because we store state in a 64 bit field, 2 bits per
// joined table.
throw DbException.getUnsupportedException(
"Too many tables in join (at most 32 supported).");
}
filters = new JoinFilter[filtersCount];
this.additionalFilter = additionalFilter;
......@@ -107,7 +109,8 @@ public final class JoinBatch {
/**
* Reset state of this batch.
*
* @param beforeQuery {@code true} if reset was called before the query run, {@code false} if after
* @param beforeQuery {@code true} if reset was called before the query run,
* {@code false} if after
*/
public void reset(boolean beforeQuery) {
current = null;
......@@ -167,7 +170,8 @@ public final class JoinBatch {
cursor = indexCursor;
}
current.updateRow(top.id, cursor, JoinRow.S_NULL, JoinRow.S_CURSOR);
// we need fake first row because batchedNext always will move to the next row
// we need fake first row because batchedNext always will move to the
// next row
JoinRow fake = new JoinRow(null);
fake.next = current;
current = fake;
......@@ -199,7 +203,8 @@ public final class JoinBatch {
found = true;
additionalFilter.reset();
}
// we call furtherFilter in usual way outside of this batch because it is more effective
// we call furtherFilter in usual way outside of this batch because
// it is more effective
if (additionalFilter.next()) {
return true;
}
......@@ -241,7 +246,8 @@ public final class JoinBatch {
fetchCurrent(jfId);
if (!current.isDropped()) {
// if current was not dropped then it must be fetched successfully
// if current was not dropped then it must be fetched
// successfully
if (jfId == lastJfId) {
// the whole join row is ready to be returned
return true;
......@@ -257,7 +263,8 @@ public final class JoinBatch {
continue;
}
}
// we have to go down and fetch next cursors for jfId if it is possible
// we have to go down and fetch next cursors for jfId if it is
// possible
if (current.next == null) {
// either dropped or null-row
if (current.isDropped()) {
......@@ -273,8 +280,8 @@ public final class JoinBatch {
while (current.row(jfId) != null) {
jfId++;
}
// force find on half filled batch (there must be either searchRows
// or Cursor.EMPTY set for null-rows)
// force find on half filled batch (there must be either
// searchRows or Cursor.EMPTY set for null-rows)
current = filters[jfId].find(current);
} else {
// here we don't care if the current was dropped
......@@ -305,7 +312,8 @@ public final class JoinBatch {
if (newCursor) {
if (jfId == 0) {
// the top cursor is new and empty, then the whole select will not produce any rows
// the top cursor is new and empty, then the whole select will
// not produce any rows
current.drop();
return;
}
......@@ -371,7 +379,8 @@ public final class JoinBatch {
* Create index lookup batch for a view index.
*
* @param viewIndex view index
* @return index lookup batch or {@code null} if batching is not supported for this query
* @return index lookup batch or {@code null} if batching is not supported
* for this query
*/
public static IndexLookupBatch createViewIndexLookupBatch(ViewIndex viewIndex) {
Query query = viewIndex.getQuery();
......@@ -465,7 +474,8 @@ public final class JoinBatch {
JoinRow find(JoinRow current) {
assert current != null;
// lookupBatch is allowed to be empty when we have some null-rows and forced find call
// lookupBatch is allowed to be empty when we have some null-rows
// and forced find call
List<Future<Cursor>> result = lookupBatch.find();
// go backwards and assign futures
......@@ -523,10 +533,16 @@ public final class JoinBatch {
/**
* May contain one of the following:
* <br/>- {@code null}: means that we need to get future cursor for this row
* <br/>- {@link Future}: means that we need to get a new {@link Cursor} from the {@link Future}
* <br/>- {@link Cursor}: means that we need to fetch {@link Row}s from the {@link Cursor}
* <br/>- {@link Row}: the {@link Row} is already fetched and is ready to be used
* <ul>
* <li>{@code null}: means that we need to get future cursor
* for this row</li>
* <li>{@link Future}: means that we need to get a new {@link Cursor}
* from the {@link Future}</li>
* <li>{@link Cursor}: means that we need to fetch {@link Row}s from the
* {@link Cursor}</li>
* <li>{@link Row}: the {@link Row} is already fetched and is ready to
* be used</li>
* </ul>
*/
private Object[] row;
private long state;
......@@ -603,7 +619,8 @@ public final class JoinBatch {
}
/**
* Copy this JoinRow behind itself in linked list of all in progress rows.
* Copy this JoinRow behind itself in linked list of all in progress
* rows.
*
* @param jfId The last fetched filter id.
* @return The copy.
......@@ -636,8 +653,8 @@ public final class JoinBatch {
}
/**
* Fake Lookup batch for indexes which do not support batching but have to participate
* in batched joins.
* Fake Lookup batch for indexes which do not support batching but have to
* participate in batched joins.
*/
private static final class FakeLookupBatch implements IndexLookupBatch {
private final TableFilter filter;
......@@ -747,7 +764,8 @@ public final class JoinBatch {
return false;
}
findCalled = false;
// method find was called, we need to reset futures to initial state for reuse
// method find was called, we need to reset futures to initial state
// for reuse
for (int i = 0; i < resultSize; i++) {
queryRunner(i).reset();
}
......@@ -862,12 +880,14 @@ public final class JoinBatch {
@Override
protected void startQueryRunners(int resultSize) {
// we do batched find only for top table filter and then lazily run the ViewIndex query
// for each received top future cursor
// we do batched find only for top table filter and then lazily run
// the ViewIndex query for each received top future cursor
List<Future<Cursor>> topFutureCursors = top.find();
if (topFutureCursors.size() != resultSize) {
throw DbException.throwInternalError("Unexpected result size: " + topFutureCursors.size() +
", expected :" + resultSize);
throw DbException
.throwInternalError("Unexpected result size: " +
topFutureCursors.size() + ", expected :" +
resultSize);
}
for (int i = 0; i < resultSize; i++) {
QueryRunner r = queryRunner(i);
......@@ -895,7 +915,8 @@ public final class JoinBatch {
@Override
protected Cursor run() throws Exception {
if (topFutureCursor == null) {
// if the top cursor is empty then the whole query will produce empty result
// if the top cursor is empty then the whole query will produce
// empty result
return EMPTY_CURSOR;
}
viewIndex.setupQueryParameters(viewIndex.getSession(), first, last, null);
......
......@@ -120,7 +120,7 @@ public class Plan {
PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i);
planItems.put(tableFilter, item);
if (t.isDebugEnabled()) {
t.debug("Plan : best plan item cost {0} index {1}",
t.debug("Plan : best plan item cost {0} index {1}",
item.cost, item.getIndex().getPlanSQL());
}
cost += cost * item.cost;
......
......@@ -10,7 +10,7 @@ import org.h2.result.SortOrder;
/**
* Information about current sub-query being prepared.
*
*
* @author Sergi Vladykin
*/
public class SubQueryInfo {
......
......@@ -639,7 +639,8 @@ public abstract class Table extends SchemaObjectBase {
Row getNullRow() {
Row row = nullRow;
if (row == null) {
// Here can be concurrently produced more than one row, but it must be ok.
// Here can be concurrently produced more than one row, but it must
// be ok.
Value[] values = new Value[columns.length];
Arrays.fill(values, ValueNull.INSTANCE);
nullRow = row = database.createRow(values, 1);
......
......@@ -123,7 +123,8 @@ public class TableFilter implements ColumnResolver {
* @param alias the alias name
* @param rightsChecked true if rights are already checked
* @param select the select statement
* @param orderInFrom Original order number of this table filter in FROM clause.
* @param orderInFrom Original order number of this table filter in FROM
* clause.
*/
public TableFilter(Session session, Table table, String alias,
boolean rightsChecked, Select select, int orderInFrom) {
......@@ -374,7 +375,8 @@ public class TableFilter implements ColumnResolver {
* Attempt to initialize batched join.
*
* @param jb join batch if it is already created
* @return join batch if query runs over index which supports batched lookups, {@code null} otherwise
* @return join batch if query runs over index which supports batched
* lookups, {@code null} otherwise
*/
public JoinBatch prepareJoinBatch(JoinBatch jb, TableFilter[] filters, int filter) {
joinBatch = null;
......@@ -387,13 +389,15 @@ public class TableFilter implements ColumnResolver {
session.popSubQueryInfo();
}
}
// For globally top table filter we don't need to create lookup batch, because
// currently it will not be used (this will be shown in ViewIndex.getPlanSQL()). Probably
// later on it will make sense to create it to better support X IN (...) conditions,
// but this needs to be implemented separately. If isAlwaysTopTableFilter is false
// then we either not a top table filter or top table filter in a sub-query, which
// in turn is not top in outer query, thus we need to enable batching here to allow
// outer query run batched join against this sub-query.
// For globally top table filter we don't need to create lookup batch,
// because currently it will not be used (this will be shown in
// ViewIndex.getPlanSQL()). Probably later on it will make sense to
// create it to better support X IN (...) conditions, but this needs to
// be implemented separately. If isAlwaysTopTableFilter is false then we
// either not a top table filter or top table filter in a sub-query,
// which in turn is not top in outer query, thus we need to enable
// batching here to allow outer query run batched join against this
// sub-query.
IndexLookupBatch lookupBatch = null;
if (jb == null && select != null && !isAlwaysTopTableFilter(filter)) {
lookupBatch = index.createLookupBatch(this);
......@@ -408,11 +412,13 @@ public class TableFilter implements ColumnResolver {
joinBatch = jb;
joinFilterId = filter;
if (lookupBatch == null && !isAlwaysTopTableFilter(filter)) {
// createLookupBatch will be called at most once because jb can be
// created only if lookupBatch is already not null from the call above.
// createLookupBatch will be called at most once because jb can
// be created only if lookupBatch is already not null from the
// call above.
lookupBatch = index.createLookupBatch(this);
if (lookupBatch == null) {
// the index does not support lookup batching, need to fake it because we are not top
// the index does not support lookup batching, need to fake
// it because we are not top
lookupBatch = JoinBatch.createFakeIndexLookupBatch(this);
}
}
......@@ -436,7 +442,8 @@ public class TableFilter implements ColumnResolver {
*/
public boolean next() {
if (joinBatch != null) {
// will happen only on topTableFilter since joinBatch.next() does not call join.next()
// will happen only on topTableFilter since joinBatch.next() does
// not call join.next()
return joinBatch.next();
}
if (state == AFTER_LAST) {
......
......@@ -121,7 +121,8 @@ public class TableView extends Table {
* @return the exception if re-compiling this or any dependent view failed
* (only when force is disabled)
*/
public synchronized DbException recompile(Session session, boolean force, boolean clearIndexCache) {
public synchronized DbException recompile(Session session, boolean force,
boolean clearIndexCache) {
try {
compileViewQuery(session, querySQL);
} catch (DbException e) {
......
......@@ -12,24 +12,25 @@ import java.util.concurrent.TimeoutException;
/**
* Future which is already done.
*
*
* @param <T> Result value.
* @author Sergi Vladykin
*/
public class DoneFuture<T> implements Future<T> {
final T x;
public DoneFuture(T x) {
this.x = x;
}
@Override
public T get() throws InterruptedException, ExecutionException {
return x;
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
public T get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return x;
}
......@@ -37,17 +38,17 @@ public class DoneFuture<T> implements Future<T> {
public boolean isDone() {
return true;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public String toString() {
return "DoneFuture->" + x;
......
......@@ -12,8 +12,8 @@ import java.util.concurrent.TimeUnit;
import org.h2.message.DbException;
/**
* Single threaded lazy future.
*
* Single threaded lazy future.
*
* @param <T>
* @author Sergi Vladykin
*/
......@@ -23,15 +23,15 @@ public abstract class LazyFuture<T> implements Future<T> {
private static final int S_DONE = 1;
private static final int S_ERROR = 2;
private static final int S_CANCELED = 3;
private int state = S_READY;
private T result;
private Exception error;
/**
* Reset this future to the initial state.
*
* @return {@code false} if it was already in initial state
*
* @return {@code false} if it was already in initial state
*/
public boolean reset() {
if (state == S_READY) {
......@@ -45,11 +45,11 @@ public abstract class LazyFuture<T> implements Future<T> {
/**
* Run computation and produce the result.
*
*
* @return the result of computation
*/
protected abstract T run() throws Exception;
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (state != S_READY) {
......
......@@ -220,7 +220,9 @@ public class ToChar {
}
StringBuilder output = new StringBuilder();
String unscaled = (number.abs().compareTo(BigDecimal.ONE) < 0 ? zeroesAfterDecimalSeparator(number) : "") + number.unscaledValue().abs().toString();
String unscaled = (number.abs().compareTo(BigDecimal.ONE) < 0 ?
zeroesAfterDecimalSeparator(number) : "") +
number.unscaledValue().abs().toString();
// start at the decimal point and fill in the numbers to the left,
// working our way from right to left
......
......@@ -56,7 +56,8 @@ public final class ValueTimestampUtc extends Value {
if (nanos < 0 || nanos >= 1000 * 1000) {
throw new IllegalArgumentException("nanos out of range " + nanos);
}
return (ValueTimestampUtc) Value.cache(new ValueTimestampUtc(utcDateTimeMillis * 1000 * 1000 + nanos));
return (ValueTimestampUtc) Value.cache(new ValueTimestampUtc(
utcDateTimeMillis * 1000 * 1000 + nanos));
}
/**
......@@ -189,12 +190,17 @@ public final class ValueTimestampUtc extends Value {
}
if (targetScale < 0) {
throw DbException.getInvalidValueException("scale", targetScale);
} /*
* TODO long n = timeNanos; BigDecimal bd = BigDecimal.valueOf(n); bd
* = bd.movePointLeft(9); bd = ValueDecimal.setScale(bd, targetScale);
* bd = bd.movePointRight(9); long n2 = bd.longValue(); if (n2 == n) {
* return this; }
*/
}
// TODO
// long n = timeNanos;
// BigDecimal bd = BigDecimal.valueOf(n);
// bd = bd.movePointLeft(9);
// bd = ValueDecimal.setScale(bd, targetScale);
// bd = bd.movePointRight(9);
// long n2 = bd.longValue();
// if (n2 == n) {
// return this;
// }
return this;
}
......
......@@ -21,7 +21,8 @@ import javax.tools.Diagnostic;
*/
public class TestAnnotationProcessor extends AbstractProcessor {
public static final String MESSAGES_KEY = TestAnnotationProcessor.class.getName() + "-messages";
public static final String MESSAGES_KEY =
TestAnnotationProcessor.class.getName() + "-messages";
@Override
public Set<String> getSupportedAnnotationTypes() {
......@@ -45,7 +46,9 @@ public class TestAnnotationProcessor extends AbstractProcessor {
if (split.length == 2) {
outputMessages.add(new OutputMessage(Diagnostic.Kind.valueOf(split[0]), split[1]));
} else {
throw new IllegalStateException("Unable to parse messages definition for: '" + messagesStr + "'");
throw new IllegalStateException(
"Unable to parse messages definition for: '" +
messagesStr + "'");
}
}
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, Version 1.0,
and under the Eclipse Public License, Version 1.0
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
An annotation processor used for testing.
</p></body></html>
\ No newline at end of file
......@@ -1028,26 +1028,37 @@ public class TestOptimizations extends TestBase {
conn.close();
}
private void testUseCoveringIndex() throws SQLException {
deleteDb("optimizations");
Connection conn = getConnection("optimizations");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TBL_A(id IDENTITY PRIMARY KEY NOT NULL, name VARCHAR NOT NULL, active BOOLEAN DEFAULT TRUE, UNIQUE KEY TBL_A_UK (name) )");
stat.execute("CREATE TABLE TBL_B(id IDENTITY PRIMARY KEY NOT NULL, tbl_a_id BIGINT NOT NULL, createDate TIMESTAMP DEFAULT NOW(), UNIQUE KEY TBL_B_UK (tbl_a_id, createDate), FOREIGN KEY (tbl_a_id) REFERENCES TBL_A(id) )");
stat.execute("INSERT INTO TBL_A (name) SELECT 'package_' || CAST(X as VARCHAR) FROM SYSTEM_RANGE(1, 100) WHERE X <= 100");
stat.execute("INSERT INTO TBL_B (tbl_a_id, createDate) SELECT CASE WHEN tbl_a_id = 0 THEN 1 ELSE tbl_a_id END, createDate FROM ( SELECT ROUND((RAND() * 100)) AS tbl_a_id, DATEADD('SECOND', X, NOW()) as createDate FROM SYSTEM_RANGE(1, 50000) WHERE X < 50000 )");
stat.execute("CREATE TABLE TBL_A(id IDENTITY PRIMARY KEY NOT NULL, " +
"name VARCHAR NOT NULL, active BOOLEAN DEFAULT TRUE, " +
"UNIQUE KEY TBL_A_UK (name) )");
stat.execute("CREATE TABLE TBL_B(id IDENTITY PRIMARY KEY NOT NULL, " +
"tbl_a_id BIGINT NOT NULL, createDate TIMESTAMP DEFAULT NOW(), " +
"UNIQUE KEY TBL_B_UK (tbl_a_id, createDate), " +
"FOREIGN KEY (tbl_a_id) REFERENCES TBL_A(id) )");
stat.execute("INSERT INTO TBL_A (name) SELECT 'package_' || CAST(X as VARCHAR) " +
"FROM SYSTEM_RANGE(1, 100) WHERE X <= 100");
stat.execute("INSERT INTO TBL_B (tbl_a_id, createDate) SELECT " +
"CASE WHEN tbl_a_id = 0 THEN 1 ELSE tbl_a_id END, createDate " +
"FROM ( SELECT ROUND((RAND() * 100)) AS tbl_a_id, " +
"DATEADD('SECOND', X, NOW()) as createDate FROM SYSTEM_RANGE(1, 50000) " +
"WHERE X < 50000 )");
stat.execute("CREATE INDEX tbl_b_idx ON tbl_b(tbl_a_id, id)");
stat.execute("ANALYZE");
stat.execute("ANALYZE");
ResultSet rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(b.id) as id FROM tbl_b b JOIN tbl_a a ON b.tbl_a_id = a.id GROUP BY b.tbl_a_id HAVING A.ACTIVE = TRUE");
rs.next();
ResultSet rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(b.id) as id " +
"FROM tbl_b b JOIN tbl_a a ON b.tbl_a_id = a.id GROUP BY b.tbl_a_id " +
"HAVING A.ACTIVE = TRUE");
rs.next();
assertContains(rs.getString(1), "/* PUBLIC.TBL_B_IDX: TBL_A_ID = A.ID */");
rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(id) FROM tbl_b GROUP BY tbl_a_id");
rs.next();
rs.next();
assertContains(rs.getString(1), "/* PUBLIC.TBL_B_IDX");
conn.close();
}
}
......@@ -125,7 +125,8 @@ public class TestOptimizerHints extends TestBase {
}
}
private void checkPlanJoin(Statement s, boolean on, boolean left, String ... t) throws SQLException {
private void checkPlanJoin(Statement s, boolean on, boolean left,
String... t) throws SQLException {
StatementBuilder from = new StatementBuilder();
for (int i = 0; i < t.length; i++) {
if (i != 0) {
......@@ -145,7 +146,7 @@ public class TestOptimizerHints extends TestBase {
int prev = plan.indexOf("FROM PUBLIC." + t[0].toUpperCase());
for (int i = 1; i < t.length; i++) {
int next = plan.indexOf(
(!left ? "INNER JOIN PUBLIC." : on ? "LEFT OUTER JOIN PUBLIC." : "PUBLIC.") +
(!left ? "INNER JOIN PUBLIC." : on ? "LEFT OUTER JOIN PUBLIC." : "PUBLIC.") +
t[i].toUpperCase());
if (prev > next) {
System.err.println(plan);
......
......@@ -59,7 +59,8 @@ public class TestView extends TestBase {
Connection conn = getConnection("view");
Statement stat = conn.createStatement();
stat.execute("drop table test if exists");
stat.execute("create table test(id int primary key, name varchar(25) unique, age int unique)");
stat.execute("create table test(id int primary key, " +
"name varchar(25) unique, age int unique)");
// check that initial cache size is empty
Session s = (Session) ((JdbcConnection) conn).getSession();
......
......@@ -307,9 +307,10 @@ public class BuildBase {
*/
protected int execScript(String script, StringList args) {
if (isWindows()) {
// Under windows, we use the "cmd" command interpreter since it will search the path for us
// without us having to hardcode an extension for the script we want.
// (Sometimes we don't know if the extension will be .bat or .cmd)
// Under windows, we use the "cmd" command interpreter since it will
// search the path for us without us having to hardcode an extension
// for the script we want. (Sometimes we don't know if the extension
// will be .bat or .cmd)
StringList newArgs = new StringList();
newArgs.add("/C");
newArgs.add(script);
......
......@@ -27,7 +27,7 @@ public class CheckTextFiles {
private static final String[] SUFFIX_CHECK = { "html", "jsp", "js", "css",
"bat", "nsi", "java", "txt", "properties", "sql", "xml", "csv",
"Driver", "prefs" };
"Driver", "Processor", "prefs" };
private static final String[] SUFFIX_IGNORE = { "gif", "png", "odg", "ico",
"sxd", "layout", "res", "win", "jar", "task", "svg", "MF", "mf",
"sh", "DS_Store", "prop" };
......
......@@ -25,7 +25,7 @@ import org.h2.util.Utils;
public class SpellChecker {
private static final String[] SUFFIX = { "html", "java", "sql", "txt",
"xml", "jsp", "css", "bat", "csv", "xml", "js", "Driver",
"xml", "jsp", "css", "bat", "csv", "xml", "js", "Driver", "Processor",
"properties", "task", "MF", "mf", "sh", "" };
private static final String[] IGNORE = { "dev", "nsi", "gif", "png", "odg",
"ico", "sxd", "zip", "bz2", "rc", "layout", "res", "dll", "jar",
......
......@@ -200,14 +200,22 @@ public class UploadBuild {
if (!ftp.exists("/httpdocs/m2-repo/com/h2database/h2-mvstore", "1.0-SNAPSHOT")) {
ftp.makeDirectory("/httpdocs/m2-repo/com/h2database/h2-mvstore/1.0-SNAPSHOT");
}
ftp.store("/httpdocs/m2-repo/com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.pom",
new FileInputStream(mavenRepoDir + "com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.pom"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.jar",
new FileInputStream(mavenRepoDir + "com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.jar"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.pom",
new FileInputStream(mavenRepoDir + "com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.pom"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.jar",
new FileInputStream(mavenRepoDir + "com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.jar"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2" +
"/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.pom",
new FileInputStream(mavenRepoDir +
"com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.pom"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2" +
"/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.jar",
new FileInputStream(mavenRepoDir +
"com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.jar"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2-mvstore" +
"/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.pom",
new FileInputStream(mavenRepoDir +
"com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.pom"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2-mvstore" +
"/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.jar",
new FileInputStream(mavenRepoDir +
"com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.jar"));
}
ftp.close();
}
......
......@@ -778,3 +778,10 @@ dance schedule hitting reverted youngest footers inliner deadlocked reorder nger
nullid syspublic sysibmts sysibminternal syscat sysfun sysstat systools sysibmadm
sysproc jcc expecting gpg showed unreferenced activating cvf stephane lacoin
centrale umr ecole nantes sticc lab reordering preferable simultaneously
--- todo
timestamputc lazily satisfy nexpected messager participating eviction milli globally
futures atp lookups batches slot nnext forced tbl diagnostic filer stamp turn going
nwhere hardcode cancellation qry nprev fetched produced nactual incurring interpreter
batching ncurr prefered fewer runners iter
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论