Skip to content

Releases: thanos/ex_arrow

v0.6.0

09 Jun 13:45
c823fdb

Choose a tag to compare

What's Changed

Full Changelog: v0.5.0...v0.6.0

v0.5.0

16 Apr 21:13

Choose a tag to compare

Full Changelog: v0.4.0...v0.5.0 ExArrow 0.5.0 — Release Notes

Released: 2026-04-16

ExArrow 0.5.0 adds a production-grade Arrow Flight SQL client, making Elixir
a first-class participant in the Flight SQL ecosystem alongside DuckDB,
DataFusion, Dremio, and InfluxDB v3. The release also delivers lazy streaming
with Enumerable support for all stream types, a Mox-compatible behaviour for
unit testing, and structured error types with gRPC status codes.

All changes are backward compatible; upgrading from 0.4.0 requires only a
version bump.


What is new

Arrow Flight SQL client

Arrow Flight SQL layers SQL query semantics on top of Arrow Flight (gRPC +
Arrow IPC). Queries are dispatched to the server, which executes them and
streams results back as columnar RecordBatch data — the same Arrow format
used everywhere in ExArrow.

Quick start:

{:ok, client} = ExArrow.FlightSQL.Client.connect("localhost:32010")

# Materialised query — all batches collected before returning
{:ok, result} = ExArrow.FlightSQL.Client.query(client, "SELECT id, name FROM users")
result.num_rows  #=> 42
result.schema    #=> %ExArrow.Schema{...}

# Lazy query — stream one batch at a time
{:ok, stream} = ExArrow.FlightSQL.Client.stream_query(client, "SELECT * FROM big_table")
Enum.each(stream, fn batch -> process(batch) end)

# DML
{:ok, 3}        = ExArrow.FlightSQL.Client.execute(client, "DELETE FROM t WHERE id < 4")
{:ok, :unknown} = ExArrow.FlightSQL.Client.execute(client, "CREATE TABLE t (id INT)")

TLS connections — plaintext is used automatically for loopback addresses;
remote hosts use the OS trust store; a custom CA certificate can be provided:

# TLS with OS trust store (automatic for remote hosts)
{:ok, client} = ExArrow.FlightSQL.Client.connect("dremio.example.com:32010")

# Custom CA
pem = File.read!("priv/ca.pem")
{:ok, client} = ExArrow.FlightSQL.Client.connect("secure.server:32010",
  tls: [ca_cert_pem: pem])

Bearer-token authentication:

{:ok, client} = ExArrow.FlightSQL.Client.connect("dremio.example.com:32010",
  tls: true,
  headers: [{"authorization", "Bearer my-pat-token"}]
)

Lazy streaming with Enumerable

ExArrow.Stream now implements the Enumerable protocol, so all Enum.*
and Stream.* functions work directly on any stream handle — IPC, Parquet,
ADBC, and Flight SQL alike.

{:ok, stream} = ExArrow.FlightSQL.Client.stream_query(client, "SELECT * FROM events")

# Collect all batches
batches = Enum.to_list(stream)

# Map, filter, reduce — standard Elixir idioms
row_counts = Enum.map(stream, &ExArrow.RecordBatch.num_rows/1)

# Take only the first N batches — the rest are never fetched
first_two = Enum.take(stream, 2)

# Comprehension syntax
for batch <- stream, do: process_batch(batch)

Early termination (e.g. Enum.take/2) is safe — the underlying gRPC channel
is released when the stream variable goes out of scope.


Prepared statements

Server-side prepared statements allow the server to parse and plan a query
once and then execute it one or more times:

{:ok, stmt} = ExArrow.FlightSQL.Client.prepare(client,
  "SELECT * FROM events WHERE ts > '2024-01-01'")

# Execute as a streaming query
{:ok, stream} = ExArrow.FlightSQL.Statement.execute(stmt)
batches = Enum.to_list(stream)

# Re-execute the same statement (reuses the server plan)
{:ok, stream2} = ExArrow.FlightSQL.Statement.execute(stmt)

# Or execute as DML
{:ok, dml_stmt} = ExArrow.FlightSQL.Client.prepare(client,
  "DELETE FROM logs WHERE ts < '2020-01-01'")
{:ok, 1042} = ExArrow.FlightSQL.Statement.execute_update(dml_stmt)

Servers that do not support prepared statements return
{:error, %Error{code: :unimplemented}}.


