Skip to content

Commit 51fb5a1

Browse files
committed
GH-49946: [Format] Better document equivalence between IPC file and streams
1 parent 7339a29 commit 51fb5a1

1 file changed

Lines changed: 91 additions & 59 deletions

File tree

docs/source/format/Columnar.rst

Lines changed: 91 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,8 +1209,8 @@ of these types:
12091209
* DictionaryBatch
12101210

12111211
We specify a so-called *encapsulated IPC message* format which
1212-
includes a serialized Flatbuffer type along with an optional message
1213-
body. We define this message format before describing how to serialize
1212+
includes a serialized Flatbuffers metadata message along with an optional
1213+
message body. We define this message format before describing how to serialize
12141214
each constituent IPC message type.
12151215

12161216
.. _ipc-message-format:
@@ -1238,7 +1238,7 @@ The encapsulated binary message format is as follows:
12381238
Schematically, we have: ::
12391239

12401240
<continuation: 0xFFFFFFFF>
1241-
<metadata_size: int32>
1241+
<metadata_size: little-endian int32>
12421242
<metadata_flatbuffer: bytes>
12431243
<padding>
12441244
<message body>
@@ -1248,8 +1248,8 @@ can be relocated between streams. Otherwise the amount of padding between the
12481248
metadata and the message body could be non-deterministic.
12491249

12501250
The ``metadata_size`` includes the size of the ``Message`` plus
1251-
padding. The ``metadata_flatbuffer`` contains a serialized ``Message``
1252-
Flatbuffer value, which internally includes:
1251+
padding. The ``metadata_flatbuffer`` contains a Flatbuffers-serialized
1252+
``Message`` value, which internally includes:
12531253

