Repository: ignite
Updated Branches:
  refs/heads/master 5e1a22db1 -> 583e34615


IGNITE-6631: Minor improvements to GridH2KeyValueRowOnheap. This closes #2855.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/583e3461
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/583e3461
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/583e3461

Branch: refs/heads/master
Commit: 583e34615bb58acf7fffeaa3e815358d7c033784
Parents: 5e1a22d
Author: devozerov <voze...@gridgain.com>
Authored: Mon Oct 16 10:33:36 2017 +0300
Committer: devozerov <voze...@gridgain.com>
Committed: Mon Oct 16 10:33:36 2017 +0300

----------------------------------------------------------------------
 .../processors/query/h2/H2RowDescriptor.java    | 431 -------------------
 .../processors/query/h2/H2TableDescriptor.java  |   2 +-
 .../processors/query/h2/H2TableEngine.java      |   5 +-
 .../internal/processors/query/h2/H2Utils.java   |   3 +-
 .../processors/query/h2/IgniteH2Indexing.java   |   9 +-
 .../query/h2/database/H2PkHashIndex.java        |   7 +-
 .../query/h2/database/H2RowFactory.java         |   6 +-
 .../query/h2/opt/GridH2KeyValueRowOnheap.java   | 147 +++----
 .../query/h2/opt/GridH2RowDescriptor.java       | 412 ++++++++++++++++--
 .../processors/query/h2/opt/GridH2Table.java    |  28 +-
 10 files changed, 473 insertions(+), 577 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2RowDescriptor.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2RowDescriptor.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2RowDescriptor.java