Metadata discovery

{:ok, stream} = ExArrow.FlightSQL.Client.get_tables(client,
  db_schema_filter: "public", table_types: ["TABLE", "VIEW"])
batches = Enum.to_list(stream)

{:ok, stream} = ExArrow.FlightSQL.Client.get_db_schemas(client)
{:ok, stream} = ExArrow.FlightSQL.Client.get_sql_info(client)

Explorer and Nx integration

# Query → Explorer DataFrame
{:ok, result} = ExArrow.FlightSQL.Client.query(client, "SELECT * FROM sales")
{:ok, df}     = ExArrow.FlightSQL.Result.to_dataframe(result)

# Query → Nx tensor (first batch only)
{:ok, result} = ExArrow.FlightSQL.Client.query(client, "SELECT price FROM quotes")
{:ok, tensor} = ExArrow.FlightSQL.Result.to_tensor(result, "price")

# Lazy stream → Explorer DataFrame (large result sets)
{:ok, stream} = ExArrow.FlightSQL.Client.stream_query(client, "SELECT * FROM big_table")
{:ok, df}     = ExArrow.Explorer.from_stream(stream)

to_dataframe/1 requires {:explorer, "~> 0.11"}. to_tensor/2 requires
{:nx, "~> 0.9"}. Both return
{:error, %ExArrow.FlightSQL.Error{code: :conversion_error}} when the
optional dependency is absent.


Mox-compatible behaviour for unit testing

Swap the real implementation for a mock without a live server:

# test/test_helper.exs
Mox.defmock(MyApp.FlightSQLMock, for: ExArrow.FlightSQL.ClientBehaviour)

# In your test
Application.put_env(:ex_arrow, :flight_sql_client_impl, MyApp.FlightSQLMock)

Mox.expect(MyApp.FlightSQLMock, :query, fn _client, "SELECT 1", [] ->
  {:ok, %ExArrow.FlightSQL.Result{schema: schema, batches: [], num_rows: 0}}
end)

Structured errors

All non-bang functions return {:ok, value} or
{:error, %ExArrow.FlightSQL.Error{}}:

case ExArrow.FlightSQL.Client.query(client, sql) do
  {:ok, result}                                          -> handle(result)
  {:error, %Error{code: :unauthenticated}}               -> reauthenticate()
  {:error, %Error{code: :not_found, message: msg}}       -> Logger.warn(msg)
  {:error, err}                                          -> raise err
end

Error codes: :transport_error, :server_error, :unimplemented,
:unauthenticated, :permission_denied, :not_found, :invalid_argument,
:protocol_error, :multi_endpoint, :invalid_option, :conversion_error.


New public API

Module Function Description
ExArrow.FlightSQL.Client connect/1,2 Connect to a Flight SQL server
ExArrow.FlightSQL.Client query/2, query!/2 Materialised SQL query
ExArrow.FlightSQL.Client stream_query/2 Lazy SQL query returning ExArrow.Stream
ExArrow.FlightSQL.Client execute/2 DML/DDL with affected-row count
ExArrow.FlightSQL.Client prepare/2 Server-side prepared statement
ExArrow.FlightSQL.Client get_tables/1,2 List tables visible to the connected user
ExArrow.FlightSQL.Client get_db_schemas/1,2 List database schemas
ExArrow.FlightSQL.Client get_sql_info/1 Server capability flags
ExArrow.FlightSQL.Statement execute/1 Execute a prepared statement as a lazy stream
ExArrow.FlightSQL.Statement execute_update/1 Execute a prepared DML statement
ExArrow.FlightSQL.Result from_stream/1 Materialise a stream into a Result struct
ExArrow.FlightSQL.Result to_dataframe/1 Convert result to Explorer.DataFrame
ExArrow.FlightSQL.Result to_tensor/2 Extract a numeric column as Nx.Tensor
ExArrow.Stream Now implements Enumerable

Changed behaviour

ExArrow.Stream is now EnumerableEnum.to_list/1, Enum.map/2,
Enum.take/2, and all other Enum.* / Stream.* functions work directly on
stream handles. Existing code using Stream.next/1 and Stream.to_list/1
continues to work unchanged.


Bug fixes

Elixir 1.17+ typing warning in Adbc.Result.from_py/1 — the
{:ok, stream_ref, capsule} match was unreachable when Pythonx is not
loaded. Both from_py/1 and from_py!/1 are now guarded with
Code.ensure_loaded?(Pythonx), eliminating the "clause will never match"
compiler warning.


