You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2021/06/08 09:52:25 UTC

[ignite] branch sql-calcite updated: IGNITE-14820 Move from H2 indexes to core indexes - Fixes #9151.

This is an automated email from the ASF dual-hosted git repository.

alexpl pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/sql-calcite by this push:
     new 3ed8179  IGNITE-14820 Move from H2 indexes to core indexes - Fixes #9151.
3ed8179 is described below

commit 3ed8179c000235ecb62d8707b0d387bfecf55385
Author: Aleksey Plekhanov <pl...@gmail.com>
AuthorDate: Tue Jun 8 12:47:57 2021 +0300

    IGNITE-14820 Move from H2 indexes to core indexes - Fixes #9151.
    
    Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
 .../query/calcite/exec/AbstractIndexScan.java      |  5 +-
 .../processors/query/calcite/exec/IndexScan.java   | 94 +++++++++++++++-------
 .../query/calcite/exec/RuntimeTreeIndex.java       |  5 +-
 .../processors/query/calcite/exec/TreeIndex.java}  |  8 +-
 .../query/calcite/prepare/QueryPlanCacheImpl.java  |  4 +-
 .../query/calcite/schema/IgniteIndex.java          | 21 +++--
 .../query/calcite/schema/SchemaHolderImpl.java     |  7 +-
 .../query/schema/SchemaChangeListener.java         | 19 +++--
 .../processors/query/h2/SchemaManager.java         | 15 ++--
 .../query/h2/database/H2TreeClientIndex.java       |  9 +++
 .../processors/query/h2/database/H2TreeIndex.java  | 29 +++----
 .../processors/query/h2/opt/GridH2IndexBase.java   | 25 +++---
 12 files changed, 138 insertions(+), 103 deletions(-)

diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java
index 52365c2..ca12e49 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java
@@ -25,7 +25,6 @@ import java.util.function.Supplier;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.internal.util.lang.GridIteratorAdapter;
 import org.jetbrains.annotations.NotNull;