deleted file mode 100644
index 8fb81ba..0000000
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2RowDescriptor.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query.h2;
-
-import java.math.BigDecimal;
-import java.sql.Date;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.processors.cache.CacheObject;
-import org.apache.ignite.internal.processors.cache.GridCacheContext;
-import org.apache.ignite.internal.processors.cache.KeyCacheObject;
-import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
-import org.apache.ignite.internal.processors.query.GridQueryProperty;
-import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
-import 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowFactory;
-import 
org.apache.ignite.internal.processors.query.h2.opt.GridH2ValueCacheObject;
-import org.h2.message.DbException;
-import org.h2.result.SearchRow;
-import org.h2.result.SimpleRow;
-import org.h2.util.LocalDateTimeUtils;
-import org.h2.value.DataType;
-import org.h2.value.Value;
-import org.h2.value.ValueArray;
-import org.h2.value.ValueBoolean;
-import org.h2.value.ValueByte;
-import org.h2.value.ValueBytes;
-import org.h2.value.ValueDate;
-import org.h2.value.ValueDecimal;
-import org.h2.value.ValueDouble;
-import org.h2.value.ValueFloat;
-import org.h2.value.ValueGeometry;
-import org.h2.value.ValueInt;
-import org.h2.value.ValueJavaObject;
-import org.h2.value.ValueLong;
-import org.h2.value.ValueNull;
-import org.h2.value.ValueShort;
-import org.h2.value.ValueString;
-import org.h2.value.ValueTime;
-import org.h2.value.ValueTimestamp;
-import org.h2.value.ValueUuid;
-import org.jetbrains.annotations.Nullable;
-
-import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.DEFAULT_COLUMNS_COUNT;
-import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.KEY_COL;
-import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.VAL_COL;
-import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.VER_COL;
-
-/**
- * Row descriptor.
- */
-public class H2RowDescriptor implements GridH2RowDescriptor {
-    /** Indexing SPI. */
-    private final IgniteH2Indexing idx;
-
-    /** Table descriptor. */
-    private final H2TableDescriptor tbl;
-
-    /** */
-    private final GridQueryTypeDescriptor type;
-
-    /** */
-    private volatile String[] fields;
-
-    /** */
-    private volatile int[] fieldTypes;
-
-    /** */
-    private final int keyType;
-
-    /** */
-    private final int valType;
-
-    /** */
-    private volatile GridQueryProperty[] props;
-
-    /** Id of user-defined key column */
-    private volatile int keyAliasColId;
-
-    /** Id of user-defined value column */
-    private volatile int valAliasColId;
-
-    /**
-     * Constructor.
-     *
-     * @param idx Indexing.
-     * @param tbl Table.
-     * @param type Type descriptor.
-     */
-    H2RowDescriptor(IgniteH2Indexing idx, H2TableDescriptor tbl, 
GridQueryTypeDescriptor type) {
-        assert type != null;
-
-        this.idx = idx;
-        this.tbl = tbl;
-        this.type = type;
-
-        keyType = DataType.getTypeFromClass(type.keyClass());
-        valType = DataType.getTypeFromClass(type.valueClass());
-
-        refreshMetadataFromTypeDescriptor();
-    }
-
-    /**
-     * Update metadata of this row descriptor according to current state of 
type descriptor.
-     */
-    @SuppressWarnings("WeakerAccess")
-    public final void refreshMetadataFromTypeDescriptor() {
-        Map<String, Class<?>> allFields = new LinkedHashMap<>();
-
-        allFields.putAll(type.fields());
-
-        fields = allFields.keySet().toArray(new String[allFields.size()]);
-
-        fieldTypes = new int[fields.length];
-
-        Class[] classes = allFields.values().toArray(new Class[fields.length]);
-
-        for (int i = 0; i < fieldTypes.length; i++)
-            fieldTypes[i] = DataType.getTypeFromClass(classes[i]);
-
-        props = new GridQueryProperty[fields.length];
-
-        for (int i = 0; i < fields.length; i++) {
-            GridQueryProperty p = type.property(fields[i]);
-
-            assert p != null : fields[i];
-
-            props[i] = p;
-        }
-
-        List<String> fieldsList = Arrays.asList(fields);
-
-        keyAliasColId =
-            (type.keyFieldName() != null) ? DEFAULT_COLUMNS_COUNT + 
fieldsList.indexOf(type.keyFieldAlias()) : -1;
-
-        valAliasColId =
-            (type.valueFieldName() != null) ? DEFAULT_COLUMNS_COUNT + 
fieldsList.indexOf(type.valueFieldAlias()) : -1;
-    }
-
-    /** {@inheritDoc} */
-    @Override public IgniteH2Indexing indexing() {
-        return idx;
-    }
-
-    /** {@inheritDoc} */
-    @Override public GridQueryTypeDescriptor type() {
-        return type;
-    }
-
-    /** {@inheritDoc} */
-    @Override public GridCacheContext<?, ?> context() {
-        return tbl.cache();
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings("ConstantConditions")
-    @Override public Value wrap(Object obj, int type) throws 
IgniteCheckedException {
-        assert obj != null;
-
-        if (obj instanceof CacheObject) { // Handle cache object.
-            CacheObject co = (CacheObject)obj;
-
-            if (type == Value.JAVA_OBJECT)
-                return new GridH2ValueCacheObject(co, idx.objectContext());
-
-            obj = co.value(idx.objectContext(), false);
-        }
-
-        switch (type) {
-            case Value.BOOLEAN:
-                return ValueBoolean.get((Boolean)obj);
-            case Value.BYTE:
-                return ValueByte.get((Byte)obj);
-            case Value.SHORT:
-                return ValueShort.get((Short)obj);
-            case Value.INT:
-                return ValueInt.get((Integer)obj);
-            case Value.FLOAT:
-                return ValueFloat.get((Float)obj);
-            case Value.LONG:
-                return ValueLong.get((Long)obj);
-            case Value.DOUBLE:
-                return ValueDouble.get((Double)obj);
-            case Value.UUID:
-                UUID uuid = (UUID)obj;
-                return ValueUuid.get(uuid.getMostSignificantBits(), 
uuid.getLeastSignificantBits());
-            case Value.DATE:
-                if (LocalDateTimeUtils.isLocalDate(obj.getClass()))
-                    return LocalDateTimeUtils.localDateToDateValue(obj);
-
-                return ValueDate.get((Date)obj);
-
-            case Value.TIME:
-                if (LocalDateTimeUtils.isLocalTime(obj.getClass()))
-                    return LocalDateTimeUtils.localTimeToTimeValue(obj);
-
-                return ValueTime.get((Time)obj);
-
-            case Value.TIMESTAMP:
-                if (obj instanceof java.util.Date && !(obj instanceof 
Timestamp))
-                    obj = new Timestamp(((java.util.Date)obj).getTime());
-
-                if (LocalDateTimeUtils.isLocalDateTime(obj.getClass()))
-                    return LocalDateTimeUtils.localDateTimeToValue(obj);
-
-                return ValueTimestamp.get((Timestamp)obj);
-
-            case Value.DECIMAL:
-                return ValueDecimal.get((BigDecimal)obj);
-            case Value.STRING:
-                return ValueString.get(obj.toString());
-            case Value.BYTES:
-                return ValueBytes.get((byte[])obj);
-            case Value.JAVA_OBJECT:
-                return ValueJavaObject.getNoCopy(obj, null, null);
-            case Value.ARRAY:
-                Object[] arr = (Object[])obj;
-
-                Value[] valArr = new Value[arr.length];
-
-                for (int i = 0; i < arr.length; i++) {
-                    Object o = arr[i];
-
-                    valArr[i] = o == null ? ValueNull.INSTANCE : wrap(o, 
DataType.getTypeFromClass(o.getClass()));
-                }
-
-                return ValueArray.get(valArr);
-
-            case Value.GEOMETRY:
-                return ValueGeometry.getFromGeometry(obj);
-        }
-
-        throw new IgniteCheckedException("Failed to wrap value[type=" + type + 
", value=" + obj + "]");
-    }
-
-    /** {@inheritDoc} */
-    @Override public GridH2Row createRow(KeyCacheObject key, int partId, 
@Nullable CacheObject val,
-        GridCacheVersion ver, long expirationTime) throws 
IgniteCheckedException {
-        GridH2Row row;
-
-        try {
-            if (val == null) // Only can happen for remove operation, can 
create simple search row.
-                row = GridH2RowFactory.create(wrap(key, keyType));
-            else
-                row = new GridH2KeyValueRowOnheap(this, key, keyType, val, 
valType, ver, expirationTime);
-        }
-        catch (ClassCastException e) {
-            throw new IgniteCheckedException("Failed to convert key to SQL 
type. " +
-                "Please make sure that you always store each value type with 
the same key type " +
-                "or configure key type as common super class for all actual 
keys for this value type.", e);
-        }
-
-        row.ver = ver;
-
-        row.key = key;
-        row.val = val;
-        row.partId = partId;
-
-        return row;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int valueType() {
-        return valType;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int fieldsCount() {
-        return fields.length;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int fieldType(int col) {
-        return fieldTypes[col];
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object columnValue(Object key, Object val, int col) {
-        try {
-            return props[col].value(key, val);
-        }
-        catch (IgniteCheckedException e) {
-            throw DbException.convert(e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setColumnValue(Object key, Object val, Object 
colVal, int col) {
-        try {
-            props[col].setValue(key, val, colVal);
-        }
-        catch (IgniteCheckedException e) {
-            throw DbException.convert(e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isColumnKeyProperty(int col) {
-        return props[col].key();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isKeyColumn(int colId) {
-        assert colId >= 0;
-        return colId == KEY_COL || colId == keyAliasColId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isValueColumn(int colId) {
-        assert colId >= 0;
-        return colId == VAL_COL || colId == valAliasColId;
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings("RedundantIfStatement")
-    @Override public boolean isKeyValueOrVersionColumn(int colId) {
-        assert colId >= 0;
-
-        if (colId < DEFAULT_COLUMNS_COUNT)
-            return true;
-
-        if (colId == keyAliasColId)
-            return true;
-
-        if (colId == valAliasColId)
-            return true;
-
-        return false;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean checkKeyIndexCondition(int masks[], int mask) {
-        assert masks != null;
-        assert masks.length > 0;
-
-        if (keyAliasColId < 0)
-            return (masks[KEY_COL] & mask) != 0;
-        else
-            return (masks[KEY_COL] & mask) != 0 || (masks[keyAliasColId] & 
mask) != 0;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void initValueCache(Value valCache[], Value key, Value 
val, Value ver) {
-        assert valCache != null;
-        assert valCache.length > 0;
-
-        valCache[KEY_COL] = key;
-        valCache[VAL_COL] = val;
-        valCache[VER_COL] = ver;
-
-        if (keyAliasColId > 0)
-            valCache[keyAliasColId] = key;
-
-        if (valAliasColId > 0)
-            valCache[valAliasColId] = val;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SearchRow prepareProxyIndexRow(SearchRow row) {
-        if (row == null)
-            return null;
-
-        Value[] data = new Value[row.getColumnCount()];
-        for (int idx = 0; idx < data.length; idx++)
-            data[idx] = row.getValue(idx);
-
-        copyAliasColumnData(data, KEY_COL, keyAliasColId);
-        copyAliasColumnData(data, VAL_COL, valAliasColId);
-
-        return new SimpleRow(data);
-    }
-
-    /**
-     * Copies data between original and alias columns
-     *
-     * @param data Array of values.
-     * @param colId Original column id.
-     * @param aliasColId Alias column id.
-     */
-    private void copyAliasColumnData(Value[] data, int colId, int aliasColId) {
-        if (aliasColId <= 0)
-            return;
-
-        if (data[aliasColId] == null && data[colId] != null)
-            data[aliasColId] = data[colId];
-
-        if (data[colId] == null && data[aliasColId] != null)
-            data[colId] = data[aliasColId];
-    }
-
-    /** {@inheritDoc} */
-    @Override public int getAlternativeColumnId(int colId) {
-        if (keyAliasColId > 0) {
-            if (colId == KEY_COL)
-                return keyAliasColId;
-            else if (colId == keyAliasColId)
-                return KEY_COL;
-        }
-        if (valAliasColId > 0) {
-            if (colId == VAL_COL)
-                return valAliasColId;
-            else if (colId == valAliasColId)
-                return VAL_COL;
-        }
-
-        return colId;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
index 391b002..899bdda 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
@@ -141,7 +141,7 @@ public class H2TableDescriptor implements 
GridH2SystemIndexFactory {
     /**
      * @return Cache context.
      */
-    GridCacheContext cache() {
+    public GridCacheContext cache() {
         return cctx;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableEngine.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableEngine.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableEngine.java
index d3e9560..c05aaf6 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableEngine.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableEngine.java
@@ -21,6 +21,7 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Statement;
 import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
 import org.h2.api.TableEngine;
 import org.h2.command.ddl.CreateTableData;
@@ -31,7 +32,7 @@ import org.h2.table.TableBase;
  */
 public class H2TableEngine implements TableEngine {
     /** */
-    private static H2RowDescriptor rowDesc0;
+    private static GridH2RowDescriptor rowDesc0;
 
     /** */
     private static H2RowFactory rowFactory0;
@@ -53,7 +54,7 @@ public class H2TableEngine implements TableEngine {
      * @throws SQLException If failed.
      * @return Created table.
      */
-    public static synchronized GridH2Table createTable(Connection conn, String 
sql, H2RowDescriptor rowDesc,
+    public static synchronized GridH2Table createTable(Connection conn, String 
sql, GridH2RowDescriptor rowDesc,
         H2RowFactory rowFactory, H2TableDescriptor tblDesc)
         throws SQLException {
         rowDesc0 = rowDesc;

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
index 157e1ba..cfbb7bb 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
@@ -247,8 +247,7 @@ public class H2Utils {
      * @return Converted object.
      * @throws IgniteCheckedException if failed.
      */
-    public static Object convert(Object val, GridH2RowDescriptor desc, int 
type)
-        throws IgniteCheckedException {
+    public static Object convert(Object val, GridH2RowDescriptor desc, int 
type) throws IgniteCheckedException {
         if (val == null)
             return null;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index c172e65..dd35723 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -675,9 +675,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
                     if (expTime == 0L)
                         expTime = Long.MAX_VALUE;
 
-                    GridH2Row row = rowDesc.createRow(key, part, val, ver, 
expTime);
-
-                    row.link(link);
+                    GridH2Row row = rowDesc.createRow(key, part, val, ver, 
expTime, link);
 
                     h2Idx.put(row);
                 }
@@ -1775,7 +1773,7 @@ public class IgniteH2Indexing implements 
GridQueryIndexing {
         if (log.isDebugEnabled())
             log.debug("Creating DB table with SQL: " + sql);
 
-        H2RowDescriptor rowDesc = new H2RowDescriptor(this, tbl, tbl.type());
+        GridH2RowDescriptor rowDesc = new GridH2RowDescriptor(this, tbl, 
tbl.type());
 
         H2RowFactory rowFactory = tbl.rowFactory(rowDesc);
 
@@ -2450,8 +2448,7 @@ public class IgniteH2Indexing implements 
GridQueryIndexing {
         assert partInfo != null;
         assert partInfo.partition() < 0;
 
-        GridH2RowDescriptor desc = dataTable(schema(partInfo.cacheName()),
-                partInfo.tableName()).rowDescriptor();
+        GridH2RowDescriptor desc = dataTable(schema(partInfo.cacheName()), 
partInfo.tableName()).rowDescriptor();
 
         Object param = H2Utils.convert(params[partInfo.paramIdx()],
                 desc, partInfo.dataType());

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2PkHashIndex.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2PkHashIndex.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2PkHashIndex.java
index 6691485..891e59f 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2PkHashIndex.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2PkHashIndex.java
@@ -197,11 +197,8 @@ public class H2PkHashIndex extends GridH2IndexBase {
             try {
                 CacheDataRow dataRow = cursor.get();
 
-                GridH2Row row = tbl.rowDescriptor().createRow(dataRow.key(), 
dataRow.partition(), dataRow.value(), dataRow.version(), 0);
-
-                row.link(dataRow.link());
-
-                return row;
+                return tbl.rowDescriptor().createRow(dataRow.key(), 
dataRow.partition(), dataRow.value(),
+                    dataRow.version(), 0, dataRow.link());
             }
             catch (IgniteCheckedException e) {
                 throw DbException.convert(e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowFactory.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowFactory.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowFactory.java
index 2e57ca3..92ecd3d 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowFactory.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowFactory.java
@@ -22,8 +22,8 @@ import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import 
org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
 
 /**
  * Data store for H2 rows.
@@ -65,9 +65,7 @@ public class H2RowFactory {
 
         try {
             row = rowDesc.createRow(rowBuilder.key(),
-                PageIdUtils.partId(link), rowBuilder.value(), 
rowBuilder.version(), rowBuilder.expireTime());
-
-            row.link = link;
+                PageIdUtils.partId(link), rowBuilder.value(), 
rowBuilder.version(), rowBuilder.expireTime(), link);
         }
         catch (IgniteCheckedException e) {
             throw new IgniteException(e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
index 390015b..63b4606 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
@@ -61,7 +61,7 @@ public class GridH2KeyValueRowOnheap extends GridH2Row {
     private Value[] valCache;
 
     /** */
-    private Value version;
+    private Value ver;
 
     /**
      * Constructor.
@@ -79,13 +79,13 @@ public class GridH2KeyValueRowOnheap extends GridH2Row {
         this.desc = desc;
         this.expirationTime = expirationTime;
 
-        setValue(KEY_COL, desc.wrap(key, keyType));
+        this.key = desc.wrap(key, keyType);
 
-        if (val != null) // We remove by key only, so value can be null here.
-            setValue(VAL_COL, desc.wrap(val, valType));
+        if (val != null)
+            this.val = desc.wrap(val, valType);
 
         if (ver != null)
-            setValue(VER_COL, desc.wrap(ver, Value.JAVA_OBJECT));
+            this.ver = desc.wrap(ver, Value.JAVA_OBJECT);
     }
 
     /** {@inheritDoc} */
@@ -103,59 +103,39 @@ public class GridH2KeyValueRowOnheap extends GridH2Row {
         return DEFAULT_COLUMNS_COUNT + desc.fieldsCount();
     }
 
-    /**
-     * @param col Column index.
-     * @return Value if exists.
-     */
-    protected final Value peekValue(int col) {
-        if (col == KEY_COL)
-            return key;
-
-        if (col == VAL_COL)
-            return val;
-
-        assert col == VER_COL;
-
-        return version;
-    }
-
     /** {@inheritDoc} */
     @Override public Value getValue(int col) {
-        Value[] vCache = valCache;
-
-        if (vCache != null) {
-            Value v = vCache[col];
+        switch (col) {
+            case KEY_COL:
+                return key;
 
-            if (v != null)
-                return v;
-        }
+            case VAL_COL:
+                return val;
 
-        Value v;
+            case VER_COL:
+                return ver;
 
-        if (desc.isValueColumn(col)) {
-            v = peekValue(VAL_COL);
+            default:
+                if (desc.isKeyAliasColumn(col))
+                    return key;
+                else if (desc.isValueAliasColumn(col))
+                    return val;
 
-            return v;
+                return getValue0(col - DEFAULT_COLUMNS_COUNT);
         }
-        else if (desc.isKeyColumn(col)) {
-            v = peekValue(KEY_COL);
+    }
 
-            assert v != null;
+    /**
+     * Get real column value.
+     *
+     * @param col Adjusted column index (without default columns).
+     * @return Value.
+     */
+    private Value getValue0(int col) {
+        Value v = getCached(col);
 
+        if (v != null)
             return v;
-        }
-        else if (col == VER_COL)
-            return version;
-
-        col -= DEFAULT_COLUMNS_COUNT;
-
-        assert col >= 0;
-
-        Value key = getValue(KEY_COL);
-        Value val = getValue(VAL_COL);
-
-        assert key != null;
-        assert val != null;
 
         Object res = desc.columnValue(key.getObject(), val.getObject(), col);
 
@@ -170,21 +150,44 @@ public class GridH2KeyValueRowOnheap extends GridH2Row {
             }
         }
 
-        if (vCache != null)
-            vCache[col + DEFAULT_COLUMNS_COUNT] = v;
+        setCached(col, v);
 
         return v;
     }
 
     /**
-     * @param valCache Value cache.
+     * Prepare values cache.
      */
-    public void valuesCache(Value[] valCache) {
-        if (valCache != null) {
-            desc.initValueCache(valCache, key, val, version);
-        }
+    public void prepareValuesCache() {
+        this.valCache = new Value[desc.fieldsCount()];
+    }
+
+    /**
+     * Clear values cache.
+     */
+    public void clearValuesCache() {
+        this.valCache = null;
+    }
+
+    /**
+     * Get cached value (if any).
+     *
+     * @param colIdx Column index.
+     * @return Value.
+     */
+    private Value getCached(int colIdx) {
+        return valCache != null ? valCache[colIdx] : null;
+    }
 
-        this.valCache = valCache;
+    /**
+     * Set cache value.
+     *
+     * @param colIdx Column index.
+     * @param val Value.
+     */
+    private void setCached(int colIdx, Value val) {
+        if (valCache != null)
+            valCache[colIdx] = val;
     }
 
     /** {@inheritDoc} */
@@ -193,13 +196,13 @@ public class GridH2KeyValueRowOnheap extends GridH2Row {
 
         sb.a(Integer.toHexString(System.identityHashCode(this)));
 
-        Value v = peekValue(KEY_COL);
+        Value v = key;
         sb.a("[ key: ").a(v == null ? "nil" : v.getString());
 
-        v = peekValue(VAL_COL);
+        v = val;
         sb.a(", val: ").a(v == null ? "nil" : v.getString());
 
-        v = peekValue(VER_COL);
+        v = ver;
         sb.a(", ver: ").a(v == null ? "nil" : v.getString());
 
         sb.a(" ][ ");
@@ -223,54 +226,46 @@ public class GridH2KeyValueRowOnheap extends GridH2Row {
 
     /** {@inheritDoc} */
     @Override public void setKeyAndVersion(SearchRow old) {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public void setKey(long key) {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public Row getCopy() {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public void setDeleted(boolean deleted) {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public long getKey() {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public void setSessionId(int sesId) {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public void setVersion(int ver) {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public void setValue(int idx, Value v) {
-        if (desc.isValueColumn(idx))
-            val = v;
-        else if (idx == VER_COL)
-            version = v;
-        else {
-            assert desc.isKeyColumn(idx) : idx + " " + v;
-
-            key = v;
-        }
+        throw new UnsupportedOperationException();
     }
 
     /** {@inheritDoc} */
     @Override public final int hashCode() {
-        throw new IllegalStateException();
+        throw new UnsupportedOperationException();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
index 1f6ff88..081805e 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
@@ -17,41 +17,259 @@
 
 package org.apache.ignite.internal.processors.query.h2.opt;
 
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
-import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.query.GridQueryProperty;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
+import org.apache.ignite.internal.processors.query.h2.H2TableDescriptor;
 import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.h2.message.DbException;
 import org.h2.result.SearchRow;
+import org.h2.result.SimpleRow;
+import org.h2.util.LocalDateTimeUtils;
+import org.h2.value.DataType;
 import org.h2.value.Value;
+import org.h2.value.ValueArray;
+import org.h2.value.ValueBoolean;
+import org.h2.value.ValueByte;
+import org.h2.value.ValueBytes;
+import org.h2.value.ValueDate;
+import org.h2.value.ValueDecimal;
+import org.h2.value.ValueDouble;
+import org.h2.value.ValueFloat;
+import org.h2.value.ValueGeometry;
+import org.h2.value.ValueInt;
+import org.h2.value.ValueJavaObject;
+import org.h2.value.ValueLong;
+import org.h2.value.ValueNull;
+import org.h2.value.ValueShort;
+import org.h2.value.ValueString;
+import org.h2.value.ValueTime;
+import org.h2.value.ValueTimestamp;
+import org.h2.value.ValueUuid;
 import org.jetbrains.annotations.Nullable;
 
+import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.DEFAULT_COLUMNS_COUNT;
+import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.KEY_COL;
+import static 
org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.VAL_COL;
+
 /**
  * Row descriptor.
  */
-public interface GridH2RowDescriptor {
+public class GridH2RowDescriptor {
+    /** Indexing SPI. */
+    private final IgniteH2Indexing idx;
+
+    /** Table descriptor. */
+    private final H2TableDescriptor tbl;
+
+    /** */
+    private final GridQueryTypeDescriptor type;
+
+    /** */
+    private volatile String[] fields;
+
+    /** */
+    private volatile int[] fieldTypes;
+
+    /** */
+    private final int keyType;
+
+    /** */
+    private final int valType;
+
+    /** */
+    private volatile GridQueryProperty[] props;
+
+    /** Id of user-defined key column */
+    private volatile int keyAliasColId;
+
+    /** Id of user-defined value column */
+    private volatile int valAliasColId;
+
+    /**
+     * Constructor.
+     *
+     * @param idx Indexing.
+     * @param tbl Table.
+     * @param type Type descriptor.
+     */
+    public GridH2RowDescriptor(IgniteH2Indexing idx, H2TableDescriptor tbl, 
GridQueryTypeDescriptor type) {
+        assert type != null;
+
+        this.idx = idx;
+        this.tbl = tbl;
+        this.type = type;
+
+        keyType = DataType.getTypeFromClass(type.keyClass());
+        valType = DataType.getTypeFromClass(type.valueClass());
+
+        refreshMetadataFromTypeDescriptor();
+    }
+
+    /**
+     * Update metadata of this row descriptor according to current state of 
type descriptor.
+     */
+    @SuppressWarnings("WeakerAccess")
+    public final void refreshMetadataFromTypeDescriptor() {
+        Map<String, Class<?>> allFields = new LinkedHashMap<>();
+
+        allFields.putAll(type.fields());
+
+        fields = allFields.keySet().toArray(new String[allFields.size()]);
+
+        fieldTypes = new int[fields.length];
+
+        Class[] classes = allFields.values().toArray(new Class[fields.length]);
+
+        for (int i = 0; i < fieldTypes.length; i++)
+            fieldTypes[i] = DataType.getTypeFromClass(classes[i]);
+
+        props = new GridQueryProperty[fields.length];
+
+        for (int i = 0; i < fields.length; i++) {
+            GridQueryProperty p = type.property(fields[i]);
+
+            assert p != null : fields[i];
+
+            props[i] = p;
+        }
+
+        List<String> fieldsList = Arrays.asList(fields);
+
+        keyAliasColId =
+            (type.keyFieldName() != null) ? DEFAULT_COLUMNS_COUNT + 
fieldsList.indexOf(type.keyFieldAlias()) : -1;
+
+        valAliasColId =
+            (type.valueFieldName() != null) ? DEFAULT_COLUMNS_COUNT + 
fieldsList.indexOf(type.valueFieldAlias()) : -1;
+    }
+
     /**
      * Gets indexing.
      *
      * @return indexing.
      */
-    public IgniteH2Indexing indexing();
+    public IgniteH2Indexing indexing() {
+        return idx;
+    }
 
     /**
      * Gets type descriptor.
      *
      * @return Type descriptor.
      */
-    public GridQueryTypeDescriptor type();
+    public GridQueryTypeDescriptor type() {
+        return type;
+    }
 
     /**
      * Gets cache context for this row descriptor.
      *
      * @return Cache context.
      */
-    public GridCacheContext<?, ?> context();
+    public GridCacheContext<?, ?> context() {
+        return tbl.cache();
+    }
+
+    /**
+     * Wraps object to respective {@link Value}.
+     *
+     * @param obj Object.
+     * @param type Value type.
+     * @return Value.
+     * @throws IgniteCheckedException If failed.
+     */
+    @SuppressWarnings("ConstantConditions")
+    public Value wrap(Object obj, int type) throws IgniteCheckedException {
+        assert obj != null;
+
+        if (obj instanceof CacheObject) { // Handle cache object.
+            CacheObject co = (CacheObject)obj;
+
+            if (type == Value.JAVA_OBJECT)
+                return new GridH2ValueCacheObject(co, idx.objectContext());
+
+            obj = co.value(idx.objectContext(), false);
+        }
+
+        switch (type) {
+            case Value.BOOLEAN:
+                return ValueBoolean.get((Boolean)obj);
+            case Value.BYTE:
+                return ValueByte.get((Byte)obj);
+            case Value.SHORT:
+                return ValueShort.get((Short)obj);
+            case Value.INT:
+                return ValueInt.get((Integer)obj);
+            case Value.FLOAT:
+                return ValueFloat.get((Float)obj);
+            case Value.LONG:
+                return ValueLong.get((Long)obj);
+            case Value.DOUBLE:
+                return ValueDouble.get((Double)obj);
+            case Value.UUID:
+                UUID uuid = (UUID)obj;
+                return ValueUuid.get(uuid.getMostSignificantBits(), 
uuid.getLeastSignificantBits());
+            case Value.DATE:
+                if (LocalDateTimeUtils.isLocalDate(obj.getClass()))
+                    return LocalDateTimeUtils.localDateToDateValue(obj);
+
+                return ValueDate.get((Date)obj);
+
+            case Value.TIME:
+                if (LocalDateTimeUtils.isLocalTime(obj.getClass()))
+                    return LocalDateTimeUtils.localTimeToTimeValue(obj);
+
+                return ValueTime.get((Time)obj);
+
+            case Value.TIMESTAMP:
+                if (obj instanceof java.util.Date && !(obj instanceof 
Timestamp))
+                    obj = new Timestamp(((java.util.Date)obj).getTime());
+
+                if (LocalDateTimeUtils.isLocalDateTime(obj.getClass()))
+                    return LocalDateTimeUtils.localDateTimeToValue(obj);
+
+                return ValueTimestamp.get((Timestamp)obj);
+
+            case Value.DECIMAL:
+                return ValueDecimal.get((BigDecimal)obj);
+            case Value.STRING:
+                return ValueString.get(obj.toString());
+            case Value.BYTES:
+                return ValueBytes.get((byte[])obj);
+            case Value.JAVA_OBJECT:
+                return ValueJavaObject.getNoCopy(obj, null, null);
+            case Value.ARRAY:
+                Object[] arr = (Object[])obj;
+
+                Value[] valArr = new Value[arr.length];
+
+                for (int i = 0; i < arr.length; i++) {
+                    Object o = arr[i];
+
+                    valArr[i] = o == null ? ValueNull.INSTANCE : wrap(o, 
DataType.getTypeFromClass(o.getClass()));
+                }
+
+                return ValueArray.get(valArr);
+
+            case Value.GEOMETRY:
+                return ValueGeometry.getFromGeometry(obj);
+        }
+
+        throw new IgniteCheckedException("Failed to wrap value[type=" + type + 
", value=" + obj + "]");
+    }
 
     /**
      * Creates new row.
@@ -63,18 +281,46 @@ public interface GridH2RowDescriptor {
      * @return Row.
      * @throws IgniteCheckedException If failed.
      */
-    public GridH2Row createRow(KeyCacheObject key, int part, @Nullable 
CacheObject val, GridCacheVersion ver,
-        long expirationTime) throws IgniteCheckedException;
+    public GridH2Row createRow(KeyCacheObject key, int partId, @Nullable 
CacheObject val, GridCacheVersion ver,
+        long expirationTime, long link) throws IgniteCheckedException {
+        GridH2Row row;
+
+        try {
+            if (val == null) // Only can happen for remove operation, can 
create simple search row.
+                row = GridH2RowFactory.create(wrap(key, keyType));
+            else
+                row = new GridH2KeyValueRowOnheap(this, key, keyType, val, 
valType, ver, expirationTime);
+        }
+        catch (ClassCastException e) {
+            throw new IgniteCheckedException("Failed to convert key to SQL 
type. " +
+                "Please make sure that you always store each value type with 
the same key type " +
+                "or configure key type as common super class for all actual 
keys for this value type.", e);
+        }
+
+        row.ver = ver;
+
+        row.key = key;
+        row.val = val;
+        row.partId = partId;
+
+        row.link(link);
+
+        return row;
+    }
 
     /**
      * @return Value type.
      */
-    public int valueType();
+    public int valueType() {
+        return valType;
+    }
 
     /**
      * @return Total fields count.
      */
-    public int fieldsCount();
+    public int fieldsCount() {
+        return fields.length;
+    }
 
     /**
      * Gets value type for column index.
@@ -82,7 +328,9 @@ public interface GridH2RowDescriptor {
      * @param col Column index.
      * @return Value type.
      */
-    public int fieldType(int col);
+    public int fieldType(int col) {
+        return fieldTypes[col];
+    }
 
     /**
      * Gets column value by column index.
@@ -92,7 +340,14 @@ public interface GridH2RowDescriptor {
      * @param col Column index.
      * @return  Column value.
      */
-    public Object columnValue(Object key, Object val, int col);
+    public Object columnValue(Object key, Object val, int col) {
+        try {
+            return props[col].value(key, val);
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
+    }
 
     /**
      * Gets column value by column index.
@@ -102,7 +357,14 @@ public interface GridH2RowDescriptor {
      * @param colVal Value to set to column.
      * @param col Column index.
      */
-    public void setColumnValue(Object key, Object val, Object colVal, int col);
+    public void setColumnValue(Object key, Object val, Object colVal, int col) 
{
+        try {
+            props[col].setValue(key, val, colVal);
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
+    }
 
     /**
      * Determine whether a column corresponds to a property of key or to one 
of value.
@@ -110,25 +372,31 @@ public interface GridH2RowDescriptor {
      * @param col Column index.
      * @return {@code true} if given column corresponds to a key property, 
{@code false} otherwise
      */
-    public boolean isColumnKeyProperty(int col);
+    public boolean isColumnKeyProperty(int col) {
+        return props[col].key();
+    }
 
     /**
-     * Wraps object to respective {@link Value}.
+     * Checks if provided column id matches key column or key alias.
      *
-     * @param o Object.
-     * @param type Value type.
-     * @return Value.
-     * @throws IgniteCheckedException If failed.
+     * @param colId Column id.
+     * @return Result.
      */
-    public Value wrap(Object o, int type) throws IgniteCheckedException;
+    public boolean isKeyColumn(int colId) {
+        assert colId >= 0;
+        return colId == KEY_COL || colId == keyAliasColId;
+    }
 
     /**
-     * Checks if provided column id matches key column or key alias.
+     * Checks if provided column id matches key alias column.
      *
      * @param colId Column id.
      * @return Result.
      */
-    public boolean isKeyColumn(int colId);
+    public boolean isKeyAliasColumn(int colId) {
+        assert colId >= 0;
+        return colId == keyAliasColId;
+    }
 
     /**
      * Checks if provided column id matches value column or alias.
@@ -136,7 +404,21 @@ public interface GridH2RowDescriptor {
      * @param colId Column id.
      * @return Result.
      */
-    public boolean isValueColumn(int colId);
+    public boolean isValueColumn(int colId) {
+        assert colId >= 0;
+        return colId == VAL_COL || colId == valAliasColId;
+    }
+
+    /**
+     * Checks if provided column id matches value alias column.
+     *
+     * @param colId Column id.
+     * @return Result.
+     */
+    public boolean isValueAliasColumn(int colId) {
+        assert colId >= 0;
+        return colId == valAliasColId;
+    }
 
     /**
      * Checks if provided column id matches key, key alias,
@@ -145,7 +427,21 @@ public interface GridH2RowDescriptor {
      * @param colId Column id.
      * @return Result.
      */
-    public boolean isKeyValueOrVersionColumn(int colId);
+    @SuppressWarnings("RedundantIfStatement")
+    public boolean isKeyValueOrVersionColumn(int colId) {
+        assert colId >= 0;
+
+        if (colId < DEFAULT_COLUMNS_COUNT)
+            return true;
+
+        if (colId == keyAliasColId)
+            return true;
+
+        if (colId == valAliasColId)
+            return true;
+
+        return false;
+    }
 
     /**
      * Checks if provided index condition is allowed for key column or key 
alias column.
@@ -154,17 +450,15 @@ public interface GridH2RowDescriptor {
      * @param mask Index Condition to check.
      * @return Result.
      */
-    public boolean checkKeyIndexCondition(int masks[], int mask);
+    public boolean checkKeyIndexCondition(int masks[], int mask) {
+        assert masks != null;
+        assert masks.length > 0;
 
-    /**
-     * Initializes value cache with key, val and version.
-     *
-     * @param valCache Value cache.
-     * @param key Key.
-     * @param value Value.
-     * @param version Version.
-     */
-    public void initValueCache(Value valCache[], Value key, Value value, Value 
version);
+        if (keyAliasColId < 0)
+            return (masks[KEY_COL] & mask) != 0;
+        else
+            return (masks[KEY_COL] & mask) != 0 || (masks[keyAliasColId] & 
mask) != 0;
+    }
 
     /**
      * Clones provided row and copies values of alias key and val columns
@@ -173,7 +467,38 @@ public interface GridH2RowDescriptor {
      * @param row Source row.
      * @return Result.
      */
-    public SearchRow prepareProxyIndexRow(SearchRow row);
+    public SearchRow prepareProxyIndexRow(SearchRow row) {
+        if (row == null)
+            return null;
+
+        Value[] data = new Value[row.getColumnCount()];
+
+        for (int idx = 0; idx < data.length; idx++)
+            data[idx] = row.getValue(idx);
+
+        copyAliasColumnData(data, KEY_COL, keyAliasColId);
+        copyAliasColumnData(data, VAL_COL, valAliasColId);
+
+        return new SimpleRow(data);
+    }
+
+    /**
+     * Copies data between original and alias columns
+     *
+     * @param data Array of values.
+     * @param colId Original column id.
+     * @param aliasColId Alias column id.
+     */
+    private void copyAliasColumnData(Value[] data, int colId, int aliasColId) {
+        if (aliasColId <= 0)
+            return;
+
+        if (data[aliasColId] == null && data[colId] != null)
+            data[aliasColId] = data[colId];
+
+        if (data[colId] == null && data[aliasColId] != null)
+            data[colId] = data[aliasColId];
+    }
 
     /**
      * Gets alternative column id that may substitute the given column id.
@@ -186,5 +511,20 @@ public interface GridH2RowDescriptor {
      * @param colId Column id.
      * @return Result.
      */
-    public int getAlternativeColumnId(int colId);
-}
\ No newline at end of file
+    public int getAlternativeColumnId(int colId) {
+        if (keyAliasColId > 0) {
+            if (colId == KEY_COL)
+                return keyAliasColId;
+            else if (colId == keyAliasColId)
+                return KEY_COL;
+        }
+        if (valAliasColId > 0) {
+            if (colId == VAL_COL)
+                return valAliasColId;
+            else if (colId == valAliasColId)
+                return VAL_COL;
+        }
+
+        return colId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/583e3461/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index 79eed12..d20b56b 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -34,7 +34,6 @@ import 
org.apache.ignite.internal.processors.cache.query.QueryTable;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.QueryField;
-import org.apache.ignite.internal.processors.query.h2.H2RowDescriptor;
 import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory;
 import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex;
 import org.apache.ignite.internal.util.typedef.F;
@@ -55,7 +54,6 @@ import org.h2.table.IndexColumn;
 import org.h2.table.TableBase;
 import org.h2.table.TableType;
 import org.h2.value.DataType;
-import org.h2.value.Value;
 import org.jetbrains.annotations.Nullable;
 import org.jsr166.ConcurrentHashMap8;
 import org.jsr166.LongAdder8;
@@ -71,7 +69,7 @@ public class GridH2Table extends TableBase {
     private final GridCacheContext cctx;
 
     /** */
-    private final H2RowDescriptor desc;
+    private final GridH2RowDescriptor desc;
 
     /** */
     private volatile ArrayList<Index> idxs;
@@ -124,7 +122,7 @@ public class GridH2Table extends TableBase {
      * @param idxsFactory Indexes factory.
      * @param cctx Cache context.
      */
-    public GridH2Table(CreateTableData createTblData, H2RowDescriptor desc, 
H2RowFactory rowFactory,
+    public GridH2Table(CreateTableData createTblData, GridH2RowDescriptor 
desc, H2RowFactory rowFactory,
         GridH2SystemIndexFactory idxsFactory, GridCacheContext cctx) {
         super(createTblData);
 
@@ -408,19 +406,21 @@ public class GridH2Table extends TableBase {
         throws IgniteCheckedException {
         assert desc != null;
 
-        GridH2Row row = desc.createRow(key, partId, val, ver, expirationTime);
+        GridH2Row row = desc.createRow(key, partId, val, ver, expirationTime, 
link);
 
-        row.link = link;
+        if (rmv)
+            return doUpdate(row, true);
+        else {
+            GridH2KeyValueRowOnheap row0 = (GridH2KeyValueRowOnheap)row;
 
-        if (!rmv)
-            ((GridH2KeyValueRowOnheap)row).valuesCache(new 
Value[getColumns().length]);
+            row0.prepareValuesCache();
 
-        try {
-            return doUpdate(row, rmv);
-        }
-        finally {
-            if (!rmv)
-                ((GridH2KeyValueRowOnheap)row).valuesCache(null);
+            try {
+                return doUpdate(row, false);
+            }
+            finally {
+                row0.clearValuesCache();
+            }
         }
     }
 

Reply via email to