tinySQL Data Migration Tool

June 23, 2026 · View on GitHub

A smart CLI tool for data pipelines and processing. Transfer data between CSV/TSV/JSON/YAML/XML files, tinySQL, and external databases (MySQL/MariaDB, PostgreSQL, SQLite, MS SQL Server). Uses tinySQL as a central query hub with cross-database transfer support.

Features

  • Web Interface: Browser-based SQL editor with dark theme, file upload, connection management, and data export — all embedded in a single binary
  • File Import/Export: Load CSV, TSV, JSON, YAML, and simple row-based XML files into tinySQL; export query results to CSV/JSON files
  • External Database Connectivity: Connect to MySQL/MariaDB, PostgreSQL, SQLite, and MS SQL Server
  • Cross-Database Transfers: Move data between any combination of files and databases
  • Inter-Database Queries: COPY SELECT ... INTO <connection>.<table> syntax for routing query results to external databases
  • Interactive REPL: Named connection management, ad-hoc queries, live data exploration
  • Pipeline Scripts: Run multi-step migration workflows from script files
  • Fuzzy Import: Intelligent parsing for malformed CSV/JSON with auto-detection of delimiters, type inference, and error recovery; other formats use the structured auto-importer
  • Single Binary Deployment: All HTML, CSS, and JS are embedded — no external files needed

Quick Start

Build

# Using Make
make build-migrate

# Or directly with Go
cd cmd/migrate && go build -o migrate .

Import a CSV and Query It

migrate import-file -file users.csv -query "SELECT * FROM users WHERE age > 25"

Export Query Results to JSON

migrate import-file -file users.csv -query "SELECT name, email FROM users" -output results.json -format json

Interactive Mode

migrate interactive

Web Interface

# Start web server on port 8080
migrate web

# Custom port and pre-load files
migrate web -addr :3000 -files users.csv,orders.json

Then open http://localhost:8080 in your browser.

Commands

CommandDescription
webStart web interface for data migration
interactiveStart interactive REPL for data migration
import-fileImport a CSV/TSV/JSON/YAML/XML file into tinySQL
import-dbImport data from an external database into tinySQL
export-fileExport tinySQL data to a CSV/JSON file
export-dbExport tinySQL data to an external database
pipelineRun a multi-step migration pipeline from a script
helpShow help message

Command Reference

web

Start the web interface — a browser-based SQL editor with file upload, database connection management, and data export. All assets are embedded in the binary for single-file deployment.

migrate web [options]
FlagDescriptionDefault
-addrListen address (host:port):8080
-filesComma-separated files to pre-load
-verboseVerbose loggingfalse

API Endpoints:

EndpointMethodDescription
/GETWeb UI (HTML/CSS/JS)
/api/queryPOSTExecute SQL query
/api/tablesGETList loaded tables
/api/connectionsGETList active connections
/api/connectPOSTRegister external database
/api/disconnectPOSTClose a connection
/api/import-filePOSTUpload and import a file
/api/import-dbPOSTImport from external database
/api/exportPOSTExport query results (JSON/CSV)

Examples:

# Start with pre-loaded data
migrate web -files data/users.csv,data/orders.json

# Custom port
migrate web -addr :3000

# Bind to all interfaces (for Docker / remote access)
migrate web -addr 0.0.0.0:8080

import-file

Import a CSV, TSV, JSON, YAML, or simple row-based XML file into tinySQL, optionally query and output results.

migrate import-file [options]
FlagDescriptionDefault
-filePath to CSV/TSV/JSON/YAML/XML file (or positional arg)Required
-tableTarget table nameFilename without extension
-querySQL query to execute after import
-outputOutput file for query resultsstdout
-formatOutput format: table, json, csvtable
-fuzzyEnable fuzzy import for malformed filestrue
-verboseVerbose outputfalse

Examples:

# Simple import and query
migrate import-file -file users.csv -query "SELECT * FROM users WHERE age > 25"

# Import with custom table name, export as JSON
migrate import-file -file data.csv -table customers -query "SELECT * FROM customers" -output out.json -format json

# Positional file argument
migrate import-file users.csv

# Import YAML or XML through the structured importer
migrate import-file -file users.yaml -table users
migrate import-file -file users.xml -table users

import-db

Import data from an external database into tinySQL.

migrate import-db [options]
FlagDescriptionDefault
-dsnDatabase connection stringRequired
-querySQL query to run on source database
-source-tableSource table name (alternative to -query)
-tableTarget table name in tinySQLSource table name or imported
-tinyquerySQL query to run on tinySQL after import
-outputOutput file for query resultsstdout
-formatOutput format: table, json, csvtable
-verboseVerbose outputfalse

Examples:

# Import a table from PostgreSQL
migrate import-db -dsn "postgres://user:pass@localhost/mydb?sslmode=disable" -source-table users -table users

# Import with a custom query
migrate import-db -dsn "postgres://user:pass@localhost/mydb?sslmode=disable" \
  -query "SELECT * FROM users WHERE active = true" -table active_users

# Import and then query in tinySQL
migrate import-db -dsn "sqlite://data.db" -source-table orders -table orders \
  -tinyquery "SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer"

export-file

Export tinySQL data to a CSV or JSON file.

migrate export-file [options]
FlagDescriptionDefault
-filesComma-separated input files to load first
-querySQL query to select data for export
-tableTable name to export (all rows)
-outputOutput file pathRequired
-formatOutput format: csv, json (auto-detected)Auto from extension
-verboseVerbose outputfalse

Examples:

# Load CSV, filter, export to JSON
migrate export-file -files users.csv -query "SELECT * FROM users WHERE age > 30" -output filtered.json

