How to Export Data from DBX in CSV Format: CLI, Core Library, and Desktop Methods
DBX supports CSV export through three integrated layers: a command-line interface that streams results to stdout, a core Rust library that formats query results with UTF-8 BOM headers, and a Tauri-based desktop application that writes paginated table data directly to disk.
DBX provides robust capabilities to export data from DBX in CSV format across its entire architecture, whether you are using the terminal, building a custom integration, or working within the desktop UI. The t8y2/dbx repository implements this functionality through complementary layers that share common escaping logic and NULL handling rules. Each layer is optimized for its specific environment while maintaining consistent output formatting.
Export Methods Overview
Command-Line Interface (CLI) Export
The CLI layer formats query results, connection lists, and schema information as CSV on-the-fly. In packages/cli/src/cli-format.ts, the csvTable() function builds the text representation, while packages/cli/src/cli.ts parses the --format csv flag to trigger this behavior. When you run a query with the CSV format flag, DBX executes the SQL and pipes the formatted result directly to stdout, allowing you to redirect the output to a file using standard shell operators.
Core Library Programmatic Export
The Rust core library handles the low-level CSV generation in crates/dbx-core/src/csv_export.rs. The format_query_result_csv() function converts generic query results into properly escaped CSV strings, prefixing the output with a UTF-8 BOM (\u{FEFF}) for Excel compatibility. This layer handles NULL values distinctly: query results render NULL as the string "NULL", while standard CSV exports use empty cells. The function relies on escape_csv() to handle field quoting and internal quote doubling.
Desktop Application (Tauri) Export
For the desktop UI, Tauri commands in src-tauri/src/commands/csv_export.rs provide file-system integration. The export_query_result_csv and export_table_data_csv commands receive a file path from the frontend and stream data to disk using BufWriter. The export_table_data_csv_core() function in the core library paginates large tables using build_table_data_select_sql(), writes the BOM once, and processes each page through write_csv_row(), ensuring memory-efficient exports of large datasets.
The CSV Export Pipeline
From Query to File
The export process follows a consistent pipeline across all interfaces. First, the system executes the SQL statement using execute_sql_statement_with_options. Then, the result columns and rows pass through format_query_result_csv(), which builds the header row by applying escape_csv() to each column name. For data rows, the system converts each serde_json::Value into CSV-compatible text using value_to_query_result_csv_text(), joining rows with newline characters and prefixing the entire output with the UTF-8 BOM.
NULL Handling and Field Escaping
DBX implements strict NULL handling rules to ensure data integrity. In query result exports, NULL values appear as the literal string "NULL" in the output, while table exports leave the cell empty. The escape_csv() function manages RFC 4180 compliance by wrapping fields containing commas, quotes, or newlines in double quotes, and doubling internal quotes to prevent parsing errors.
Practical Code Examples
Export a query directly to a CSV file using the CLI:
dbx query local "SELECT id, name FROM users ORDER BY id" --format csv > users.csv
Use the Node.js core library to format query results as CSV:
import { format_query_result_csv } from '@dbx-app/node-core';
const columns = ['id', 'name'];
const rows = [
[{ id: 1 }, { name: 'Ada' }],
[{ id: 2 }, { name: 'Bob' }],
];
const csv = format_query_result_csv(columns, rows);
console.log(csv); // prints a BOM‑prefixed CSV string
Export an entire table from the Desktop application (Rust internals):
// This represents the internal call structure used by the Tauri command
export_table_data_csv_core(
connection_id,
TableCsvExportOptions {
file_path: "/tmp/orders.csv".into(),
database: "mydb".into(),
schema: None,
table_name: "orders".into(),
columns: vec![], // empty → export all columns
page_size: Some(5000), // optional paging size
timeout_secs: Some(30),
}
)
Generate CSV internally within a CLI extension:
import { csvTable } from '@dbx-app/cli';
const headers = ['id', 'name'];
const data = [{ id: 1, name: 'Ada' }, { id: 2, name: 'Bob' }];
const csv = csvTable(headers, data);
process.stdout.write(csv);
Summary
- DBX provides three export layers: CLI (
csvTable()incli-format.ts), Core library (format_query_result_csv()incsv_export.rs), and Desktop (export_table_data_csvin Tauri commands). - All layers share
escape_csv()logic and prefix output with a UTF-8 BOM (\u{FEFF}) for Excel compatibility. - The CLI streams results to stdout using the
--format csvflag, while the Desktop interface paginates large tables viaexport_table_data_csv_core()and writes directly to disk. - NULL handling differs between query results (rendered as
"NULL") and standard table exports (empty cells). - Key files:
crates/dbx-core/src/csv_export.rscontains the core logic;src-tauri/src/commands/csv_export.rshandles the desktop API;packages/cli/src/cli-format.tsmanages CLI formatting.
Frequently Asked Questions
How do I export a large table to CSV without running out of memory?
The Desktop export method uses export_table_data_csv_core() in crates/dbx-core/src/csv_export.rs, which implements pagination via build_table_data_select_sql(). It processes data in configurable chunks (defaulting to 5000 rows) and streams each page to a BufWriter, ensuring constant memory usage regardless of table size.
Why does my exported CSV file start with strange characters?
The DBX core library intentionally prefixes every CSV export with a UTF-8 Byte Order Mark (\u{FEFF}) as implemented in format_query_result_csv(). This mark ensures Microsoft Excel and other applications correctly interpret the file as UTF-8 encoded, preventing character corruption in international datasets.
Can I export query results programmatically from Node.js?
Yes. The @dbx-app/node-core package exposes format_query_result_csv(), which accepts column names and rows as serde_json::Value objects and returns a complete CSV string. This function handles all escaping and BOM insertion automatically, matching the output of the CLI and Desktop versions.
How does the CLI handle NULL values compared to the Desktop export?
In the CLI query results processed by format_query_result_csv(), NULL values appear as the literal string "NULL" in the CSV output. Conversely, when using the Desktop's table export via export_table_data_csv(), NULL values result in empty cells. This distinction ensures query results preserve semantic NULL information while table exports maintain compatibility with standard CSV consumers.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →