Skip to content

Commit a0ec2ec

Browse files
authored
IGNITE-28453 Avoid index key materialization during index row verification (#7932)
1 parent 1a36a03 commit a0ec2ec

10 files changed

Lines changed: 821 additions & 3 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.internal.binarytuple;
19+
20+
import java.nio.ByteBuffer;
21+
import java.util.List;
22+
import org.apache.ignite.internal.type.DecimalNativeType;
23+
import org.apache.ignite.internal.type.NativeType;
24+
import org.apache.ignite.internal.type.StructNativeType;
25+
import org.apache.ignite.internal.util.StringUtils;
26+
27+
/**
28+
* Produces a human-readable string representation of a {@link BinaryTuple} given a {@link StructNativeType} that describes the row schema.
29+
*
30+
* <p>Intended for debugging and logging purposes only.
31+
*/
32+
public class BinaryTuplePrinter {
33+
private final StructNativeType schema;
34+
35+
/** Constructor. */
36+
public BinaryTuplePrinter(StructNativeType schema) {
37+
this.schema = schema;
38+
}
39+
40+
/**
41+
* Renders the given tuple as a string.
42+
*
43+
* @param tuple Binary tuple.
44+
* @return Human-readable representation.
45+
*/
46+
public String print(BinaryTuple tuple) {
47+
return printTuple(tuple);
48+
}
49+
50+
/**
51+
* Renders the given tuple as a string.
52+
*
53+
* @param tuple Byte buffer representing the binary tuple.
54+
* @return Human-readable representation.
55+
*/
56+
public String print(ByteBuffer tuple) {
57+
return printTuple(new BinaryTupleReader(schema.fieldsCount(), tuple));
58+
}
59+
60+
private String printTuple(BinaryTupleReader reader) {
61+
List<StructNativeType.Field> fields = schema.fields();
62+
63+
StringBuilder sb = new StringBuilder("BinaryTuple[");
64+
65+
for (int i = 0; i < fields.size(); i++) {
66+
if (i > 0) {
67+
sb.append(", ");
68+
}
69+
70+
StructNativeType.Field field = fields.get(i);
71+
sb.append(field.name()).append('=');
72+
73+
if (reader.hasNullValue(i)) {
74+
sb.append("null");
75+
} else {
76+
sb.append(readValue(reader, i, field.type()));
77+
}
78+
}
79+
80+
return sb.append(']').toString();
81+
}
82+
83+
private static Object readValue(BinaryTupleReader reader, int index, NativeType type) {
84+
switch (type.spec()) {
85+
case BOOLEAN:
86+
return reader.booleanValue(index);
87+
case INT8:
88+
return reader.byteValue(index);
89+
case INT16:
90+
return reader.shortValue(index);
91+
case INT32:
92+
return reader.intValue(index);
93+
case INT64:
94+
return reader.longValue(index);
95+
case FLOAT:
96+
return reader.floatValue(index);
97+
case DOUBLE:
98+
return reader.doubleValue(index);
99+
case DECIMAL:
100+
return reader.decimalValue(index, ((DecimalNativeType) type).scale());
101+
case UUID:
102+
return reader.uuidValue(index);
103+
case STRING:
104+
return "'" + reader.stringValue(index) + "'";
105+
case BYTE_ARRAY:
106+
return StringUtils.toHexString(reader.bytesValue(index));
107+
case DATE:
108+
return reader.dateValue(index);
109+
case TIME:
110+
return reader.timeValue(index);
111+
case DATETIME:
112+
return reader.dateTimeValue(index);
113+
case TIMESTAMP:
114+
return reader.timestampValue(index);
115+
case DURATION:
116+
return reader.durationValue(index);
117+
case PERIOD:
118+
return reader.periodValue(index);
119+
default:
120+
return "?(" + type.spec() + ")";
121+
}
122+
}
123+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.internal.binarytuple;
19+
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
22+
import java.nio.ByteBuffer;
23+
import java.time.LocalDate;
24+
import java.time.LocalDateTime;
25+
import java.time.LocalTime;
26+
import org.apache.ignite.internal.type.NativeTypes;
27+
import org.apache.ignite.internal.type.StructNativeType;
28+
import org.apache.ignite.internal.util.StringUtils;
29+
import org.junit.jupiter.api.Test;
30+
31+
/** Tests for {@link BinaryTuplePrinter}. */
32+
class BinaryTuplePrinterTest {
33+
34+
@Test
35+
void printScalarFields() {
36+
StructNativeType schema = NativeTypes.structBuilder()
37+
.addField("id", NativeTypes.INT32, false)
38+
.addField("score", NativeTypes.INT64, false)
39+
.addField("flag", NativeTypes.BOOLEAN, false)
40+
.build();
41+
42+
BinaryTuple tuple = new BinaryTuple(3,
43+
new BinaryTupleBuilder(3)
44+
.appendInt(7)
45+
.appendLong(42L)
46+
.appendBoolean(true)
47+
.build()
48+
);
49+
50+
String result = new BinaryTuplePrinter(schema).print(tuple);
51+
52+
assertEquals("BinaryTuple[id=7, score=42, flag=true]", result);
53+
}
54+
55+
@Test
56+
void printStringIsQuoted() {
57+
StructNativeType schema = NativeTypes.structBuilder()
58+
.addField("name", NativeTypes.STRING, false)
59+
.build();
60+
61+
BinaryTuple tuple = new BinaryTuple(1,
62+
new BinaryTupleBuilder(1).appendString("hello world").build()
63+
);
64+
65+
assertEquals("BinaryTuple[name='hello world']", new BinaryTuplePrinter(schema).print(tuple));
66+
}
67+
68+
@Test
69+
void printNullFieldRendersAsNull() {
70+
StructNativeType schema = NativeTypes.structBuilder()
71+
.addField("id", NativeTypes.INT32, false)
72+
.addField("name", NativeTypes.STRING, true)
73+
.build();
74+
75+
BinaryTuple tuple = new BinaryTuple(2,
76+
new BinaryTupleBuilder(2).appendInt(1).appendNull().build()
77+
);
78+
79+
assertEquals("BinaryTuple[id=1, name=null]", new BinaryTuplePrinter(schema).print(tuple));
80+
}
81+
82+
@Test
83+
void printByteArrayRenderedAsHex() {
84+
StructNativeType schema = NativeTypes.structBuilder()
85+
.addField("data", NativeTypes.BYTES, false)
86+
.build();
87+
88+
@SuppressWarnings("NumericCastThatLosesPrecision")
89+
byte[] bytes = {0x01, (byte) 0xAB, (byte) 0xFF};
90+
91+
BinaryTuple tuple = new BinaryTuple(1,
92+
new BinaryTupleBuilder(1).appendBytes(bytes).build()
93+
);
94+
95+
String expected = "BinaryTuple[data=" + StringUtils.toHexString(bytes) + "]";
96+
assertEquals(expected, new BinaryTuplePrinter(schema).print(tuple));
97+
}
98+
99+
@Test
100+
void printDateTimeFields() {
101+
LocalDate date = LocalDate.of(2024, 6, 15);
102+
LocalTime time = LocalTime.of(10, 30, 0);
103+
LocalDateTime dateTime = LocalDateTime.of(date, time);
104+
105+
StructNativeType schema = NativeTypes.structBuilder()
106+
.addField("d", NativeTypes.DATE, false)
107+
.addField("t", NativeTypes.time(0), false)
108+
.addField("dt", NativeTypes.datetime(0), false)
109+
.build();
110+
111+
BinaryTuple tuple = new BinaryTuple(3,
112+
new BinaryTupleBuilder(3)
113+
.appendDate(date)
114+
.appendTime(time)
115+
.appendDateTime(dateTime)
116+
.build()
117+
);
118+
119+
assertEquals(
120+
"BinaryTuple[d=" + date + ", t=" + time + ", dt=" + dateTime + "]",
121+
new BinaryTuplePrinter(schema).print(tuple)
122+
);
123+
}
124+
125+
@Test
126+
void printByteBufferOverloadMatchesBinaryTupleOverload() {
127+
StructNativeType schema = NativeTypes.structBuilder()
128+
.addField("x", NativeTypes.INT32, false)
129+
.addField("y", NativeTypes.STRING, true)
130+
.build();
131+
132+
ByteBuffer buf = new BinaryTupleBuilder(2).appendInt(99).appendString("test").build();
133+
BinaryTuple tuple = new BinaryTuple(2, buf);
134+
135+
BinaryTuplePrinter printer = new BinaryTuplePrinter(schema);
136+
assertEquals(printer.print(tuple), printer.print(buf));
137+
}
138+
139+
@Test
140+
void printEmptySchemaProducesEmptyBrackets() {
141+
StructNativeType schema = NativeTypes.structBuilder().build();
142+
143+
BinaryTuple tuple = new BinaryTuple(0, new BinaryTupleBuilder(0).build());
144+
145+
assertEquals("BinaryTuple[]", new BinaryTuplePrinter(schema).print(tuple));
146+
}
147+
}

0 commit comments

Comments
 (0)