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

Formatting

上级 5c555202
...@@ -7,7 +7,7 @@ SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...] ...@@ -7,7 +7,7 @@ SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...]
FROM tableExpression [,...] [ WHERE expression ] FROM tableExpression [,...] [ WHERE expression ]
[ GROUP BY expression [,...] ] [ HAVING expression ] [ GROUP BY expression [,...] ] [ HAVING expression ]
[ { UNION [ ALL ] | MINUS | EXCEPT | INTERSECT } select ] [ ORDER BY order [,...] ] [ { 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 ] [ FOR UPDATE ]
"," ","
Selects data from a table or multiple tables. Selects data from a table or multiple tables.
......
...@@ -1885,8 +1885,8 @@ public class Parser { ...@@ -1885,8 +1885,8 @@ public class Parser {
parseJoinTableFilter(filter, command); parseJoinTableFilter(filter, command);
} while (readIf(",")); } while (readIf(","));
// Parser can reorder joined table filters, need to explicitly sort them to // Parser can reorder joined table filters, need to explicitly sort them
// get the order as it was in the original query. // to get the order as it was in the original query.
if (session.isForceJoinOrder()) { if (session.isForceJoinOrder()) {
sortTableFilters(command.getTopFilters()); sortTableFilters(command.getTopFilters());
} }
......
...@@ -232,7 +232,8 @@ class Optimizer { ...@@ -232,7 +232,8 @@ class Optimizer {
/** /**
* Calculate the best query plan to use. * 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) { void optimize(boolean parse) {
if (parse) { if (parse) {
......
...@@ -73,7 +73,7 @@ public abstract class Query extends Prepared { ...@@ -73,7 +73,7 @@ public abstract class Query extends Prepared {
/** /**
* Check if this is a UNION query. * Check if this is a UNION query.
* *
* @return {@code true} if this is a UNION query * @return {@code true} if this is a UNION query
*/ */
public abstract boolean isUnion(); public abstract boolean isUnion();
......
...@@ -963,7 +963,7 @@ public class Select extends Query { ...@@ -963,7 +963,7 @@ public class Select extends Query {
TableFilter f = getTopTableFilter(); TableFilter f = getTopTableFilter();
do { do {
if (f.getNestedJoin() != null) { if (f.getNestedJoin() != null) {
// we do not support batching with nested joins // we do not support batching with nested joins
return; return;
} }
list.add(f); list.add(f);
......
...@@ -302,6 +302,13 @@ public class Database implements DataHandler { ...@@ -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) { public Row createRow(Value[] data, int memory) {
return rowFactory.createRow(data, memory); return rowFactory.createRow(data, memory);
} }
......
...@@ -170,15 +170,33 @@ public class Session extends SessionWithState { ...@@ -170,15 +170,33 @@ public class Session extends SessionWithState {
return joinBatchEnabled; 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) { public Row createRow(Value[] data, int memory) {
return database.createRow(data, 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, public void pushSubQueryInfo(int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder) { SortOrder sortOrder) {
subQueryInfo = new SubQueryInfo(subQueryInfo, masks, filters, filter, sortOrder); subQueryInfo = new SubQueryInfo(subQueryInfo, masks, filters, filter, sortOrder);
} }
/**
* Remove the current subquery info from the stack.
*/
public void popSubQueryInfo() { public void popSubQueryInfo() {
subQueryInfo = subQueryInfo.getUpper(); subQueryInfo = subQueryInfo.getUpper();
} }
...@@ -198,8 +216,15 @@ public class Session extends SessionWithState { ...@@ -198,8 +216,15 @@ public class Session extends SessionWithState {
return parsingView != 0; 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) { 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 tmp = subQueryInfo;
subQueryInfo = null; subQueryInfo = null;
preparingQueryExpression++; preparingQueryExpression++;
...@@ -1376,10 +1401,19 @@ public class Session extends SessionWithState { ...@@ -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) { public Map<Object, ViewIndex> getViewIndexCache(boolean subQuery) {
if (subQuery) { if (subQuery) {
// for sub-queries we don't need to use LRU because the cache should not // for sub-queries we don't need to use LRU because the cache should
// grow too large for a single query (we drop the whole cache in the end of prepareLocal) // not grow too large for a single query (we drop the whole cache in
// the end of prepareLocal)
if (subQueryIndexCache == null) { if (subQueryIndexCache == null) {
subQueryIndexCache = New.hashMap(); subQueryIndexCache = New.hashMap();
} }
...@@ -1572,6 +1606,9 @@ public class Session extends SessionWithState { ...@@ -1572,6 +1606,9 @@ public class Session extends SessionWithState {
closeTemporaryResults(); closeTemporaryResults();
} }
/**
* Clear the view cache for this session.
*/
public void clearViewIndexCache() { public void clearViewIndexCache() {
viewIndexCache = null; viewIndexCache = null;
} }
......
...@@ -153,15 +153,17 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -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 * b-tree range index. This is the estimated cost required to search one
* row, and then iterate over the given number of rows. * 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 rowCount the number of rows in the index
* @param filters all joined table filters * @param filters all joined table filters
* @param filter the current table filter index * @param filter the current table filter index
* @param sortOrder the sort order * @param sortOrder the sort order
* @return the estimated cost * @return the estimated cost
*/ */
protected final long getCostRangeIndex(int[] masks, long rowCount, TableFilter[] filters, int filter, protected final long getCostRangeIndex(int[] masks, long rowCount,
SortOrder sortOrder, boolean isScanIndex) { TableFilter[] filters, int filter, SortOrder sortOrder,
boolean isScanIndex) {
rowCount += Constants.COST_ROW_OFFSET; rowCount += Constants.COST_ROW_OFFSET;
int totalSelectivity = 0; int totalSelectivity = 0;
long rowsCost = rowCount; long rowsCost = rowCount;
...@@ -175,7 +177,8 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -175,7 +177,8 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
rowsCost = 3; rowsCost = 3;
break; break;
} }
totalSelectivity = 100 - ((100 - totalSelectivity) * (100 - column.getSelectivity()) / 100); totalSelectivity = 100 - ((100 - totalSelectivity) *
(100 - column.getSelectivity()) / 100);
long distinctRows = rowCount * totalSelectivity / 100; long distinctRows = rowCount * totalSelectivity / 100;
if (distinctRows <= 0) { if (distinctRows <= 0) {
distinctRows = 1; distinctRows = 1;
...@@ -279,7 +282,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -279,7 +282,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
} }
return rc; return rc;
} }
@Override @Override
public int compareRows(SearchRow rowData, SearchRow compare) { public int compareRows(SearchRow rowData, SearchRow compare) {
if (rowData == compare) { if (rowData == compare) {
......
...@@ -258,11 +258,12 @@ public interface Index extends SchemaObject { ...@@ -258,11 +258,12 @@ public interface Index extends SchemaObject {
void setSortedInsertMode(boolean sortedInsertMode); void setSortedInsertMode(boolean sortedInsertMode);
/** /**
* Creates new lookup batch. Note that returned {@link IndexLookupBatch} instance * Creates new lookup batch. Note that returned {@link IndexLookupBatch}
* can be used multiple times. * instance can be used multiple times.
* *
* @param filter Table filter. * @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); IndexLookupBatch createLookupBatch(TableFilter filter);
} }
...@@ -10,13 +10,14 @@ import java.util.concurrent.Future; ...@@ -10,13 +10,14 @@ import java.util.concurrent.Future;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
/** /**
* Support for asynchronous batched lookups in indexes. The flow is the following: * Support for asynchronous batched lookups in indexes. The flow is the
* H2 engine will be calling {@link #addSearchRows(SearchRow, SearchRow)} until * following: H2 engine will be calling
* method {@link #isBatchFull()}} will return {@code true} or there are no more * {@link #addSearchRows(SearchRow, SearchRow)} until method
* search rows to add. Then method {@link #find()} will be called to execute batched lookup. * {@link #isBatchFull()} will return {@code true} or there are no more search
* Note that a single instance of {@link IndexLookupBatch} can be reused for multiple * rows to add. Then method {@link #find()} will be called to execute batched
* sequential batched lookups, moreover it can be reused for multiple queries for * lookup. Note that a single instance of {@link IndexLookupBatch} can be reused
* the same prepared statement. * 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) * @see Index#createLookupBatch(org.h2.table.TableFilter)
* @author Sergi Vladykin * @author Sergi Vladykin
...@@ -27,8 +28,8 @@ public interface IndexLookupBatch { ...@@ -27,8 +28,8 @@ public interface IndexLookupBatch {
* *
* @param first the first row, or null for no limit * @param first the first row, or null for no limit
* @param last the last 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 * @return {@code false} if this search row pair is known to produce no
* and thus the given row pair was not added * results and thus the given row pair was not added
* @see Index#find(org.h2.table.TableFilter, SearchRow, SearchRow) * @see Index#find(org.h2.table.TableFilter, SearchRow, SearchRow)
*/ */
boolean addSearchRows(SearchRow first, SearchRow last); boolean addSearchRows(SearchRow first, SearchRow last);
...@@ -42,10 +43,11 @@ public interface IndexLookupBatch { ...@@ -42,10 +43,11 @@ public interface IndexLookupBatch {
boolean isBatchFull(); boolean isBatchFull();
/** /**
* Execute batched lookup and return future cursor for each provided * Execute batched lookup and return future cursor for each provided search
* search row pair. Note that this method must return exactly the same number * row pair. Note that this method must return exactly the same number of
* of future cursors in result list as number of {@link #addSearchRows(SearchRow, SearchRow)} * future cursors in result list as number of
* calls has been done before {@link #find()} call exactly in the same order. * {@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. * @return List of future cursors for collected search rows.
*/ */
...@@ -59,7 +61,8 @@ public interface IndexLookupBatch { ...@@ -59,7 +61,8 @@ public interface IndexLookupBatch {
String getPlanSQL(); 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 * @param beforeQuery if it is being called before query execution
*/ */
......
...@@ -69,12 +69,14 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -69,12 +69,14 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
columns = new Column[0]; columns = new Column[0];
this.createSession = null; this.createSession = null;
this.indexMasks = 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; 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 view the table view
* @param index the view index * @param index the view index
...@@ -97,9 +99,10 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -97,9 +99,10 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
if (!recursive) { if (!recursive) {
query = getQuery(session, masks, filters, filter, sortOrder); query = getQuery(session, masks, filters, filter, sortOrder);
} }
// we don't need eviction for recursive views since we can't calculate their cost // we don't need eviction for recursive views since we can't calculate
// if it is a sub-query we don't need eviction as well because the whole ViewIndex cache // their cost if it is a sub-query we don't need eviction as well
// is getting dropped in Session.prepareLocal // because the whole ViewIndex cache is getting dropped in
// Session.prepareLocal
evaluatedAt = recursive || view.getTopQuery() != null ? Long.MAX_VALUE : System.nanoTime(); evaluatedAt = recursive || view.getTopQuery() != null ? Long.MAX_VALUE : System.nanoTime();
} }
......
...@@ -13,7 +13,8 @@ import java.nio.ByteBuffer; ...@@ -13,7 +13,8 @@ import java.nio.ByteBuffer;
public class WriteBuffer { 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; private static final int MAX_REUSE_CAPACITY = 4 * 1024 * 1024;
......
...@@ -237,9 +237,10 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex { ...@@ -237,9 +237,10 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
} }
@Override @Override
public double getCost(Session session, int[] masks, public double getCost(Session session, int[] masks, TableFilter[] filters,
TableFilter[] filters, int filter, SortOrder sortOrder) { int filter, SortOrder sortOrder) {
return SpatialTreeIndex.getCostRangeIndex(masks, table.getRowCountApproximation(), columns); return SpatialTreeIndex.getCostRangeIndex(masks,
table.getRowCountApproximation(), columns);
} }
@Override @Override
......
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
90084=Kann das letzte Feld nicht löschen {0} 90084=Kann das letzte Feld nicht löschen {0}
90085=Index {0} gehört zur Bedingung {1} 90085=Index {0} gehört zur Bedingung {1}
90086=Klasse {0} nicht gefunden 90086=Klasse {0} nicht gefunden
90087=Method {0} with matching arguments not found 90087=Methode {0} nicht gefunden
90088=Unbekannter Modus {0} 90088=Unbekannter Modus {0}
90089=Textvergleich-Modus kann nicht geändert werden wenn eine Daten-Tabelle existiert : {0} 90089=Textvergleich-Modus kann nicht geändert werden wenn eine Daten-Tabelle existiert : {0}
90090=Schema {0} kann nicht gelöscht werden 90090=Schema {0} kann nicht gelöscht werden
......
...@@ -7,7 +7,7 @@ SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...] ...@@ -7,7 +7,7 @@ SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...]
FROM tableExpression [,...] [ WHERE expression ] FROM tableExpression [,...] [ WHERE expression ]
[ GROUP BY expression [,...] ] [ HAVING expression ] [ GROUP BY expression [,...] ] [ HAVING expression ]
[ { UNION [ ALL ] | MINUS | EXCEPT | INTERSECT } select ] [ ORDER BY order [,...] ] [ { 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 ] [ FOR UPDATE ]
"," ","
Selects data from a table or multiple tables." 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; package org.h2.result;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -16,9 +21,9 @@ public abstract class RowFactory { ...@@ -16,9 +21,9 @@ public abstract class RowFactory {
/** /**
* Create new row. * Create new row.
* *
* @param data row values * @param data the values
* @param memory memory * @param memory whether the row is in memory
* @return created row * @return the created row
*/ */
public abstract Row createRow(Value[] data, int memory); public abstract Row createRow(Value[] data, int memory);
......
...@@ -87,8 +87,10 @@ public final class JoinBatch { ...@@ -87,8 +87,10 @@ public final class JoinBatch {
*/ */
public JoinBatch(int filtersCount, TableFilter additionalFilter) { public JoinBatch(int filtersCount, TableFilter additionalFilter) {
if (filtersCount > 32) { if (filtersCount > 32) {
// This is because we store state in a 64 bit field, 2 bits per joined table. // This is because we store state in a 64 bit field, 2 bits per
throw DbException.getUnsupportedException("Too many tables in join (at most 32 supported)."); // joined table.
throw DbException.getUnsupportedException(
"Too many tables in join (at most 32 supported).");
} }
filters = new JoinFilter[filtersCount]; filters = new JoinFilter[filtersCount];
this.additionalFilter = additionalFilter; this.additionalFilter = additionalFilter;
...@@ -107,7 +109,8 @@ public final class JoinBatch { ...@@ -107,7 +109,8 @@ public final class JoinBatch {
/** /**
* Reset state of this batch. * 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) { public void reset(boolean beforeQuery) {
current = null; current = null;
...@@ -167,7 +170,8 @@ public final class JoinBatch { ...@@ -167,7 +170,8 @@ public final class JoinBatch {
cursor = indexCursor; cursor = indexCursor;
} }
current.updateRow(top.id, cursor, JoinRow.S_NULL, JoinRow.S_CURSOR); 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); JoinRow fake = new JoinRow(null);
fake.next = current; fake.next = current;
current = fake; current = fake;
...@@ -199,7 +203,8 @@ public final class JoinBatch { ...@@ -199,7 +203,8 @@ public final class JoinBatch {
found = true; found = true;
additionalFilter.reset(); 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()) { if (additionalFilter.next()) {
return true; return true;
} }
...@@ -241,7 +246,8 @@ public final class JoinBatch { ...@@ -241,7 +246,8 @@ public final class JoinBatch {
fetchCurrent(jfId); fetchCurrent(jfId);
if (!current.isDropped()) { 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) { if (jfId == lastJfId) {
// the whole join row is ready to be returned // the whole join row is ready to be returned
return true; return true;
...@@ -257,7 +263,8 @@ public final class JoinBatch { ...@@ -257,7 +263,8 @@ public final class JoinBatch {
continue; 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) { if (current.next == null) {
// either dropped or null-row // either dropped or null-row
if (current.isDropped()) { if (current.isDropped()) {
...@@ -273,8 +280,8 @@ public final class JoinBatch { ...@@ -273,8 +280,8 @@ public final class JoinBatch {
while (current.row(jfId) != null) { while (current.row(jfId) != null) {
jfId++; jfId++;
} }
// force find on half filled batch (there must be either searchRows // force find on half filled batch (there must be either
// or Cursor.EMPTY set for null-rows) // searchRows or Cursor.EMPTY set for null-rows)
current = filters[jfId].find(current); current = filters[jfId].find(current);
} else { } else {
// here we don't care if the current was dropped // here we don't care if the current was dropped
...@@ -305,7 +312,8 @@ public final class JoinBatch { ...@@ -305,7 +312,8 @@ public final class JoinBatch {
if (newCursor) { if (newCursor) {
if (jfId == 0) { 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(); current.drop();
return; return;
} }
...@@ -371,7 +379,8 @@ public final class JoinBatch { ...@@ -371,7 +379,8 @@ public final class JoinBatch {
* Create index lookup batch for a view index. * Create index lookup batch for a view index.
* *
* @param viewIndex 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) { public static IndexLookupBatch createViewIndexLookupBatch(ViewIndex viewIndex) {
Query query = viewIndex.getQuery(); Query query = viewIndex.getQuery();
...@@ -465,7 +474,8 @@ public final class JoinBatch { ...@@ -465,7 +474,8 @@ public final class JoinBatch {
JoinRow find(JoinRow current) { JoinRow find(JoinRow current) {
assert current != null; 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(); List<Future<Cursor>> result = lookupBatch.find();
// go backwards and assign futures // go backwards and assign futures
...@@ -523,10 +533,16 @@ public final class JoinBatch { ...@@ -523,10 +533,16 @@ public final class JoinBatch {
/** /**
* May contain one of the following: * May contain one of the following:
* <br/>- {@code null}: means that we need to get future cursor for this row * <ul>
* <br/>- {@link Future}: means that we need to get a new {@link Cursor} from the {@link Future} * <li>{@code null}: means that we need to get future cursor
* <br/>- {@link Cursor}: means that we need to fetch {@link Row}s from the {@link Cursor} * for this row</li>
* <br/>- {@link Row}: the {@link Row} is already fetched and is ready to be used * <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 Object[] row;
private long state; private long state;
...@@ -603,7 +619,8 @@ public final class JoinBatch { ...@@ -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. * @param jfId The last fetched filter id.
* @return The copy. * @return The copy.
...@@ -636,8 +653,8 @@ public final class JoinBatch { ...@@ -636,8 +653,8 @@ public final class JoinBatch {
} }
/** /**
* Fake Lookup batch for indexes which do not support batching but have to participate * Fake Lookup batch for indexes which do not support batching but have to
* in batched joins. * participate in batched joins.
*/ */
private static final class FakeLookupBatch implements IndexLookupBatch { private static final class FakeLookupBatch implements IndexLookupBatch {
private final TableFilter filter; private final TableFilter filter;
...@@ -747,7 +764,8 @@ public final class JoinBatch { ...@@ -747,7 +764,8 @@ public final class JoinBatch {
return false; return false;
} }
findCalled = 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++) { for (int i = 0; i < resultSize; i++) {
queryRunner(i).reset(); queryRunner(i).reset();
} }
...@@ -862,12 +880,14 @@ public final class JoinBatch { ...@@ -862,12 +880,14 @@ public final class JoinBatch {
@Override @Override
protected void startQueryRunners(int resultSize) { protected void startQueryRunners(int resultSize) {
// we do batched find only for top table filter and then lazily run the ViewIndex query // we do batched find only for top table filter and then lazily run
// for each received top future cursor // the ViewIndex query for each received top future cursor
List<Future<Cursor>> topFutureCursors = top.find(); List<Future<Cursor>> topFutureCursors = top.find();
if (topFutureCursors.size() != resultSize) { if (topFutureCursors.size() != resultSize) {
throw DbException.throwInternalError("Unexpected result size: " + topFutureCursors.size() + throw DbException
", expected :" + resultSize); .throwInternalError("Unexpected result size: " +
topFutureCursors.size() + ", expected :" +
resultSize);
} }
for (int i = 0; i < resultSize; i++) { for (int i = 0; i < resultSize; i++) {
QueryRunner r = queryRunner(i); QueryRunner r = queryRunner(i);
...@@ -895,7 +915,8 @@ public final class JoinBatch { ...@@ -895,7 +915,8 @@ public final class JoinBatch {
@Override @Override
protected Cursor run() throws Exception { protected Cursor run() throws Exception {
if (topFutureCursor == null) { 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; return EMPTY_CURSOR;
} }
viewIndex.setupQueryParameters(viewIndex.getSession(), first, last, null); viewIndex.setupQueryParameters(viewIndex.getSession(), first, last, null);
......
...@@ -120,7 +120,7 @@ public class Plan { ...@@ -120,7 +120,7 @@ public class Plan {
PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i); PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i);
planItems.put(tableFilter, item); planItems.put(tableFilter, item);
if (t.isDebugEnabled()) { 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()); item.cost, item.getIndex().getPlanSQL());
} }
cost += cost * item.cost; cost += cost * item.cost;
......
...@@ -10,7 +10,7 @@ import org.h2.result.SortOrder; ...@@ -10,7 +10,7 @@ import org.h2.result.SortOrder;
/** /**
* Information about current sub-query being prepared. * Information about current sub-query being prepared.
* *
* @author Sergi Vladykin * @author Sergi Vladykin
*/ */
public class SubQueryInfo { public class SubQueryInfo {
......
...@@ -639,7 +639,8 @@ public abstract class Table extends SchemaObjectBase { ...@@ -639,7 +639,8 @@ public abstract class Table extends SchemaObjectBase {
Row getNullRow() { Row getNullRow() {
Row row = nullRow; Row row = nullRow;
if (row == null) { 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]; Value[] values = new Value[columns.length];
Arrays.fill(values, ValueNull.INSTANCE); Arrays.fill(values, ValueNull.INSTANCE);
nullRow = row = database.createRow(values, 1); nullRow = row = database.createRow(values, 1);
......
...@@ -123,7 +123,8 @@ public class TableFilter implements ColumnResolver { ...@@ -123,7 +123,8 @@ public class TableFilter implements ColumnResolver {
* @param alias the alias name * @param alias the alias name
* @param rightsChecked true if rights are already checked * @param rightsChecked true if rights are already checked
* @param select the select statement * @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, public TableFilter(Session session, Table table, String alias,
boolean rightsChecked, Select select, int orderInFrom) { boolean rightsChecked, Select select, int orderInFrom) {
...@@ -374,7 +375,8 @@ public class TableFilter implements ColumnResolver { ...@@ -374,7 +375,8 @@ public class TableFilter implements ColumnResolver {
* Attempt to initialize batched join. * Attempt to initialize batched join.
* *
* @param jb join batch if it is already created * @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) { public JoinBatch prepareJoinBatch(JoinBatch jb, TableFilter[] filters, int filter) {
joinBatch = null; joinBatch = null;
...@@ -387,13 +389,15 @@ public class TableFilter implements ColumnResolver { ...@@ -387,13 +389,15 @@ public class TableFilter implements ColumnResolver {
session.popSubQueryInfo(); session.popSubQueryInfo();
} }
} }
// For globally top table filter we don't need to create lookup batch, because // For globally top table filter we don't need to create lookup batch,
// currently it will not be used (this will be shown in ViewIndex.getPlanSQL()). Probably // because currently it will not be used (this will be shown in
// later on it will make sense to create it to better support X IN (...) conditions, // ViewIndex.getPlanSQL()). Probably later on it will make sense to
// but this needs to be implemented separately. If isAlwaysTopTableFilter is false // create it to better support X IN (...) conditions, but this needs to
// then we either not a top table filter or top table filter in a sub-query, which // be implemented separately. If isAlwaysTopTableFilter is false then we
// in turn is not top in outer query, thus we need to enable batching here to allow // either not a top table filter or top table filter in a sub-query,
// outer query run batched join against this 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; IndexLookupBatch lookupBatch = null;
if (jb == null && select != null && !isAlwaysTopTableFilter(filter)) { if (jb == null && select != null && !isAlwaysTopTableFilter(filter)) {
lookupBatch = index.createLookupBatch(this); lookupBatch = index.createLookupBatch(this);
...@@ -408,11 +412,13 @@ public class TableFilter implements ColumnResolver { ...@@ -408,11 +412,13 @@ public class TableFilter implements ColumnResolver {
joinBatch = jb; joinBatch = jb;
joinFilterId = filter; joinFilterId = filter;
if (lookupBatch == null && !isAlwaysTopTableFilter(filter)) { if (lookupBatch == null && !isAlwaysTopTableFilter(filter)) {
// createLookupBatch will be called at most once because jb can be // createLookupBatch will be called at most once because jb can
// created only if lookupBatch is already not null from the call above. // be created only if lookupBatch is already not null from the
// call above.
lookupBatch = index.createLookupBatch(this); lookupBatch = index.createLookupBatch(this);
if (lookupBatch == null) { 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); lookupBatch = JoinBatch.createFakeIndexLookupBatch(this);
} }
} }
...@@ -436,7 +442,8 @@ public class TableFilter implements ColumnResolver { ...@@ -436,7 +442,8 @@ public class TableFilter implements ColumnResolver {
*/ */
public boolean next() { public boolean next() {
if (joinBatch != null) { 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(); return joinBatch.next();
} }
if (state == AFTER_LAST) { if (state == AFTER_LAST) {
......
...@@ -121,7 +121,8 @@ public class TableView extends Table { ...@@ -121,7 +121,8 @@ public class TableView extends Table {
* @return the exception if re-compiling this or any dependent view failed * @return the exception if re-compiling this or any dependent view failed
* (only when force is disabled) * (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 { try {
compileViewQuery(session, querySQL); compileViewQuery(session, querySQL);
} catch (DbException e) { } catch (DbException e) {
......
...@@ -12,24 +12,25 @@ import java.util.concurrent.TimeoutException; ...@@ -12,24 +12,25 @@ import java.util.concurrent.TimeoutException;
/** /**
* Future which is already done. * Future which is already done.
* *
* @param <T> Result value. * @param <T> Result value.
* @author Sergi Vladykin * @author Sergi Vladykin
*/ */
public class DoneFuture<T> implements Future<T> { public class DoneFuture<T> implements Future<T> {
final T x; final T x;
public DoneFuture(T x) { public DoneFuture(T x) {
this.x = x; this.x = x;
} }
@Override @Override
public T get() throws InterruptedException, ExecutionException { public T get() throws InterruptedException, ExecutionException {
return x; return x;
} }
@Override @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; return x;
} }
...@@ -37,17 +38,17 @@ public class DoneFuture<T> implements Future<T> { ...@@ -37,17 +38,17 @@ public class DoneFuture<T> implements Future<T> {
public boolean isDone() { public boolean isDone() {
return true; return true;
} }
@Override @Override
public boolean cancel(boolean mayInterruptIfRunning) { public boolean cancel(boolean mayInterruptIfRunning) {
return false; return false;
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
return false; return false;
} }
@Override @Override
public String toString() { public String toString() {
return "DoneFuture->" + x; return "DoneFuture->" + x;
......
...@@ -12,8 +12,8 @@ import java.util.concurrent.TimeUnit; ...@@ -12,8 +12,8 @@ import java.util.concurrent.TimeUnit;
import org.h2.message.DbException; import org.h2.message.DbException;
/** /**
* Single threaded lazy future. * Single threaded lazy future.
* *
* @param <T> * @param <T>
* @author Sergi Vladykin * @author Sergi Vladykin
*/ */
...@@ -23,15 +23,15 @@ public abstract class LazyFuture<T> implements Future<T> { ...@@ -23,15 +23,15 @@ public abstract class LazyFuture<T> implements Future<T> {
private static final int S_DONE = 1; private static final int S_DONE = 1;
private static final int S_ERROR = 2; private static final int S_ERROR = 2;
private static final int S_CANCELED = 3; private static final int S_CANCELED = 3;
private int state = S_READY; private int state = S_READY;
private T result; private T result;
private Exception error; private Exception error;
/** /**
* Reset this future to the initial state. * 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() { public boolean reset() {
if (state == S_READY) { if (state == S_READY) {
...@@ -45,11 +45,11 @@ public abstract class LazyFuture<T> implements Future<T> { ...@@ -45,11 +45,11 @@ public abstract class LazyFuture<T> implements Future<T> {
/** /**
* Run computation and produce the result. * Run computation and produce the result.
* *
* @return the result of computation * @return the result of computation
*/ */
protected abstract T run() throws Exception; protected abstract T run() throws Exception;
@Override @Override
public boolean cancel(boolean mayInterruptIfRunning) { public boolean cancel(boolean mayInterruptIfRunning) {
if (state != S_READY) { if (state != S_READY) {
......
...@@ -220,7 +220,9 @@ public class ToChar { ...@@ -220,7 +220,9 @@ public class ToChar {
} }
StringBuilder output = new StringBuilder(); 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, // start at the decimal point and fill in the numbers to the left,
// working our way from right to left // working our way from right to left
......
...@@ -56,7 +56,8 @@ public final class ValueTimestampUtc extends Value { ...@@ -56,7 +56,8 @@ public final class ValueTimestampUtc extends Value {
if (nanos < 0 || nanos >= 1000 * 1000) { if (nanos < 0 || nanos >= 1000 * 1000) {
throw new IllegalArgumentException("nanos out of range " + nanos); 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 { ...@@ -189,12 +190,17 @@ public final class ValueTimestampUtc extends Value {
} }
if (targetScale < 0) { if (targetScale < 0) {
throw DbException.getInvalidValueException("scale", targetScale); throw DbException.getInvalidValueException("scale", targetScale);
} /* }
* TODO long n = timeNanos; BigDecimal bd = BigDecimal.valueOf(n); bd // TODO
* = bd.movePointLeft(9); bd = ValueDecimal.setScale(bd, targetScale); // long n = timeNanos;
* bd = bd.movePointRight(9); long n2 = bd.longValue(); if (n2 == n) { // BigDecimal bd = BigDecimal.valueOf(n);
* return this; } // bd = bd.movePointLeft(9);
*/ // bd = ValueDecimal.setScale(bd, targetScale);
// bd = bd.movePointRight(9);
// long n2 = bd.longValue();
// if (n2 == n) {
// return this;
// }
return this; return this;
} }
......
...@@ -21,7 +21,8 @@ import javax.tools.Diagnostic; ...@@ -21,7 +21,8 @@ import javax.tools.Diagnostic;
*/ */
public class TestAnnotationProcessor extends AbstractProcessor { 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 @Override
public Set<String> getSupportedAnnotationTypes() { public Set<String> getSupportedAnnotationTypes() {
...@@ -45,7 +46,9 @@ public class TestAnnotationProcessor extends AbstractProcessor { ...@@ -45,7 +46,9 @@ public class TestAnnotationProcessor extends AbstractProcessor {
if (split.length == 2) { if (split.length == 2) {
outputMessages.add(new OutputMessage(Diagnostic.Kind.valueOf(split[0]), split[1])); outputMessages.add(new OutputMessage(Diagnostic.Kind.valueOf(split[0]), split[1]));
} else { } 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 { ...@@ -1028,26 +1028,37 @@ public class TestOptimizations extends TestBase {
conn.close(); conn.close();
} }
private void testUseCoveringIndex() throws SQLException { private void testUseCoveringIndex() throws SQLException {
deleteDb("optimizations"); deleteDb("optimizations");
Connection conn = getConnection("optimizations"); Connection conn = getConnection("optimizations");
Statement stat = conn.createStatement(); 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_A(id IDENTITY PRIMARY KEY NOT NULL, " +
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) )"); "name VARCHAR NOT NULL, active BOOLEAN DEFAULT TRUE, " +
stat.execute("INSERT INTO TBL_A (name) SELECT 'package_' || CAST(X as VARCHAR) FROM SYSTEM_RANGE(1, 100) WHERE X <= 100"); "UNIQUE KEY TBL_A_UK (name) )");
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_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("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"); ResultSet rs = stat.executeQuery("EXPLAIN ANALYZE SELECT MAX(b.id) as id " +
rs.next(); "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 */"); 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 = 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"); assertContains(rs.getString(1), "/* PUBLIC.TBL_B_IDX");
conn.close(); conn.close();
} }
} }
...@@ -125,7 +125,8 @@ public class TestOptimizerHints extends TestBase { ...@@ -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(); StatementBuilder from = new StatementBuilder();
for (int i = 0; i < t.length; i++) { for (int i = 0; i < t.length; i++) {
if (i != 0) { if (i != 0) {
...@@ -145,7 +146,7 @@ public class TestOptimizerHints extends TestBase { ...@@ -145,7 +146,7 @@ public class TestOptimizerHints extends TestBase {
int prev = plan.indexOf("FROM PUBLIC." + t[0].toUpperCase()); int prev = plan.indexOf("FROM PUBLIC." + t[0].toUpperCase());
for (int i = 1; i < t.length; i++) { for (int i = 1; i < t.length; i++) {
int next = plan.indexOf( 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()); t[i].toUpperCase());
if (prev > next) { if (prev > next) {
System.err.println(plan); System.err.println(plan);
......
...@@ -59,7 +59,8 @@ public class TestView extends TestBase { ...@@ -59,7 +59,8 @@ public class TestView extends TestBase {
Connection conn = getConnection("view"); Connection conn = getConnection("view");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("drop table test if exists"); 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 // check that initial cache size is empty
Session s = (Session) ((JdbcConnection) conn).getSession(); Session s = (Session) ((JdbcConnection) conn).getSession();
......
...@@ -307,9 +307,10 @@ public class BuildBase { ...@@ -307,9 +307,10 @@ public class BuildBase {
*/ */
protected int execScript(String script, StringList args) { protected int execScript(String script, StringList args) {
if (isWindows()) { if (isWindows()) {
// Under windows, we use the "cmd" command interpreter since it will search the path for us // Under windows, we use the "cmd" command interpreter since it will
// without us having to hardcode an extension for the script we want. // search the path for us without us having to hardcode an extension
// (Sometimes we don't know if the extension will be .bat or .cmd) // for the script we want. (Sometimes we don't know if the extension
// will be .bat or .cmd)
StringList newArgs = new StringList(); StringList newArgs = new StringList();
newArgs.add("/C"); newArgs.add("/C");
newArgs.add(script); newArgs.add(script);
......
...@@ -27,7 +27,7 @@ public class CheckTextFiles { ...@@ -27,7 +27,7 @@ public class CheckTextFiles {
private static final String[] SUFFIX_CHECK = { "html", "jsp", "js", "css", private static final String[] SUFFIX_CHECK = { "html", "jsp", "js", "css",
"bat", "nsi", "java", "txt", "properties", "sql", "xml", "csv", "bat", "nsi", "java", "txt", "properties", "sql", "xml", "csv",
"Driver", "prefs" }; "Driver", "Processor", "prefs" };
private static final String[] SUFFIX_IGNORE = { "gif", "png", "odg", "ico", private static final String[] SUFFIX_IGNORE = { "gif", "png", "odg", "ico",
"sxd", "layout", "res", "win", "jar", "task", "svg", "MF", "mf", "sxd", "layout", "res", "win", "jar", "task", "svg", "MF", "mf",
"sh", "DS_Store", "prop" }; "sh", "DS_Store", "prop" };
......
...@@ -25,7 +25,7 @@ import org.h2.util.Utils; ...@@ -25,7 +25,7 @@ import org.h2.util.Utils;
public class SpellChecker { public class SpellChecker {
private static final String[] SUFFIX = { "html", "java", "sql", "txt", 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", "" }; "properties", "task", "MF", "mf", "sh", "" };
private static final String[] IGNORE = { "dev", "nsi", "gif", "png", "odg", private static final String[] IGNORE = { "dev", "nsi", "gif", "png", "odg",
"ico", "sxd", "zip", "bz2", "rc", "layout", "res", "dll", "jar", "ico", "sxd", "zip", "bz2", "rc", "layout", "res", "dll", "jar",
......
...@@ -200,14 +200,22 @@ public class UploadBuild { ...@@ -200,14 +200,22 @@ public class UploadBuild {
if (!ftp.exists("/httpdocs/m2-repo/com/h2database/h2-mvstore", "1.0-SNAPSHOT")) { 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.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", ftp.store("/httpdocs/m2-repo/com/h2database/h2" +
new FileInputStream(mavenRepoDir + "com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.pom")); "/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 +
new FileInputStream(mavenRepoDir + "com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.jar")); "com/h2database/h2/1.0-SNAPSHOT/h2-1.0-SNAPSHOT.pom"));
ftp.store("/httpdocs/m2-repo/com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.pom", ftp.store("/httpdocs/m2-repo/com/h2database/h2" +
new FileInputStream(mavenRepoDir + "com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.pom")); "/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.jar", new FileInputStream(mavenRepoDir +
new FileInputStream(mavenRepoDir + "com/h2database/h2-mvstore/1.0-SNAPSHOT/h2-mvstore-1.0-SNAPSHOT.jar")); "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(); ftp.close();
} }
......
...@@ -778,3 +778,10 @@ dance schedule hitting reverted youngest footers inliner deadlocked reorder nger ...@@ -778,3 +778,10 @@ dance schedule hitting reverted youngest footers inliner deadlocked reorder nger
nullid syspublic sysibmts sysibminternal syscat sysfun sysstat systools sysibmadm nullid syspublic sysibmts sysibminternal syscat sysfun sysstat systools sysibmadm
sysproc jcc expecting gpg showed unreferenced activating cvf stephane lacoin sysproc jcc expecting gpg showed unreferenced activating cvf stephane lacoin
centrale umr ecole nantes sticc lab reordering preferable simultaneously 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论