Dependencies

No new required dependencies. Optional dependencies for new features:

# Required only for TLS with a custom CA (Flight SQL connect option)
# Uses OTP :ssl and :public_key — no new Hex packages needed.

# Optional (unchanged from 0.4.0 — enable for ecosystem bridges)
{:explorer, "~> 0.11", optional: true}   # Result.to_dataframe/1
{:nx, "~> 0.9", optional: true}          # Result.to_tensor/2

Upgrade guide

No breaking changes. Update your version pin:

# Before
{:ex_arrow, "~> 0.4.0"}

# After
{:ex_arrow, "~> 0.5.0"}

Then run mix deps.get and mix compile.


Full changelog

See CHANGELOG.md for the complete list of changes including
internal fixes and documentation updates.

v0.4.0

21 Mar 16:10

Choose a tag to compare

What's Changed

Full Changelog: v0.3.0...v0.4.0

v0.3.0

14 Mar 17:15

Choose a tag to compare

ExArrow 0.3.0 — Release Notes

Released: 2026-03-10
Hex: https://hex.pm/packages/ex_arrow/0.3.0
Docs: https://hexdocs.pm/ex_arrow/0.3.0
Changelog: https://github.com/thanos/ex_arrow/blob/main/CHANGELOG.md#030---2026-03-10


What's new

Arrow compute kernels (ExArrow.Compute)

Three native operations on RecordBatch values — entirely in Rust Arrow
memory, no BEAM-side data copy:

Function Description
filter/2 Keep rows where the first column of a boolean batch is true
project/2 Select and reorder columns by name
sort/3 Sort a batch by a named column, ascending or descending

Results are new ExArrow.RecordBatch handles that compose with IPC writers,
Flight do_put, further compute calls, or the Parquet writer.

{:ok, filtered} = ExArrow.Compute.filter(batch, mask_batch)
{:ok, projected} = ExArrow.Compute.project(filtered, ["id", "score"])
{:ok, sorted} = ExArrow.Compute.sort(projected, "score", direction: :desc)

Backed by the arrow-select and arrow-ord Rust crates (both part of the
arrow-rs 56 release family, so no extra dependency resolution).


Parquet support (ExArrow.Parquet.Reader / ExArrow.Parquet.Writer)

Read and write the Apache Parquet format using the parquet Rust crate.
Both file paths and in-memory binaries are supported on both sides.

# Read
{:ok, stream}   = ExArrow.Parquet.Reader.from_file("/data/events.parquet")
{:ok, schema}   = ExArrow.Stream.schema(stream)
batches         = ExArrow.Stream.to_list(stream)

# Write
:ok = ExArrow.Parquet.Writer.to_file("/out/result.parquet", schema, batches)

# In-memory round-trip
{:ok, bytes}  = ExArrow.Parquet.Writer.to_binary(schema, batches)
{:ok, stream2} = ExArrow.Parquet.Reader.from_binary(bytes)

Parquet streams use the same ExArrow.Stream interface as IPC and ADBC
streams — schema/1, next/1, and to_list/1 work identically across all
three backends. No new consumption patterns to learn.


Explorer bridge (ExArrow.Explorer)

One-call conversion between ExArrow.Stream / ExArrow.RecordBatch and
Explorer.DataFrame:

# ExArrow → Explorer
{:ok, stream} = ExArrow.IPC.Reader.from_file("/data/events.arrow")
{:ok, df}     = ExArrow.Explorer.from_stream(stream)

# Explorer → ExArrow (e.g. write to Parquet or send via Flight)
df = Explorer.DataFrame.new(x: [1, 2, 3], y: ["a", "b", "c"])
{:ok, stream} = ExArrow.Explorer.to_stream(df)

All four bridge functions: from_stream/1, from_record_batch/1,
to_stream/1, to_record_batches/1.

Opt in by adding {:explorer, "~> 0.8"} to your mix.exs. When Explorer is
absent every function returns {:error, "Explorer is not available…"} rather
than failing to compile.


Nx bridge (ExArrow.Nx)

Zero-copy column extraction to Nx.Tensor by sharing the raw byte buffer:

{:ok, stream}  = ExArrow.Parquet.Reader.from_file("/data/features.parquet")
batch          = ExArrow.Stream.next(stream)
{:ok, tensor}  = ExArrow.Nx.column_to_tensor(batch, "price")