# Load multiple files, join, export
migrate export-file -files users.csv,orders.csv \
  -query "SELECT u.name, COUNT(o.id) AS order_count FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.name" \
  -output summary.csv

export-db

Export tinySQL data to an external database.

migrate export-db [options]
FlagDescriptionDefault
-dsnTarget database connection stringRequired
-filesComma-separated input files to load first
-querySQL query to select data for export
-tableSource table name in tinySQL
-targetTarget table name in external databaseSource table name or exported
-createCreate target table if it doesn't existtrue
-verboseVerbose outputfalse

Examples:

# Load CSV and export to SQLite
migrate export-db -dsn "sqlite://output.db" -files users.csv -table users -target users_backup

# Export with a query
migrate export-db -dsn "mysql://user:pass@tcp(localhost:3306)/mydb" \
  -files data.csv -query "SELECT * FROM data WHERE status = 'active'" -target active_records

pipeline

Run a multi-step migration workflow from a script file.

migrate pipeline -script migration.sql
FlagDescriptionDefault
-scriptPath to pipeline script (or positional arg)Required
-verboseVerbose outputfalse

Pipeline Script Format:

-- Comments start with -- or #
# This is also a comment

-- Load files
load data/users.csv AS users
load data/orders.json AS orders

-- Connect to external databases
connect pg postgres://user:pass@localhost/mydb?sslmode=disable
connect mysql mysql://user:pass@tcp(localhost:3306)/dest

-- Import from external database
import pg "SELECT * FROM products WHERE active = true" AS products

-- Run SQL queries in tinySQL
CREATE TABLE summary (name TEXT, total FLOAT)
INSERT INTO summary SELECT u.name, SUM(o.amount) FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.name

-- Export results
export mysql summary
COPY SELECT * FROM summary WHERE total > 100 INTO mysql.high_value_customers

interactive

Start an interactive REPL session for data migration.

migrate interactive

Interactive Commands:

CommandDescription
connect <name> <dsn>Register an external database connection
disconnect <name>Close a connection
connectionsList active connections
load <file> [AS <table>]Load a CSV/TSV/JSON/YAML/XML file into tinySQL
import <conn> <table>Import a table from an external database
import <conn> "<query>" AS <table>Import query results as a table
export file <query> TO <file>Export query results to a file
export <conn> <table> [AS <target>]Export a tinySQL table to an external database
COPY SELECT ... INTO <conn>.<table>Cross-database query and transfer
tablesShow loaded tinySQL tables
helpShow help
exitExit the program

Example Session:

migrate> load users.csv
✓ Loaded users.csv as table 'users' (42µs)

migrate> SELECT * FROM users WHERE age > 25
name   age  email
─────  ───  ─────────────────
Alice  30   alice@example.com
Carol  28   carol@example.com

(2 rows in 15µs)

migrate> connect mydb sqlite://output.db
✓ Connected 'mydb' (sqlite)

migrate> COPY SELECT * FROM users WHERE age > 25 INTO mydb.senior_users
✓ Copied 2 rows to mydb.senior_users (3ms)

migrate> exit
Goodbye!

DSN Formats

The tool auto-detects the database driver from the DSN URI scheme:

DatabaseDSN FormatExample
PostgreSQLpostgres://user:pass@host:port/dbname?optspostgres://admin:secret@localhost:5432/mydb?sslmode=disable
MySQL/MariaDBmysql://user:pass@tcp(host:port)/dbnamemysql://root:pass@tcp(localhost:3306)/mydb
SQLitesqlite://path/to/file.dbsqlite:///tmp/data.db
MS SQL Serversqlserver://user:pass@host:port?database=namesqlserver://sa:pass@localhost:1433?database=mydb

Auto-detection also works for common patterns without explicit scheme prefixes:

  • Paths ending in .db, .sqlite, .sqlite3 → SQLite
  • DSNs containing tcp( or @/ → MySQL
  • DSNs containing sslmode= or host= → PostgreSQL

Supported File Formats

FormatExtensionsFeatures
CSV.csv, .tsv, .txtAuto-delimiter detection, header inference, type coercion
JSON.json, .jsonl, .ndjsonArray of objects, line-delimited JSON, nested structures
YAML.yaml, .ymlSequence of mappings or a single mapping
XML.xmlSimple row-based XML with attributes or child elements as columns

Fuzzy import (enabled by default) handles:

  • Inconsistent column counts
  • Unmatched quotes
  • Numbers with thousand separators
  • Mixed-type columns
  • Invalid UTF-8 characters

Building

# Build with Make
make build-migrate

# Build directly
cd cmd/migrate && go build -o ../../bin/migrate .

# Run tests
cd cmd/migrate && go test -v ./...

Architecture

The tool uses tinySQL as a central in-memory SQL engine:

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│ CSV/JSON/...│────▶│              │────▶│  CSV/JSON    │
│  Files      │     │              │     │  Files       │
└─────────────┘     │              │     └──────────────┘
                    │   tinySQL    │
┌─────────────┐     │   Engine     │     ┌──────────────┐
│  PostgreSQL │────▶│              │────▶│  MySQL       │
│  SQLite     │     │  (in-memory  │     │  MS SQL      │
│  MySQL      │     │   SQL hub)   │     │  PostgreSQL  │
│  MS SQL     │────▶│              │────▶│  SQLite      │
└─────────────┘     └──────────────┘     └──────────────┘

Data flows through tinySQL where it can be queried, joined, filtered, and aggregated using standard SQL before being routed to any output target.

Contributing

This tool is part of the tinySQL project by Simon Waldherr.