use of org.h2.index.IndexLookupBatch in project h2database by h2database.
the class TableFilter method getPlanSQL.
/**
* Get the query execution plan text to use for this table filter.
*
* @param isJoin if this is a joined table
* @return the SQL statement snippet
*/
public String getPlanSQL(boolean isJoin) {
StringBuilder buff = new StringBuilder();
if (isJoin) {
if (joinOuter) {
buff.append("LEFT OUTER JOIN ");
} else {
buff.append("INNER JOIN ");
}
}
if (nestedJoin != null) {
StringBuilder buffNested = new StringBuilder();
TableFilter n = nestedJoin;
do {
buffNested.append(n.getPlanSQL(n != nestedJoin));
buffNested.append('\n');
n = n.getJoin();
} while (n != null);
String nested = buffNested.toString();
boolean enclose = !nested.startsWith("(");
if (enclose) {
buff.append("(\n");
}
buff.append(StringUtils.indent(nested, 4, false));
if (enclose) {
buff.append(')');
}
if (isJoin) {
buff.append(" ON ");
if (joinCondition == null) {
// need to have a ON expression,
// otherwise the nesting is unclear
buff.append("1=1");
} else {
buff.append(StringUtils.unEnclose(joinCondition.getSQL()));
}
}
return buff.toString();
}
if (table.isView() && ((TableView) table).isRecursive()) {
buff.append(table.getName());
} else {
buff.append(table.getSQL());
}
if (table.isView() && ((TableView) table).isInvalid()) {
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, table.getName(), "not compiled");
}
if (alias != null) {
buff.append(' ').append(Parser.quoteIdentifier(alias));
}
if (indexHints != null) {
buff.append(" USE INDEX (");
boolean first = true;
for (String index : indexHints.getAllowedIndexes()) {
if (!first) {
buff.append(", ");
} else {
first = false;
}
buff.append(Parser.quoteIdentifier(index));
}
buff.append(")");
}
if (index != null) {
buff.append('\n');
StatementBuilder planBuff = new StatementBuilder();
if (joinBatch != null) {
IndexLookupBatch lookupBatch = joinBatch.getLookupBatch(joinFilterId);
if (lookupBatch == null) {
if (joinFilterId != 0) {
throw DbException.throwInternalError("" + joinFilterId);
}
} else {
planBuff.append("batched:");
String batchPlan = lookupBatch.getPlanSQL();
planBuff.append(batchPlan);
planBuff.append(" ");
}
}
planBuff.append(index.getPlanSQL());
if (!indexConditions.isEmpty()) {
planBuff.append(": ");
for (IndexCondition condition : indexConditions) {
planBuff.appendExceptFirst("\n AND ");
planBuff.append(condition.getSQL());
}
}
String plan = StringUtils.quoteRemarkSQL(planBuff.toString());
if (plan.indexOf('\n') >= 0) {
plan += "\n";
}
buff.append(StringUtils.indent("/* " + plan + " */", 4, false));
}
if (isJoin) {
buff.append("\n ON ");
if (joinCondition == null) {
// need to have a ON expression, otherwise the nesting is
// unclear
buff.append("1=1");
} else {
buff.append(StringUtils.unEnclose(joinCondition.getSQL()));
}
}
if (filterCondition != null) {
buff.append('\n');
String condition = StringUtils.unEnclose(filterCondition.getSQL());
condition = "/* WHERE " + StringUtils.quoteRemarkSQL(condition) + "\n*/";
buff.append(StringUtils.indent(condition, 4, false));
}
if (scanCount > 0) {
buff.append("\n /* scanCount: ").append(scanCount).append(" */");
}
return buff.toString();
}
use of org.h2.index.IndexLookupBatch in project h2database by h2database.
the class TableFilter method prepareJoinBatch.
/**
* Attempt to initialize batched join.
*
* @param jb join batch if it is already created
* @param filters the table filters
* @param filter the filter index (0, 1,...)
* @return join batch if query runs over index which supports batched
* lookups, {@code null} otherwise
*/
public JoinBatch prepareJoinBatch(JoinBatch jb, TableFilter[] filters, int filter) {
assert filters[filter] == this;
joinBatch = null;
joinFilterId = -1;
if (getTable().isView()) {
session.pushSubQueryInfo(masks, filters, filter, select.getSortOrder());
try {
((ViewIndex) index).getQuery().prepareJoinBatch();
} finally {
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.
IndexLookupBatch lookupBatch = null;
if (jb == null && select != null && !isAlwaysTopTableFilter(filter)) {
lookupBatch = index.createLookupBatch(filters, filter);
if (lookupBatch != null) {
jb = new JoinBatch(filter + 1, join);
}
}
if (jb != null) {
if (nestedJoin != null) {
throw DbException.throwInternalError();
}
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.
lookupBatch = index.createLookupBatch(filters, filter);
if (lookupBatch == null) {
// the index does not support lookup batching, need to fake
// it because we are not top
lookupBatch = JoinBatch.createFakeIndexLookupBatch(this);
}
}
jb.register(this, lookupBatch);
}
return jb;
}
use of org.h2.index.IndexLookupBatch in project h2database by h2database.
the class JoinBatch method createViewIndexLookupBatch.
/**
* 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
*/
public static IndexLookupBatch createViewIndexLookupBatch(ViewIndex viewIndex) {
Query query = viewIndex.getQuery();
if (query.isUnion()) {
ViewIndexLookupBatchUnion unionBatch = new ViewIndexLookupBatchUnion(viewIndex);
return unionBatch.initialize() ? unionBatch : null;
}
JoinBatch jb = ((Select) query).getJoinBatch();
if (jb == null || jb.getLookupBatch(0) == null) {
// our sub-query is not batched or is top batched sub-query
return null;
}
assert !jb.batchedSubQuery;
jb.batchedSubQuery = true;
return jb.viewIndexLookupBatch(viewIndex);
}
use of org.h2.index.IndexLookupBatch in project ignite by apache.
the class GridH2ProxyIndex method createLookupBatch.
/**
* {@inheritDoc}
*/
@Override
public IndexLookupBatch createLookupBatch(TableFilter[] filters, int filter) {
IndexLookupBatch batch = idx.createLookupBatch(filters, filter);
if (batch == null)
return null;
GridH2RowDescriptor rowDesc = ((GridH2Table) idx.getTable()).rowDescriptor();
return new ProxyDistributedLookupBatch(batch, rowDesc);
}
use of org.h2.index.IndexLookupBatch in project ignite by apache.
the class GridH2IndexBase method createLookupBatch.
/**
* {@inheritDoc}
*/
@Override
public IndexLookupBatch createLookupBatch(TableFilter[] filters, int filter) {
GridH2QueryContext qctx = GridH2QueryContext.get();
if (qctx == null || qctx.distributedJoinMode() == OFF || !getTable().isPartitioned())
return null;
IndexColumn affCol = getTable().getAffinityKeyColumn();
GridH2RowDescriptor desc = getTable().rowDescriptor();
int affColId = -1;
boolean ucast = false;
if (affCol != null) {
affColId = affCol.column.getColumnId();
int[] masks = filters[filter].getMasks();
if (masks != null) {
ucast = (masks[affColId] & IndexCondition.EQUALITY) != 0 || desc.checkKeyIndexCondition(masks, IndexCondition.EQUALITY);
}
}
GridCacheContext<?, ?> cctx = getTable().rowDescriptor().context();
return new DistributedLookupBatch(cctx, ucast, affColId);
}
Aggregations