Skip to content

Commit c2e8388

Browse files
authored
SOLR-17588 : javabin must support primitive arrays (#2900)
1 parent 704f2fe commit c2e8388

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public class JavaBinCodec implements PushWriter {
103103
MAP_ENTRY = 19,
104104
UUID = 20, // This is reserved to be used only in LogCodec
105105
// types that combine tag + length (or other info) in a single byte
106+
PRIMITIVE_ARR = 21,
106107
TAG_AND_LEN = (byte) (1 << 5),
107108
STR = (byte) (1 << 5),
108109
SINT = (byte) (2 << 5),
@@ -348,6 +349,8 @@ protected Object readObject(DataInputInputStream dis) throws IOException {
348349
return readMapEntry(dis);
349350
case MAP_ENTRY_ITER:
350351
return readMapIter(dis);
352+
case PRIMITIVE_ARR:
353+
return readPrimitiveArray(dis);
351354
}
352355

353356
throw new RuntimeException("Unknown type " + tagByte);
@@ -438,9 +441,150 @@ public boolean writeKnownType(Object val) throws IOException {
438441
writeBoolean(((AtomicBoolean) val).get());
439442
return true;
440443
}
444+
if (val instanceof float[] ff) {
445+
writeFloatArr(ff);
446+
return true;
447+
}
448+
if (val instanceof int[] ii) {
449+
writeIntArr(ii);
450+
return true;
451+
}
452+
if (val instanceof long[] ll) {
453+
writeLongArr(ll);
454+
return true;
455+
}
456+
if (val instanceof double[] dd) {
457+
writeDoubleArr(dd);
458+
return true;
459+
}
460+
if (val instanceof short[] ss) {
461+
writeShortArr(ss);
462+
return true;
463+
}
464+
if (val instanceof boolean[] bb) {
465+
writeBoolArr(bb);
466+
return true;
467+
}
441468
return false;
442469
}
443470

471+
public Object readPrimitiveArray(DataInputInputStream dis) throws IOException {
472+
tagByte = dis.readByte();
473+
int len = readVInt(dis);
474+
switch (tagByte) {
475+
case FLOAT:
476+
{
477+
float[] v = new float[len];
478+
for (int i = 0; i < len; i++) {
479+
v[i] = dis.readFloat();
480+
}
481+
return v;
482+
}
483+
case INT:
484+
{
485+
int[] v = new int[len];
486+
for (int i = 0; i < len; i++) {
487+
v[i] = dis.readInt();
488+
}
489+
return v;
490+
}
491+
492+
case LONG:
493+
{
494+
long[] v = new long[len];
495+
for (int i = 0; i < len; i++) {
496+
v[i] = dis.readLong();
497+
}
498+
return v;
499+
}
500+
case DOUBLE:
501+
{
502+
double[] v = new double[len];
503+
for (int i = 0; i < len; i++) {
504+
v[i] = dis.readDouble();
505+
}
506+
return v;
507+
}
508+
case SHORT:
509+
{
510+
short[] v = new short[len];
511+
for (int i = 0; i < len; i++) {
512+
v[i] = dis.readShort();
513+
}
514+
return v;
515+
}
516+
case BOOL_TRUE:
517+
case BOOL_FALSE:
518+
{
519+
boolean[] v = new boolean[len];
520+
for (int i = 0; i < len; i++) {
521+
byte b = dis.readByte();
522+
v[i] = b == BOOL_FALSE ? false : true;
523+
}
524+
return v;
525+
}
526+
case BYTE:
527+
{
528+
// it should be possible to serialize byte[] in the new format as well
529+
byte[] v = new byte[len];
530+
dis.readFully(v);
531+
return v;
532+
}
533+
default:
534+
{
535+
throw new RuntimeException("Invalid type : " + tagByte);
536+
}
537+
}
538+
}
539+
540+
public void writePrimitiveArrHeader(byte tag, int len) throws IOException {
541+
writeTag(PRIMITIVE_ARR);
542+
writeTag(tag);
543+
writeVInt(len, daos);
544+
}
545+
546+
public void writeFloatArr(float[] vals) throws IOException {
547+
writePrimitiveArrHeader(FLOAT, vals.length);
548+
for (float f : vals) {
549+
daos.writeFloat(f);
550+
}
551+
}
552+
553+
public void writeIntArr(int[] vals) throws IOException {
554+
writePrimitiveArrHeader(INT, vals.length);
555+
for (int i : vals) {
556+
daos.writeInt(i);
557+
}
558+
}
559+
560+
public void writeDoubleArr(double[] vals) throws IOException {
561+
writePrimitiveArrHeader(DOUBLE, vals.length);
562+
for (double d : vals) {
563+
daos.writeDouble(d);
564+
}
565+
}
566+
567+
public void writeLongArr(long[] vals) throws IOException {
568+
writePrimitiveArrHeader(LONG, vals.length);
569+
for (long l : vals) {
570+
daos.writeLong(l);
571+
}
572+
}
573+
574+
public void writeBoolArr(boolean[] vals) throws IOException {
575+
writePrimitiveArrHeader(BOOL_TRUE, vals.length);
576+
for (boolean b : vals) {
577+
writeBoolean(b);
578+
}
579+
}
580+
581+
public void writeShortArr(short[] vals) throws IOException {
582+
writePrimitiveArrHeader(SHORT, vals.length);
583+
for (short l : vals) {
584+
daos.writeShort(l);
585+
}
586+
}
587+
444588
public class BinEntryWriter implements MapWriter.EntryWriter {
445589
@Override
446590
public MapWriter.EntryWriter put(CharSequence k, Object v) throws IOException {

solr/solrj/src/test/org/apache/solr/common/util/TestJavaBinCodec.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,20 @@ public static SolrDocument generateSolrDocumentWithChildDocs() {
108108
return parentDocument;
109109
}
110110

111+
@Test
112+
public void testPrimitiveArrays() throws Exception {
113+
List<Object> types = new ArrayList<>();
114+
115+
types.add(new float[] {1.0678f, 4.094565f, 0.000456f});
116+
types.add(new double[] {1.0678d, 4.094565d, 0.000456d});
117+
types.add(new int[] {145543, 4546354, 9789857});
118+
types.add(new long[] {145543L, 4546354L, 9789857L});
119+
types.add(new short[] {43, 454, 857});
120+
types.add(new boolean[] {true, true, false});
121+
122+
compareObjects((List<?>) getObject(getBytes(types)), types);
123+
}
124+
111125
private List<Object> generateAllDataTypes() {
112126
List<Object> types = new ArrayList<>();
113127

@@ -223,6 +237,23 @@ private void compareObjects(List<?> unmarshalledObj, List<?> matchObj) {
223237
} else if (unmarshalledObj.get(i) instanceof SolrInputField
224238
&& matchObj.get(i) instanceof SolrInputField) {
225239
assertTrue(assertSolrInputFieldEquals(unmarshalledObj.get(i), matchObj.get(i)));
240+
} else if (unmarshalledObj.get(i) instanceof float[] a
241+
&& matchObj.get(i) instanceof float[] e) {
242+
assertArrayEquals(e, a, 0.000000f);
243+
} else if (unmarshalledObj.get(i) instanceof double[] a
244+
&& matchObj.get(i) instanceof double[] e) {
245+
assertArrayEquals(e, a, 0.000000d);
246+
} else if (unmarshalledObj.get(i) instanceof long[] a
247+
&& matchObj.get(i) instanceof long[] e) {
248+
assertArrayEquals(e, a);
249+
} else if (unmarshalledObj.get(i) instanceof int[] a && matchObj.get(i) instanceof int[] e) {
250+
assertArrayEquals(e, a);
251+
} else if (unmarshalledObj.get(i) instanceof short[] a
252+
&& matchObj.get(i) instanceof short[] e) {
253+
assertArrayEquals(e, a);
254+
} else if (unmarshalledObj.get(i) instanceof boolean[] a
255+
&& matchObj.get(i) instanceof boolean[] e) {
256+
assertArrayEquals(e, a);
226257
} else {
227258
assertEquals(unmarshalledObj.get(i), matchObj.get(i));
228259
}

0 commit comments

Comments
 (0)