API Reference

April 11, 2026 · View on GitHub

Rust

Function / TypeDescription
read_qvd_file(path)Read a QVD file into QvdTable
write_qvd_file(table, path)Write QvdTable to QVD file
QvdTableBuilder::new(name)Build a QVD table from scratch
QvdTable::normalize()Auto-set Qlik-compatible types, tags, format
open_qvd_stream(path)Open streaming chunk-based reader
ExistsIndex::from_column(table, col)Build O(1) lookup index
filter_rows_by_exists_fast(table, col, idx)Filter rows using EXISTS index
concatenate(a, b)Append two QVD tables (strict schema)
concatenate_with_schema(a, b, mode)Append with SchemaMode::Strict or Union
concatenate_with_pk(a, b, pk, on_conflict)PK-based upsert/dedup merge
concatenate_with_pk_schema(a, b, pk, on_conflict, mode)PK merge with schema mode
convert_parquet_to_qvd(src, dst)Parquet -> QVD
convert_qvd_to_parquet(src, dst, compression)QVD -> Parquet
qvd_to_record_batch(table)QVD -> Arrow RecordBatch
record_batch_to_qvd(batch, name)Arrow RecordBatch -> QVD
write_record_batch_to_qvd(batch, name, path)Arrow -> QVD file directly
register_qvd(ctx, name, path)Register QVD as DataFusion table

Python

Function / MethodDescription
qvd.read_qvd(path)Read QVD into QvdTable
table.save(path)Write QVD to file
qvd.read_qvd_to_arrow(path)Read as PyArrow RecordBatch
qvd.read_qvd_to_pandas(path)Read as pandas DataFrame
qvd.read_qvd_to_polars(path)Read as Polars DataFrame
qvd.read_qvd_filtered(path, col, idx, ...)Streaming filtered read
QvdTable.from_arrow(batch, name)Create from PyArrow RecordBatch
QvdTable.from_parquet(path)Create from Parquet file
qvd.write_arrow(data, path, table_name)Write PyArrow RecordBatch/Table to QVD
table.concatenate(other, schema)Append (schema: "strict" / "union")
table.concatenate_pk(other, pk, on_conflict, schema)PK merge
qvd.concatenate_qvd(existing, new, out, schema)File-level append
qvd.concatenate_pk_qvd(existing, new, out, pk, ...)File-level PK merge
qvd.ExistsIndex(table, col)Build EXISTS index
qvd.filter_exists(table, col, idx)Filter rows
qvd.register_duckdb(conn, name, path)Register as DuckDB table
qvd.register_duckdb_folder(conn, path)Register folder of QVDs
qvd.register_duckdb_filtered(conn, ...)Register with EXISTS filter
qvd.convert_parquet_to_qvd(src, dst)Parquet -> QVD
qvd.convert_qvd_to_parquet(src, dst, compression)QVD -> Parquet

TypeScript / Node.js

Function / MethodDescription
readQvd(path)Read QVD file (async, returns Promise)
readQvdSync(path)Read QVD file (sync)
saveQvd(table, path)Write QVD to file (async)
saveQvdSync(table, path)Write QVD to file (sync)
readQvdFiltered(path, col, values, ...)Streaming filtered read (async)
JsQvdTable.get(row, col)Get cell by index
JsQvdTable.getByName(row, colName)Get cell by column name
JsQvdTable.columnValues(col)Get column values by index
JsQvdTable.columnValuesByName(colName)Get column values by name
JsQvdTable.toJson()Convert to array of objects
JsQvdTable.head(n?)First N rows as objects
JsQvdTable.filterByValues(col, values)Filter rows by matching values
JsQvdTable.subsetRows(indices)Subset by row indices
JsQvdTable.normalize()Normalize for Qlik compatibility
JsQvdTable.concatenate(other, schema?)Append (schema: "strict" / "union")
JsQvdTable.concatenatePk(other, pk, ...)PK merge
concatenateQvd(a, b, out, schema?)File-level append (async)
concatenatePkQvd(a, b, out, pk, ...)File-level PK merge (async)
JsExistsIndex.fromColumn(table, col)Build EXISTS index from column
JsExistsIndex.fromValues(values)Build EXISTS index from values
filterExists(table, col, index)Filter rows by EXISTS index

Enums

SchemaMode (Rust) / schema parameter (Python/TypeScript)

ValueDescription
Strict / "strict"Error if column names differ (default)
Union / "union"Fill missing columns with NULL (Qlik CONCATENATE behavior)

OnConflict (Rust) / on_conflict parameter (Python/TypeScript)

ValueDescription
Replace / "replace"New rows win on PK collision (default)
Skip / "skip"Existing rows win
Error / "error"Return error on any collision

Performance

Tested on 399 real QVD files (11 KB -- 2.8 GB), all byte-identical roundtrip (MD5 match).

FileSizeRowsColumnsReadWrite
tiny11 KB1250.0s0.0s
small418 KB2,74680.0s0.0s
medium41 MB465,810120.5s0.0s
large587 MB5,458,618156.1s0.4s
xlarge1.7 GB87,617,047823.6s1.6s
huge2.8 GB11,907,6484224.3s2.4s

Feature Flags

FeatureDependenciesDescription
(default)noneCore QVD read/write
parquet_supportarrow, parquet, chronoParquet/Arrow conversion
datafusion_support+ datafusion, tokioSQL queries via DataFusion
cli+ clapCLI binary
python+ pyo3, arrow/pyarrowPython bindings
napi_support+ napi, napi-derive, serde_jsonNode.js/TypeScript bindings

Architecture

src/
├── lib.rs        — public API, re-exports
├── reader.rs     — QVD reader + QvdTable + normalize()
├── writer.rs     — QVD writer + QvdTableBuilder
├── concat.rs     — concatenate + PK merge/upsert
├── exists.rs     — ExistsIndex + filter functions
├── streaming.rs  — streaming chunk-based reader
├── parquet.rs    — Parquet/Arrow <-> QVD (optional)
├── datafusion.rs — DataFusion TableProvider (optional)
├── python.rs     — PyO3 bindings (optional)
├── napi.rs       — napi-rs Node.js bindings (optional)
└── bin/qvd.rs    — CLI binary (optional)