1616 */
1717package org .apache .arrow .vector ;
1818
19+ import static org .junit .jupiter .api .Assertions .assertArrayEquals ;
1920import static org .junit .jupiter .api .Assertions .assertEquals ;
2021import static org .junit .jupiter .api .Assertions .assertFalse ;
2122import static org .junit .jupiter .api .Assertions .assertNull ;
2223import static org .junit .jupiter .api .Assertions .assertSame ;
24+ import static org .junit .jupiter .api .Assertions .assertThrows ;
2325import static org .junit .jupiter .api .Assertions .assertTrue ;
2426
2527import java .nio .ByteBuffer ;
4143import org .apache .arrow .vector .complex .writer .BaseWriter .MapWriter ;
4244import org .apache .arrow .vector .complex .writer .FieldWriter ;
4345import org .apache .arrow .vector .holder .UuidHolder ;
46+ import org .apache .arrow .vector .holders .FixedSizeBinaryHolder ;
4447import org .apache .arrow .vector .types .Types .MinorType ;
4548import org .apache .arrow .vector .types .pojo .ArrowType ;
4649import org .apache .arrow .vector .types .pojo .Field ;
@@ -168,7 +171,6 @@ public void testCopyFrom() throws Exception {
168171 // {1 -> 11, 2 -> 22, 3 -> 33}
169172 // null
170173 // {2 -> null}
171- // {3 -> null}
172174 writer .setPosition (0 ); // optional
173175 writer .startMap ();
174176 writer .startEntry ();
@@ -192,22 +194,14 @@ public void testCopyFrom() throws Exception {
192194 writer .endEntry ();
193195 writer .endMap ();
194196
195- writer .setPosition (3 );
196- writer .startMap ();
197- writer .startEntry ();
198- writer .key ().bigInt ().writeBigInt (3 );
199- writer .value ().fixedSizeBinary ().writeNull ();
200- writer .endEntry ();
201- writer .endMap ();
202-
203- writer .setValueCount (4 );
197+ writer .setValueCount (3 );
204198
205199 // copy values from input to output
206200 outVector .allocateNew ();
207- for (int i = 0 ; i < 4 ; i ++) {
201+ for (int i = 0 ; i < 3 ; i ++) {
208202 outVector .copyFrom (i , i , inVector );
209203 }
210- outVector .setValueCount (4 );
204+ outVector .setValueCount (3 );
211205
212206 // assert the output vector is correct
213207 FieldReader reader = outVector .getReader ();
@@ -216,8 +210,6 @@ public void testCopyFrom() throws Exception {
216210 assertFalse (reader .isSet (), "should be null" );
217211 reader .setPosition (2 );
218212 assertTrue (reader .isSet (), "shouldn't be null" );
219- reader .setPosition (3 );
220- assertTrue (reader .isSet (), "shouldn't be null" );
221213
222214 /* index 0 */
223215 Object result = outVector .getObject (0 );
@@ -244,14 +236,6 @@ public void testCopyFrom() throws Exception {
244236 resultStruct = (Map <?, ?>) resultSet .get (0 );
245237 assertEquals (2L , getResultKey (resultStruct ));
246238 assertFalse (resultStruct .containsKey (MapVector .VALUE_NAME ));
247-
248- /* index 3 */
249- result = outVector .getObject (3 );
250- resultSet = (ArrayList <?>) result ;
251- assertEquals (1 , resultSet .size ());
252- resultStruct = (Map <?, ?>) resultSet .get (0 );
253- assertEquals (3L , getResultKey (resultStruct ));
254- assertFalse (resultStruct .containsKey (MapVector .VALUE_NAME ));
255239 }
256240 }
257241
@@ -1378,4 +1362,216 @@ public void testCopyFromForExtensionType() throws Exception {
13781362 assertEquals (u2 , actualUuid );
13791363 }
13801364 }
1365+
1366+ private FixedSizeBinaryHolder getFixedSizeBinaryHolder (byte [] array ) {
1367+ // {1 -> [11, 22], 2 -> [32, 21]}
1368+ FixedSizeBinaryHolder holder = new FixedSizeBinaryHolder ();
1369+ holder .byteWidth = array .length ;
1370+ holder .buffer = allocator .buffer (array .length );
1371+ for (int i = 0 ; i < array .length ; i ++) {
1372+ holder .buffer .setByte (i , array [i ]);
1373+ }
1374+
1375+ return holder ;
1376+ }
1377+
1378+ /**
1379+ * Regression test for GH-586: UnionMapWriter.fixedSizeBinary() should properly delegate to the
1380+ * entry writer for both key and value paths.
1381+ */
1382+ @ Test
1383+ public void testFixedSizeBinaryWriter () {
1384+ try (MapVector mapVector = MapVector .empty ("map_vector" , allocator , false )) {
1385+ UnionMapWriter writer = mapVector .getWriter ();
1386+ writer .allocate ();
1387+
1388+ // populate input vector with the following records
1389+ // {1 -> 2, 2 -> 3} - is used to initialize `key` and `value` writers - todo: this needs to be
1390+ // removed (test should work without it)
1391+ // {1 -> [11, 22], 2 -> [32, 21]}
1392+ // null
1393+ // {[11, 22] -> 1, [32, 21] -> 2}
1394+ // {[11, 22] -> null}
1395+ // {null -> [32, 21]} - wrong "for a given entry, the "key" is non-nullable" - todo: it
1396+ // shouldn't work. Should it?
1397+ writer .setPosition (0 ); // optional
1398+ writer .startMap ();
1399+ writer .startEntry ();
1400+ writer .key ().bigInt ().writeBigInt (1 );
1401+ writer .value ().bigInt ().writeBigInt (2 );
1402+ writer .endEntry ();
1403+ writer .startEntry ();
1404+ writer .key ().bigInt ().writeBigInt (2 );
1405+ writer .value ().bigInt ().writeBigInt (3 );
1406+ writer .endEntry ();
1407+ writer .endMap ();
1408+
1409+ // {1 -> [11, 22], 2 -> [32, 21]}
1410+ FixedSizeBinaryHolder holder1 = getFixedSizeBinaryHolder (new byte [] {11 , 22 });
1411+ FixedSizeBinaryHolder holder2 = getFixedSizeBinaryHolder (new byte [] {32 , 21 });
1412+ writer .setPosition (1 );
1413+ writer .startMap ();
1414+ writer .startEntry ();
1415+ writer .key ().bigInt ().writeBigInt (1 );
1416+ writer .value ().fixedSizeBinary ().write (holder1 );
1417+ writer .endEntry ();
1418+ holder1 .buffer .close ();
1419+ writer .startEntry ();
1420+ writer .key ().bigInt ().writeBigInt (2 );
1421+ writer .value ().fixedSizeBinary ().write (holder2 );
1422+ writer .endEntry ();
1423+ writer .endMap ();
1424+ holder2 .buffer .close ();
1425+
1426+ // {[11, 22] -> 1, [32, 21] -> 2}
1427+ holder1 = getFixedSizeBinaryHolder (new byte [] {11 , 22 });
1428+ holder2 = getFixedSizeBinaryHolder (new byte [] {32 , 21 });
1429+ writer .setPosition (3 );
1430+ writer .startMap ();
1431+ writer .startEntry ();
1432+ writer .key ().fixedSizeBinary ().write (holder1 );
1433+ writer .value ().bigInt ().writeBigInt (1 );
1434+ writer .endEntry ();
1435+ holder1 .buffer .close ();
1436+ writer .startEntry ();
1437+ writer .key ().fixedSizeBinary ().write (holder2 );
1438+ writer .value ().bigInt ().writeBigInt (2 );
1439+ writer .endEntry ();
1440+ writer .endMap ();
1441+ holder2 .buffer .close ();
1442+
1443+ // {[11, 22] -> null}
1444+ holder1 = getFixedSizeBinaryHolder (new byte [] {11 , 22 });
1445+ writer .setPosition (4 );
1446+ writer .startMap ();
1447+ writer .startEntry ();
1448+ writer .key ().fixedSizeBinary ().write (holder1 );
1449+ writer .endEntry ();
1450+ writer .endMap ();
1451+ holder1 .buffer .close ();
1452+
1453+ // {null -> [32, 21]}
1454+ holder2 = getFixedSizeBinaryHolder (new byte [] {32 , 21 });
1455+ writer .setPosition (5 );
1456+ writer .startMap ();
1457+ writer .startEntry ();
1458+ writer .value ().fixedSizeBinary ().write (holder2 );
1459+ writer .endEntry ();
1460+ writer .endMap ();
1461+ holder2 .buffer .close ();
1462+
1463+ writer .setValueCount (6 );
1464+
1465+ // assert the output vector is correct
1466+ FieldReader reader = mapVector .getReader ();
1467+ assertTrue (reader .isSet (), "shouldn't be null" );
1468+ reader .setPosition (1 );
1469+ assertTrue (reader .isSet (), "shouldn't be null" );
1470+ reader .setPosition (2 );
1471+ assertFalse (reader .isSet (), "should be null" );
1472+ reader .setPosition (3 );
1473+ assertTrue (reader .isSet (), "shouldn't be null" );
1474+ reader .setPosition (4 );
1475+ assertTrue (reader .isSet (), "shouldn't be null" );
1476+ reader .setPosition (5 );
1477+ assertTrue (reader .isSet (), "shouldn't be null" );
1478+
1479+ /* index 0 */
1480+ Object result = mapVector .getObject (0 );
1481+ ArrayList <?> resultSet = (ArrayList <?>) result ;
1482+ assertEquals (2 , resultSet .size ());
1483+ Map <?, ?> resultStruct = (Map <?, ?>) resultSet .get (0 );
1484+ assertEquals (1L , getResultKey (resultStruct ));
1485+ assertEquals (2L , getResultValue (resultStruct ));
1486+ resultStruct = (Map <?, ?>) resultSet .get (1 );
1487+ assertEquals (2L , getResultKey (resultStruct ));
1488+ assertEquals (3L , getResultValue (resultStruct ));
1489+
1490+ /* index 1 */
1491+ result = mapVector .getObject (1 );
1492+ resultSet = (ArrayList <?>) result ;
1493+ assertEquals (2 , resultSet .size ());
1494+ resultStruct = (Map <?, ?>) resultSet .get (0 );
1495+ assertEquals (1L , getResultKey (resultStruct ));
1496+ assertTrue (resultStruct .containsKey (MapVector .VALUE_NAME ));
1497+ assertArrayEquals (new byte [] {11 , 22 }, (byte []) resultStruct .get (MapVector .VALUE_NAME ));
1498+ resultStruct = (Map <?, ?>) resultSet .get (1 );
1499+ assertEquals (2L , getResultKey (resultStruct ));
1500+ assertTrue (resultStruct .containsKey (MapVector .VALUE_NAME ));
1501+ assertArrayEquals (new byte [] {32 , 21 }, (byte []) resultStruct .get (MapVector .VALUE_NAME ));
1502+
1503+ /* index 2 */
1504+ result = mapVector .getObject (2 );
1505+ assertNull (result );
1506+
1507+ /* index 3 */
1508+ result = mapVector .getObject (3 );
1509+ resultSet = (ArrayList <?>) result ;
1510+ assertEquals (2 , resultSet .size ());
1511+ resultStruct = (Map <?, ?>) resultSet .get (0 );
1512+ assertTrue (resultStruct .containsKey (MapVector .KEY_NAME ));
1513+ assertArrayEquals (new byte [] {11 , 22 }, (byte []) resultStruct .get (MapVector .KEY_NAME ));
1514+ assertEquals (1L , getResultValue (resultStruct ));
1515+ resultStruct = (Map <?, ?>) resultSet .get (1 );
1516+ assertTrue (resultStruct .containsKey (MapVector .KEY_NAME ));
1517+ assertArrayEquals (new byte [] {32 , 21 }, (byte []) resultStruct .get (MapVector .KEY_NAME ));
1518+ assertEquals (2L , getResultValue (resultStruct ));
1519+
1520+ /* index 4 */
1521+ result = mapVector .getObject (4 );
1522+ resultSet = (ArrayList <?>) result ;
1523+ assertEquals (1 , resultSet .size ());
1524+ resultStruct = (Map <?, ?>) resultSet .get (0 );
1525+ assertTrue (resultStruct .containsKey (MapVector .KEY_NAME ));
1526+ assertArrayEquals (new byte [] {11 , 22 }, (byte []) resultStruct .get (MapVector .KEY_NAME ));
1527+ assertFalse (resultStruct .containsKey (MapVector .VALUE_NAME ));
1528+
1529+ /* index 5 */
1530+ result = mapVector .getObject (5 );
1531+ resultSet = (ArrayList <?>) result ;
1532+ assertEquals (1 , resultSet .size ());
1533+ resultStruct = (Map <?, ?>) resultSet .get (0 );
1534+ assertFalse (resultStruct .containsKey (MapVector .KEY_NAME ));
1535+ assertTrue (resultStruct .containsKey (MapVector .VALUE_NAME ));
1536+ assertArrayEquals (new byte [] {32 , 21 }, (byte []) resultStruct .get (MapVector .VALUE_NAME ));
1537+ }
1538+ }
1539+
1540+ @ Test
1541+ public void testFixedSizeBinaryWriterInitializationError () {
1542+ try (MapVector mapVector = MapVector .empty ("map_vector" , allocator , false )) {
1543+ UnionMapWriter writer = mapVector .getWriter ();
1544+ writer .allocate ();
1545+
1546+ // populate input vector with the following records
1547+ // {[11, 22] -> [32, 21]} - todo: it shouldn't throw. Should it?
1548+ FixedSizeBinaryHolder holder1 = getFixedSizeBinaryHolder (new byte [] {11 , 22 });
1549+ FixedSizeBinaryHolder holder2 = getFixedSizeBinaryHolder (new byte [] {32 , 21 });
1550+
1551+ writer .setPosition (0 ); // optional
1552+ writer .startMap ();
1553+ writer .startEntry ();
1554+ assertThrows (NullPointerException .class , () -> writer .key ().fixedSizeBinary ().write (holder1 ));
1555+ assertThrows (
1556+ NullPointerException .class , () -> writer .value ().fixedSizeBinary ().write (holder2 ));
1557+ writer .endEntry ();
1558+ holder1 .buffer .close ();
1559+ holder2 .buffer .close ();
1560+ writer .endMap ();
1561+
1562+ writer .setValueCount (1 );
1563+
1564+ // assert the output vector is correct
1565+ FieldReader reader = mapVector .getReader ();
1566+ assertTrue (reader .isSet (), "shouldn't be null" );
1567+
1568+ /* index 0 */
1569+ Object result = mapVector .getObject (0 );
1570+ ArrayList <?> resultSet = (ArrayList <?>) result ;
1571+ assertEquals (1 , resultSet .size ());
1572+ Map <?, ?> resultStruct = (Map <?, ?>) resultSet .get (0 );
1573+ assertFalse (resultStruct .containsKey (MapVector .KEY_NAME ));
1574+ assertFalse (resultStruct .containsKey (MapVector .VALUE_NAME ));
1575+ }
1576+ }
13811577}
0 commit comments