# Or extract all numeric columns at once
{:ok, tensors} = ExArrow.Nx.to_tensors(batch)
# %{"price" => #Nx.Tensor<f64[1000]>, "qty" => #Nx.Tensor<s32[1000]>, …}

Reverse path: from_tensor/2 writes an Nx.Tensor into a
single-column RecordBatch without going through an Elixir list.

Supported Arrow types: Int8/16/32/64, UInt8/16/32/64, Float32/64.
Non-numeric columns return {:error, …} from column_to_tensor/2 and are
silently skipped by to_tensors/1.

Opt in by adding {:nx, "~> 0.9"} to your mix.exs.


New public API surface

Module New functions
ExArrow.Compute filter/2, project/2, sort/3
ExArrow.Parquet.Reader from_file/1, from_binary/1
ExArrow.Parquet.Writer to_file/3, to_binary/2
ExArrow.Explorer from_stream/1, from_record_batch/1, to_stream/1, to_record_batches/1
ExArrow.Nx column_to_tensor/2, to_tensors/1, from_tensor/2

Optional dependencies

Add to mix.exs Unlocks
{:explorer, "~> 0.8"} ExArrow.Explorer bridge
{:nx, "~> 0.9"} ExArrow.Nx bridge

Both are optional. ExArrow compiles and works without them; the bridge modules
gracefully degrade to {:error, "… is not available…"} at runtime.


Upgrade guide from 0.2.0

# mix.exs — bump the version pin
{:ex_arrow, "~> 0.3.0"}

# Optional: add if you use the new bridges
{:explorer, "~> 0.8", optional: true}
{:nx, "~> 0.9", optional: true}

No breaking changes to existing IPC, Flight, or ADBC APIs. All existing calls
continue to work without modification.


Fixes

  • Dialyzer call_without_opaque errors in ExArrow.Explorer and ExArrow.Nx
    — function heads no longer pattern-match on the concrete struct behind
    @opaque types; resource extraction uses the dedicated resource_ref/1
    helpers instead.
  • Credo warnings in new test files (alias ordering, pipe chains, length/1
    vs != []).

What's next (v0.4.0)

v0.4.0 is already released and ships:

  • Arrow C Data Interface (ExArrow.CDI) — zero-copy batch transfer via
    raw C-struct pointers; foundation for a future zero-copy Explorer bridge.
  • ExArrow.Nx.from_tensors/1 — multi-column RecordBatch from a tensor
    map in one call.
  • Lazy Parquet streaming — row groups decoded on demand via
    Stream.next/1; peak memory proportional to the largest row group, not
    the full file.

# ExArrow 0.2.0 — Release Notes

10 Mar 17:05

Choose a tag to compare

Released: 2026-03-09

ExArrow 0.2.0 delivers the four features promised on the v0.2 roadmap: TLS for
Arrow Flight, multi-dataset server routing, an ADBC connection pool, and a
broader integration test matrix. All changes are backward compatible; no
existing code needs to change to upgrade from 0.1.0.


What is new

TLS for Arrow Flight

The built-in Flight server now supports encrypted connections. Pass a :tls
option to Server.start_link/2:

# One-way TLS (server presents a certificate)
cert = File.read!("server.crt")
key  = File.read!("server.key")
{:ok, server} = ExArrow.Flight.Server.start_link(9999,
  tls: [cert_pem: cert, key_pem: key])

# Mutual TLS (both sides present certificates)
ca = File.read!("ca.crt")
{:ok, server} = ExArrow.Flight.Server.start_link(9999,
  tls: [cert_pem: cert, key_pem: key, ca_cert_pem: ca])

The client already selected TLS automatically for non-loopback hosts (using the
OS certificate store). For a custom or self-signed CA, pass
tls: [ca_cert_pem: pem] to Client.connect/3.

Plaintext (tls: false, or no :tls option on loopback) continues to work
exactly as before.


Flight server routing — multiple named datasets

The built-in Flight server now stores datasets in a HashMap keyed by ticket,
rather than always overwriting a single "echo" slot.

Upload with a descriptor to store under a named ticket:

:ok = ExArrow.Flight.Client.do_put(client, schema, batches,
        descriptor: {:cmd, "sales_2024"})

