+ {`CREATE TABLE "users" (
+ "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "name" TEXT NOT NULL
+);
+
+INSERT INTO "users" VALUES
+(1,'O''Connor');`}
+
+
+
+
+
{warnings.length > 0 ? (
Date: Tue, 28 Apr 2026 18:03:47 +0800
Subject: [PATCH 3/5] Bump version to 0.0.3
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 6770de1..3c7513e 100644
--- a/package.json
+++ b/package.json
@@ -43,5 +43,5 @@
"lint": "knip && biome check --write . && tsc --noEmit"
},
"type": "module",
- "version": "0.0.2"
+ "version": "0.0.3"
}
From 7a51a46d5df8b14e3c16889c1363c0bf55b971a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=F0=9F=8D=95?=
Date: Tue, 28 Apr 2026 18:14:59 +0800
Subject: [PATCH 4/5] Refactor README for clarity and detail
Updates the README to provide a more comprehensive explanation of the SQL Converter's purpose, features, and limitations.
- Enhances the "Why This Exists" section to better articulate the need for the tool.
- Clarifies privacy aspects, emphasizing local execution and data security.
- Updates browser requirements and usage instructions.
- Provides a clearer example of input and output SQL.
- Expands the "Supported Conversion Scope" and "Known Limits" sections for better user understanding.
- Restructures local development, import, and reporting issue sections.
---
README.md | 162 +++++++++++++++++++++++++++++-------------------------
1 file changed, 87 insertions(+), 75 deletions(-)
diff --git a/README.md b/README.md
index 6299b49..c879dac 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,79 @@
# SQL Converter
-SQL Converter is a browser-side tool for converting MariaDB/MySQL `.sql` dump files into SQLite-compatible SQL.
+SQL Converter converts MariaDB/MySQL `.sql` dump files into SQLite-compatible SQL in the browser.
Live app: https://dominosaurs.github.io/sql-converter/
-## What It Does
+## ✨ Why This Exists
-- Converts MariaDB/MySQL dump syntax into SQLite-oriented SQL.
-- Streams large input files directly from the browser.
-- Writes the converted output to a local file without uploading database data.
-- Handles common dump features such as data type conversion, quoted identifiers, auto-increment primary keys, indexes, foreign keys, JSON checks, dump directives, and MySQL string escapes.
+MariaDB and MySQL dumps often contain syntax that SQLite cannot import directly: backtick identifiers, `AUTO_INCREMENT`, engine options, charset/collation options, MariaDB dump directives, and MySQL-style escaped strings.
-## Browser Requirement
+SQL Converter rewrites the common parts of those dumps so the output can be imported into SQLite with fewer manual edits.
-Large-file conversion uses the File System Access API so the app can stream output directly to disk.
+## 🔒 Privacy
-Use a browser that supports `showSaveFilePicker`, such as:
+Conversion runs locally in your browser.
+
+- The input dump is read from your disk.
+- The converted file is written back to your disk.
+- The app does not upload your database dump to a server.
+
+## 🌐 Browser Requirement
+
+Large-file conversion uses the File System Access API so output can be streamed directly to disk.
+
+Recommended browsers:
- Chrome
- Edge
-Firefox and Safari may not support the required direct-to-disk streaming flow.
+Firefox and Safari may not support the required `showSaveFilePicker` API for large-file direct-to-disk conversion.
+
+## 🚀 Usage
+
+1. Open https://dominosaurs.github.io/sql-converter/
+2. Select a MariaDB/MySQL `.sql` dump file.
+3. Choose where to save the converted SQLite SQL file.
+4. Wait for conversion to finish.
+5. Import the generated `.sqlite.sql` file with your SQLite client.
+
+## 🔁 Example
+
+MariaDB/MySQL dump input:
+
+```sql
+CREATE TABLE `users` (
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+INSERT INTO `users` VALUES
+(1,'O\'Connor');
+```
-## Supported Conversion Scope
+SQLite output:
-The converter is designed for common `mysqldump` / MariaDB dump files.
+```sql
+CREATE TABLE "users" (
+ "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "name" TEXT NOT NULL
+);
+
+INSERT INTO "users" VALUES
+(1,'O''Connor');
+```
+
+## ✅ Supported Conversion Scope
+
+The converter is designed for common `mysqldump`, MariaDB dump, and phpMyAdmin-style SQL exports.
Currently handled:
- `CREATE TABLE`
- `DROP TABLE`
- `INSERT`
+- Backtick identifiers to SQLite double-quoted identifiers
- MariaDB/MySQL integer, decimal, text, blob, date/time, enum/set, and JSON-like column types
- `AUTO_INCREMENT` to SQLite `INTEGER PRIMARY KEY AUTOINCREMENT`
- Table-level primary keys
@@ -42,87 +85,56 @@ Currently handled:
- MySQL escaped string values in inserts
- MySQL hex literals like `0xDEADBEEF`
-Known limits:
+Generated string values use standard SQLite single-quoted strings:
-- This is not a full SQL parser.
-- Stored procedures, triggers, views, generated columns, and complex vendor-specific SQL may need more handling.
-- Memory use is bounded by chunks and completed statements, but a single extremely large SQL statement can still be expensive.
+```sql
+'O''Connor'
+```
-## Usage
+Multi-row inserts are preserved for performance.
-1. Open https://dominosaurs.github.io/sql-converter/
-2. Select a MariaDB/MySQL `.sql` dump file.
-3. Choose the output file location when prompted.
-4. Wait for conversion to finish.
-5. Import the generated `.sqlite.sql` file with your SQLite client.
+## ⚠️ Known Limits
-## Local Development
+This is a practical dump converter, not a full SQL parser or validator.
-This project uses Bun.
+Known limits:
-```bash
-bun install
-bun run dev
-```
+- Stored procedures are not supported.
+- Triggers and views may need manual review.
+- Generated columns may need manual review.
+- Vendor-specific functions may need manual review.
+- A single extremely large SQL statement can still be expensive, even though file reading/writing is streamed.
+- SQLite client/importer behavior varies. Some GUI tools may have script execution bugs even when the generated SQL is valid SQLite.
-Run checks:
+## 📥 Import Notes
-```bash
-bun run lint
-bun test
-bun run build
-```
+If your SQLite GUI client fails to import a generated file, test the failing statement with another importer before assuming the SQL is invalid.
-Preview production build:
+Recommended SQLite CLI import:
```bash
-bun run build
-bun run preview
+sqlite3 output.sqlite < converted.sqlite.sql
```
-## Scripts
+Or inside SQLite:
-- `bun run dev` starts the Vite dev server.
-- `bun run build` type-checks and builds the app.
-- `bun run lint` runs Knip, Biome, and TypeScript checks.
-- `bun run format` applies Biome formatting/fixes.
-- `bun test` runs converter tests.
-- `bun run preview` previews the production build.
+```sql
+.read converted.sqlite.sql
+```
-## Deployment
+## 🛠️ Local Development
-The app is configured for GitHub Pages at:
+This project uses Bun.
-```text
-https://dominosaurs.github.io/sql-converter/
+```bash
+bun install
+bun run dev
```
-Vite uses:
+Run checks:
-```ts
-base: '/sql-converter/'
+```bash
+bun run lint
+bun test
+bun run build
```
-
-GitHub Actions workflows:
-
-- `.github/workflows/ci.yml` runs lint, tests, and build.
-- `.github/workflows/deploy-pages.yml` builds and deploys `dist` to GitHub Pages.
-
-In GitHub repository settings, configure Pages source as **GitHub Actions**.
-
-## Reporting Issues
-
-If a dump fails to import after conversion, open an issue:
-
-https://github.com/dominosaurs/sql-converter/issues
-
-Include:
-
-- The SQLite error message.
-- The source SQL statement that caused it.
-- The converted output statement.
-- Whether the dump came from MariaDB, MySQL, phpMyAdmin, or another tool.
-
-## License
-
-MIT
From 86daa1c2673509845fada1c54c2b81debca5e23e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=F0=9F=8D=95?=
Date: Tue, 28 Apr 2026 18:20:58 +0800
Subject: [PATCH 5/5] Detect and disable unsupported browsers
Detects if the browser supports the File System Access API, which is required for streaming large files directly to disk.
If the browser is not supported, the UI is updated to reflect this limitation. The file drop area and convert button are disabled, and the status message is updated to inform the user.
This prevents users from attempting conversions that are known to fail in their current browser, improving the user experience and preventing errors.
---
src/app.tsx | 67 +++++++++++++++++++++++++++++++++++++++-----------
src/styles.css | 5 ++++
2 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/src/app.tsx b/src/app.tsx
index 30ceee4..1855564 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -36,22 +36,35 @@ type ConversionState =
| 'error'
| 'cancelled'
+const DEFAULT_STATUS =
+ 'Choose a MariaDB .sql dump, then convert it to a SQLite import file.'
+const UNSUPPORTED_BROWSER_STATUS =
+ 'This browser cannot stream directly to disk. Use Chrome or Edge before selecting a large SQL file.'
+
export default function App() {
const inputFileRef = useRef(null)
const abortControllerRef = useRef(null)
+ const isBrowserSupported = supportsSaveFilePicker()
const [warnings, setWarnings] = useState([])
const [progress, setProgress] = useState(null)
const [selectedFileName, setSelectedFileName] = useState('')
const [selectedFileSize, setSelectedFileSize] = useState(0)
const [outputFileName, setOutputFileName] = useState('')
- const [status, setStatus] = useState(
- 'Choose a MariaDB .sql dump, then convert it to a SQLite import file.',
+ const [status, setStatus] = useState(() =>
+ isBrowserSupported ? DEFAULT_STATUS : UNSUPPORTED_BROWSER_STATUS,
+ )
+ const [conversionState, setConversionState] = useState(
+ () => (isBrowserSupported ? 'idle' : 'error'),
)
- const [conversionState, setConversionState] =
- useState('idle')
const [isConverting, setIsConverting] = useState(false)
const handleConvertClick = () => {
+ if (!isBrowserSupported) {
+ setStatus(UNSUPPORTED_BROWSER_STATUS)
+ setConversionState('error')
+ return
+ }
+
const file = inputFileRef.current?.files?.[0]
if (!file) {
@@ -63,6 +76,12 @@ export default function App() {
}
const handleFileChange = (file: File | undefined) => {
+ if (!isBrowserSupported) {
+ setStatus(UNSUPPORTED_BROWSER_STATUS)
+ setConversionState('error')
+ return
+ }
+
setSelectedFileName(file?.name ?? '')
setSelectedFileSize(file?.size ?? 0)
@@ -78,9 +97,7 @@ export default function App() {
.showSaveFilePicker
if (!saveFilePicker) {
- setStatus(
- 'This browser cannot stream directly to disk. Use Chrome or Edge for large 1GB files.',
- )
+ setStatus(UNSUPPORTED_BROWSER_STATUS)
setConversionState('error')
return
}
@@ -168,9 +185,9 @@ export default function App() {
setSelectedFileSize(0)
setOutputFileName('')
setStatus(
- 'Choose a MariaDB .sql dump, then convert it to a SQLite import file.',
+ isBrowserSupported ? DEFAULT_STATUS : UNSUPPORTED_BROWSER_STATUS,
)
- setConversionState('idle')
+ setConversionState(isBrowserSupported ? 'idle' : 'error')
}
const isFinished =
@@ -212,10 +229,12 @@ export default function App() {