CSharpDB v3.8.0 turns table export into something more useful than a CSV button. The new work adds native table archives, Admin Import / Export tooling, SQL DDL for read-only external tables, and a query path that can join archived data with live tables.
The goal is practical: move a large table out to a local archive file, keep its schema and rows intact, then query that file without restoring it into the main database.
.csdbtable files store schema, manifest, encoded rows, and an optional primary-key index in one seekable native package.CREATE EXTERNAL TABLE registers an archive file as a read-only SQL table that works in normal SELECT queries and joins.sys.external_tables, and uses archive scan and indexed lookup operators.Why Native Table Archives?
CSV and JSON are useful interchange formats, but they are not great table backups. They do not preserve all CSharpDB table metadata, large binary values need special handling, and querying them efficiently means inventing a second import path anyway.
The .csdbtable format is intentionally database-native. It stores the table schema, row count, source table name, created timestamp, column metadata, foreign key metadata, encoded row records, and index metadata. Integer primary-key tables also get an embedded page-based index so point lookups do not have to scan the whole archive.
CSDBTBL3. Rows are stored as length-prefixed records using the same record encoding CSharpDB already understands, with schema and manifest sections stored as JSON metadata. The archive is not a ZIP of JSON rows.
The Admin Experience
Admin now has a first-class Import / Export surface. You can open it from the Object Explorer Tools section, from the command palette, or from a table context menu. Opening it from a table still preselects that table; opening it from Tools starts unseeded.
The tab has three modes:
| Mode | What it does |
|---|---|
Export Table |
Writes a full table snapshot to a native .csdbtable archive. The destination can be a one-time browser download or a server/database-local path. |
Register External Table |
Registers an existing archive path under a SQL table name, with optional replacement of an existing registration. |
Restore Table |
Reads an archive and creates a normal physical table from it. |
Exports report progress as they move through preparing, exporting, finalizing, and download preparation. Large exports can be canceled, and the UI no longer depends on loading the whole archive into browser memory. Download exports are staged server-side and served through a one-time download endpoint.
Fast Snapshot Export
The engine transport path now exports archives directly from a read session. That matters for large tables because it avoids the Admin fallback path of paging through the table over the UI client. The export opens a reader snapshot, streams SELECT * rows to the archive writer, and reports row progress while it writes.
For a table with millions of rows, this is the difference between a UI-driven export loop and a storage-adjacent streaming backup path. The snapshot is read-only, consistent for the export, and cancellable through the same cancellation token used by the Admin progress UI.
Registering an Archive as an External Table
Once an archive exists, registration is a metadata operation. CSharpDB reads the archive metadata, stores the registration in an internal metadata table, invalidates external table caches, and exposes the result through sys.external_tables. It does not import rows into the database.
CREATE EXTERNAL TABLE archived_customers
FROM 'exports/customers.csdbtable';
SELECT c.id, c.name, a.status
FROM customers c
JOIN archived_customers a ON a.id = c.id
WHERE a.status = 'active';
SELECT table_name, path, source_table_name, row_count
FROM sys.external_tables
ORDER BY table_name;
DROP EXTERNAL TABLE archived_customers;
Relative archive paths resolve from the database file directory. That keeps registrations portable when the database and its exports folder move together.
Read-Only by Design
External tables are queryable, but they are not mutable. v3.8.0 rejects writes and schema mutations against external table names:
INSERT,UPDATE, andDELETEare blocked.ALTER TABLEis blocked.CREATE INDEXand trigger-target usage are blocked.DROP TABLEtells you to useDROP EXTERNAL TABLEinstead.
That keeps the archive contract simple. The file is a stable snapshot. If you want to edit data, restore it to a normal table or export a new archive.
Query Planner Integration
External tables sit in the normal name-resolution flow after common table expressions and system catalog checks. When the planner sees a registered external table, it reads the archive schema and builds an external scan source. Projection, filters, ordering, aggregates, and joins reuse the same operators as regular query pipelines where possible.
| Query shape | Planner behavior |
|---|---|
SELECT * FROM archived_customers |
Uses ExternalTableScanOperator over the archive row stream. |
SELECT COUNT(*) FROM archived_customers |
Uses registration row-count metadata instead of scanning the file. |
WHERE id = 123 on an integer primary key |
Uses the embedded archive primary-key index when present. |
| Live table joined to external table | Uses the existing join/projection/filter pipeline once the external source is resolved. |
Object Explorer Changes
The Admin Object Explorer now has two external-table entry points. The External Tables group lists registered archives from sys.external_tables, showing source table and row count. Each item can open a top-50 query, open metadata, copy name/path, count rows, or drop the registration.
The Tools group also includes Import / Export, so users do not have to first select a physical table to reach the tab. The table context menu remains useful for table-specific exports because it opens the same tab preselected for that table.
What Changed Under the Hood
The release adds two project areas:
CSharpDB.ImportExportowns the archive models, native serialization, archive reader/writer, and primary-key lookup reader.CSharpDB.Admin.ImportExportowns the Admin contracts, page components, progress UI, download store, endpoint mapping, and orchestration service.
Core SQL/runtime changes include parser support for CREATE EXTERNAL TABLE and DROP EXTERNAL TABLE, metadata storage in the internal __external_tables table, sys.external_tables, external table resolution in the planner, archive scan and lookup operators, and read-only guards across DML and DDL paths.
The client layer adds archive-export interfaces so embedded transports can stream native exports directly. Admin falls back to paged export only when the transport does not support native archive export.
Tests and Safety Nets
The implementation includes coverage for archive roundtrips, empty tables, BLOBs, native primary-key indexes, parser DDL, external table joins, filtering, projection, metadata, read-only rejections, drop/re-register behavior, and transport-level archive export progress.
The Admin side also gained tests around tab manager behavior, and the UI work fixed a real usability issue: long-running query/grid loads now move off the UI path and can be canceled.
Where This Leaves v3.8.0
This is the first release where a CSharpDB table can become a portable native archive and still remain queryable without restoration. It is not a replacement for full database backup. It is a table-level snapshot and external-table feature aimed at archival, staging, investigation, and large-table offloading workflows.
The next natural steps are broader archive index support, richer external-table planner costing, and more restore/import ergonomics. The important foundation is now in place: table archives are native, external tables are visible in SQL, and Admin gives users a practical workflow for moving data in and out.