Skip to content
Back to skills

Arrow Columnar

ASecurity

Export and import sparq SPARQL SELECT QueryResult values through Apache Arrow RecordBatch, in-memory Parquet bytes, Arrow IPC stream bytes, or flattened CSV bytes with the opt-in sparq-arrow crate. Use when moving query results into dataframe, analytics, transport, or storage tooling while preserving RDF term kinds, datatype and language metadata, RDF 1.2 triple terms, empty literals, and unbound cells.

  • 12 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 12, 2026
developmentrustgoexpressapi

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 12, 2026

npx -y skills add sparq-org/sparq --skill arrow-columnar --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Arrow Columnar?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Arrow Columnar
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sparq-org-arrow-columnar/badge)](https://www.skillsdirectory.com/skills/sparq-org-arrow-columnar)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: arrow-columnar
description: Export and import sparq SPARQL SELECT QueryResult values through Apache Arrow RecordBatch, in-memory Parquet bytes, Arrow IPC stream bytes, or flattened CSV bytes with the opt-in sparq-arrow crate. Use when moving query results into dataframe, analytics, transport, or storage tooling while preserving RDF term kinds, datatype and language metadata, RDF 1.2 triple terms, empty literals, and unbound cells.
---

# sparq-arrow — Arrow, Parquet, IPC, and CSV interop

Use `sparq-arrow` when a Rust application needs a faithful columnar representation of a
`sparq_engine::QueryResult`. The crate maps every SELECT variable to one nullable Arrow
`Struct` column with five nullable UTF-8 children: `kind`, `value`, `datatype`,
`language`, and `direction`.

## Choose a feature

- Enable `arrow` for `to_record_batch`, `from_record_batch`, `term_schema`, and
  `term_struct_type`.
- Enable `parquet` for `to_parquet_bytes`, `from_parquet_bytes`,
  `parquet_variables_from_bytes`, and `parquet_row_count_from_bytes`; it implies
  `arrow`.
- Enable `ipc` for `to_ipc_bytes`, `from_ipc_bytes`, and
  `ipc_variables_from_bytes`; it implies `arrow`.
- Enable `csv` for `to_csv_bytes`, `from_csv_bytes`, and
  `csv_variables_from_bytes`; it implies `arrow` and adds no further dependencies
  (the RFC 4180 serializer and parser are hand-rolled over `std`).
- Leave all features disabled to retain only the dependency-free field-name constants.

All features are default-OFF. The crate is a leaf capability crate, so no Arrow
container dependency enters `sparq-core`, `sparq-engine`, or the WebAssembly bundle.

## Use a RecordBatch

```rust,ignore
use sparq_arrow::{from_record_batch, to_record_batch};

let batch = to_record_batch(&result)?;
let restored = from_record_batch(&batch)?;
assert_eq!(restored.vars, result.vars);
assert_eq!(restored.rows, result.rows);
# Ok::<(), Box<dyn std::error::Error>>(())
```

Add the feature with `cargo add sparq-arrow --features arrow`.

## Use Parquet bytes

```rust,ignore
use sparq_arrow::{
    from_parquet_bytes, parquet_row_count_from_bytes, parquet_variables_from_bytes,
    to_parquet_bytes,
};

let bytes: Vec<u8> = to_parquet_bytes(&result)?;
let variables = parquet_variables_from_bytes(&bytes)?;
let row_count = parquet_row_count_from_bytes(&bytes)?;
let restored = from_parquet_bytes(&bytes)?;
assert_eq!(variables, result.vars);
assert_eq!(row_count, result.rows.len());
assert_eq!(restored.vars, result.vars);
assert_eq!(restored.rows, result.rows);
# Ok::<(), Box<dyn std::error::Error>>(())
```

Add the feature with `cargo add sparq-arrow --features parquet`. Parquet is only a
serialization of the same RecordBatch projection; it does not use a second term
encoding. `parquet_variables_from_bytes` validates and reads only the stored schema,
while `parquet_row_count_from_bytes` reads the total row count from file metadata;
neither decodes row groups. `from_parquet_bytes` additionally rejects invalid RDF
lexical components while decoding rows.

## Use Arrow IPC stream bytes

```rust,ignore
use sparq_arrow::{from_ipc_bytes, ipc_variables_from_bytes, to_ipc_bytes};

let bytes: Vec<u8> = to_ipc_bytes(&result)?;
let variables = ipc_variables_from_bytes(&bytes)?;
let restored = from_ipc_bytes(&bytes)?;
assert_eq!(variables, result.vars);
assert_eq!(restored.vars, result.vars);
assert_eq!(restored.rows, result.rows);
# Ok::<(), Box<dyn std::error::Error>>(())
```

Add the feature with `cargo add sparq-arrow --features ipc`. The IPC stream carries the
same schema as the RecordBatch and preserves variable names for an empty result.
`ipc_variables_from_bytes` validates and reads that schema without decoding batches.

## Use CSV bytes

```rust,ignore
use sparq_arrow::{csv_variables_from_bytes, from_csv_bytes, to_csv_bytes};

let bytes: Vec<u8> = to_csv_bytes(&result)?;
let variables = csv_variables_from_bytes(&bytes)?;
let restored = from_csv_bytes(&bytes)?;
assert_eq!(variables, result.vars);
assert_eq!(restored.vars, result.vars);
assert_eq!(restored.rows, result.rows);
# Ok::<(), Box<dyn std::error::Error>>(())
```

Add the feature with `cargo add sparq-arrow --features csv`. CSV has no nested types,
so each variable's five-field term struct is flattened to the five header columns
`var.kind`, `var.value`, `var.datatype`, `var.language`, and `var.direction`; and CSV
has no value-level null, so an unbound cell is five empty fields with boundness carried
by the `kind` column — still distinct from a bound empty-string literal (`kind` is
`literal` with the explicit `xsd:string` datatype). The dialect is RFC 4180 (quoting
on comma, quote, CR, or LF; doubled-quote escaping; LF record terminators, with CRLF
accepted on read). Every term the struct can express round-trips losslessly; the one
shape CSV cannot carry is a zero-variable result, which `to_csv_bytes` rejects with an
error. `csv_variables_from_bytes` validates and reads only the header row.

## Preserve the mapping

- A null outer struct is an unbound cell. It is distinct from a bound empty-string
  literal, whose `kind` is `"literal"` and `value` is `""`.
- Plain string literals carry the explicit
  `http://www.w3.org/2001/XMLSchema#string` datatype.
- Language-tagged literals use `language`; RDF 1.2 directional literals additionally
  use `direction` with `"ltr"` or `"rtl"`.
- RDF 1.2 triple terms use `kind = "triple"` and store their N-Triples lexical form in
  `value`.
- Numeric and temporal literals remain lexical strings plus datatype IRIs. This surface
  does not narrow them into native Arrow numeric or temporal columns.

Treat the Arrow batch, Parquet bytes, or IPC stream as a transport projection, not as a
canonical RDF serialization or an RDF document.

[GPT-5.6] Verified against `sparq-arrow` for beads `sq-r3cab` and `sq-kix7x`.

Files in this skill

  • SKILL.md5.7 KB
  • agents/openai.yaml281 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.