This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-erlang.git


The following commit(s) were added to refs/heads/main by this push:
     new 24790a4  feat: symbolically represent IPC message bodies in IR (#115)
24790a4 is described below

commit 24790a4e24e457441114bf8b57b41cb601b7f049
Author: Benjamin Philip <[email protected]>
AuthorDate: Fri Aug 7 05:46:18 2026 +0530

    feat: symbolically represent IPC message bodies in IR (#115)
    
    ## What issue does this PR close?
    
    Closes #112.
    
    The body of a message needs to represented symbolically in Arrow JSON.
    We
    previously serialized it within our internal representation, making it
    impossible to produce Arrow JSON from the IR.
    
    ## What's Changed
    
    We now leave the body as-is in the IR and only serialize it on `to_ipc`.
    
    ---------
    
    Co-authored-by: Copilot Autofix powered by AI 
<[email protected]>
---
 guides/quick-run-through.livemd       | 22 ++++++++--------------
 src/arrow_ipc_message.erl             | 19 +++++++++++--------
 src/arrow_ipc_message.hrl             |  2 +-
 src/arrow_ipc_record_batch.erl        | 18 ++++++++++++++++--
 test/arrow_ipc_marks_data.hrl         |  4 ++--
 test/arrow_ipc_message_SUITE.erl      |  2 +-
 test/arrow_ipc_record_batch_SUITE.erl |  6 +++++-
 7 files changed, 44 insertions(+), 29 deletions(-)

diff --git a/guides/quick-run-through.livemd b/guides/quick-run-through.livemd
index a3d6220..b781f97 100644
--- a/guides/quick-run-through.livemd
+++ b/guides/quick-run-through.livemd
@@ -1,5 +1,7 @@
 <!-- -*- mode: markdown; fill-column: 80; -*- -->
-<!---
+
+<!--
+-
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
@@ -22,7 +24,7 @@
 
 ```elixir
 Mix.install([
-  {:arrow, git: "https://github.com/Benjamin-Philip/arrow.git"}
+  {:arrow, git: "https://github.com/apache/arrow-erlang.git"}
 ])
 ```
 
@@ -159,20 +161,12 @@ Class2RecordBatch = 
arrow_ipc_record_batch:from_erlang(Class2Columns),
 Class3RecordBatch = arrow_ipc_record_batch:from_erlang(Class3Columns).
 ```
 
-Each of these RecordBatches need a body:
-
-```erlang
-Class1Msg = arrow_ipc_message:body_from_erlang(Class1Columns),
-Class2Msg = arrow_ipc_message:body_from_erlang(Class2Columns),
-Class3Msg = arrow_ipc_message:body_from_erlang(Class3Columns).
-```
-
-Which can then be combined into a message:
+We can then create a Message from each Record Batch:
 
 ```erlang
-Class1Msg = arrow_ipc_message:from_erlang(Class1RecordBatch, Class1Body),
-Class2Msg = arrow_ipc_message:from_erlang(Class2RecordBatch, Class3Body),
-Class3Msg = arrow_ipc_message:from_erlang(Class3RecordBatch, Class3Body).
+Class1Msg = arrow_ipc_message:from_erlang(Class1RecordBatch, Class1Columns),
+Class2Msg = arrow_ipc_message:from_erlang(Class2RecordBatch, Class2Columns),
+Class3Msg = arrow_ipc_message:from_erlang(Class3RecordBatch, Class3Columns).
 ```
 
 If we wanted to, we could serialize these messages into an [Encapsulated 
message](https://arrow.apache.org/docs/format/Columnar.html#encapsulated-message-format):
diff --git a/src/arrow_ipc_message.erl b/src/arrow_ipc_message.erl
index c27eb14..95adb42 100644
--- a/src/arrow_ipc_message.erl
+++ b/src/arrow_ipc_message.erl
@@ -33,7 +33,7 @@ to represent a message. Metadata such as:
 3.  `body_length`: The length of the body in bytes
 4.  `custom_metadata`: A list of custom metadata in key-value format
 5.  `body`: The actual body. Can be undefined (in the case of Schema)
-    or a binary (in the case of Record Batch).
+    or a `[t:arrow_array:array/0]` (in the case of Record Batch).
 
 Currently, changing the version and custom metadata are not supported, but they
 have been added for forwards compatibility.
@@ -68,21 +68,24 @@ for more info:
 -type key_value() :: #{key => string(), value => string()}.
 
 -doc """
-Creates a message given a data header.
+Creates a message given a schema data header.
 """.
--spec from_erlang(Header :: arrow_ipc_schema:schema() | 
arrow_ipc_record_batch:record_batch()) ->
+-spec from_erlang(Header :: arrow_ipc_schema:schema()) ->
     Message :: message().
 from_erlang(Header) ->
     #message{header = Header, body_length = 0}.
 
 -doc """
-Creates a message given a data header and a body.
+Creates a message given a record batch data header and a body.
 """.
 -spec from_erlang(
-    Header :: arrow_ipc_schema:schema() | 
arrow_ipc_record_batch:record_batch(), Body :: binary()
+    Header :: arrow_ipc_record_batch:record_batch(),
+    Body :: [arrow_array:array()]
 ) -> Message :: message().
 from_erlang(Header, Body) ->
-    #message{header = Header, body = Body, body_length = byte_size(Body)}.
+    #message{
+        header = Header, body = Body, body_length = 
arrow_ipc_record_batch:body_length(Header)
+    }.
 
 -doc """
 Serializes a message into the Encapsulated Message Format.
@@ -98,8 +101,8 @@ to_ipc(Message) ->
         case Message#message.body of
             undefined ->
                 <<>>;
-            Bin ->
-                Bin
+            Arrays ->
+                body_from_erlang(Arrays)
         end,
 
     <<Continuation/binary, MetadataSize/binary, Metadata/binary, Body/binary>>.
diff --git a/src/arrow_ipc_message.hrl b/src/arrow_ipc_message.hrl
index d818269..08bd187 100644
--- a/src/arrow_ipc_message.hrl
+++ b/src/arrow_ipc_message.hrl
@@ -27,5 +27,5 @@
 
     %% This field is unique to arrow.
     %% The rest are from the flatbuffers definitions.
-    body :: binary() | undefined
+    body :: [arrow_array:array()] | undefined
 }).
diff --git a/src/arrow_ipc_record_batch.erl b/src/arrow_ipc_record_batch.erl
index 6d1cd77..6e79919 100644
--- a/src/arrow_ipc_record_batch.erl
+++ b/src/arrow_ipc_record_batch.erl
@@ -44,7 +44,7 @@ comapatibility.
 You can find RecordBatches in the Arrow spec
 [here](https://arrow.apache.org/docs/format/Columnar.html#recordbatch-message).
 """.
--export([from_erlang/1]).
+-export([from_erlang/1, body_length/1]).
 -export_type([field_node/0, buffer/0, record_batch/0]).
 
 -include("arrow_ipc_record_batch.hrl").
@@ -55,7 +55,7 @@ You can find RecordBatches in the Arrow spec
 -type record_batch() :: #record_batch{}.
 
 -doc """
-Creates a RecordBatch given a list of arrays
+Creates a RecordBatch given a list of arrays.
 """.
 -spec from_erlang(Arrays :: [arrow_array:array()]) -> RecordBatch :: 
record_batch().
 from_erlang(Arrays) ->
@@ -114,3 +114,17 @@ buffer_data(Buffer, CurOffset) ->
         #{offset => CurOffset, length => Buffer#buffer.length},
         arrow_buffer:size(Buffer) + CurOffset
     }.
+
+-doc """
+Returns the body length of a Record Batch.
+""".
+-spec body_length(RecordBatch :: record_batch()) -> non_neg_integer().
+body_length(RecordBatch) ->
+    case RecordBatch#record_batch.buffers of
+        [] ->
+            0;
+        Buffers ->
+            #{offset := Offset, length := Length} = lists:last(Buffers),
+            End = Offset + Length,
+            End + arrow_utils:pad_len(End)
+    end.
diff --git a/test/arrow_ipc_marks_data.hrl b/test/arrow_ipc_marks_data.hrl
index 39669f7..cb6ac56 100644
--- a/test/arrow_ipc_marks_data.hrl
+++ b/test/arrow_ipc_marks_data.hrl
@@ -61,9 +61,9 @@
 ).
 -define(Columns, [?ID, ?Name, ?Age, ?AnnualMarks]).
 -define(RecordBatch, arrow_ipc_record_batch:from_erlang(?Columns)).
--define(Body, <<<<(arrow_array:to_arrow(Array))/binary>> || Array <- 
?Columns>>).
--define(RecordBatchMsg, arrow_ipc_message:from_erlang(?RecordBatch, ?Body)).
+-define(RecordBatchMsg, arrow_ipc_message:from_erlang(?RecordBatch, ?Columns)).
 -define(RecordBatchEMF, arrow_ipc_message:to_ipc(?RecordBatchMsg)).
+-define(Body, <<<<(arrow_array:to_arrow(Array))/binary>> || Array <- 
?Columns>>).
 
 %%%%%%%%%%%%%%%%
 %% IPC Stream %%
diff --git a/test/arrow_ipc_message_SUITE.erl b/test/arrow_ipc_message_SUITE.erl
index 27c928e..6116804 100644
--- a/test/arrow_ipc_message_SUITE.erl
+++ b/test/arrow_ipc_message_SUITE.erl
@@ -68,7 +68,7 @@ valid_custom_metadata_on_from_erlang(_Config) ->
 
 valid_body_on_from_erlang(_Config) ->
     ?assertEqual((?SchemaMsg)#message.body, undefined),
-    ?assertEqual((?RecordBatchMsg)#message.body, ?Body).
+    ?assertEqual((?RecordBatchMsg)#message.body, ?Columns).
 
 %%%%%%%%%%%%%%
 %% to_ipc/1 %%
diff --git a/test/arrow_ipc_record_batch_SUITE.erl 
b/test/arrow_ipc_record_batch_SUITE.erl
index 2195e4f..f564f4a 100644
--- a/test/arrow_ipc_record_batch_SUITE.erl
+++ b/test/arrow_ipc_record_batch_SUITE.erl
@@ -32,7 +32,8 @@ all() ->
         valid_length_on_from_erlang,
         valid_nodes_on_from_erlang,
         valid_buffers_on_from_erlang,
-        valid_compression_on_from_erlang
+        valid_compression_on_from_erlang,
+        body_length
     ].
 
 valid_length_on_from_erlang(_Config) ->
@@ -62,3 +63,6 @@ valid_buffers_on_from_erlang(_Config) ->
 
 valid_compression_on_from_erlang(_Config) ->
     ?assertEqual((?RecordBatch)#record_batch.compression, undefined).
+
+body_length(_Config) ->
+    ?assertEqual(arrow_ipc_record_batch:body_length(?RecordBatch), 
byte_size(?Body)).

Reply via email to