[ASTERIXDB-2607][RT][*DB] Fix detecting duplicate fields in record construction
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
Fix detecting duplicate field names in record construction.
Change-Id: Ib11647cee4e6dd07f04b9e91ce03cb72f293bcb2
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3479
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/builders/RecordBuilder.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/builders/RecordBuilder.java
index 1273ed1..742cfb3 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/builders/RecordBuilder.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/builders/RecordBuilder.java
@@ -218,16 +218,25 @@
openPartOffsetArray = new byte[openPartOffsetArraySize];
}
+ // field names with the same hash code should be adjacent to each other after sorting
Arrays.sort(this.openPartOffsets, 0, numberOfOpenFields);
if (numberOfOpenFields > 1) {
byte[] openBytes = openPartOutputStream.getByteArray();
- for (int i = 1; i < numberOfOpenFields; i++) {
- if (utf8Comparator.compare(openBytes, (int) openPartOffsets[i - 1], openFieldNameLengths[i - 1],
- openBytes, (int) openPartOffsets[i], openFieldNameLengths[i]) == 0) {
+ for (int i = 0, k = 1; i < numberOfOpenFields - 1;) {
+ if (utf8Comparator.compare(openBytes, (int) openPartOffsets[i], openFieldNameLengths[i], openBytes,
+ (int) openPartOffsets[k], openFieldNameLengths[k]) == 0) {
String field = utf8SerDer.deserialize(new DataInputStream(new ByteArrayInputStream(openBytes,
(int) openPartOffsets[i], openFieldNameLengths[i])));
throw new HyracksDataException(
- "Open fields " + (i - 1) + " and " + i + " have the same field name \"" + field + "\"");
+ "Open fields " + i + " and " + k + " have the same field name \"" + field + "\"");
+ }
+ if (sameHashes(openPartOffsets, i, k) && k < numberOfOpenFields - 1) {
+ // keep comparing the current field i with the next field k
+ k++;
+ } else {
+ // the current field i has no duplicates; move to the adjacent one
+ i++;
+ k = i + 1;
}
}
}
@@ -249,6 +258,10 @@
writeRecord(out, writeTypeTag, h, recordLength);
}
+ private static boolean sameHashes(long[] hashAndOffset, int fieldId1, int fieldId2) {
+ return (int) (hashAndOffset[fieldId1] >>> 32) == (int) (hashAndOffset[fieldId2] >>> 32);
+ }
+
private void writeRecord(DataOutput out, boolean writeTypeTag, int headerSize, int recordLength)
throws HyracksDataException {
try {