:ok = ExArrow.Flight.Client.do_put(client, schema, other_batches,
        descriptor: {:path, ["metrics", "daily"]})

Retrieve by ticket:

{:ok, stream} = ExArrow.Flight.Client.do_get(client, "sales_2024")
{:ok, stream} = ExArrow.Flight.Client.do_get(client, "metrics/daily")

List all stored datasets:

{:ok, flights} = ExArrow.Flight.Client.list_flights(client)
{:ok, tickets} = ExArrow.Flight.Client.do_action(client, "list_tickets", <<>>)

Calls that do not pass a :descriptor default to the "echo" ticket, so all
existing code continues to work without modification.


ADBC connection pool

ExArrow.ADBC.ConnectionPool is a NimblePool-backed pool that reuses open
Connection handles across callers.

Supervised pool (recommended)

children = [
  {ExArrow.ADBC.DatabaseServer,
    name: :mydb,
    driver_path: "/usr/local/lib/libadbc_driver_duckdb.so"},
  {ExArrow.ADBC.ConnectionPool,
    name: :mypool, database: :mydb, pool_size: 4}
]
Supervisor.start_link(children, strategy: :one_for_one)

# Anywhere in the application:
{:ok, stream} = ExArrow.ADBC.ConnectionPool.query(:mypool,
                  "SELECT * FROM events WHERE day = today()")

Ad-hoc pool

{:ok, db}   = ExArrow.ADBC.Database.open(driver_path: "/path/to/driver.so")
{:ok, pool} = ExArrow.ADBC.ConnectionPool.start_link(database: db, pool_size: 4)
{:ok, stream} = ExArrow.ADBC.ConnectionPool.query(pool, "SELECT 42 AS n")

Multi-statement checkout

ExArrow.ADBC.ConnectionPool.with_connection(pool, fn conn ->
  {:ok, stmt} = ExArrow.ADBC.Statement.new(conn)
  ExArrow.ADBC.Statement.set_sql(stmt, "BEGIN")
  ExArrow.ADBC.Statement.execute(stmt)
  # ... more statements ...
  {result, :ok}
end)

Larger integration test matrix

A new .github/workflows/integration.yml workflow runs ADBC integration tests
against:

  • PostgreSQL 14, 15, and 16 (via GitHub Actions service containers)
  • DuckDB 1.1.3 and 1.2.0 (via downloaded ADBC driver binary)

The tests live in test/ex_arrow/adbc_integration_test.exs and are excluded
from the default test run. To run them locally:

# Start PostgreSQL
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:16

PG_HOST=localhost mix test --include adbc_integration \
  test/ex_arrow/adbc_integration_test.exs

# DuckDB
DUCKDB_DRIVER=/usr/local/lib/libduckdb_adbc.so \
  mix test --include adbc_integration \
  test/ex_arrow/adbc_integration_test.exs

New public API additions

Module Function Description
ExArrow.Schema field_names/1 Returns field names as [String.t()]
ExArrow.Stream to_list/1 Collects all batches into a list
ExArrow.ADBC.Database close/1 Explicit handle release
ExArrow.ADBC.Connection close/1 Explicit handle release
ExArrow.ADBC.ConnectionPool start_link/1, query/3, with_connection/3 NimblePool pool
ExArrow.ADBC.DatabaseServer start_link/1, get/1 Supervised database handle

Upgrade guide

No breaking changes. The only API change that requires attention is if you
have a Mox stub for ClientBehaviour.do_put: the callback now takes four
arguments (client, schema, batches, opts). Update your mock expectation:

# Before (0.1.0)
Mox.expect(MyMock, :do_put, fn client, schema, batches -> :ok end)

# After (0.2.0)
Mox.expect(MyMock, :do_put, fn client, schema, batches, _opts -> :ok end)

Dependencies

No new required dependencies. The connection pool requires nimble_pool
(already optional in 0.1.0); add it to your mix.exs to use
ExArrow.ADBC.ConnectionPool:

{:nimble_pool, "~> 1.1"}

Full changelog

See CHANGELOG.md for the complete list of changes.

v0.1.0-rc.9

27 Feb 03:41

Choose a tag to compare

v0.1.0

27 Feb 11:34

Choose a tag to compare

ExArrow 0.1.0 — Release notes

Release date: 2026-02-26
Package: Hex | Docs: hexdocs.pm/ex_arrow | Source: GitHub


Summary

