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(); + } } }