@@ -35,7 +34,7 @@ import org.jetbrains.annotations.NotNull;
  */
 public abstract class AbstractIndexScan<Row, IdxRow> implements Iterable<Row>, AutoCloseable {
     /** */
-    private final GridIndex<IdxRow> idx;
+    private final TreeIndex<IdxRow> idx;
 
     /** Additional filters. */
     private final Predicate<Row> filters;
@@ -65,7 +64,7 @@ public abstract class AbstractIndexScan<Row, IdxRow> implements Iterable<Row>, A
     protected AbstractIndexScan(
         ExecutionContext<Row> ectx,
         RelDataType rowType,
-        GridIndex<IdxRow> idx,
+        TreeIndex<IdxRow> idx,
         Predicate<Row> filters,
         Supplier<Row> lowerBound,
         Supplier<Row> upperBound,
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
index cca3cba..ea37f49 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
@@ -24,37 +24,37 @@ import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.cache.query.index.sorted.IndexRow;
+import org.apache.ignite.internal.cache.query.index.sorted.IndexSearchRowImpl;
+import org.apache.ignite.internal.cache.query.index.sorted.InlineIndexRowHandler;
 import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
+import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndex;
+import org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey;
+import org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKeyFactory;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
-import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition;
 import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
 import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopology;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
-import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler.RowFactory;
 import org.apache.ignite.internal.processors.query.calcite.schema.TableDescriptor;
-import org.apache.ignite.internal.processors.query.h2.H2Utils;
-import org.apache.ignite.internal.processors.query.h2.opt.H2PlainRow;
-import org.apache.ignite.internal.processors.query.h2.opt.H2Row;
+import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.spi.indexing.IndexingQueryFilter;
 import org.apache.ignite.spi.indexing.IndexingQueryFilterImpl;
-import org.h2.value.DataType;
-import org.h2.value.Value;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * Scan on index.
  */
-public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
+public class IndexScan<Row> extends AbstractIndexScan<Row, IndexRow> {
     /** */
     private final GridKernalContext kctx;
 
@@ -85,9 +85,16 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
     /** */
     private final ImmutableBitSet requiredColumns;
 
+    /** */
+    private final InlineIndex idx;
+
+    /** Mapping from index keys to row fields. */
+    private final ImmutableIntList idxFieldMapping;
+
     /**
      * @param ectx Execution context.
      * @param desc Table descriptor.
+     * @param idxFieldMapping Mapping from index keys to row fields.
      * @param idx Phisycal index.
      * @param filters Additional filters.
      * @param lowerBound Lower index scan bound.
@@ -96,7 +103,8 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
     public IndexScan(
         ExecutionContext<Row> ectx,
         TableDescriptor desc,
-        GridIndex<H2Row> idx,
+        InlineIndex idx,
+        ImmutableIntList idxFieldMapping,
         int[] parts,
         Predicate<Row> filters,
         Supplier<Row> lowerBound,
@@ -107,7 +115,7 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
         super(
             ectx,
             desc.rowType(ectx.getTypeFactory(), requiredColumns),
-            idx,
+            new TreeIndexWrapper(idx),
             filters,
             lowerBound,
             upperBound,
@@ -115,6 +123,7 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
         );
 
         this.desc = desc;
+        this.idx = idx;
         cctx = desc.cacheContext();
         kctx = cctx.kernalContext();
         coCtx = cctx.cacheObjectContext();
@@ -124,6 +133,7 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
         this.parts = parts;
         mvccSnapshot = ectx.mvccSnapshot();
         this.requiredColumns = requiredColumns;
+        this.idxFieldMapping = idxFieldMapping;
     }
 
     /** {@inheritDoc} */
@@ -141,13 +151,37 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
     }
 
     /** {@inheritDoc} */
-    @Override protected H2Row row2indexRow(Row bound) {
-        return new H2PlainRow(values(coCtx, ectx, bound));
+    @Override protected IndexRow row2indexRow(Row bound) {
+        if (bound == null)
+            return null;
+
+        InlineIndexRowHandler idxRowHnd = idx.segment(0).rowHandler();
+        RowHandler<Row> rowHnd = ectx.rowHandler();
+
+        IndexKey[] keys = new IndexKey[idxRowHnd.indexKeyDefinitions().size()];
+
+        assert keys.length >= idxFieldMapping.size() : "Unexpected index keys [keys.length=" + keys.length +
+            ", idxFieldMapping.size()=" + idxFieldMapping.size() + ']';
+
+        boolean nullSearchRow = true;
+
+        for (int i = 0; i < idxFieldMapping.size(); ++i) {
+            Object key = rowHnd.get(idxFieldMapping.getInt(i), bound);
+
+            if (key != null) {
+                keys[i] = IndexKeyFactory.wrap(key, idxRowHnd.indexKeyDefinitions().get(i).idxType(),
+                    cctx.cacheObjectContext(), idxRowHnd.indexKeyTypeSettings());
+
+                nullSearchRow = false;
+            }
+        }
+
+        return nullSearchRow ? null : new IndexSearchRowImpl(keys, idxRowHnd);
     }
 
     /** {@inheritDoc} */
-    @Override protected Row indexRow2Row(H2Row row) throws IgniteCheckedException {
-        return desc.toRow(ectx, (CacheDataRow)row, factory, requiredColumns);
+    @Override protected Row indexRow2Row(IndexRow row) throws IgniteCheckedException {
+        return desc.toRow(ectx, row.cacheDataRow(), factory, requiredColumns);
     }
 
     /** */
@@ -243,23 +277,25 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
     }
 
     /** */
-    private Value[] values(CacheObjectValueContext cctx, ExecutionContext<Row> ectx, Row row) {
-        try {
-            RowHandler<Row> rowHnd = ectx.rowHandler();
-            int rowLen = rowHnd.columnCount(row);
+    private static class TreeIndexWrapper implements TreeIndex<IndexRow> {
+        /** Underlying index. */
+        private final InlineIndex idx;
 
-            Value[] values = new Value[rowLen];
-            for (int i = 0; i < rowLen; i++) {
-                Object o = rowHnd.get(i, row);
+        /** */
+        private TreeIndexWrapper(InlineIndex idx) {
+            this.idx = idx;
+        }
 
-                if (o != null)
-                    values[i] = H2Utils.wrap(cctx, o, DataType.getTypeFromClass(o.getClass()));
-            }
+        /** {@inheritDoc} */
+        @Override public GridCursor<IndexRow> find(IndexRow lower, IndexRow upper, IndexQueryContext qctx) {
+            try {
+                int seg = 0; // TODO segments support
 
-            return values;
-        }
-        catch (IgniteCheckedException e) {
-            throw new IgniteException("Failed to wrap object into H2 Value.", e);
+                return idx.find(lower, upper, seg, qctx);
+            }
+            catch (IgniteCheckedException e) {
+                throw new IgniteException("Failed to find index rows", e);
+            }
         }
     }
 }
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java
index 7f125f9..6db5262 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java
@@ -30,14 +30,13 @@ import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.internal.util.typedef.F;
 
 /**
  * Runtime sorted index based on on-heap tree.
  */
-public class RuntimeTreeIndex<Row> implements RuntimeIndex<Row>, GridIndex<Row> {
+public class RuntimeTreeIndex<Row> implements RuntimeIndex<Row>, TreeIndex<Row> {
     /** */
     protected final ExecutionContext<Row> ectx;
 
@@ -174,7 +173,7 @@ public class RuntimeTreeIndex<Row> implements RuntimeIndex<Row>, GridIndex<Row>
          */
         IndexScan(
             RelDataType rowType,
-            GridIndex<Row> idx,
+            TreeIndex<Row> idx,
             Predicate<Row> filter,
             Supplier<Row> lowerBound,
             Supplier<Row> upperBound) {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridIndex.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/TreeIndex.java
similarity index 86%
rename from modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridIndex.java
rename to modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/TreeIndex.java
index 0e4bb0a..91cb912 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridIndex.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/TreeIndex.java
@@ -14,17 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.internal.processors.query;
+package org.apache.ignite.internal.processors.query.calcite.exec;
 
 import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
 import org.apache.ignite.internal.util.lang.GridCursor;
 
 /**
- * Index interface.
+ * Tree index interface.
  *
  * @param <R> Indexing row type.
  */
-public interface GridIndex<R> {
+public interface TreeIndex<R> {
     /**
      * Index lookup method.
      *
@@ -33,5 +33,5 @@ public interface GridIndex<R> {
      * @param qctx Index query context.
      * @return Cursor over the rows within bounds.
      */
-    GridCursor<R> find(R lower, R upper, IndexQueryContext qctx);
+    public GridCursor<R> find(R lower, R upper, IndexQueryContext qctx);
 }
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/QueryPlanCacheImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/QueryPlanCacheImpl.java
index 7a960d3..b709d12 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/QueryPlanCacheImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/QueryPlanCacheImpl.java
@@ -20,8 +20,8 @@ package org.apache.ignite.internal.processors.query.calcite.prepare;
 import java.util.List;
 import java.util.Map;
 import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.cache.query.index.Index;
 import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
@@ -107,7 +107,7 @@ public class QueryPlanCacheImpl extends AbstractService implements QueryPlanCach
 
     /** {@inheritDoc} */
     @Override public void onIndexCreated(String schemaName, String tblName, String idxName,
-        GridQueryIndexDescriptor idxDesc, GridIndex<?> idx) {
+        GridQueryIndexDescriptor idxDesc, Index idx) {
         clear();
     }
 
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteIndex.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteIndex.java
index dd42ad3..c5afdbb 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteIndex.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteIndex.java
@@ -23,11 +23,11 @@ import java.util.function.Predicate;
 import java.util.function.Supplier;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.ignite.internal.processors.query.GridIndex;
+import org.apache.ignite.internal.cache.query.index.Index;
+import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndex;
 import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
 import org.apache.ignite.internal.processors.query.calcite.exec.IndexScan;
 import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
-import org.apache.ignite.internal.processors.query.h2.opt.H2Row;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -41,13 +41,13 @@ public class IgniteIndex {
     private final String idxName;
 
     /** */
-    private final GridIndex<H2Row> idx;
+    private final Index idx;
 
     /** */
     private final IgniteTable tbl;
 
     /** */
-    public IgniteIndex(RelCollation collation, String name, GridIndex<H2Row> idx, IgniteTable tbl) {
+    public IgniteIndex(RelCollation collation, String name, Index idx, IgniteTable tbl) {
         this.collation = collation;
         idxName = name;
         this.idx = idx;
@@ -65,11 +65,6 @@ public class IgniteIndex {
     }
 
     /** */
-    public GridIndex<H2Row> index() {
-        return idx;
-    }
-
-    /** */
     public IgniteTable table() {
         return tbl;
     }
@@ -84,9 +79,11 @@ public class IgniteIndex {
         Function<Row, Row> rowTransformer,
         @Nullable ImmutableBitSet requiredColumns) {
         UUID localNodeId = execCtx.planningContext().localNodeId();
-        if (group.nodeIds().contains(localNodeId))
-            return new IndexScan<>(execCtx, table().descriptor(), idx, group.partitions(localNodeId),
-                filters, lowerIdxConditions, upperIdxConditions, rowTransformer, requiredColumns);
+        if (group.nodeIds().contains(localNodeId) && idx != null) {
+            return new IndexScan<>(execCtx, table().descriptor(), idx.unwrap(InlineIndex.class), collation.getKeys(),
+                group.partitions(localNodeId), filters, lowerIdxConditions, upperIdxConditions, rowTransformer,
+                requiredColumns);
+        }
 
         return Collections.emptyList();
     }
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/SchemaHolderImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/SchemaHolderImpl.java
index b8e1630..a82d7c9 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/SchemaHolderImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/SchemaHolderImpl.java
@@ -31,12 +31,11 @@ import org.apache.ignite.cache.affinity.AffinityFunction;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.cache.query.index.Index;
 import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
-import org.apache.ignite.internal.processors.query.h2.opt.H2Row;
 import org.apache.ignite.internal.processors.query.schema.SchemaChangeListener;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -217,7 +216,7 @@ public class SchemaHolderImpl extends AbstractService implements SchemaHolder, S
 
     /** {@inheritDoc} */
     @Override public synchronized void onIndexCreated(String schemaName, String tblName, String idxName,
-        GridQueryIndexDescriptor idxDesc, @Nullable GridIndex<?> gridIdx) {
+        GridQueryIndexDescriptor idxDesc, @Nullable Index gridIdx) {
         IgniteSchema schema = igniteSchemas.get(schemaName);
         assert schema != null;
 
@@ -226,7 +225,7 @@ public class SchemaHolderImpl extends AbstractService implements SchemaHolder, S
 
         RelCollation idxCollation = deriveSecondaryIndexCollation(idxDesc, tbl);
 
-        IgniteIndex idx = new IgniteIndex(idxCollation, idxName, (GridIndex<H2Row>)gridIdx, tbl);
+        IgniteIndex idx = new IgniteIndex(idxCollation, idxName, gridIdx, tbl);
         tbl.addIndex(idx);
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/schema/SchemaChangeListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/schema/SchemaChangeListener.java
index 52c29bc..27e5ff2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/schema/SchemaChangeListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/schema/SchemaChangeListener.java
@@ -17,8 +17,8 @@
 
 package org.apache.ignite.internal.processors.query.schema;
 
+import org.apache.ignite.internal.cache.query.index.Index;
 import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.jetbrains.annotations.Nullable;
@@ -32,14 +32,14 @@ public interface SchemaChangeListener {
      *
      * @param schemaName Schema name.
      */
-    void onSchemaCreated(String schemaName);
+    public void onSchemaCreated(String schemaName);
 
     /**
      * Callback method.
      *
      * @param schemaName Schema name.
      */
-    void onSchemaDropped(String schemaName);
+    public void onSchemaDropped(String schemaName);
 
     /**
      * Callback method.
@@ -48,7 +48,8 @@ public interface SchemaChangeListener {
      * @param typeDesc Type descriptor.
      * @param cacheInfo Cache info.
      */
-    void onSqlTypeCreated(String schemaName, GridQueryTypeDescriptor typeDesc, GridCacheContextInfo<?, ?> cacheInfo);
+    public void onSqlTypeCreated(String schemaName, GridQueryTypeDescriptor typeDesc,
+        GridCacheContextInfo<?, ?> cacheInfo);
 
     /**
      * Callback method.
@@ -57,7 +58,8 @@ public interface SchemaChangeListener {
      * @param typeDesc Type descriptor.
      * @param cacheInfo Cache info.
      */
-    void onSqlTypeUpdated(String schemaName, GridQueryTypeDescriptor typeDesc, GridCacheContextInfo<?, ?> cacheInfo);
+    public void onSqlTypeUpdated(String schemaName, GridQueryTypeDescriptor typeDesc,
+        GridCacheContextInfo<?, ?> cacheInfo);
 
     /**
      * Callback method.
@@ -65,7 +67,7 @@ public interface SchemaChangeListener {
      * @param schemaName Schema name.
      * @param typeDesc Type descriptor.
      */
-    void onSqlTypeDropped(String schemaName, GridQueryTypeDescriptor typeDesc);
+    public void onSqlTypeDropped(String schemaName, GridQueryTypeDescriptor typeDesc);
 
     /**
      * Callback on index creation.
@@ -76,7 +78,8 @@ public interface SchemaChangeListener {
      * @param idxDesc Index descriptor.
      * @param idx Index.
      */
-    void onIndexCreated(String schemaName, String tblName, String idxName, GridQueryIndexDescriptor idxDesc, @Nullable GridIndex<?> idx);
+    public void onIndexCreated(String schemaName, String tblName, String idxName, GridQueryIndexDescriptor idxDesc,
+        @Nullable Index idx);
 
     /**
      * Callback on index drop.
@@ -85,5 +88,5 @@ public interface SchemaChangeListener {
      * @param tblName Table name.
      * @param idxName Index name.
      */
-    void onIndexDropped(String schemaName, String tblName, String idxName);
+    public void onIndexDropped(String schemaName, String tblName, String idxName);
 }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java
index b76ded9..89498ee 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/SchemaManager.java
@@ -33,7 +33,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
@@ -49,7 +48,6 @@ import org.apache.ignite.internal.managers.systemview.walker.SqlViewViewWalker;
 import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 import org.apache.ignite.internal.processors.cache.query.QueryTable;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
@@ -595,7 +593,8 @@ public class SchemaManager {
 
             QuerySysIndexDescriptorImpl desc = new QuerySysIndexDescriptorImpl(idxName, idxCols);
 
-            lsnr.onIndexCreated(schemaName, tbl.tableName(), idxName, desc, (GridIndex<?>)idx);
+            lsnr.onIndexCreated(schemaName, tbl.tableName(), idxName, desc,
+                ((GridH2IndexBase)idx).unwrap(org.apache.ignite.internal.cache.query.index.Index.class));
         }
     }
 
@@ -674,7 +673,8 @@ public class SchemaManager {
 
         GridQueryIndexDescriptor idxDesc = desc.type().indexes().get(h2Idx.getName());
 
-        lsnr.onIndexCreated(schemaName, desc.tableName(), h2Idx.getName(), idxDesc, h2Idx);
+        lsnr.onIndexCreated(schemaName, desc.tableName(), h2Idx.getName(), idxDesc,
+            h2Idx.unwrap(org.apache.ignite.internal.cache.query.index.Index.class));
     }
 
     /**
@@ -719,7 +719,8 @@ public class SchemaManager {
             throw e;
         }
 
-        lsnr.onIndexCreated(schemaName, desc.tableName(), h2Idx.getName(), idxDesc, h2Idx);
+        lsnr.onIndexCreated(schemaName, desc.tableName(), h2Idx.getName(), idxDesc,
+            h2Idx.unwrap(org.apache.ignite.internal.cache.query.index.Index.class));
     }
 
     /**
@@ -909,7 +910,7 @@ public class SchemaManager {
 
         /** {@inheritDoc} */
         @Override public void onIndexCreated(String schemaName, String tblName, String idxName,
-            GridQueryIndexDescriptor idxDesc, GridIndex<?> idx) {}
+            GridQueryIndexDescriptor idxDesc, org.apache.ignite.internal.cache.query.index.Index idx) {}
 
         /** {@inheritDoc} */
         @Override public void onIndexDropped(String schemaName, String tblName, String idxName) {}
@@ -979,7 +980,7 @@ public class SchemaManager {
 
         /** {@inheritDoc} */
         @Override public void onIndexCreated(String schemaName, String tblName, String idxName,
-            GridQueryIndexDescriptor idxDesc, GridIndex<?> idx) {
+            GridQueryIndexDescriptor idxDesc, org.apache.ignite.internal.cache.query.index.Index idx) {
             lsnrs.forEach(lsnr -> lsnr.onIndexCreated(schemaName, tblName, idxName, idxDesc, idx));
         }
 
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeClientIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeClientIndex.java
index a35e982..9d85d71 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeClientIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeClientIndex.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.processors.query.h2.database;
 
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.cache.query.index.Index;
 import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndex;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
@@ -104,4 +105,12 @@ public class H2TreeClientIndex extends H2TreeIndexBase {
     private static IgniteException unsupported() {
         return new IgniteSQLException("Shouldn't be invoked on non-affinity node.");
     }
+
+    /** {@inheritDoc} */
+    @Override public <T extends Index> T unwrap(Class<T> clazz) {
+        if (clazz.isInstance(clientIdx))
+            return clazz.cast(clientIdx);
+
+        return super.unwrap(clazz);
+    }
 }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
index 9bf2f1e..743b362 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
@@ -29,6 +29,7 @@ import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.GridTopic;
+import org.apache.ignite.internal.cache.query.index.Index;
 import org.apache.ignite.internal.cache.query.index.sorted.IndexRow;
 import org.apache.ignite.internal.cache.query.index.sorted.IndexRowImpl;
 import org.apache.ignite.internal.cache.query.index.sorted.IndexSearchRowImpl;
@@ -215,26 +216,6 @@ public class H2TreeIndex extends H2TreeIndexBase {
         }
     }
 
-    /** {@inheritDoc} */
-    @Override public GridCursor<H2Row> find(
-        H2Row lower,
-        H2Row upper,
-        IndexQueryContext qctx
-    ) {
-        try {
-            int seg = 0; // TODO segments support
-
-            T2<IndexRow, IndexRow> key = prepareIndexKeys(lower, upper);
-
-            GridCursor<IndexRow> cursor = queryIndex.find(key.get1(), key.get2(), seg, qctx);
-
-            return new IndexValueCursor<>(cursor, this::mapIndexRow);
-        }
-        catch (IgniteCheckedException e) {
-            throw U.convertException(e);
-        }
-    }
-
     /** */
     private IndexQueryContext idxQryContext(QueryContext qctx) {
         assert qctx != null || !cctx.mvccEnabled();
@@ -685,4 +666,12 @@ public class H2TreeIndex extends H2TreeIndexBase {
     public long size() throws IgniteCheckedException {
         return queryIndex.totalCount();
     }
+
+    /** {@inheritDoc} */
+    @Override public <T extends Index> T unwrap(Class<T> clazz) {
+        if (clazz.isInstance(queryIndex))
+            return clazz.cast(queryIndex);
+
+        return super.unwrap(clazz);
+    }
 }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
index 0289205..5af9892 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
@@ -18,15 +18,13 @@
 package org.apache.ignite.internal.processors.query.h2.opt;
 
 import java.util.List;
-import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
+import org.apache.ignite.internal.cache.query.index.Index;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
-import org.apache.ignite.internal.processors.query.GridIndex;
 import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.processors.query.h2.H2Utils;
 import org.apache.ignite.internal.processors.query.h2.opt.join.CollocationModel;
 import org.apache.ignite.internal.processors.query.h2.opt.join.CollocationModelMultiplier;
-import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.spi.indexing.IndexingQueryCacheFilter;
 import org.h2.engine.Session;
 import org.h2.index.IndexType;
@@ -41,7 +39,7 @@ import org.jetbrains.annotations.NotNull;
 /**
  * Index base.
  */
-public abstract class GridH2IndexBase extends H2IndexCostedBase implements GridIndex<H2Row> {
+public abstract class GridH2IndexBase extends H2IndexCostedBase {
     /**
      * Constructor.
      *
@@ -261,12 +259,17 @@ public abstract class GridH2IndexBase extends H2IndexCostedBase implements GridI
         return cols;
     }
 
-    /** {@inheritDoc} */
-    @Override public GridCursor<H2Row> find(
-        H2Row lower,
-        H2Row upper,
-        IndexQueryContext qctx
-    ) {
-        throw new UnsupportedOperationException();
+    /**
+     * Finds an instance of an interface implemented by this object,
+     * or returns null if this object does not support that interface.
+     */
+    public <T extends Index> T unwrap(Class<T> clazz) {
+        if (clazz == null)
+            return null;
+
+        if (clazz.isAssignableFrom(getClass()))
+            return clazz.cast(this);
+
+        return null;
     }
 }