ExArrow 0.1.0 is the first public release. It brings Apache Arrow support to the BEAM: IPC (stream and file), Arrow Flight (client and server), and ADBC (Arrow Database Connectivity). Data stays in native Rust/Arrow buffers; Elixir uses opaque handles. Precompiled NIFs are provided for Linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (x86_64), so no Rust toolchain is required for normal use.

Requirements: Elixir ~> 1.14 (OTP 25 / NIF 2.15 and OTP 26+ / NIF 2.16)


What's included

IPC (Inter-Process Communication)

  • Read/write Arrow stream format from binary or file.
  • Random-access file format: open by path or binary, read schema, batch count, and any batch by index.
  • Same ExArrow.Stream and ExArrow.Schema / ExArrow.RecordBatch handles as Flight and ADBC.

Arrow Flight

  • gRPC client: connect, do_put, do_get, list_flights, get_flight_info, get_schema, list_actions, do_action.
  • Built-in echo server for testing or simple services.
  • Plaintext HTTP/2 only in this release (TLS planned). Compatible with Dremio, InfluxDB IOx, and custom Flight servers.

ADBC

  • Open database by driver path or driver name (e.g. SQLite, PostgreSQL). Execute SQL and get an Arrow result stream.
  • Metadata APIs where the driver supports them: get_table_types, get_table_schema, get_objects.
  • Statement.bind for parameter binding where supported.
  • Optional integration with the adbc package: use it to configure and download drivers (e.g. SQLite, PostgreSQL) on first use; ExArrow then opens the database and returns Arrow streams.
  • ExArrow.ADBC.DriverHelper.ensure_driver_and_open/2: one-step “ensure driver then open”: when the adbc package is present it calls Adbc.download_driver/1, then opens the database via ExArrow.ADBC.Database.open/1. When adbc is not installed, it skips the download step and opens with the inferred options. Returns {:ok, db} or {:error, reason} (no raises).

Livebook tutorials

  • Four notebooks in the repo: quick start (IPC, Flight, ADBC in one place), plus tutorials for IPC (stream vs file, read/write, schema, Explorer interop), Flight (echo server, client, list_flights, get_schema, actions), and ADBC (Database → Connection → Statement → Stream, metadata). Suitable for learning and for an introductory article.

Explorer interop

  • Move data between ExArrow and Explorer via Arrow IPC: use ExArrow.IPC.Writer.to_binary/2 (or to_file/3) and Explorer.DataFrame.load_ipc_stream!/1 to get a dataframe from ExArrow streams (stream format); use Explorer.DataFrame.dump_ipc_stream!/1 (stream format) and ExArrow.IPC.Reader.from_binary/1 for the reverse. ExArrow handles streaming and protocols; Explorer handles in-memory analysis.

Memory and scheduling

  • Arrow data lives in native memory; no BEAM heap copy by default.
  • Long-running NIF work uses dirty schedulers so the BEAM is not blocked.

Installation

def deps do
  [{:ex_arrow, "~> 0.1.0"}]
end

Then mix deps.get and mix compile. The precompiled NIF is downloaded from GitHub releases. To build from source (e.g. unsupported platform), set EX_ARROW_BUILD=1 and have Rust installed.


Changelog

See CHANGELOG.md for the full 0.1.0 entry.


Feedback

Issues and discussions: GitHub Issues.

v0.1.0-rc.8

26 Feb 15:25

Choose a tag to compare

What's Changed

Full Changelog: v0.1.0-rc.7...v0.1.0-rc.8

v0.1.0-rc.7

26 Feb 12:32

Choose a tag to compare

v0.1.0-rc.6

25 Feb 19:36

Choose a tag to compare

What's Changed

  • Implement Milestone 1: IPC MVP (streaming only) by @thanos in #12
  • Milestone 2/ipc complete by @thanos in #24
  • Milestone 3 by @thanos in #34
  • closed #37 and closed #36 - In native/ex_arrow_native/src/flight.rs E… by @thanos in #38
  • feat: Milestone 4 — complete Arrow Flight RPC surface by @thanos in #44
  • Implement Milestone 5: ADBC MVP (Database, Connection, Statement, exe… by @thanos in #55
  • Milestone 6/adbc complete by @thanos in #66
  • Release/prepare by @thanos in #71

New Contributors

Full Changelog: https://github.com/thanos/ex_arrow/commits/v0.1.0-rc.6