|
| 1 | +# AI Assistant Project Instructions |
| 2 | + |
| 3 | +Concise, project-specific guidance for code-generation agents working in this repository. |
| 4 | + |
| 5 | +## 1. Purpose & High-Level Architecture |
| 6 | + |
| 7 | +This package provides a robust one-shot transfer of a MySQL/MariaDB database schema + data into a single SQLite file via |
| 8 | +a CLI (`mysql2sqlite`). Core orchestration lives in `transporter.py` (`MySQLtoSQLite` class) and is invoked by the Click |
| 9 | +CLI defined in `cli.py`. The transfer pipeline: |
| 10 | + |
| 11 | +1. Parse/validate CLI options (mutually exclusive flags, charset/collation validation). |
| 12 | +2. Introspect MySQL schema via `information_schema` (columns, indices, foreign keys). |
| 13 | +3. Generate SQLite DDL (type & default translation, index naming, optional foreign keys, JSON1 detection). |
| 14 | +4. Stream or chunk table data rows from MySQL → SQLite with optional chunk size and progress bars (`tqdm`). |
| 15 | +5. Post-process (optional `VACUUM`). |
| 16 | + |
| 17 | +## 2. Key Modules & Responsibilities |
| 18 | + |
| 19 | +- `src/mysql_to_sqlite3/cli.py`: Click command. Central place to add new user-facing options (update docs + README + |
| 20 | + `docs/index.rst` if changed). |
| 21 | +- `src/mysql_to_sqlite3/transporter.py`: Core transfer logic, schema introspection, type/default translation, batching, |
| 22 | + logging, reconnection handling. |
| 23 | +- `sqlite_utils.py` / `mysql_utils.py`: Helpers for charset/collation sets, adapting/encoding values and SQLite |
| 24 | + extension capability detection. |
| 25 | +- `types.py`: Typed parameter & attribute Protocols / TypedDict-like structures for constructor kwargs (mypy relies on |
| 26 | + this; keep hints exhaustive). |
| 27 | +- `debug_info.py`: Version table printed with `--version` (tabulated output). |
| 28 | + |
| 29 | +## 3. Patterns & Conventions |
| 30 | + |
| 31 | +- Strict option conflict handling: e.g. `--mysql-tables` vs `--exclude-mysql-tables`; `--without-tables` + |
| 32 | + `--without-data` is invalid. Mirror same validation in new features. |
| 33 | +- AUTO_INCREMENT single primary key columns converted to `INTEGER PRIMARY KEY AUTOINCREMENT` only when underlying |
| 34 | + translated type is an integer (see `Integer_Types`). Log a warning otherwise. |
| 35 | +- Index naming collision avoidance: when an index name equals a table name or `--prefix-indices` set, prefix with |
| 36 | + `<table>_` to ensure uniqueness. |
| 37 | +- Default value translation centralised in `_translate_default_from_mysql_to_sqlite`; extend here for new MySQL |
| 38 | + constructs instead of sprinkling conditionals elsewhere. |
| 39 | +- JSON handling: if `JSON` column and SQLite JSON1 compiled (`PRAGMA compile_options`), map to `JSON`; else fallback to |
| 40 | + `TEXT` unless `--json-as-text` provided. Preserve logic when adding new types. |
| 41 | +- Foreign keys generation skipped if any table subset restriction applied (ensures referential integrity isn’t partially |
| 42 | + generated). |
| 43 | +- Logging: use `_setup_logger` — do not instantiate new loggers ad hoc. |
| 44 | + |
| 45 | +## 4. Testing Approach |
| 46 | + |
| 47 | +- Use `pytest` framework; tests in `tests/` mirror `src/mysql_to_sqlite3/` structure. |
| 48 | +- Unit tests in `tests/unit/` focus on isolated helpers (e.g. type/default translation, JSON1 detection, constructor |
| 49 | + validation). When adding logic, create a targeted test file `test_<feature>.py`. |
| 50 | +- Functional / transfer tests in `tests/func/` (may require live MySQL). Respect existing pytest markers: add |
| 51 | + `@pytest.mark.transfer` for heavy DB flows, `@pytest.mark.cli` for CLI option parsing. |
| 52 | +- Keep mypy passing (configured for Python 3.9 baseline). Avoid untyped dynamic attributes; update `types.py` if |
| 53 | + constructor kwargs change. |
| 54 | + |
| 55 | +## 5. Developer Workflows |
| 56 | + |
| 57 | +- Dev install: `pip install -e .` then `pip install -r requirements_dev.txt`. |
| 58 | +- Run full test + coverage: `pytest -v --cov=src/mysql_to_sqlite3` (tox orchestrates matrix via `tox`). |
| 59 | +- Lint suite: `tox -e linters` (runs black, isort, flake8, pylint, bandit, mypy). Ensure new files adhere to 120-char |
| 60 | + lines (black config) and import ordering (isort profile=black). |
| 61 | +- Build distribution: `python -m build` or `hatch build`. |
| 62 | + |
| 63 | +## 6. Performance & Reliability Considerations |
| 64 | + |
| 65 | +- Large tables: prefer `--chunk` to bound memory; logic uses `fetchmany(self._chunk_size)` with `executemany` inserts |
| 66 | + for efficiency. |
| 67 | +- Reconnection: On `CR_SERVER_LOST` errors during schema creation or data transfer, a single reconnect attempt is made; |
| 68 | + preserve pattern if extending. |
| 69 | +- Foreign keys disabled (`PRAGMA foreign_keys=OFF`) during bulk load, then re-enabled in `finally`; ensure any |
| 70 | + early-return path still re-enables. |
| 71 | +- Use `INSERT OR IGNORE` to gracefully handle potential duplicates. |
| 72 | + |
| 73 | +## 7. Adding New CLI Flags |
| 74 | + |
| 75 | +1. Add `@click.option` in `cli.py` (keep mutually exclusive logic consistent). |
| 76 | +2. Thread parameter through `MySQLtoSQLite` constructor (update typing + tests). |
| 77 | +3. Update docs: `README.md` + `docs/index.rst` + optionally changelog. |
| 78 | +4. Add at least one unit test exercising the new behavior / validation. |
| 79 | + |
| 80 | +## 8. Error Handling Philosophy |
| 81 | + |
| 82 | +- Fail fast on invalid configuration (raise `click.ClickException` or `UsageError` in CLI, `ValueError` in constructor). |
| 83 | +- Swallow and print only when `--debug` not set; with `--debug` re-raise for stack inspection. |
| 84 | + |
| 85 | +## 9. Security & Credentials |
| 86 | + |
| 87 | +- Never log raw passwords. Current design only accepts password via argument or prompt; continue that pattern. |
| 88 | +- MySQL SSL can be disabled via `--skip-ssl`; default is encrypted where possible—don’t silently change. |
| 89 | + |
| 90 | +## 10. Common Extension Points |
| 91 | + |
| 92 | +- Type mapping additions: edit `_translate_type_from_mysql_to_sqlite` and corresponding tests. |
| 93 | +- Default expression support: `_translate_default_from_mysql_to_sqlite` + tests. |
| 94 | +- Progress/UI changes: centralize around `tqdm` usage; respect `--quiet` flag. |
| 95 | + |
| 96 | +## 11. Examples |
| 97 | + |
| 98 | +- Chunked transfer: `mysql2sqlite -f out.db -d db -u user -p -c 50000` (efficient large table copy). |
| 99 | +- Subset tables (no FKs): `mysql2sqlite -f out.db -d db -u user -t users orders`. |
| 100 | + |
| 101 | +## 12. PR Expectations |
| 102 | + |
| 103 | +- Include before/after CLI snippet when adding flags. |
| 104 | +- Keep coverage steady; add or adapt tests for new branches. |
| 105 | +- Update `SECURITY.md` only if security-relevant surface changes (e.g., new credential flag). |
| 106 | + |
| 107 | +--- |
| 108 | +Questions or unclear areas? Ask which section needs refinement or provide the diff you’re planning; guidance here should |
| 109 | +remain minimal but precise. |
0 commit comments