12541254
* A version number
12551255
* A particular message value (one of ``Schema``, ``RecordBatch``, or
@@ -1264,11 +1264,11 @@ can be read.
12641264
Schema message
12651265
--------------
12661266

1267-
The Flatbuffers files `Schema.fbs`_ contains the definitions for all
1267+
The Flatbuffers definition file `Schema.fbs`_ contains the definitions for all
12681268
built-in data types and the ``Schema`` metadata type which represents
12691269
the schema of a given record batch. A schema consists of an ordered
12701270
sequence of fields, each having a name and type. A serialized ``Schema``
1271-
does not contain any data buffers, only type metadata.
1271+
does not contain any body, only metadata.
12721272

12731273
The ``Field`` Flatbuffers type contains the metadata for a single
12741274
array. This includes:
@@ -1287,7 +1287,7 @@ array. This includes:
12871287

12881288
We additionally provide both schema-level and field-level
12891289
``custom_metadata`` attributes allowing for systems to insert their
1290-
own application defined metadata to customize behavior.
1290+
own application-defined metadata to customize behavior.
12911291

12921292
.. _ipc-recordbatch-message:
12931293

@@ -1302,17 +1302,18 @@ thus no memory copying.
13021302

13031303
The serialized form of the record batch is the following:
13041304

1305-
* The ``data header``, defined as the ``RecordBatch`` type in
1306-
`Message.fbs`_.
1307-
* The ``body``, a flat sequence of memory buffers written end-to-end
1308-
with appropriate padding to ensure a minimum of 8-byte alignment
1305+
* The metadata describing the record batch layout, defined as the ``RecordBatch``
1306+
type in `Message.fbs`_.
1307+
* The record batch body, a flat sequence of binary buffers written end-to-end,
1308+
with appropriate padding between each of them to ensure a minimum of 8-byte
1309+
alignment.
13091310

1310-
The data header contains the following:
1311+
The record batch metadata contains the following:
13111312

13121313
* The length and null count for each flattened field in the record
1313-
batch
1314+
batch.
13141315
* The memory offset and length of each constituent ``Buffer`` in the
1315-
record batch's body
1316+
record batch's body.
13161317

13171318
Fields and buffers are flattened by a pre-order depth-first traversal
13181319
of the fields in the record batch. For example, let's consider the
@@ -1333,22 +1334,21 @@ The flattened version of this is: ::
13331334
For the buffers produced, we would have the following (refer to the
13341335
table above): ::
13351336

1336-
buffer 0: field 0 validity
1337-
buffer 1: field 1 validity
1338-
buffer 2: field 1 values
1339-
buffer 3: field 2 validity
1340-
buffer 4: field 2 offsets
1341-
buffer 5: field 3 validity
1342-
buffer 6: field 3 values
1343-
buffer 7: field 4 validity
1344-
buffer 8: field 4 values
1345-
buffer 9: field 5 validity
1346-
buffer 10: field 5 offsets
1347-
buffer 11: field 5 data
1348-
1349-
The ``Buffer`` Flatbuffers value describes the location and size of a
1350-
piece of memory. Generally these are interpreted relative to the
1351-
**encapsulated message format** defined below.
1337+
buffer 0: field 0 ('col1') validity
1338+
buffer 1: field 1 ('col1.a') validity
1339+
buffer 2: field 1 ('col1.a') values
1340+
buffer 3: field 2 ('col1.b') validity
1341+
buffer 4: field 2 ('col1.b') offsets
1342+
buffer 5: field 3 ('col1.b.item') validity
1343+
buffer 6: field 3 ('col1.b.item') values
1344+
buffer 7: field 4 ('col1.c') validity
1345+
buffer 8: field 4 ('col1.c') values
1346+
buffer 9: field 5 ('col2') validity
1347+
buffer 10: field 5 ('col2') offsets
1348+
buffer 11: field 5 ('col2') data
1349+
1350+
The ``Buffer`` Flatbuffers value describes the location and size of a buffer's
1351+
data, relatively to the start of the RecordBatch message's body.
13521352

13531353
The ``size`` field of ``Buffer`` is not required to account for padding
13541354
bytes. Since this metadata can be used to communicate in-memory pointer
@@ -1391,7 +1391,6 @@ have two entries in each RecordBatch. For a RecordBatch of this schema with
13911391
buffer 12: col2 data
13921392
buffer 13: col2 data
13931393

1394-
13951394
Compression
13961395
-----------
13971396

@@ -1452,18 +1451,19 @@ serialized form is as follows:
14521451
ratios.
14531452

14541453
Byte Order (`Endianness`_)
1455-
---------------------------
1454+
--------------------------
14561455

1457-
The Arrow format is little endian by default.
1456+
The Arrow IPC format is little-endian by default.
14581457

1459-
Serialized Schema metadata has an endianness field indicating
1460-
endianness of RecordBatches. Typically this is the endianness of the
1461-
system where the RecordBatch was generated. The main use case is
1462-
exchanging RecordBatches between systems with the same Endianness. At
1463-
first we will return an error when trying to read a Schema with an
1464-
endianness that does not match the underlying system. The reference
1465-
implementation is focused on Little Endian and provides tests for
1466-
it. Eventually we may provide automatic conversion via byte swapping.
1458+
Serialized Schema metadata has an endianness field indicating the endianness of
1459+
Arrow data in all the RecordBatch and DictionaryBatch message bodies.
1460+
Typically this is the endianness of the system where the Arrow data was generated.
1461+
While some IPC reader implementations may allow for byte-swapping when reading
1462+
an IPC Stream or File with non-native endianness, other implementations may simply
1463+
refuse reading such data.
1464+
1465+
Note that the endianness field only applies to RecordBatch and DictionaryBatch
1466+
message bodies, not to message metadata or any other signaling in the IPC formats.
14671467

14681468
IPC Streaming Format
14691469
--------------------
@@ -1483,7 +1483,7 @@ a ``RecordBatch`` it should be defined in a ``DictionaryBatch``. ::
14831483
<DICTIONARY k - 1>
14841484
<RECORD BATCH 0>
14851485
...
1486-
<DICTIONARY x DELTA>
1486+
<DICTIONARY x REPLACEMENT>
14871487
...
14881488
<DICTIONARY y DELTA>
14891489
...
@@ -1502,9 +1502,14 @@ message flatbuffer is read, you can then read the message body.
15021502

15031503
The stream writer can signal end-of-stream (EOS) either by writing 8 bytes
15041504
containing the 4-byte continuation indicator (``0xFFFFFFFF``) followed by 0
1505-
metadata length (``0x00000000``) or closing the stream interface. We
1506-
recommend the ".arrows" file extension for the streaming format although
1507-
in many cases these streams will not ever be stored as files.
1505+
metadata length (``0x00000000``) or closing the stream interface.
1506+
1507+
File extension and MIME type
1508+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1509+
1510+
IPC Streams are not always stored as files, but when they are, we recommend
1511+
the ".arrows" file extension. The registered MIME type for IPC Streams is
1512+
`vnd.apache.arrow.stream`_.
15081513

15091514
IPC File Format
15101515
---------------
@@ -1524,21 +1529,46 @@ Schematically we have: ::
15241529
<empty padding bytes [to 8 byte boundary]>
15251530
<STREAMING FORMAT with EOS>
15261531
<FOOTER>
1527-
<FOOTER SIZE: int32>
1532+
<FOOTER SIZE: little-endian int32>
15281533
<magic number "ARROW1">
15291534

1530-
In the file format, there is no requirement that dictionary keys
1531-
should be defined in a ``DictionaryBatch`` before they are used in a
1532-
``RecordBatch``, as long as the keys are defined somewhere in the
1533-
file. Further more, it is invalid to have more than one **non-delta**
1534-
dictionary batch per dictionary ID (i.e. dictionary replacement is not
1535-
supported). Delta dictionaries are applied in the order they appear in
1536-
the file footer. We recommend the ".arrow" extension for files created with
1537-
this format. Note that files created with this format are sometimes called
1538-
"Feather V2" or with the ".feather" extension, the name and the extension
1539-
derived from "Feather (V1)", which was a proof of concept early in
1540-
the Arrow project for language-agnostic fast data frame storage for
1541-
Python (pandas) and R.
1535+
Equivalence with the IPC Streaming Format
1536+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1537+
1538+
While it is theoretically possible for the IPC File footer to list RecordBatch
1539+
messages in a differing order from the embedded IPC Stream's sequential order
1540+
(or even to repeat or omit some of the IPC Stream's RecordBatch messages),
1541+
compliant writers SHOULD arrange the IPC File footer so that an IPC File can be
1542+
read using an IPC Stream reader with equivalent results.
1543+
1544+
Deviations from the IPC Streaming Format
1545+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1546+
1547+
The random accessible nature of IPC Files leads to semantic differences when
1548+
decoding dictionary-encoded data:
1549+
1550+
1. While the IPC Streaming format requires that all initial dictionary batches
1551+
are emitted before any record batch, there is no such requirement in the IPC
1552+
File format.
1553+
1554+
2. The IPC File format does not support dictionary replacement, i.e. only one
1555+
non-delta dictionary batch can be emitted for a given dictionary ID.
1556+
1557+
3. Delta dictionary batches in an IPC File are applied in the order they appear
1558+
in the file footer.
1559+
1560+
File extension and MIME type
1561+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1562+
1563+
We recommend the ".arrow" extension for IPC Files. The registered MIME type for
1564+
IPC Files is `vnd.apache.arrow.file`_.
1565+
1566+
.. admonition:: Historical note
1567+
1568+
Files created with this format were sometimes called "Feather V2" or
1569+
named with the ".feather" extension, stemming from "Feather (V1)", a proof of
1570+
concept early in the Arrow project for fast language-agnostic dataframe storage
1571+
supporting only a small subset of Arrow types.
15421572

15431573
Dictionary Messages
15441574
-------------------
@@ -1728,3 +1758,5 @@ the Arrow spec.
17281758
.. _SIMD: https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/simd-data-layout-templates.html
17291759
.. _Parquet: https://parquet.apache.org/docs/
17301760
.. _UmbraDB: https://db.in.tum.de/~freitag/papers/p29-neumann-cidr20.pdf
1761+
.. _vnd.apache.arrow.stream: https://www.iana.org/assignments/media-types/application/vnd.apache.arrow.stream
1762+
.. _vnd.apache.arrow.file: https://www.iana.org/assignments/media-types/application/vnd.apache.arrow.file

0 commit comments

Comments
 (0)