You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2021/05/24 07:12:10 UTC
[ignite-3] branch main updated: IGNITE-14759: Fix wrong offset
calculation for fix-sized column when nullmap is omitted. (#140)
This is an automated email from the ASF dual-hosted git repository.
amashenkov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new ed4788a IGNITE-14759: Fix wrong offset calculation for fix-sized column when nullmap is omitted. (#140)
ed4788a is described below
commit ed4788a271ee5c8c8be277378fac6e8fa980bea4
Author: Andrew V. Mashenkov <AM...@users.noreply.github.com>
AuthorDate: Mon May 24 10:12:02 2021 +0300
IGNITE-14759: Fix wrong offset calculation for fix-sized column when nullmap is omitted. (#140)
---
.../table/IndexColumnConfigurationSchema.java | 4 +-
.../runner/app/DynamicTableCreationTest.java | 99 +++++++++++++-----
.../internal/runner/app/TableCreationTest.java | 48 +++++++--
.../org/apache/ignite/internal/schema/Row.java | 42 +++++---
.../ignite/internal/schema/SchemaManager.java | 12 ++-
.../ignite/internal/schema/SchemaRegistry.java | 6 +-
.../org/apache/ignite/internal/schema/RowTest.java | 113 ++++++++++++++++-----
7 files changed, 240 insertions(+), 84 deletions(-)
diff --git a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/IndexColumnConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/IndexColumnConfigurationSchema.java
index e915040..3cf584c 100644
--- a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/IndexColumnConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/IndexColumnConfigurationSchema.java
@@ -30,6 +30,6 @@ public class IndexColumnConfigurationSchema {
String name;
/** Ascending flag. */
- @Value
- boolean asc;
+ @Value(hasDefault = true)
+ boolean asc = true;
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java
index 385d1f7..9cf1e02 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java
@@ -24,6 +24,7 @@ import org.apache.ignite.app.Ignite;
import org.apache.ignite.app.IgnitionManager;
import org.apache.ignite.internal.schema.SchemaManager;
import org.apache.ignite.lang.IgniteLogger;
+import org.apache.ignite.table.KeyValueBinaryView;
import org.apache.ignite.table.Table;
import org.apache.ignite.table.Tuple;
import org.junit.jupiter.api.Disabled;
@@ -31,6 +32,7 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* Ignition interface tests.
@@ -82,21 +84,21 @@ class DynamicTableCreationTest {
*/
@Test
void testDynamicSimpleTableCreation() {
- List<Ignite> clusterNodex = new ArrayList<>();
+ List<Ignite> clusterNodes = new ArrayList<>();
for (String nodeBootstrapCfg : nodesBootstrapCfg)
- clusterNodex.add(IgnitionManager.start(nodeBootstrapCfg));
+ clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg));
- assertEquals(3, clusterNodex.size());
+ assertEquals(3, clusterNodes.size());
// Create table on node 0.
- clusterNodex.get(0).tables().createTable("tbl1", tbl -> tbl
+ clusterNodes.get(0).tables().createTable("tbl1", tbl -> tbl
.changeName("tbl1")
.changeReplicas(1)
.changePartitions(10)
.changeColumns(cols -> cols
- .create("key", c -> c.changeName("key").changeNullable(false).changeType(t -> t.changeType("int")))
- .create("val", c -> c.changeName("val").changeNullable(true).changeType(t -> t.changeType("int")))
+ .create("key", c -> c.changeName("key").changeNullable(false).changeType(t -> t.changeType("INT64")))
+ .create("val", c -> c.changeName("val").changeNullable(true).changeType(t -> t.changeType("INT32")))
)
.changeIndices(idxs -> idxs
.create("PK", idx -> idx
@@ -104,17 +106,33 @@ class DynamicTableCreationTest {
.changeType("PRIMARY")
.changeColNames(new String[] {"key"})
.changeColumns(c -> c
- .create("key", t -> t.changeName("key").changeAsc(true)))
+ .create("key", t -> t.changeName("key")))
.changeAffinityColumns(new String[] {"key"}))
));
// Put data on node 1.
- Table tbl1 = waitForTable(clusterNodex.get(1));
- tbl1.insert(tbl1.tupleBuilder().set("key", 1).set("val", 111).build());
+ Table tbl1 = waitForTable(clusterNodes.get(1));
+ KeyValueBinaryView kvView1 = tbl1.kvView();
+
+ tbl1.insert(tbl1.tupleBuilder().set("key", 1L).set("val", 111).build());
+ kvView1.put(tbl1.tupleBuilder().set("key", 2L).build(), tbl1.tupleBuilder().set("val", 222).build());
// Get data on node 2.
- Table tbl2 = waitForTable(clusterNodex.get(2));
- assertEquals(111, (int)tbl2.get(tbl2.tupleBuilder().set("key", 1).build()).value("val"));
+ Table tbl2 = waitForTable(clusterNodes.get(2));
+ KeyValueBinaryView kvView2 = tbl2.kvView();
+
+ final Tuple keyTuple1 = tbl2.tupleBuilder().set("key", 1L).build();
+ final Tuple keyTuple2 = kvView2.tupleBuilder().set("key", 2L).build();
+
+ assertThrows(IllegalArgumentException.class, () -> kvView2.get(keyTuple1).value("key"));
+ assertThrows(IllegalArgumentException.class, () -> kvView2.get(keyTuple1).value("key"));
+ assertEquals(1, (Long)tbl2.get(keyTuple1).value("key"));
+ assertEquals(2, (Long)tbl2.get(keyTuple2).value("key"));
+
+ assertEquals(111, (Integer)tbl2.get(keyTuple1).value("val"));
+ assertEquals(111, (Integer)kvView2.get(keyTuple1).value("val"));
+ assertEquals(222, (Integer)tbl2.get(keyTuple2).value("val"));
+ assertEquals(222, (Integer)kvView2.get(keyTuple2).value("val"));
}
/**
@@ -154,11 +172,11 @@ class DynamicTableCreationTest {
.changeReplicas(1)
.changePartitions(10)
.changeColumns(cols -> cols
- .create("key", c -> c.changeName("key").changeNullable(false).changeType(t -> t.changeType("uuid")))
- .create("affKey", c -> c.changeName("affKey").changeNullable(false).changeType(t -> t.changeType("int")))
- .create("valStr", c -> c.changeName("valStr").changeNullable(true).changeType(t -> t.changeType("string")))
- .create("valInt", c -> c.changeName("valInt").changeNullable(true).changeType(t -> t.changeType("int")))
- .create("valNullable", c -> c.changeName("valNullable").changeNullable(true).changeType(t -> t.changeType("short")).changeNullable(true))
+ .create("key", c -> c.changeName("key").changeNullable(false).changeType(t -> t.changeType("UUID")))
+ .create("affKey", c -> c.changeName("affKey").changeNullable(false).changeType(t -> t.changeType("INT64")))
+ .create("valStr", c -> c.changeName("valStr").changeNullable(true).changeType(t -> t.changeType("STRING")))
+ .create("valInt", c -> c.changeName("valInt").changeNullable(true).changeType(t -> t.changeType("INT32")))
+ .create("valNull", c -> c.changeName("valNull").changeNullable(true).changeType(t -> t.changeType("INT16")).changeNullable(true))
)
.changeIndices(idxs -> idxs
.create("PK", idx -> idx
@@ -167,23 +185,56 @@ class DynamicTableCreationTest {
.changeColNames(new String[] {"key", "affKey"})
.changeColumns(c -> c
.create("key", t -> t.changeName("key").changeAsc(true))
- .create("affKey", t -> t.changeName("affKey").changeAsc(true)))
+ .create("affKey", t -> t.changeName("affKey").changeAsc(false)))
.changeAffinityColumns(new String[] {"affKey"}))
));
final UUID uuid = UUID.randomUUID();
+ final UUID uuid2 = UUID.randomUUID();
// Put data on node 1.
Table tbl1 = waitForTable(clusterNodes.get(1));
- tbl1.insert(tbl1.tupleBuilder().set("key", uuid).set("affKey", 42)
- .set("valStr", "String value").set("valInt", 73).set("valNullable", null).build());
+ KeyValueBinaryView kvView1 = tbl1.kvView();
+
+ tbl1.insert(tbl1.tupleBuilder().set("key", uuid).set("affKey", 42L)
+ .set("valStr", "String value").set("valInt", 73).set("valNull", null).build());
+
+ kvView1.put(kvView1.tupleBuilder().set("key", uuid2).set("affKey", 4242L).build(),
+ kvView1.tupleBuilder().set("valStr", "String value 2").set("valInt", 7373).set("valNull", null).build());
// Get data on node 2.
Table tbl2 = waitForTable(clusterNodes.get(2));
- final Tuple val = tbl2.get(tbl2.tupleBuilder().set("key", uuid).set("affKey", 42).build());
-
- assertEquals("String value", val.value("valStr"));
- assertEquals(73, (int)val.value("valInt"));
- assertNull(val.value("valNullable"));
+ KeyValueBinaryView kvView2 = tbl2.kvView();
+
+ final Tuple keyTuple1 = tbl2.tupleBuilder().set("key", uuid).set("affKey", 42L).build();
+ final Tuple keyTuple2 = tbl2.tupleBuilder().set("key", uuid2).set("affKey", 4242L).build();
+
+ // KV view must NOT return key columns in value.
+ assertThrows(IllegalArgumentException.class, () -> kvView2.get(keyTuple1).value("key"));
+ assertThrows(IllegalArgumentException.class, () -> kvView2.get(keyTuple1).value("affKey"));
+ assertThrows(IllegalArgumentException.class, () -> kvView2.get(keyTuple2).value("key"));
+ assertThrows(IllegalArgumentException.class, () -> kvView2.get(keyTuple2).value("affKey"));
+
+ // Record binary view MUST return key columns in value.
+ assertEquals(uuid, tbl2.get(keyTuple1).value("key"));
+ assertEquals(42L, (Long)tbl2.get(keyTuple1).value("affKey"));
+ assertEquals(uuid2, tbl2.get(keyTuple2).value("key"));
+ assertEquals(4242L, (Long)tbl2.get(keyTuple2).value("affKey"));
+
+ assertEquals("String value", tbl2.get(keyTuple1).value("valStr"));
+ assertEquals(73, (Integer)tbl2.get(keyTuple1).value("valInt"));
+ assertNull(tbl2.get(keyTuple1).value("valNull"));
+
+ assertEquals("String value 2", tbl2.get(keyTuple2).value("valStr"));
+ assertEquals(7373, (Integer)tbl2.get(keyTuple2).value("valInt"));
+ assertNull(tbl2.get(keyTuple2).value("valNull"));
+
+ assertEquals("String value", kvView2.get(keyTuple1).value("valStr"));
+ assertEquals(73, (Integer)kvView2.get(keyTuple1).value("valInt"));
+ assertNull(kvView2.get(keyTuple1).value("valNull"));
+
+ assertEquals("String value 2", kvView2.get(keyTuple2).value("valStr"));
+ assertEquals(7373, (Integer)kvView2.get(keyTuple2).value("valInt"));
+ assertNull(kvView2.get(keyTuple2).value("valNull"));
}
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java
index 035caad..e9834ae 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.UUID;
import org.apache.ignite.app.Ignite;
import org.apache.ignite.app.IgnitionManager;
+import org.apache.ignite.table.KeyValueBinaryView;
import org.apache.ignite.table.Table;
import org.apache.ignite.table.Tuple;
import org.junit.jupiter.api.Assertions;
@@ -162,29 +163,58 @@ class TableCreationTest {
clusterNodes.forEach(Assertions::assertNotNull);
- { /* Table 1.*/
+ { /* Table 1. */
Table tbl1 = clusterNodes.get(1).tables().table("tbl1");
- tbl1.insert(tbl1.tupleBuilder().set("key", 1L).set("val", 111L).build());
+ KeyValueBinaryView kvView1 = tbl1.kvView();
+
+ tbl1.insert(tbl1.tupleBuilder().set("key", 1L).set("val", 111).build());
+ kvView1.put(tbl1.tupleBuilder().set("key", 2L).build(), tbl1.tupleBuilder().set("val", 222).build());
Table tbl2 = clusterNodes.get(2).tables().table("tbl1");
- assertEquals(111L, tbl2.get(tbl2.tupleBuilder().set("key", 1L).build()));
+ KeyValueBinaryView kvView2 = tbl2.kvView();
+
+ final Tuple keyTuple1 = tbl2.tupleBuilder().set("key", 1L).build();
+ final Tuple keyTuple2 = kvView2.tupleBuilder().set("key", 2L).build();
+
+ assertEquals(111, (Integer)tbl2.get(keyTuple1).value("val"));
+ assertEquals(111, (Integer)kvView1.get(keyTuple1).value("val"));
+ assertEquals(222, (Integer)tbl2.get(keyTuple2).value("val"));
+ assertEquals(222, (Integer)kvView1.get(keyTuple2).value("val"));
}
{ /* Table 2. */
final UUID uuid = UUID.randomUUID();
+ final UUID uuid2 = UUID.randomUUID();
// Put data on node 1.
Table tbl1 = clusterNodes.get(1).tables().table("tbl1");
+ KeyValueBinaryView kvView1 = tbl1.kvView();
+
tbl1.insert(tbl1.tupleBuilder().set("key", uuid).set("affKey", 42L)
- .set("valStr", "String value").set("valInt", 73L).set("valNullable", null).build());
+ .set("valStr", "String value").set("valInt", 73).set("valNullable", null).build());
+
+ kvView1.put(kvView1.tupleBuilder().set("key", uuid2).set("affKey", 4242L).build(),
+ kvView1.tupleBuilder().set("valStr", "String value 2").set("valInt", 7373).set("valNullable", null).build());
// Get data on node 2.
Table tbl2 = clusterNodes.get(2).tables().table("tbl1");
- final Tuple val = tbl2.get(tbl1.tupleBuilder().set("key", uuid).set("affKey", 42L).build());
-
- assertEquals("String value", val.value("valStr"));
- assertEquals(73L, (Long)val.value("valInt"));
- assertNull(val.value("valNullable"));
+ KeyValueBinaryView kvView2 = tbl2.kvView();
+
+ final Tuple keyTuple1 = tbl2.tupleBuilder().set("key", uuid).set("affKey", 42L).build();
+ final Tuple keyTuple2 = kvView2.tupleBuilder().set("key", uuid2).set("affKey", 4242L).build();
+
+ assertEquals("String value", tbl2.get(keyTuple1).value("valStr"));
+ assertEquals("String value", kvView2.get(keyTuple1).value("valStr"));
+ assertEquals("String value 2", tbl2.get(keyTuple2).value("valStr"));
+ assertEquals("String value 2", kvView2.get(keyTuple2).value("valStr"));
+ assertEquals(73, (Integer)tbl2.get(keyTuple1).value("valInt"));
+ assertEquals(73, (Integer)kvView2.get(keyTuple1).value("valInt"));
+ assertEquals(7373, (Integer)tbl2.get(keyTuple2).value("valInt"));
+ assertEquals(7373, (Integer)kvView2.get(keyTuple2).value("valInt"));
+ assertNull(tbl2.get(keyTuple1).value("valNullable"));
+ assertNull(kvView2.get(keyTuple1).value("valNullable"));
+ assertNull(tbl2.get(keyTuple2).value("valNullable"));
+ assertNull(kvView2.get(keyTuple2).value("valNullable"));
}
}
}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
index 9d967d3..c3bb8c5 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
@@ -492,33 +492,43 @@ public class Row implements BinaryRow {
* @return Encoded offset (from the row start) of the requested fixlen column.
*/
int fixlenColumnOffset(Columns cols, int baseOff, int idx, boolean hasVarTbl, boolean hasNullMap) {
- int off = 0;
+ int colOff = 0;
int payloadOff = baseOff + CHUNK_LEN_FIELD_SIZE;
- if (hasNullMap) {
- payloadOff += cols.nullMapSize();
-
- int nullMapOff = nullMapOffset(baseOff);
-
- int nullMapIdx = idx / 8;
-
- // Fold offset based on the whole map bytes in the schema
- for (int i = 0; i < nullMapIdx; i++)
- off += cols.foldFixedLength(i, readByte(nullMapOff + i));
+ // Calculate fixlen column offset.
+ {
+ int colByteIdx = idx / 8;
// Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
int startBit = idx % 8;
- int endBit = nullMapIdx == cols.nullMapSize() - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
+ int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
- off += cols.foldFixedLength(nullMapIdx, readByte(nullMapOff + nullMapIdx) | mask);
+ if (hasNullMap) {
+ payloadOff += cols.nullMapSize();
+
+ // Fold offset based on the whole map bytes in the schema
+ for (int i = 0; i < colByteIdx; i++)
+ colOff += cols.foldFixedLength(i, readByte(nullMapOffset(baseOff) + i));
+
+ colOff += cols.foldFixedLength(colByteIdx, readByte(nullMapOffset(baseOff) + colByteIdx) | mask);
+ }
+ else {
+ for (int i = 0; i < colByteIdx; i++)
+ colOff += cols.foldFixedLength(i, 0);
+
+ colOff += cols.foldFixedLength(colByteIdx, mask);
+ }
}
- if (hasVarTbl)
- payloadOff += varlenItemOffset(readShort(payloadOff));
+ if (hasVarTbl) {
+ short verlenItems = readShort(payloadOff);
+
+ payloadOff += varlenItemOffset(verlenItems);
+ }
- return payloadOff + off;
+ return payloadOff + colOff;
}
/**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
index 83233a9..b1ae96a 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
@@ -252,13 +252,13 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
*/
private NativeType createType(ColumnTypeView type) {
switch (type.type().toLowerCase()) {
- case "byte":
+ case "int8":
return NativeTypes.BYTE;
- case "short":
+ case "int16":
return NativeTypes.SHORT;
- case "int":
+ case "int32":
return NativeTypes.INTEGER;
- case "long":
+ case "int64":
return NativeTypes.LONG;
case "float":
return NativeTypes.FLOAT;
@@ -267,11 +267,13 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
case "uuid":
return NativeTypes.UUID;
case "bitmask":
+ assert type.length() > 0;
+
return NativeTypes.bitmaskOf(type.length());
case "string":
return type.length() == 0 ? NativeTypes.STRING : NativeTypes.stringOf(type.length());
case "bytes":
- return NativeTypes.blobOf(type.length());
+ return type.length() == 0 ? NativeTypes.BYTES : NativeTypes.blobOf(type.length());
default:
throw new IllegalStateException("Unsupported column type: " + type.type());
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java
index 8da7278..777adf1 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java
@@ -17,6 +17,9 @@
package org.apache.ignite.internal.schema;
+import org.apache.ignite.internal.schema.registry.SchemaRegistryException;
+import org.jetbrains.annotations.NotNull;
+
/**
* Table schema registry interface.
*/
@@ -29,6 +32,7 @@ public interface SchemaRegistry {
/**
* @param ver Schema version.
* @return Schema of given version.
+ * @throws SchemaRegistryException If schema was not found.
*/
- SchemaDescriptor schema(int ver);
+ @NotNull SchemaDescriptor schema(int ver) throws SchemaRegistryException;
}
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
index cdb1d31..659dd5f 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
@@ -40,11 +40,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* Tests row assembling and reading.
*/
public class RowTest {
- /** */
+ /** Random. */
private Random rnd;
/**
- *
+ * Initialization.
*/
@BeforeEach
public void initRandom() {
@@ -56,10 +56,42 @@ public class RowTest {
}
/**
- *
+ * Check row serialization for schema with nullable fix-sized columns only.
*/
@Test
- public void fixedSizes() {
+ public void nullableFixSizedColumns() {
+ Column[] keyCols = new Column[] {
+ new Column("keyByteCol", BYTE, false),
+ new Column("keyShortCol", SHORT, false),
+ new Column("keyIntCol", INTEGER, false),
+ new Column("keyLongCol", LONG, false),
+ new Column("keyFloatCol", FLOAT, false),
+ new Column("keyDoubleCol", DOUBLE, false),
+ new Column("keyUuidCol", UUID, false),
+ new Column("keyBitmask1Col", NativeTypes.bitmaskOf(4), false),
+ new Column("keyBitmask2Col", NativeTypes.bitmaskOf(22), false)
+ };
+
+ Column[] valCols = new Column[] {
+ new Column("valByteCol", BYTE, false),
+ new Column("valShortCol", SHORT, false),
+ new Column("valIntCol", INTEGER, false),
+ new Column("valLongCol", LONG, false),
+ new Column("valFloatCol", FLOAT, false),
+ new Column("valDoubleCol", DOUBLE, false),
+ new Column("valUuidCol", UUID, false),
+ new Column("valBitmask1Col", NativeTypes.bitmaskOf(4), false),
+ new Column("valBitmask2Col", NativeTypes.bitmaskOf(22), false)
+ };
+
+ checkSchema(keyCols, valCols);
+ }
+
+ /**
+ * Check row serialization for schema with non-nullable fix-sized columns only.
+ */
+ @Test
+ public void fixSizedColumns() {
Column[] keyCols = new Column[] {
new Column("keyByteCol", BYTE, true),
new Column("keyShortCol", SHORT, true),
@@ -88,17 +120,17 @@ public class RowTest {
}
/**
- *
+ * Check row serialization for schema with various columns.
*/
@Test
- public void variableSizes() {
+ public void mixedColumns() {
Column[] keyCols = new Column[] {
- new Column("keyByteCol", BYTE, true),
- new Column("keyShortCol", SHORT, true),
- new Column("keyIntCol", INTEGER, true),
- new Column("keyLongCol", LONG, true),
- new Column("keyBytesCol", BYTES, true),
- new Column("keyStringCol", STRING, true),
+ new Column("keyByteCol", BYTE, false),
+ new Column("keyShortCol", SHORT, false),
+ new Column("keyIntCol", INTEGER, false),
+ new Column("keyLongCol", LONG, false),
+ new Column("keyBytesCol", BYTES, false),
+ new Column("keyStringCol", STRING, false),
};
Column[] valCols = new Column[] {
@@ -114,10 +146,28 @@ public class RowTest {
}
/**
- *
+ * Check row serialization for schema with non-nullable varlen columns only.
+ */
+ @Test
+ public void varlenColumns() {
+ Column[] keyCols = new Column[] {
+ new Column("keyBytesCol", BYTES, false),
+ new Column("keyStringCol", STRING, false),
+ };
+
+ Column[] valCols = new Column[] {
+ new Column("valBytesCol", BYTES, false),
+ new Column("valStringCol", STRING, false),
+ };
+
+ checkSchema(keyCols, valCols);
+ }
+
+ /**
+ * Check row serialization for schema with nullable varlen columns only.
*/
@Test
- public void mixedSizes() {
+ public void nullableVarlenColumns() {
Column[] keyCols = new Column[] {
new Column("keyBytesCol", BYTES, true),
new Column("keyStringCol", STRING, true),
@@ -132,7 +182,10 @@ public class RowTest {
}
/**
+ * Checks schema is independent from prodived column order.
*
+ * @param keyCols Key columns.
+ * @param valCols Value columns.
*/
private void checkSchema(Column[] keyCols, Column[] valCols) {
checkSchemaShuffled(keyCols, valCols);
@@ -144,38 +197,38 @@ public class RowTest {
}
/**
+ * Checks schema for given columns.
*
+ * @param keyCols Key columns.
+ * @param valCols Value columns.
*/
private void checkSchemaShuffled(Column[] keyCols, Column[] valCols) {
SchemaDescriptor sch = new SchemaDescriptor(java.util.UUID.randomUUID(), 1, keyCols, valCols);
- Object[] checkArr = sequence(sch);
+ Object[] checkArr = generateRowValues(sch);
checkValues(sch, checkArr);
- while (checkArr[0] != null) {
- int idx = 0;
+ for (int idx = 0; idx < checkArr.length; idx++) {
+ if (!sch.column(idx).nullable())
+ continue;
Object prev = checkArr[idx];
checkArr[idx] = null;
checkValues(sch, checkArr);
- while (idx < checkArr.length - 1 && checkArr[idx + 1] != null) {
- checkArr[idx] = prev;
- prev = checkArr[idx + 1];
- checkArr[idx + 1] = null;
- idx++;
-
- checkValues(sch, checkArr);
- }
+ checkArr[idx] = prev;
}
}
/**
+ * Generate row values for given row schema.
*
+ * @param schema Row schema.
+ * @return Row values.
*/
- private Object[] sequence(SchemaDescriptor schema) {
+ private Object[] generateRowValues(SchemaDescriptor schema) {
Object[] res = new Object[schema.length()];
for (int i = 0; i < res.length; i++) {
@@ -188,14 +241,20 @@ public class RowTest {
}
/**
+ * Generates random value of a given type.
*
+ * @param type Value type.
+ * @return Random value of requested type.
*/
private Object generateRandomValue(NativeType type) {
return TestUtils.generateRandomValue(rnd, type);
}
/**
+ * Validates row values after serialization-then-deserialization.
*
+ * @param schema Row schema.
+ * @param vals Row values.
*/
private void checkValues(SchemaDescriptor schema, Object... vals) {
assertEquals(schema.keyColumns().length() + schema.valueColumns().length(), vals.length);
@@ -312,7 +371,7 @@ public class RowTest {
}
/**
- *
+ * Shuffle columns.
*/
private void shuffle(Column[] cols) {
Collections.shuffle(Arrays.asList(cols));